Announcement Announcement Module
Collapse
No announcement yet.
Book: "Domain driven design" implemented in Spring Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Book: "Domain driven design" implemented in Spring

    I recently started reading the book "Domain driven design" and I would like to start a little discussion here about how to implemented a good layered design, especially input from people who also read the book.

    Let me start by telling you that I also made the fault of making my domain model looking like the anemic model. I guess the influence of using EJB's inthe past was greater than I thought ... So to gain some more insight in the way a "good" domain model should be designed I started reading the book I mentioned above.

    So this is the architecture I had before ()

    controller
    ---
    usecase
    ---
    service
    ---
    domain
    ---
    dao

    Now let me explain
    - Controller has the only responsability to put an get data from the screen / form. The controller gets his business data from a class in the use case layer, also the submission of data will be handled by that use case class.
    - Usecase is responsible for handling, like the name indicates, use case functionalities. It is actually a facade to hide multiple service activities behind one method.
    - Service layer handles everything what is beneed its layer, so it is responsible for crud operations and also for "service" operations. So it wraps multiple daos. Business logic and validation is handles by this layer
    - Dao has only crud operations, no validation, no logic, just orm mapping
    - Domain = anemic model ... no business logic

    So after reading (I'm only half way) I'm thinking of using architectures like

    controller
    -------------------
    Usecase
    -------------------
    service | repository
    ------- -----------
    domain
    ---------- DAO
    -------------------

    - So for now I would keep the concept of a use case layer., but instead of only accessing the service layer it can now also access the repository
    - The service layer has now only "service" functionality, so no explicit crud operations, so its responsability is now more clear. The service layer cannot call the dao directly for crud but should use the repository.
    - The crud operations on the database have been move to the repository which also handles the extra business / domain logic (This is the logic that was difficult to implement directly in the domain class, I'll come back on this later)
    - The dao still only holds the crud operations with orm mapping, no logic there.
    - The domain has now been extended by more logic in the methods, and extra classes in its package that do what is called in the book "specifications pattern". These specifications can be validation on the domain object or extra logic that was difficult to put directly into the domain layer. This extra logic now belongs all to the domain layer but will be handled by the repository.

    I'm still halfway in the book but seperating the service and repository seems a good idea, also making use of "specifications" is helping me put more logic in the domain layer that was before not 100% clear how to implement it directly into the domain object.

    So anyone else who read the book or wo has suggestions.

    I'll keep posting some thoughts on this topic when I found useful stuff in the book

    I also found an interesting article about a generic dao http://blog.hibernate.org/cgi-bin/bl.../08#genericdao, I still need to read it a second time to see if it can be used to really make a generic dao. For now I redefine my crud operations for each domain model, perhaps this can make it more easily.

    Grtz

  • #2
    Interesting post, I will be monitoring this thread and hope to contribute as well in the nearby future. I own the book as well, I am looking for time to start reading it. Therfore it is hard to comment on your post. But I am curious about the sepertion, of your service and repository layer. Sounds just like a special service to me, not really a seperate layer. Triggers me more to start reading the book :-)

    Comment


    • #3
      Jettro,

      If that doesn't trigger you ... what about terms like anti-corruption layer
      Sounds hot doesn't it!

      About the seperation:
      What's in a name, I have a service "layer" and a repository "layer", I found that those two approaches belong side by side. Perhaps using the term "layer" is somewhat misleading.. perhaps pattern is a better name?

      So in that case I'll have a service and repository pattern

      Grtz

      Comment


      • #4
        Module pattern

        Recently I posted some remarks about the best way to handle modules in Spring. Instead of having 1 project its its always better to have multiple independent building blocks that you make use of when designing your application.

        So following the "module' pattern from the book I guess that each module should represent an aggregation, clearly defined by its boundaries. The module name could be the for example the same as the root aggregation.

        I find the isolation of aggregations into modules very interesting when writing unit tests. When each module has its own Spring application context configuration, unit and module (integeration) tests really mark clear boundaries.

        Dividing the Spring context files up into service, repository, dao, ... makes it easier to test because for example unit testing my dao layer needs to load the hibernate session and dao bean from the context files. When you have 1 context file per module the test will take much longer because all the other beans must be loaded.

        Anyone out that has good experience with modules and a good way to unit test?

        Comment


        • #5
          A few remarks about your design.

          The Service layer doesn`t have the same scope as the gui/domain/dao layers. It is a sublayer in the domainlayer, that sits on top of the domain model. It is responsible for providing a clear api (a facade) but it also is very usable for adding transactions/security. The ServiceLayer is use-case oriented, so you don`t need an extra Use-case layer.

          - The service layer has now only "service" functionality, so no explicit crud operations, so its responsability is now more clear. The service layer cannot call the dao directly for crud but should use the repository.
          The service layer has all the methods clients are going to use. So the service-layer does have a lot of crud-operations (although most calls can be forwarded to the dao).

          But I don`t see how the repository fits in. I know the 'Repository' from the 'Patterns of Enterprise Application Architecture', but they are for entity storage and with an or-mapper like hibernate, you don`t need to write them anymore.
          Last edited by Alarmnummer; Nov 7th, 2005, 06:43 AM.

          Comment


          • #6
            I agree with you that service layer is already use-case oriented, but in that way that its use case functionalities that it offers is limited to the underlying domain model. So in our application we have multiple services, when a creen action is taking, the logic behind is needs to perform multiple tasks, spread around in multiple services. So we created a use case layer that actually handles end user / end application use-cases scenarios. That way we hide the multiple services we need from the mvc controller. The mvc controller only has one dependency and that is our use case layer.

            Secondly, about the seperation between the service and repository class. I was just reading through the book and keeping an open mind... so here some thoughts:

            - The DAO layer should not contain ANY business logic, its only responsability is to handle the ORM mapping
            - The domain model should hold as much as possible domain logic as possible. But sometimes to perform this domain logic, the model needs another dao or service and this is for the moment not simple to implement in Spring. I know they are working on it but it is still in the sandbox and I'm going to wait for it until it is in the releases.
            - So were do we put the logic, for now, that we cannot put in the domain model but that is part of the model? In the book these problems are handled by the Specifucation pattern. The specification pattern is used to solve problems like business logic validation, logic that cannot be placed in the domain model, ... . Can these business logic validations, and other specifications go in the service layer or not? I gues that all these kinds of specifications can go into the service layer for my part ... I as just looking at our service and dao and there were so many methods that were just delegating to the dao that I thought I was doing something wrong.
            - I see service as something on top of the domain, logic that realy does not belong t the domain model itself, I see specifications as part of the domain model so perhaps mixing these two in the same layer (services) is not best idea?

            I'm still reading the book, but for now I find the specification pattern nice to have, but still not sure about the repository layer, thats way I posted this message to see how people layer they apps.

            Feedback would be nice

            Comment


            • #7
              first a disclamer:
              anything I say can`t be hold against me in a court of law. I`m also learning about this subject and I don`t have a lot of practical experience. So it could be that I`m wrong.

              Originally posted by rebornspirit
              I agree with you that service layer is already use-case oriented, but in that way that its use case functionalities that it offers is limited to the underlying domain model. So in our application we have multiple services, when a creen action is taking, the logic behind is needs to perform multiple tasks, spread around in multiple services. So we created a use case layer that actually handles end user / end application use-cases scenarios.
              I think you mean a service layer when you say use-case layer. Service layer shouldn`t contain much logic and the service layer is the place to add transaction/security. If you need to combine different services to create a new piece of functionality, this new peace of functionality also is a service. And if those other 'lower' services only are called from 'higher' services, I think it is questionable if those lower services should be called service.

              - The DAO layer should not contain ANY business logic, its only responsability is to handle the ORM mapping
              true.

              - The domain model should hold as much as possible domain logic as possible. But sometimes to perform this domain logic, the model needs another dao or service
              true.

              extra:
              It should contain logic, but you don`t need to place all logic into domain objects. Sometimes it is better to move the logic to a different class (in your domain layer).

              and this is for the moment not simple to implement in Spring. I know they are working on it but it is still in the sandbox and I'm going to wait for it until it is in the releases.
              This is true. I also have commented on this problem a couple of times.

              - So were do we put the logic, for now, that we cannot put in the domain model but that is part of the model?
              There is a servicelocator your domain objects can use to retrieve dependencies.

              In the book these problems are handled by the Specifucation pattern. The specification pattern is used to solve problems like business logic validation, logic that cannot be placed in the domain model, ... . Can these business logic validations, and other specifications go in the service layer or not?
              The service layer shouldn`t contain much logic. It`s only goal is to provide a facade (easy api) where transactions and security can be coordinated. You also could add the application logic in a service object, but the domain logic belongs to the domain-layer.

              I gues that all these kinds of specifications can go into the service layer for my part ... I as just looking at our service and dao and there were so many methods that were just delegating to the dao that I thought I was doing something wrong.
              Nope.. I don`t think you are doing anything wrong. The Service layer will contain a lot of CRUD operations that can be forwarded to 'lower' objects without any extra operations. But this approach is better than direct access (using a dao in a MVC-controller for example) because it will be difficult to introduce a service layer later.

              [edit]
              for my part
              Nice translation to english Dead giveaway you speak dutch

              - I see service as something on top of the domain, logic that realy does not belong t the domain model itself, I see specifications as part of the domain model so perhaps mixing these two in the same layer (services) is not best idea?
              It is on top of your domain model. Why? If the Service was a true Layer, the Layer on top of the Service (gui-layer for example) shouldn`t know about structure below the Service layer (the Domain layer). And another reason is: the domain layer is on the same abstraction level as the service layer and with layering this isn`t the case.
              Last edited by Alarmnummer; Nov 7th, 2005, 08:21 AM.

              Comment


              • #8
                Thanks for the reply

                Could you explain by usng the small example below where you should put the business logic (the one that was not possible to put in the domain layer) because of dependecies):

                So what you are saying is that I should just use the following structure:

                Code:
                Service ---> dao ---> database
                and in between the dao and the service layer, the domain floats. But where would you validate and add business logic, for example if we would have the simple update method

                Code:
                DomainObject update(DomainObject o)
                We would have an update method in the dap, that just checks that the object to update is not null for example and that is has an id. But where would you put the validation and other business logic that is needed to update the object. If you say that the service should not contain that logic and the dao should definitly not contian that logic ... where should this logic go?

                If you would drawn a layered diagram of your application, how would you draw it?

                Code:
                service - dao -domain
                or

                Code:
                service
                dao domain
                or ...

                Because perhaps I have a wrong view on what "layered" means? I always talked about a layer that is something that hides what is beneed. So a service hides that it is using some king of dao (hibernate/jdbc...)

                It would be great if you could tell me (with an example ... ) what the true meaning of a layer is, because the more I seem to work with "layered" design, to more I get confused

                But I'm learning

                Comment


                • #9
                  Originally posted by rebornspirit
                  Thanks for the reply

                  Could you explain by usng the small example below where you should put the business logic (the one that was not possible to put in the domain layer) because of dependecies):
                  It should be put in the domain layer, but a (bad) example of domain logic in the service is:

                  Code:
                  EmployeeService{
                      void fire(Employee employee){
                          Desk desk = employee.getDesk();
                          desk.clean();
                          employee.setStatus(FIRED);
                          employee.setSalary(0);
                          employee.setFiredDate(new Date());
                          employeeDao.save(employee);
                      }
                  }
                  So what you are saying is that I should just use the following structure:

                  Code:
                  Service ---> dao ---> database
                  No:

                  DomainLayer -> Data accesslayer -> Database

                  the service layer only is a very small layer that is part of your domain layer.

                  If you focus on the domain layer, you see:

                  ServiceLayer : DomainLayer

                  But where would you validate and add business logic, for example if we would have the simple update method
                  It should be part of the domain model:

                  Code:
                  class Employee{
                  
                     void setSalary(int amount){
                          Validator validator = ... retrieve salary validator
                          validator.validate(amount);
                          _amount = amount;
                     }
                  }
                  But if you use a weblayer, this logic is repeated (ugly) in the weblayer. I think people should stop writing weblayers for applications, because it makes everything so complex

                  We would have an update method in the dap, that just checks that the object to update is not null for example and that is has an id. But where would you put the validation and other business logic that is needed to update the object.
                  Example:

                  Code:
                  class Employee{
                    void fire(){
                          Desk desk = getDesk();
                          desk.clean();
                          setStatus(FIRED);
                          setSalary(0);
                          setFiredDate(new Date());
                          employeeDao.save(employee); //this one is questionable.
                      }
                  }
                  UI -> Domain -> DAO.

                  Because perhaps I have a wrong view on what "layered" means?
                  in "Patterns of Software Architecture" there is a great topic about layering.

                  But I'm learning
                  I`m also learning. I have to get a better understanding on this subject and a good discussion helps a lot.
                  Last edited by Alarmnummer; Nov 7th, 2005, 09:09 AM.

                  Comment


                  • #10
                    Thanks for the reply,

                    I always thought when you were talking about the domain layer that you where talking about something above the domain model, but know I see that the term domain model and domain layer are the same... sometimes mixed terminologie can lead also to misunderstanding.

                    Correct me if I'm wrong here

                    Code:
                    class Employee{
                    
                       void setSalary(int amount){
                            Validator validator = ... retrieve salary validator
                            validator.validate(amount);
                            _amount = amount;
                       }
                    }
                    I agree that this is the best way, the problem is that Spring has no nice way to handle this and I cannot use the solution in the sandbox. So I guess that you would move the validation to the service, corect?

                    Grtz

                    Comment


                    • #11
                      Originally posted by rebornspirit
                      Thanks for the reply,

                      I always thought when you were talking about the domain layer that you where talking about something above the domain model, but know I see that the term domain model and domain layer are the same... sometimes mixed terminologie can lead also to misunderstanding.
                      This is true and with enterprise applications it irritates me quite a lot.

                      Code:
                      class Employee{
                      
                         void setSalary(int amount){
                              Validator validator = ... retrieve salary validator
                              validator.validate(amount);
                              _amount = amount;
                         }
                      }
                      I agree that this is the best way, the problem is that Spring has no nice way to handle this and I cannot use the solution in the sandbox.

                      So I guess that you would move the validation to the service, corect?
                      Personally I would use the ServiceLocator to get my dependencies. Your design won`t be damaged as much as the anemic domain model (putting all the logic in service-like objects).

                      Comment


                      • #12
                        A few thoughts (I`m reading DDD and PEAA):

                        The term Service object is used in different context. With Patterns of Enterprise Application Architecture it is a facade for your domain layer, that coordinates transactions/security but doesn`t do anything else (it doesn`t contain any logic)

                        In Domain Driven Design you have (at least) 2 types of Service objects:
                        ApplicationService objects.
                        DomainService objects.

                        A Service object in DDD is an object that only has logic that shouldn`t be part of the entities (sometimes your objects can get very bloated and it is better to group the logic instead of scattering it over a lot of domain objects). But DDD-Service objects are part of the Layer and don`t sit on top of it. The difference between a Application Service Object and a Domain Service Object is that the Application Service object contains application logic, but the Application Service Object will forward the call to objects in the Domain Layer eventually.. adding extra domain logic).

                        Personally I would like to drop the name 'Service object' from DDD and replace it with Manager object (if you know something better I would be happy to accept it). In your case you have a lot of objects that combine logic from other objects to create new functions and I would call these object: Managers.

                        And you also have a boundary for the rest of your system (your gui for example) and these boundries I would call services.

                        If someone else (with more insight than I have) has some ideas about this subject, please reply Enterprise problems are difficult enough, but creating so many names for the same thing, or one name for thing that have a different meaning (depending on who said it) doesn`t make it any easier. It would be nice if someone wrote a nice article about the unification of PEAA en DDD.
                        Last edited by Alarmnummer; Nov 7th, 2005, 04:08 PM.

                        Comment


                        • #13
                          Originally posted by Alarmnummer
                          Example:

                          Code:
                          class Employee{
                            void fire(){
                                  Desk desk = getDesk();
                                  desk.clean();
                                  setStatus(FIRED);
                                  setSalary(0);
                                  setFiredDate(new Date());
                                  employeeDao.save(employee); //this one is questionable.
                              }
                          }
                          And if "fire" logic is put inside Employee domain object, then transaction demarcation should take place inside EmployeeService object that coordinates/delegates call to this domain object's method, right?

                          But since good practice is reusing domain objects in UI layer, thus avoiding DTOs for that, that means someone in UI layer could easily call this Employee.fire() method in that layer, which is dangerous since it is out of transaction? In example above it wouldn't be possible since it is not public method, but I guess you would have to have some of these methods being public if you want to delegate calls to them from services in different packages?

                          -Vjeran

                          Comment


                          • #14
                            Originally posted by Alarmnummer
                            Enterprise problems are difficult enough, but creating so many names for the same thing, or one name for thing that have a different meaning (depending on who said it) doesn`t make it any easier. It would be nice if someone wrote a nice article about the unification of PEAA en DDD.
                            :-)))
                            So much about UBIQUITOUS LANGUAGE heavily propagated by DDD, when even Evans and Fowler can't practice it between themselves!

                            Comment


                            • #15
                              Originally posted by vmarcinko
                              And if "fire" logic is put inside Employee domain object, then transaction demarcation should take place inside EmployeeService object that coordinates/delegates call to this domain object's method, right?
                              It should be in the Martin-Fowler-EmployeeService object. Not in the DDD-EmployeeService object

                              But since good practice is reusing domain objects in UI layer, thus avoiding DTOs for that, that means someone in UI layer could easily call this Employee.fire() method in that layer, which is dangerous since it is out of transaction?
                              Yes.

                              In example above it wouldn't be possible since it is not public method, but I guess you would have to have some of these methods being public if you want to delegate calls to them from services in different packages?
                              In examples I almost never write access modifiers, but in most cases these methodes are public.

                              Comment

                              Working...
                              X