programing

내 도메인 엔터티를 프레젠테이션 레이어에서 분리해야하는 이유는 무엇입니까?

nasanasas 2020. 9. 22. 08:17
반응형

내 도메인 엔터티를 프레젠테이션 레이어에서 분리해야하는 이유는 무엇입니까?


세부 사항이 많지 않은 것으로 보이는 도메인 중심 설계의 한 부분은 도메인 모델을 인터페이스에서 분리하는 방법과 이유입니다. 동료들에게 이것이 좋은 관행이라고 설득하려고 노력하고 있지만, 많은 진전이없는 것 같습니다 ...

그들은 프레젠테이션 및 인터페이스 레이어에서 원하는 곳 어디에서나 도메인 엔티티를 사용합니다. 내가 그들에게 디스플레이 모델이나 DTO를 사용하여 인터페이스 레이어로부터 도메인 레이어를 격리해야한다고 주장 할 때, 그들은 그런 일을 할 때 비즈니스 가치를 보지 못한다고 반박합니다. 왜냐하면 이제는 유지할 UI 개체가 있기 때문입니다. 원본 도메인 개체도 마찬가지입니다.

그래서 저는 이것을 백업하는 데 사용할 수있는 몇 가지 구체적인 이유를 찾고 있습니다. 구체적으로 특별히:

  1. 프레젠테이션 레이어에서 도메인 개체를 사용하지 않는 이유는 무엇입니까?
    (답이 명백한 '디커플링'이라면이 맥락에서 왜 이것이 중요한지 설명해주세요)
  2. 인터페이스에서 도메인 개체를 격리하기 위해 추가 개체 또는 구성을 사용해야합니까?

간단히 말해서 그 이유는 구현과 드리프트 중 하나입니다. 예, 프레젠테이션 계층은 비즈니스 개체를 제대로 표현할 수 있도록 비즈니스 개체에 대해 알아야합니다. 예, 처음에는 두 가지 유형의 객체 구현간에 많은 겹침이있는 것처럼 보입니다. 문제는 시간이 지남에 따라 양측에 모든 것이 추가된다는 것입니다. 프레젠테이션 변경 및 프레젠테이션 레이어의 요구 사항은 비즈니스 레이어와 완전히 독립적 인 항목 (예 : 색상)을 포함하도록 진화합니다. 한편, 도메인 개체는 시간이 지남에 따라 변경되며, 인터페이스에서 적절한 분리가없는 경우 비즈니스 개체를 겉보기에 무해하게 변경하여 인터페이스 계층을 망칠 위험이 있습니다.

개인적으로, 사물에 접근하는 가장 좋은 방법은 엄격하게 시행되는 인터페이스 패러다임을 통하는 것입니다. 즉, 비즈니스 개체 계층은 통신 할 수있는 유일한 방법 인 인터페이스를 노출합니다. 인터페이스에 대한 구현 세부 정보 (예 : 도메인 개체)가 노출되지 않습니다. 예, 이것은 두 위치에서 도메인 개체를 구현해야 함을 의미합니다. 인터페이스 계층과 BO 계층에 있습니다. 그러나 이러한 재 구현은 처음에는 추가 작업처럼 보일 수 있지만 향후 어느 시점에서 작업 톤을 절약 할 수있는 분리를 강화하는 데 도움이됩니다.


나는 이것으로 나 자신을 고투했다. 프레젠테이션에서 DTO를 사용하는 것이 합당한 경우가 있습니다. 시스템에서 회사 드롭 다운을 표시하고 값을 바인딩 할 회사 ID가 필요하다고 가정 해 보겠습니다.

구독에 대한 참조가 있거나 다른 것을 알고있는 CompanyObject를로드하는 대신 이름과 ID와 함께 DTO를 다시 보낼 수 있습니다. 이것은 IMHO를 잘 사용합니다.

이제 다른 예를 들어 보겠습니다. 견적을 나타내는 개체가 있습니다.이 견적은 노동력, 장비 등으로 구성 될 수 있습니다. 사용자가 정의한 많은 계산을 통해 이러한 모든 항목을 가져와 합계 할 수 있습니다 (각 견적은 유형에 따라 다를 수 있음). 계산). 이 객체를 두 번 모델링해야하는 이유는 무엇입니까? 내 UI가 계산을 열거하고 표시하도록 할 수없는 이유는 무엇입니까?

나는 일반적으로 DTO를 사용하여 내 UI에서 내 도메인 계층을 격리하지 않습니다. 제어 할 수없는 경계에서 도메인 레이어를 분리하는 데 사용합니다. 누군가가 자신의 비즈니스 객체에 탐색 정보를 넣는다는 생각은 말도 안되며 비즈니스 객체를 오염시키지 마십시오.

