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

  • #61
    Employee persistence question

    Regarding the persistence question with the Employee class as an example. I think this is a really bad example for the purpose of discussing domain model design as it's clearly not been taken from a proven design. In my experience you can only have a useful discussion based on a proven design.

    For example, is it the responsibility of the fire() method on the Employee class to clean the employee's desk? It's hard to be sure, but Employee is probably an Aggregate and Desk an immutable Value Object. I don't see what functionality would be implemented in the clean() method of the Desk class. A more useful thing to do in the fire() method to me seems to set the desk member variable to null. So the fire() method looks like this:

    Code:
    class Employee{
       public void fire(){
           setDesk(null);
           setStatus(FIRED);
           setSalary(0);
           setFiredDate(new Date());
        }
    }

    What's the impact on persistence? If you use Hibernate the relationship between Employee and Desk will be automatically removed.

    A comment on the exact role of the Desk class. First I talk about Desk as a Value Object, next I say it's managed by Hibernate as an Entity. Which one will it be? In this use case Desk clearly is a Value Object for Employee, and probably for the entire application. It's not the role of an HR application to manages desks in a database. Even if the HR application does manage desks, this should be implement as a separate module using it's own domain model. In this case you can implement the Desk class as a value object yet configure the class as an Entity in Hibernate.

    How to call the fire() method when the FIRE! button is clicked in the web browser? First of all, the Employee that is being viewed should be loaded in the HTTP session (or flow scope is you use Spring Web Flow) to enable Optimistic Locking.

    In the controller I would call a EmployeeManager.fire() method. The method looks like this:

    Code:
    public class EmployeeManager {
       /* setter ommitted */
    
       public void fire(Employee employee) {
          employee.fire();
          employeeOrmRepository.attach(employee);
       }
    }
    It makes a lot of sense to me to keep the persistence details out of the domain model in this case, I see no reason why the Employee class should be responsible for updating its state in the database.

    Why? Well, I guess there's only one place in the application where an Employee can be fired, for example the Employee detail screen.

    Does this answer all questions about persistence and domain models? No. Do we need a catalog of domain models used in real applications for educational purposes? Yes.

    Comment


    • #62
      Originally posted by josenyimi
      Still struggling where to put logic ?
      I hope this read may help:
      http://www.springframework.org/node/97

      The responsability of
      Presentation Layer
      Business Layer
      Persistence Layer
      Domain Layer
      Is well explained there.

      Important note is that the domain layer is a "cross-layer" layer (not just a layer on top of another layer).

      Quote:
      "The business layer should be responsible for the following:
      * Handling application business logic and business validation
      * Managing transactions
      * Allowing interfaces for interaction with other layers
      * Managing dependencies between business level objects
      * Adding flexibility between the presentation and the persistence layer so they do not directly communicate with each other
      * Exposing a context to the business layer from the presentation layer to obtain business services
      * Managing implementations from the business logic to the persistence layer"

      Quote:
      "... The domain object layer consists of objects that represent real-world business objects such as an Order, OrderLineItem, Product, and so on ..."


      HTH,
      Josť.

      I went through this example and here are a few words of caution

      a) It is too "Hello World" ish to demonstrate DDD
      b) It encourages the anemic domain model with all the code being in the OrderServiceSpringImpl.java and the Order and OrderLineItem to have no behavior.

      Comment


      • #63
        >The business layer should be responsible for the following:
        >* Managing transactions
        Business, real world transactions yes, but not implementation specific transactions
        >* Adding flexibility between the presentation and the persistence layer so they do not directly communicate with each other
        That is the responsibility of a controller layer not domain layer

        Comment


        • #64
          Hi folks,

          been reading this thread with enormous intrest, because im at the Fowler book these days, too. Just wanted to post my 2 cents on two topics you discussed here:

          1. The business objects <-> DAO issue
          To my understanding business objects should not contain any "data access" access code at all. To me there are 2 important reaseons for that. First, why should BOs know that they are held persistent? So for me its kind of task of the application infrastructure to do this job. If you develop a domain model you abstract "real world" objects into domain objects. So when a Product in the real world doesn't know anything about being saved, why should the domain object?
          Second, there is the problem of cyclic dependencies. Your DAO has to know about your domain object. If you domain object has to know about your DAO you've just created such kind of dependency. It makes objects harder to test, harder to deploy, harder to reuse...
          I personally use the domain layer as some kind of vertical layer all my other layers (DA, Service, Presentation) use.

          2. Domain methods in presentation layer
          You've mentioned an intresting problem with using domain objects at presentation level. You want to avoid domain logic methods be called from the presentation layer. I recently thought about introducing an interface (e.g. ProductView) where you only define the methods you want to give access to and let your domain objects implement this interface. As long the methods in the interface are a subset of the domain objects methods, theres no more work to do actually. Now place the Interface into your presentation package and typecast the objects that return from services to that ViewInterface.

          ProductView product = (ProductView) someService.getProduct(id);

          It's just a brainstorming idea. I haven't tried it so far... should work, shouldn't it?

          Regards,
          Ollie

          Comment


          • #65
            Hi,

            I agree with #1 and I initially like the concept of having a view specific interface. However, if the interface resides in the presentation layer and your domain objects implement that interface, haven't you made your domain objects dependant on your presentation layer?

            Originally posted by Oliver Schlicht
            Hi folks,

            1. The business objects <-> DAO issue

            2. Domain methods in presentation layer
            You've mentioned an intresting problem with using domain objects at presentation level. You want to avoid domain logic methods be called from the presentation layer. I recently thought about introducing an interface (e.g. ProductView) where you only define the methods you want to give access to and let your domain objects implement this interface. As long the methods in the interface are a subset of the domain objects methods, theres no more work to do actually. Now place the Interface into your presentation package and typecast the objects that return from services to that ViewInterface.

            ProductView product = (ProductView) someService.getProduct(id);

            It's just a brainstorming idea. I haven't tried it so far... should work, shouldn't it?

            Regards,
            Ollie

            Comment


            • #66
              You definately would if you'd have to write extra methods in the domain class to implement the interface. What you do here is simply abstract away already existing interfaces of that object. It seems to me a little bit like defining remote and home interfaces for EJBs (uhhh... that ugly word ... But in a pure object oriented way you are right, of course.

              I think that the problem is, that if the Service returns a domain object, you have to import it into your presentation class for example. And if you can't force presentation class developers to use the interface, all the fancy interfacing isn't worth a penny

              Damn... it looked to good

              Regards

              Comment


              • #67
                Couldn't your services return the View Interface?

                Comment


                • #68
                  2. Domain methods in presentation layer
                  You've mentioned an intresting problem with using domain objects at presentation level. You want to avoid domain logic methods be called from the presentation layer. I recently thought about introducing an interface (e.g. ProductView) where you only define the methods you want to give access to and let your domain objects implement this interface. As long the methods in the interface are a subset of the domain objects methods, theres no more work to do actually. Now place the Interface into your presentation package and typecast the objects that return from services to that ViewInterface.

                  ProductView product = (ProductView) someService.getProduct(id);

                  It's just a brainstorming idea. I haven't tried it so far... should work, shouldn't it?
                  The problem with simply using Interfaces here is that most view layers won't respect them, since they typically rely on reflective invocation to back resolution of some form of EL expressions. However, a more firm barrier to access could be supplied by fabricating proxies to represent the domain objects, or else some other form of EL interception.

                  In the "anaemic" view of course, you would be happy to permit arbitrary modification by your domain objects through view, since this would have no behavioural impact until the modifications were inspected by the service layer. I do accept all the arguments against anaemic models, but am continuing to find they offer a number of practical and design benefits - on the other hand I'm firmly convinced we must make sure not to adopt principles and technologies that rule out the use of "full" domain models.

                  In general I think some form of declarative proxying ("declarative" used in the sense that Spring offers "declarative" transaction management to contrast with the "programmatic" variety) could be very productive in this area.

                  Comment


                  • #69
                    2 types of domain objects

                    When I code domain objects I like to break them into 2 types: regular domain objects( Customer, Address, etc.) and stateful Use Case controllers. I don't break controllers one for every use case. They might be responsible for few related use cases and they use the state and references to regular domain objects to fulfil their responsibilities. I like to move as much as possible domain logic into regular domain objects except data access. Controllers are aware and initiate calls to DAOs or repositories.

                    Comment


                    • #70
                      Hi folks, excelent post. I'd like to share my experiance in a quite big project, with hundreds (or even thousands) of services and tens of business modules.
                      I also have some architectural and design questions, some related to Spring usage good practices.

                      The application was built upon business modules, each consisting of these layers:

                      BUSINESS MODULE
                      +---------------+
                      | view |
                      +---------------+
                      | communication |
                      +---------------+
                      | service |
                      +---------------+
                      | domain |
                      +---------------+
                      | dao |
                      +---------------+

                      * Business modules where divided so as to model different business areas of the client organization.
                      * Interaction beween business modules was service-driven, with the idea of hiding business details (and model) inside each module. We had some trouble though, in the dao layer, when objects from one module needed to store references to objects from another module.
                      * The communication layer was completely use-case oriented (see ahead what I mean). This layer consisted basically in dto's and proxies with logic for transforming domain objects to and from the dto's. By use-case oriented I mean that each use case had it's own dto with only extrictly the information needed for the use case. DTO's where first intendend to serve as the clasic pattern suggests, since the view and the application server where in separate machines. They also accomplished an excelent work in decoupling the business domain and the views, flattening complex domain object graphs into simple single objects. Another achievement of this layer was that these dto worked as dettached objects allowing to close hibenrate sessions BEFORE rendering the view.
                      * The service layer worked properly as a service layer :P, only as a facade of the underlying domain and for transaction demarcation. They where NOT AWARE of the dto's. All the transformations between dto's and model-objects was handled by the communication layer.
                      * The domain layer consisted in all business logic.
                      * The dao layer consisted in crud and query operations, with no business logic.

                      In my experience, the DTO's did a great job in the last two points and I prefer this approach rather than the "Open Session in View" pattern, which is not applicable in a distributed environment. Even if the environment is not distributed, I'd prefer this pattern rather than coupling the view to such low-level implementation issues. The fact that they were use-case specific also draw in a significant performance improvement, compared to initializing the whole domain-graph before detaching. We worked a lot with code generation, to simplify the coding and mantenience of this DTO's.

                      So, here is are a few questions:
                      1. Does your view layers interact directly with the domain objects?
                      2. If so, Don't you think this approach couples the view and the domain too tight? How do you manage the detaching? Do you initialize the complete graph?
                      3. If not so, do you work with dto's? how do you create them? by hand? code generation? dynamically?
                      4. Which should be the scope of the application contexts / bean factories (ej: layer, module)? How many of them should exists?
                      5. Which classes should do de beanFactory.getBean("someBean")?
                      6.
                      Originally posted by rebornspirit
                      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.
                      Why do you think that (or what do you mean by) it's not easy to implement that model-objects uses another dao or service? Is it because you cant't inject this dependencies and you don't want your domain object to do something like ServiceLocator.locate(some service) or I'm missing something? Is there any other way?


                      PS:
                      Originally posted by rebornspirit
                      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 came across the same situation and was wondering a way of creating dynamic services that just delegate the operations to de daos.

                      Comment


                      • #71
                        Originally posted by vmarcinko
                        And if "fire" logic is put inside Employee domain object, then 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?
                        This is for me a good point for dtos. I have just posted a reply where I describe an architecture I worked with, using dto's with great success. This types of things makes me question whether is it true that DTO's are an anti-pattern. Why is it better to couple the presentation layer to the business model and expose methods that should not be exposed rather than use DTOs?

                        Comment


                        • #72
                          If you are implementing to interfaces anyway then it shouldn't really matter....the interface that the view uses doesn't expose the "fire" method. Of course, if you know that there is a single object implementing all the different interfaces then you can still cast them (i.e. ReadOnlyEmployee, FireableEmployee...silly names, but you get the idea), but you would explicitly need to do that.

                          Just a thought in passing.

                          Comment


                          • #73
                            Originally posted by rebornspirit
                            The MyService interface implementation looks something like

                            Code:
                            public class MyServiceImpl implements MyService {
                             
                                private ViewObjectAssembler assembler;
                            
                                public ViewObject getSomething(Integer id) {
                                    MyDomainObject do = ... retrieve the domain object;
                                    return assembler.assemble(do);
                                }
                            }
                            and a custom assembler being set by Spring:
                            Two comments about this:
                            1. what if the same service has to be used in the same application context but for different views?
                            Suppose an ABM where different data from the same object can be accessed by different users? How do you handle this with spring without support for runtime mappings?
                            2. It smells like the last line of code would be the same for ALL the services. Perhaps a better approach is to put a proxy (dynamic perhaps) on top of the service layer where this logic would be written only once. And as an additional benefit, my service layer doesn't have to know anything about how the data it returns would be used.

                            Comment


                            • #74
                              Originally posted by apostiglioni
                              This is for me a good point for dtos. I have just posted a reply where I describe an architecture I worked with, using dto's with great success. This types of things makes me question whether is it true that DTO's are an anti-pattern. Why is it better to couple the presentation layer to the business model and expose methods that should not be exposed rather than use DTOs?
                              After using the domain model (contains business logic) and the DTO patterns (only setters and getters), I have to say the domain model can never be really used in a consistent way in a multi-tiered system.

                              Comment


                              • #75
                                Spring-based domain model

                                After reading the thread with great interest. I see many different opinions and still not sure about how to impl domain model with spring. I have following questions:

                                1. should domain object modelled as spring bean?

                                2. if yes - who manage domain object relationships, spring or hibernate? think of example: an order has many line items, each line item refer to product

                                3. if not - and everyone is agreeing that domain object should contain biz logic. what if order object wants to find any product on its lineitems has unit price greater than $1000 (this product may need company authorization before ordering). how should order run this query on product? - I assume DAO are spring bean.

                                4. also if biz logic in domain object. what should service layer do? is service a spring bean?

                                cheers
                                chuck

                                Comment

                                Working...
                                X