Is Value Object a bad pattern?

2020-06-06 05:01发布

Is use of VO´s (POCO) a bad design pattern? Some people say that all domain logic of an object needs to be together in that object.

Ex.: ProductVO: Id, Name, Description

ProductBO: SearchById(int id), Insert(ProductVO newProduct), Update(ProductVO updatedProduct, SearchByKeyword(string word)......

6条回答
等我变得足够好
2楼-- · 2020-06-06 05:37

Is use of VO´s (POCO) a bad design pattern? Some people say that all domain logic of an object needs to be together in that object.

I think there's a lot of confusion here because there are two almost completely contradictory definitions of "Value Object".

  • One is "An object with value semantics", i.e. immutable and often validated for correctness at construction.
  • Another is "An object that has state but no logic". I think that's what you mean. It's better to call this a Data Transfer Object, since that expression is better defined.

POCO/POJO is also not a fitting expression because it does not mean absence of logic either, only that no specific superclass, interface or bytecode enhancement is required.

As for your question: having a domain model in classes without logic for no other reason than having seen other people doing it like that and having a name for it is indeed very bad design - it's an anti-pattern known as anemic domain model. Unfortunately, there have been a number of badly designed frameworks (now generally abandoned) that required and promoted this "pattern".

It ignores the fundamental idea of object orientation: encapsulating data with the logic that operates on it, and it generally leads to verbose, inflexible and fragile code because the external logic now needs to be called explicitly and passed the model, it becomes much harder to ensure that invalid data is not passed around, and the knowledge about the structure of the domain model is spread around widely.

That being said, it's definitely not true that "all domain logic of an object needs to be together in that object" - sometimes there are good reasons to extract some of the domain logic and keep it in separate classes:

  • When it's not really domain logic but a technical aspect, like persistence, that should be in a separate layer
  • when the logic is different in different parts of the application
  • generally, when it's so complex that the domain classes would become too big, and you need to structure it more.

But generally, the domain logic concerning an object should be part of that object, unless you have a specific reason to put it somewhere else.

查看更多
不美不萌又怎样
3楼-- · 2020-06-06 05:42

Value objects are great!

Why in the world would you want to keep calling "IsValidName(myString)" all over the place when you could just encapsulate the rules of what makes a name into a Name class, and then have the compiler make sure that a non-validated name never gets passed around?

查看更多
Emotional °昔
4楼-- · 2020-06-06 05:45

I think they are a good pattern for certain environments (e.g. service-oriented applications).

Using DTOs is often valuable when you want to decouple layers of an application. The reason that DTOs help you do this is that you can easily serialize a DTO with the understanding that any behavior that can be applied to it is located elsewhere.

In situations where decoupling of state and behavior is not needed I wouldn't recommend the use of this pattern as it simply clutters the domain.

查看更多
做自己的国王
5楼-- · 2020-06-06 05:46

All Domain logic should be in the Domain layer, in Domain Objects... but there is a strong argument to be made that technical concerns, like how to save an object to the database, or log an objects activities, are not domain behaviors, they are infrastructure, or application concerns, and should NOT be in the domain objects...

Examine Domain Driven Design, In this methodology, it is recommended that you separate Domain-related aspects of persistence logic (like persisting/Fetching objects) into a separate Type (also in the Domain Layer) called a Repository... But even here, the technical aspects of how to talk to a database or other persistence storage technology are furthur separated into an infrastructure service.

One way to look at this is that services should be partitioned into three sets,

  • Infrsastructure Services. those that relate to general technical aspects (like generic database access, caching, logging, configuration, messaging, etc.)

  • Application services. That relate to technical or application design aspects that have nothing to do with the business domain (MVC pattern in UI, Screen navigation, domain entity initialization methodology, etc.

  • Domain Services. Services that are explicitly related to the business model. (for example, creating a reservation for a airline seat on a specific flight, with specific meal requests and seat assignment, and appropriate transactional debits to a specified credit card...)

    The last type of "service" should be in the Domain Layer, the first two, - not...

查看更多
▲ chillily
6楼-- · 2020-06-06 05:49

Not a bad design pattern if used properly. For me POCOs should have only intra-object logic, all inter-object logic belongs in the business layer.

查看更多
SAY GOODBYE
7楼-- · 2020-06-06 05:55

Using VO's lets you decouple state from behavior, which sounds incompatible with OOP, but may well be appropriate when different aspects of the application view the state with their own goals in mind.

A general argument against VO's is that they allow invalid states, but what constitutes validity may well differ depending on what stage something is in a processing pipeline or what treatment it is being considered for. For example, data entry may require only that the birth year is in the past and not over 120 years ago, but qualification for a student will impose a tighter range. The VO could be created from importing or data entry, then passed to a student business logic object that maintains a reference to the VO and ensures validity with regard to its requirements. The student can then be passed around, instead of the raw VO, allowing full object-oriented behavior. This works particularly well if the business logic object exposes the VO through an immutable interface.

查看更多
登录 后发表回答