78

This is not brittle in the usual sense. A unit test is considered brittle if it breaks due to implementation changes which does not affect the behavior under test. But if the business logic itself changes, then a test of this logic is supposed to break. That said, if the business logic indeed changes often, perhaps it is not appropriate to hardcode the ...


39

These days, you are likely to see reads (queries) handled differently than writes (commands). In a system with a complicated query, the query itself is unlikely to pass through the domain model (which is primarily responsible for maintaining the consistency of writes). You are absolutely right that we should render unto SQL that which is SQL. So we'll ...


19

As I understand it, a main point is to split the Domain Logic (Business Logic) from the Infrastructure (DB, File System, etc.). This is the foundation of the misunderstanding: the purpose of DDD isn't to separate things along a hard line like "this is in the SQL server, so must not be BL", the purpose of DDD is to separate domains and create barriers ...


18

If you've ever been on a project where the organization paying to host the application decides that the database layer licenses are too expensive, you'll appreciate the ease of which you can migrate your database/data storage. All things considered, while this does happen, it doesn't happen often. You can get the best of both worlds so to speak. If you ...


14

When the property is defined in the production database (or a clone for testing), this is not a unit test. A unit test checks a unit of work and does not require a particular external state to work. This assumes that Offer1 is defined in the database to be a male-only offer. That's external state. So this is more of an integration test, specifically a ...


9

Let's start with a short review of the problem-space here. The fundamental benefit of adopting a CQRS pattern is to solve/simplify your problem domain by reducing the interleaving and leakage that begins to occur when utilizing the same model for your write-side as your read-side. Often, the tension that arises serves as a detriment to both. CQRS seeks to ...


8

An entity has a concept of identity that is independent of its value. For the concept of a Point, are two separate point-objects Point(x: 1, y: 2) and Point(x: 1, y: 2) considered the same? If they are entities, then the points might have different identities and would then be different. In practice, a point is likely to be identified by its coordinates. ...


7

DDD and EF have little to nothing to do with each other. DDD is a modeling concept. It means to think about the Domain, the Business Requirements, and model those. Especially in the context of object-orientation it means to create a design which mirrors business functions and capabilities. EF is a persistence technology. It is mainly concerned with data ...


6

You wrote On the other hand, OOP says a Product object should know how to save itself and in a comment. ... should be responsible for all the operation done with it This is a common misunderstanding. Product is a domain object, so it should be responsible for the domain operations which involve a single product object, no less, no more - so ...


6