누군가가 자신의 비즈니스 객체에 유효성 검사를 할 것이라는 생각? 나는 이것이 좋은 것이라고 말합니다. UI는 비즈니스 객체의 유효성을 검사 할 책임이 없어야합니다. 비즈니스 계층 자체 검증을 수행 해야 합니다.

왜 busienss 객체에 UI 생성 코드를 넣을까요? 제 경우에는 UI에서 별도의 UI 코드를 생성하는 별도의 개체가 있습니다. 내 비즈니스 개체를 Xml로 렌더링하는 별도의 개체가 있습니다. 이러한 유형의 오염을 방지하기 위해 레이어를 분리해야한다는 생각은 저에게 너무 낯설습니다. 왜 비즈니스 개체에 HTML 생성 코드를 넣을까요?

편집 조금 더 생각해 보면 UI 정보가 도메인 레이어에 속할 수있는 경우가 있습니다. 그리고 이것은 도메인 레이어라고 부르는 것을 흐리게 할 수 있지만 UI 모양과 느낌과 기능적 워크 플로 모두 매우 다른 동작을 가진 멀티 테넌트 애플리케이션에서 작업했습니다. 다양한 요인에 따라. 이 경우 테넌트와 해당 구성을 나타내는 도메인 모델이 있습니다. 그들의 구성에는 UI 정보가 포함되었습니다 (예 : 일반 필드에 대한 레이블).

개체를 지속 가능하도록 디자인해야한다면 개체도 복제해야합니까? 이제 새 필드를 추가하려는 경우 두 곳에 추가 할 수 있습니다. 아마도 이것은 DDD를 사용하는 경우 다른 질문을 제기 할 수 있습니다. 모든 영구 엔티티 도메인 객체입니까? 나는 내 예에서 그들이 있었다는 것을 압니다.


ASP / JSP 페이지에서 SQL을 사용하지 않는 것과 같은 이유로 수행합니다.

프레젠테이션 및 도메인 계층에서 사용하기 위해 하나의 도메인 개체 만 유지하면 해당 개체가 곧 모 놀리식이됩니다. UI 유효성 검사 코드, UI 탐색 코드 및 UI 생성 코드가 포함되기 시작합니다. 그런 다음 곧 그 위에 모든 비즈니스 계층 메서드를 추가합니다. 이제 비즈니스 계층과 UI가 모두 섞여 있고 모두 도메인 엔터티 계층에서 엉망이됩니다.

You want to reuse that nifty UI widget in another app? Well, You have to create a database with this name, these two schemas, and these 18 tables. You must also configure Hibernate and Spring ( or your frameworks of choice ) to do the business validation. Oh, you must also include these 85 other non-related classes because they are referenced in the business layer, which just happens to be in the same file.


I disagree.

I think the best way to go is to start with domain objects in your presentation layer UNTIL IT MAKES SENSE TO DO OTHERWISE.

Contrary to popular belief, "Domain Objects" and "Value Objects" can happily co-exist in the presentation layer. And this is the best way to do it - you get the benefit of both worlds, reduced duplication (and boilerplate code) with the domain objects; and the tailoring and conceptual simplification of using value objects across requests.


We are using the same model in the server and on the ui. And it's a pain. We have to refactor it some day.

The problems are mainly because the domain model needs to be cut into smaller pieces to be able to serialize it without having the whole database referenced. This makes it harder to use on the server. Important links are missing. Some types are also not serializable and can't be sent to the client. For instance 'Type' or any generic class. They need to be non-generic and Type needs to be transferred as string. This generates extra properties for serialization, they are redundant and confusing.

Another problem is that the entities on the UI don't really fit. We are using databinding and many entities have lots of redundant properties only for ui purposes. Additionally there are many 'BrowsableAttribute' and others in the entity model. This is really bad.

At the end, I think it is just a matter of which way is easier. There might by projects where it just works fine and where is no need to write another DTO model.


Answer depends on scale of your application.


Simple CRUD (Create, Read, Update, Delete) application

For basic crud applications you do not have any functionality. Adding DTO on top of entities woudl be a waste of time. It would increase complexity without increasing scalability.

enter image description here


Moderately complicated Non-CRUD application

In this size of application you will have few entities which have true lifeclycle and some business logic associated with them.

Adding DTOs on this case is a good idea for few reasons:

  • Presentation layer can see only subset of fields which entity has. You encapsulate Entities
  • No coupling between backend and frontent
  • If you have business methods inside entities, but not in DTO then adding DTOs means that outside code can't ruin state of your entity.

enter image description here


Complicated Enterprise Application

Single entity might need multiple ways of presentation. Each of them will need different set of fields. In this case you encounter the same issues as in previous example plus need to control amount of fields visible for each client. Having separate DTO for each client will help you to chose what should be visible.

enter image description here


It's about dependencies for the most part. The core functional structure of the organization has its own functional requirements, and the UI should enable people to modify and view the core; but the core itself should not be required to accommodate the UI. (If it needs to happen, it's usually an indication the core is not property designed.)

