3

I'm creating an application which's architecture is based on Uncle Bob's Clean Architecture concepts and DDD. Note that it is BASED on DDD, so I gave myself the freedom to differ from strict DDD.

To create this application, I am using C# with .Net Standard 2.0

One of the principles of DDD relates to Value Objects. The definition for Value Objects, according to Wikipedia is as follows:

Value Object

An object that contains attributes but has no conceptual identity. They should be treated as immutable.

Example: When people exchange business cards, they generally do not distinguish between each unique card; they only are concerned about the information printed on the card. In this context, business cards are value object

Now, I want that my Value Objects does not allow their creation if some validation does not succeed. When it happens, an exception would be thrown during the instantiation. I really meant to throw an exception there, because the core of the architecture really does not expect any invalid data to reach that point.

Before going further on this question, to give you guys some more background, here is my architecture (NOTE: still incomplete):

My Clean Architecture Proposal

The rules I am following in this architecture is:

  1. A layer can only know about its immediate innermost neighbor layer's interfaces
  2. A layer cannot know anything about any outermost layer
  3. All communications between layers MUST be done through interfaces
  4. Each layer must be independently deployable
  5. Each layer must be independently developable

To better understand the arrows in this diagram, I recommend reading those Stack Exchanges's questions:

Explanation of the UML arrows

https://softwareengineering.stackexchange.com/questions/61376/aggregation-vs-composition

Now, the challenge I'm facing right now, is finding a good way to use the validators. I'm not satisfied with my architecture in this point. The problem is the following:

Since I can have thousands of Value Objects being instantiated at a given time, I don't want each instance of the Value Objects to have an instance method to perform the validation. I want the validation method to be static, since it's logic will be the same for every instance. Also, I want the validation logic to be available for the upper layer of the architecture to use to perform validations without trying to instantiating the Value Objects, thus causing an expensive exception to be thrown.

The problem is: C# DOES NOT ALLOW polymorphism with static methods, so I can't do something like:

internal interface IValueObject<T>
{
    T Value { get; }
    static bool IsValid(T value);
}

How can I achieve this functionality without relying on static methods polymorphism and, at the same time, not wasting memory?

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
  • Make the constructor private and use static factory methods. – Constantin Galbenu Mar 15 '18 at 19:54
  • @ConstantinGalbenu this sounds like a good solution. However, it would lead me to code repetition in all the Value Objects that share the same validation logic –  Mar 15 '18 at 19:57
  • then extract those pieces of code in separate components and use them. – Constantin Galbenu Mar 15 '18 at 19:59
  • 3
    Sounds like premature optimisation to me. How many commands are you expecting to process per second? If I look at your concerns, I would expect at least half a million per second, so you can really see a significant difference of not creating an instance. Plus, I see that you want to build a bunch of dogmas for yourself before even writing a single line of code. This will never turn to be good. – Alexey Zimarev Mar 15 '18 at 20:24
  • You guys are right. I need to revalidate my assumptions here. :) –  Mar 15 '18 at 21:27
  • DDD is not an architecture. You shouldn't have _thousands_ of VO instantiated if you use CQRS. The Domain validation is your last stand, they should throw hard 'cuz it means you have a bug somewhere. You can use a lib like fluent validation to create validators (by hand) that use the VO's IsValid function. And 'strict' DDD doesn't exist. It's all a set of principles. – MikeSW Mar 16 '18 at 03:15
  • Guys, feel free to go into my repository in GitHub and contribute to create a good proposal of a Clean Architecture based on DDD :) –  Mar 16 '18 at 04:50

3 Answers3

2

It's a good thing that you can think abstractly but you should generalize after you write some working code.

A general clean on-size-fit-all architecture DDD is a Mith. In fact DDD applies only to the Domain layer. That's the beauty of it, it's technology agnostic.

In my projects I don't even have a base class or an interface for Value objects, Entities or Aggregate roots. I don't need them. All the these building blocks are POPO (PHP).

In my opinion, a Clean architecture is the one that keeps the Domain layer technology agnostic, without dependencies to any external frameworks. The other layers could be almost anything.

Constantin Galbenu
  • 16,951
  • 3
  • 38
  • 54
  • I think this comment might be a philosophycal thought, but in the moment you are using a programming language, you are not technology agnostic anymore. If you think about it, if you are programming, or using computers, you are not technology agnostic. :p –  Aug 23 '20 at 19:59
  • @AndréMarcondesTeixeira If we thing about being technology agnostic as a a continuous range from 0 to 100% then the idea is to keep the domain layer closer to 0. Anyway, you are right, we are all not technology agnostic. – Constantin Galbenu Sep 04 '20 at 11:36
0

I suggest you get rid of IsValid() and make your Value Objects self-checking, always valid objects. Making them immutable is recommended and will obviously help a lot in that regard. You only have to check the invariants once during creation.

[Edit]

You might need to treat that as a first pass of input validation instead of value object invariant enforcement. If there's a huge amount of unsafe data coming in that you want to turn into value objects, first handle it in a validation process in the outer layer - you can make all performance optimizations you need, implement error logic and coordinate VO creation there.

guillaume31
  • 13,738
  • 1
  • 32
  • 51
  • I AM trying to make my value objects immutable, self-checking objects. But I want to provide a way to validate the invariants before creation –  Mar 20 '18 at 04:03
  • I misread the part about the whole context and number of VO's. See my edit. – guillaume31 Mar 20 '18 at 09:52
0

In clean architecture all business logic goes into use case interactors. Validation rules are part of the business logic so should go into use case interactors as well.

In ur case I would suggest to put ur validation in interactors which take a "request model", validate the "parameters" and then return the respective value object(s) as (part of the) response model.

This way the validation logic is in the right layer and value objects are only created when validation succeeds - so no invalid value objects are created and no performance is wasted.

plainionist
  • 2,950
  • 1
  • 15
  • 27
  • That is actually not quite true. Martin (aka "Uncle Bob") places "enterprise" business rules at the entity level, and "application" business rules at the application level. The idea being that if multiple applications share the same entities, the enterprise-wide business rules are applied centrally in one place. The application business rules would an additional layer of rules, specific to your application. That said, if you are confident that your entities will never be used for other applications, then it won't matter much, and you could probably compile both layers into a single assembly. – RogerMKE May 18 '20 at 17:27