The set manipulation logic that SQL is good at can be integrated with DDD no problem. Say for example I need to know some aggregate value, total count of product by type. Easy to run in sql, but slow if I load every product into memory and add them all up. I simply introduce a new Domain object, ProductInventory { ProductType TotalCount ...


5

Domain Driven Design does not provide an answer for this. DDD is more focused on business logic. Your problem is how to represent data as a string of characters sent to and from a client across a network. What you need is a Data Transfer Object (DTO). Any time you need to transfer data between processes, where the call to another process is the expensive ...


5

If you have no reason to think that you will need to know more information than just the label text, then yes, the State pattern is a serious overkill. You only need a lookup table to return the label. Even should you need more information in the future, you can return the data in its own bean class dedicated to the task. I would recommend State Pattern ...


5

Treat EF for what it is i.e. data access library which is only slightly more strongly-typed than raw ADO.NET. I wouldn't recommend to model your domain using EF entity classes just like I wouldn't recommend to model domain using raw DataSet or DataTable. I do understand that EF is being sold as a shortcut between database access and domain modeling however ...


5

ViewModel Architecture and Clean Architecture are not the same. In some ways they are incompatible. Please don't mix them carelessly. The number one thing that separates them is cycles. ViewModel architecture is comfortable creating cycles in it's design. Clean (or Onion, or Hex) Architecture is not. ViewModel uses a binder to resolve the problems this ...


5

The refresh token is solely defined by its values. And there is no continuity of the object when the values change, because it would be replaced by a new token. This is why it is a value object. This does not prevent that one of the value refers to a given user-id, which gives the impression of continuity between successive values. But it is not ...


5

I am going to assume that we don't have to debate the need for two systems (orders and accounts) and you have a real need for them to be so. It's a good analogy to consider each domain to be a separate microservice, that are running on different machines and ports, and are scaled differently. Then the requirement becomes clearer. It is a bad idea to try to ...


5

Pagination is not a domain concern. The domain layer typically does not care to know the number of records fetched from a persistence store. It is a performance concern, specifically on the database side. And the only domain elements that deal with the database are repositories. So the way I see it, you need a mechanism to send it from the API request (or ...


4

From everything I've read, here and elsewhere, the reason seems to be that changing multiple aggregates in one transaction creates the requirement that they are stored on the same database host. (Let's not even consider two-phase commit.) This introduces a trade-off, one that makes this a consideration rather than a rule of thumb. Is your bounded context ...


4

Actually, this is what I am thinking on and searching for an answer at the moment, which led me here. So, answering your questions as I understand the topic at the moment: What is the context means on C4Model? Well, it's a context that your system is working in - an environment, external systems and people interacting with your system, according to C4 ...


4

No, duplication of input validation is unavoidable in an application that is split into a front-end and a back-end and where the front- and back-end communicate over an untrusted communication channel like a network. Not doing the validation twice means that either you give the user a very bad UX by giving very late feedback on validation errors, or you ...


4

CRUD is an acronym for Create, Read, Update, Delete, the four fundamental operations of a database system, and that's all it is. I suppose you could describe a system as CRUD-like. Where I currently work we are having ongoing discussions about this, because the existing system is very database-operation-centric, and while this is very convenient for the ...


4

Your basic understanding is correct and the architecture you sketch out is good and works well. Reading between the lines it seems like you are coming from a more database-centric active record style of programming? To get to a working implementation I would say you need to 1: Domain objects don't have to include the whole object graph. For example I could ...


4

I'm assuming UserAggregate is supposed to model a User? In which case user creation should arguably not be in it. Whoever actually "creates" users could check whether the username is unique, and yes, it should have any and all dependencies it needs to do that. If UserAggregate is not a User than it's probably a technical class in which case the design is ...


4

Put the permissions and authentication on a separate Auth service. This checks the username/password and issues a signed token containing all the roles the user is in. You microservices can then check the signature of the token against the public key and compare the users roles with the required role for the method they are calling. The benefits of this ...


4

If your addBook method is designed so that it will always succeed, a void is preferred. If your method does validation on book, then returning a result is better then handling it with exceptions. In my opinion, exceptions should be used for exceptional situations only; if a database or webservice is down, throw an exception, but if the title should be ...


4

Entity Framework brings UoW & Repository (DbSet) out of the box No. Entity Framework abstractions were built with ORM, not DDD, in mind. The DbSet abstraction in any version of Entity Framework is nowhere near the simplicity of a DDD Repository - not to mention DbContext which exposes a zillion things more than a UnitOfWork. Here is a non-exhaustive ...


4

Bounded contexts are a way of modeling a large domain as independent sub-domains. Each bounded context will have several concepts unique to that context, and also its own internal model for shared concepts such as Customer. Your example doesn't seem complex enough to warrant multiple bounded contexts. All of your use cases revolve around reservations, and ...


4

In my experience, at least in in application development, it is seldom necessary to decide this beforehand. Instead, I would recommend to start with one repo class and see how far it brings you. When the code base grows and you get some indications that splitting up the repo into two becomes beneficial, then refactor immediately. Such indications are the ...


4

In this setup, all Entity properties have Public getters and setters, there is no encapsulation, no OOP, no code re-usability. When I need to update this entity in another Service (or any other method for that matter), I have to write the same code again. Yup - that's a completely normal starting point. If you squint, you can see that the database sort of ...


4

Practice trumps theory. Experience teaches us that Product.Save() leads to lots of problems. To get around those problems we invented the repository pattern. Sure it breaks the OOP rule of hiding the product data. But it works well. Its much harder to make a set of consistent rules which cover everything than it is to make some general good rules that ...


Only top voted, non community-wiki answers of a minimum length are eligible