My accounting system has a structure and content (and data) that are supposed to model the operation of my company. That structure is real and exists regardless of what accounting software I use. (Inevitably a given software package contains structure and content for its own sake, but part of the challenge is minimizing this overhead.)

Basically a person has a job to do. The DDD should match the flow and content of the job. DDD is about making explicit all the jobs that need being done ad completely and independently as possible. Then the UI hopefully facilitates getting the job done as transparently as possible, as productively as possible.

Interfaces are about the inputs and views provided for the properly modeled and invariant functional core.


Dammit, I swear this said persistence.

Anyway, it's one more instance of the same thing: Parnas's law says a module should keep a secret, and the secret is a requirement that can change. (Bob Martin has a rule that's another version of this.) In a system like this, the presentation can change independently of the domain. Such as, for example, a company that maintains prices in Euros and uses French in the company offices, but wants to present prices in dollars with text in Mandarin. The domain is the same; the presentation can change. So, to minimize the brittleness of the system — that is, the number of things that must be changed to implement a change in requirements — you separate the concerns.


Your presentation may reference your domain layer, but there should be no binding directly from your ui to your domain objects. Domain objects are not intended for UI usage since they are often, if properly designed, based around behaviors and not data representations. There should be a mapping layer between the UI and the Domain. MVVM, or MVP, is a good pattern for this. If you try to directly bind your UI to the Domain, you will probalby create a lot of headache for yourself. They have two different purposes.


Perhaps you are not conceptualizing the UI layer in broad enough terms. Think in terms of multiple forms of response (web pages, voice response, printed letters etc) and in terms of multiple languages (English, French etc.).

Now suppose that the speech engine for the telephone call-in system runs on a completely different type of computer (Mac for example) from the computer that runs the website (Windows perhaps).

Of course it is easy to fall into the trap "Well in my company we only care about English, run our website on LAMP (Linux, Apache, MySQL and PHP) and everyone uses the same version of Firefox". But what about in 5 or 10 years?


See also the section "Data propagation between layers" in the following, which I think presents compelling arguments:

http://galaxy.andromda.org/docs/andromda-documentation/andromda-getting-started-java/java/index.html


With the help of tool like 'Value Injecter' and the concept of 'Mappers' in the presentation layer while working with views, it's much more easy to understand each piece of code. If you have a little bit of code, you will not see the advantages immediately but when your project will growing more and more, you will be very happy while working with the views to don't have to enter into the logic of the services, repositories to understand the view model. View Model is another guard in the vast world of anti-corruption layer and worth its weight in gold in a long term project.

The only reason why I see no advantage of using view model is if your project is small and simple enough to have views binded directly to each property of your model. But if in the futur, the requirement change and some controls in the views will not be binded to the model and you don't have a view model concept, you will start adding patches in many places and you will begin having a legacy code that you will not appreciate. Sure, you can do some refactoring to transform your view-model in view-viewmodel and follow the YAGNI principle while not adding code if you don't need it but for myself, it's much more a best practice that I must follow to add a presentation layer exposing only view-model objects.


Here's a real example as to why I find it good practice to separate domain entities from the view.

A few months ago I created a simple UI to show the values of Nitrogen, Phosphorus and Potassium in a soil sample through a series of 3 gauges. Each gauge had a red, green and red section, i.e. you could either have too little or too much of each component, but there was a safe green level in the middle.

Without much thought, I modelled my business logic to supply data for these 3 chemical components and a separate data sheet, containing data about the accepted levels in each of the 3 cases (including which measurement unit was being used, i.e. moles or percentage). I then modelled my UI to use a very different model, this model was concerned about gauge labels, values, boundary values and colours.

This meant when I later had to show 12 components, I just mapped the extra data into 12 new gauge view models and they appeared on the screen. It also meant I could reuse the gauge control easily and have them display other data sets.

If I'd had coupled these gauges directly into my domain entities, I would not have any of the above flexibility and any future modifications would be a headache. I've come across very similar issues when modelling calendars in the UI. If there is a requirement for a calendar appointment to turn red when there are 10+ attendees, then the business logic to handle this should remain in the business layer and all the calendar in the UI needs to know, is that it has been instructed to turn red, it should not need to know why.


The only sensible reason for adding additional mapping between generalized and domain specific semantics is that you have (access to) an existing body of code (and tools) that are based on a generalized (but mappable) semantics distinct from your domain semantics.

Domain driven designs work best when used in conjunction with an orthogonal set of functional domain frameworks (such as ORM, GUI, Workflow, etc.). Always remember that it is only in the outer layer adjacencies that domain semantics need to be exposed. Typically this is the front end (GUI) and persistent back-end (RDBM,ORM). Any effectively designed intervening layers can and should be domain invariant.

참고URL : https://stackoverflow.com/questions/821276/why-should-i-isolate-my-domain-entities-from-my-presentation-layer

반응형