So I'm reading about package by feature and domain-driven-design
https://phauer.com/2020/package-by-feature/
https://dzone.com/articles/package-by-layer-for-spring-projects-is-obsolete
What I'm curios about is how do you solve, or is there a way of solving to not tie down your main domain with heavy dependencies. I'll explain.
If you have all your feature related assets under one package, you will need to import the database library dependency on that subproject. Also if you're exposing this on an HTTP endpoint you might be introducing your HTTP dependency too.
com.myname.myservice.vehicle
|-Vehicle
|-VehicleService
|-VehicleRepository
|-VehicleQueries
So dependencies of com.myname.myservice.vehicle will be:
HttpLibrary-1.0
SQLLibrary-1.0
If you want to import this submodule's domain object Vehicle into another feature project Advertisements, you will drag both SQLLibrary-1.0 and HttpLibrary-1.0 with it. This way it's really difficult to develop Advertisements project losely coupled to Vehicles project because if one went too far ahead that would bring in binary incompatibilities.
Are there solutions for this. Am I not understanding package-by-feature or DDD correctly? Is this a pro-contra, it can't be solved? How do you deal with this in your projects?
FYI i'm using Scala, or you may note Java, but I think this applies to any language.
The problem with most "package by feature" supporters is that they aren't actually packaging by features, but by entities/aggregates, leading to a huge dependency mess across so called "features".
This by "feature" structure...
/user
UserController
UserRepository
User
UserDto
/project
ProjectController
ProjectRepository
Project
ProjectDto
...is actually much worse than the following "by layer" architecture, because it only gives the illusion of decoupling, but in practice it's still a single Bounded Context (BC) and it's completely normal & expected that the model components living inside the same BC are coupled.
/domain
User
Project
UserRepository
ProjectRepository
/web
UserController
UserDto
ProjectController
ProjectDto
/infrastructure
JdbcProjectRepository
JpaUserRepository
The package by layer approach gives you several advantages, but most importantly it allows you to isolate domain logic so that it's free of infrastructural concerns & ideally remains pure, making it highly testable, without mocking.
You could theorically do the same with the above by "feature" structure, but it's much more difficult to maintain the isolation given all concerns are mixed together and it's also harder to leverage tools such as ArchUnit to ensure the isolation.
My favorite approach is to package by Bounded Contexts -> Layers -> Aggregates and that's usually the kind of structure you find with popular DDD project samples:
IDDD Samples
Modular Monolith Sample
As a side note, a lot of people promoting micro-services are making the same mistake of having a service per entity/aggregate instead of segregating per Bounded Contexts, ending up with an even bigger mess...
Related
I have several modules in NestJS:
StudentModule
FinanesModule
GroupModule
ScoresModule
SubjectModule
A module includes model, repository, service, controller related to single resource or functionality.
Before crud operations, I need to check if we can update/delete some resource(student, group, etc.). For example, we cannot delete subject, while some students are studying it.
After some operations, I want to call some "side-effect" operations, for example:
When student is deleted, it should also be removed from all groups.
When a student is created in DB, an finances record should be also created for the student
when a student is added in a group, a score sheet document should be inserted in the DB
How can I organize project architecture, to avoid "wrong" dependencies?
If I call ScoresService.createEmptySheet(...args) method in StudentService.create() method, it would make StudentModule as a dependent of ScoresModule(as ScoresService is a part of ScoresModule) which seems to be wrong, as student module exists independently from finances module, actually, a finances are depended on student, not vice versa.
Do you think, it's normal to make StudentModule dependent on ScoresModule?!
In other words I need to organize communication between modules without make them dependent on each other when logically they aren't.
P.S I can't use SQL's foreign keys, I am using MongoDB.
I would say that this question points at something much broader than NestJs modules in particular and aims at Software Architecture as a whole.
To answer your question specifically your intuition is likely correct, making UserService depend upon ScoresService is not the best solution in a larger system.
Depending on the specific different solutions would be correct but it may be as simple as creating a third service UserScoreService which depends upon both ScoresService and UserService allowing them to remain independent of each other.
Speaking more broadly, if you are interested in knowing more about this topic I recommend checking out Robert C. Martin's Clean Architecture and Hexagonal Architecture.
You could look into Pub-Sub pattern, if you want that kind of decoupling (i.e. https://github.com/glebbash/nestjs-pubsub-core).
Using DDD w/ Clean Architecture, I'm instantiating all of my dependencies (e.g. Repositories and Services) first and injecting them into my UseCases. What I've noticed over time is that my list of dependencies for each UseCase has grown quite large over time. For example, my UseCase uses 3 Aggregate Roots so I have 3 repositories. Not so bad. But, as I add more features, I find myself adding Domain Services or more Repositories and having to inject them into the UseCase Constructor as well. Is it ok to have 10+ parameters in a UseCase Interactor? I've always thought having more than 2-3 parameters is a code smell. Is there a better way to handle this? Thank you in advance.
Having to many dependencies in constructor is definitely code smell. It's not very easy to handle it and often time it's more matter of experience and skills, but basically you need to look at your system from different perspective and check whether some services/aggregates can be substituted (merged) by new one, which is dependent on your old ones. Than this new one can eventually prove useful also in other places in your system, so you will reduce your code duplicity. You must just follow SRP.
You can find nice example here:
http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/
When comming accross concepts within a Domain Model where there exists something that has a name and sounds like an object but overlaps with the responsiblility of one of the 5 main DDD building blocks what is the best practice for naming this object and or dealing with design which may or may not include that name or phrase in the actual implementation?
To give a more concrete example lets say that we are designing a time tracking application in the spirit of DDD and encounter something that the domain experts refer to as a "time log" which is supposed to be the log which holds punch-in and corresponding punch-out times for all employees.
With this information my initial thought is that if there were a class written called TimeLog which allowed for querying existing time entries and also for persisting new or amended time log entries that such a class is really playing the role of a DDD repository. For simplicity sake, lets assume that after various discussions and refactoring that we come to a conclusion that each time log entry is essentially it's own aggregate root and thus has the need for a corresponding repository.
Now we are left with the option of either naming our repository as TimeLog which seems more in line with the DDD concept of ubiquitous language or we could call it TimeLogEntryRepository which seems to fit the more general convention for naming Repositories after the Aggregate root that they query/persist. I'm leaning more towards the the idea of using TimeLog since it is more descriptive of the actual role that it plays in the domain model which should in turn help in communicating design to domain experts. The choice of using TimeLogEntryRepository on the other hand follows existing DDD conventions and thus would make the design easier to follow for developers. A compromise could also be to go with the TimeLog naming but to have all repositories implement an IRepository interface or inherit from a common Repository base class to help developers locate and distinguish repository classes from others that make up the domain model. The main concern I have with using a base class is that it may encourage the use of marker interfaces or a weak unnecessary base class just for the purpose of organization and not due to behavioral factors.
What is the best practice in cases like this? I can see the same type of issue perhaps happening for services as they are another piece of the typical DDD building blocks that developers typically name using a "Service" suffix such as in SomeComplexActivityService but for Entities and Value Objects this is really a non-issue. I'm especially interested to see what others may have to say that have more DDD experience under their belt.
I personally prefer TimeLog.
It's actually amazing how much easier it becomes once you switch focus to business instead of technology. Proper naming is main weapon to keep that focus sharp.
The same goes for services - instead of ApplicationRegistrationService, I use ApplicationRegistrator.
Here's quite nice article about repositories.
I second #Arnis L. suggestion. I would also add that in respect to DDD your domain should reflect the actual UL (Ubiquitous Language) which you share with business analysist and other people that are often non technical people. So I think that you will talk with them about TimeLog and not TimeLogEntryRepository. Repository is just a pattern and it's name should not be in the naming conventions.
I am on a tight schedule with my project so don't have time to read books to understand it.
Just like anything else we can put it in few lines after reading books for few times. So here i need some description about each terms in DDD practices guideline so I can apply them bit at a piece to my project.
I already know terms in general but can't put it in terms with C# Project.
Below are the terms i have so far known out of reading some brief description in relation with C# project. Like What is the purpose of it in C# project.
Services
Factories
Repository
Aggregates
DomainObjects
Infrastructure
I am really confused about Infrastructure, Repository and Services
When to use Services and when to use Repository?
Please let me know if anyway i can make this question more clear
I recommend that you read through the Domain-Driven Design Quickly book from infoq, it is short, free in pdf form that you can download right away and does its' best to summarize the concepts presented in Eric Evan's Blue Bible
You didn't specify which language/framework the project you are currently working on is in, if it is a .NET project then take a look at the source code for CodeCampServer for a good example.
There is also a fairly more complicated example named Fohjin.DDD that you can look at (it has a focus on CQRS concepts that may be more than you are looking for)
Steve Bohlen has also given a presentation to an alt.net crowd on DDD, you can find the videos from links off of his blog post
I've just posted a blog post which lists these and some other resources as well.
Hopefully some of these resources will help you get started quickly.
This is my understanding and I did NOT read any DDD book, even the holy bible of it.
Services - stateless classes that usually operate on different layer objects, thus helping to decouple them; also to avoid code duplication
Factories - classes that knows how to create objects, thus decouple invoking code from knowing implementation details, making it easier to switch implementations; many factories also help to auto-resolve object dependencies (IoC containers); factories are infrastructure
Repository - interfaces (and corresponding implementations) that narrows data access to the bare minimum that clients should know about
Aggregates - classes that unifies access to several related entities via single interfaces (e.g. order and line items)
Domain Objects - classes that operate purely on domain/business logic, and do not care about persistence, presentation, or other concerns
Infrastructure - classes/layers that glue different objects or layers together; contains the actual implementation details that are not important to real application/user at all (e.g. how data is written to database, how HTTP form is mapped to view models).
Repository provides access to a very specific, usually single, kind of domain object. They emulate collection of objects, to some extent. Services usually operate on very different types of objects, usually accessed via static methods (do not have state), and can perform any operation (e.g. send email, prepare report), while repositories concentrate on CRUD methods.
DDD what all terms mean for Joe the plumber who can’t afford to read books few times?
I would say - not much. Not enough for sure.
I think you're being quite ambitious in trying to apply a new technique to a project that's under such tight deadlines that you can't take the time to study the technique in detail.
At a high level DDD is about decomposing your solution into layers and allocating responsibilities cleanly. If you attempt just to do that in your application you're likely to get some benefit. Later, when you have more time to study, you may discover that you didn't quite follow all the details of the DDD approach - I don't see that as a problem, you proabably already got some benefit of thoughtful structure even if you deviated from some of the DDD guidance.
To specifically answer your question in detail would just mean reiterating material that's already out there: Seems to me that this document nicely summarises the terms you're asking about.
They say about Services:
Some concepts from the domain aren’t
natural to model as objects. Forcing
the required domain functionality to
be the responsibility of an ENTITY or
VALUE either distorts the definition
of a model-based object or adds
meaningless artificial objects.
Therefore: When a significant process
or transformation in the domain is not
a natural responsibility of an ENTITY
or VALUE OBJECT, add an operation to
the model as a standalone interface
declared as a SERVICE.
Now the thing about this kind of wisdom is that to apply it you need to be able to spot when you are "distorting the definition". And I suspect that only with experience (or guidance from someone who is experienced) do you gain the insight to spot such things.
You must expect to experiment with ideas, get it a bit wrong sometimes, then reflect on why your decisions hurt or work. Your goal should not be to do DDD for its own sake, but to produce good software. When you find it cumbersome to implement something, or difficult to maintain something think about why this is, then examine what you did in the light of DDD advice. At that point you may say "Oh, if I had made that a Service, the Model would be so nmuch cleaner", or whatever.
You may find it helpful to read an example.:
I've started learning about DDD and wanted to know how others have organised their projects.
I've started off by organising around my AggregateRoots:
MyApp.Domain (namespace for domain model)
MyApp.Domain.Product
- Product
- IProductService
- IProductRepository
- etc
MyApp.Domain.Comment
- Comment
- ICommentService
- ICommentRepository
- etc
MyApp.Infrastructure
- ...
MyApp.Repositories
- ProductRepository : IProductRepository
- etc
The problem i've bumped into with this is that i have to reference my domain product as MyApp.Domain.Product.Product or Product.Product. I also get a conflict with my linq data model for product....I have to use ugly lines of code to distiguish between the two such as MyApp.Domain.Product.Product and MyApp.Respoitories.Product.
I am really interested to see how others have organised their solutions for DDD...
I am using Visual Studio as my IDE.
Thanks alot.
I try to keep things very simple whenever I can, so usually something like this works for me:
Myapp.Domain - All domain specific classes share this namespace
Myapp.Data - Thin layer that abstracts the database from the domain.
Myapp.Application - All "support code", logging, shared utility code, service consumers etc
Myapp.Web - The web UI
So classes will be for example:
Myapp.Domain.Sales.Order
Myapp.Domain.Sales.Customer
Myapp.Domain.Pricelist
Myapp.Data.OrderManager
Myapp.Data.CustomerManager
Myapp.Application.Utils
Myapp.Application.CacheTools
Etc.
The idea I try to keep in mind as I go along is that the "domain" namespace is what captures the actual logic of the application. So what goes there is what you can talk to the "domain experts" (The dudes who will be using the application) about.
If I am coding something because of something that they have mentioned, it should be in the domain namespace, and whenever I code something that they have not mentioned (like logging, tracing errors etc) it should NOT be in the domain namespace.
Because of this I am also wary about making too complicated object hierarchies. Ideally a somewhat simplified drawing of the domain model should be intuitively understandable by non-coders.
To this end I don't normally start out by thinking about patterns in much detail. I try to model the domain as simple as I can get away with, following just standard object-oriented design guidelines. What needs to be an object? How are they related?
DDD in my mind is about handling complex software, but if your software is not itself very complex to begin with you could easily end up in a situation where the DDD way of doing things adds complexity rather than removes it.
Once you have a certain level of complexity in your model you will start to see how certain things should be organised, and then you will know which patterns to use, which classes are aggregates etc.
In my example, Myapp.Domain.Sales.Order would be an aggregate root in the sense that when it is instanced it will likely contain other objects, such as a customer object and collection of order lines, and you would only access the order lines for that particular order through the order object.
However, in order to keep things simple, I would not have a "master" object that only contains everything else and has no other purpose, so the order class will itself have values and properties that are useful in the application.
So I will reference things like:
Myapp.Domain.Sales.Order.TotalCost
Myapp.Domain.Sales.Order.OrderDate
Myapp.Domain.Sales.Order.Customer.PreferredInvoiceMethod
Myapp.Domain.Sales.Order.Customer.Address.Zip
etc.
I like having the domain in the root namespace of the application, in its own assembly:
Acme.Core.dll [root namespace: Acme]
This neatly represents the fact that the domain is in scope of all other portions of the application. (For more, see The Onion Architecture by Jeffrey Palermo).
Next, I have a data assembly (usually with NHibernate) that maps the domain objects to the database. This layer implements repository and service interfaces:
Acme.Data.dll [root namespace: Acme.Data]
Then, I have a presentation assembly declaring elements of my UI-pattern-of-choice:
Acme.Presentation.dll [root namespace: Acme.Presentation]
Finally, there is the UI project (assuming a web app here). This is where the composition of the elements in preceding layers takes place:
Acme.Web [root namespace: Acme.Web]
Although you're also a .Net developer, the Java implementation reference of the cargo app from DDD by Eric Evans and Citerus is a good resource.
In the doc'd code, you can see the DDD-organization into bounded contexts and aggregates in action, right in the Java packages.
Additionally, you might consider Billy McCafferty's Sharp Architecture. It's an ASP.Net MVC, NHibernate/Fluent NHibernate implementation that is built with DDD in mind.
Admittedly, you will still need to apply a folder/namespace solution to provide the contexts. But, couple the Evans approach with #Arch and you should be well on your way.
Let us know what you are going with. I am on the same path as well, and not far from you!
Happy coding,
Kurt Johnson
Your domain probably have a
name, so you should use this
name as namespace.
I usally put repository
implementation and data access
details in a namespace called
Persistance under the domain
namespace.
The application use its own name
as namespace.
I'd check out codecampserver since the setup there is quite common.
They have a core project in which they include both the application and domain layers. I.e. the insides of the onion (http://jeffreypalermo.com/blog/the-onion-architecture-part-1/).
I actually like to break the core apart into separate projects to control the direction of dependency. So typically I have:
MyNamespace.SomethingWeb <-- multiple UIs
MyNamespace.ExtranetWeb <-- multiple UIs
MyNamespace.Application <-- Evans' application layer with classes like CustomerService
MyNamespace.Domain
MyNamespace.Domain.Model <-- entities
MyNamespace.Domain.Services <-- doman services
MyNamespace.Domain.Repositories
MyNamespace.Infrastructure <-- repo implementation etc.
MyNamespace.Common <-- A project which all other projects have a dependency to which has things like a Logger, Util classes, etc.