Spring 2.0 vs. the Anemic Domain Model

Discussions

News: Spring 2.0 vs. the Anemic Domain Model

  1. Spring 2.0 vs. the Anemic Domain Model (144 messages)

    In "Spring 2.0 vs. the Anemic Domain Model," Craig Walls discusses how the upcoming Spring 2.0 release might be able to configure beans after instantiation to help avoid anemic domain models. Craig shows a very detailed explanation of how the domain model might look.

    From the introduction:
    One of the most interesting aspects (no pun intended) of Spring 2.0 that was discussed this past week at The Spring Experience was the idea of letting Spring configure beans post-instantiation and regardless of how the bean became instantiated. This Spring 2.0 feature helps avoid the Anemic Domain Model" anti-pattern as described by Martin Fowler.

    It's very common in Spring to build applications where service objects are injected with DAO objects and use those DAO objects to handle persistence of domain objects. The domain objects themselves, however, are little more than dumb data holders. The problem with this approach is that the interaction between the service object and the DAO object is very procedural. The service object makes one or more calls to the DAO, passing the domain object around like cargo.

    Ideally, the domain object would contain behavior to handle its own persistence. If domain objects offered such behavior, then the service object could deal directly with the domain object in a very object-oriented way. Instead of telling a DAO to persist a customer, the service would tell the customer to persist itself. There will still be a DAO, but the domain object will do its own dealing with the DAO, unbeknownst to the service object. In effect, the domain object and the DAO swap positions with relation to the service object.

    If the domain object is responsible for dealing with the DAO, then the domain object must have access to the DAO. In Spring, we'd like to do this through dependency injection. But domain objects are typically instantiated outside of Spring (e.g. in Hibernate, iBATIS, or some other persistence mechanism). How can Spring inject a DAO into a domain object when Spring isn't the one instantiating that domain object?

    What do you think of the vision?

    **************************

    And on a similar subject: Evil Design Patterns

    Threaded Messages (144)

  2. ...Ideally, the domain object would contain behavior to handle its own persistence.

    Nonsense. I've disagree with this completely. I thought true OO should reflect reality - you know, model your objects on real-world objects.

    Take for example a Bakery project. The primary objects that come to mind are a Cake, an Oven and a Baker. The Cake is the Domain object. The Oven is the Processor (persistence) and the Baker is the Controller. Should the cake know how to bake itself? What the author is proposing is that we tell the cake to bake itself. Does the Baker call cake.bake()? No, the Baker gets and Oven and calls oven.bake(cake) Why should the cake know about the process?(in this case, persistence) The Cake already has its own set of concerns - data and logic. The Cake is not just a "dumb" data holder. The Cake understands how to combine Sugar, Water, Flour and Eggs. The Cake knows how long it will remain fresh. The Cake has knowledge of the things that make sense for the cake to know about. The Cake should know nothing of the Oven or the Baker.

    Am I wrong? If I am wrong then what the author is proposing is not Object Oriented programming as I have come to understand it. If a Domain object is to know about Persistence, then why should the Domain object not understand Presentation as well?
  3. Object-Oriented design[ Go to top ]

    ...Object Oriented programming as I have come to understand it. If a Domain object is to know about Persistence, then why should the Domain object not understand Presentation as well?

    Its not so much about the different aspects domain objects should know about, it is more about the domain itself and its inherent processes that domain objects should take care of. (Like you describe above)

    People tend to design a big, all-knowing process maintainer which just dumps and exchanges data with dumb data-model objects.
    This shows a fundamental lack of understand object-oriented design and is bound to become a huge mess once the projects
    starts to grow.

    Concerning real object-oriented design and aspects like "presentation" and persistence:
    Domain objects have to have some limited knowledge about persistence and distribution boundaries for some very practical reasons. (Like the need for performance tweaks, minimizing resource usage like networkd bandwidth etc.)

    How this limited knowledge about these aspects is implemented is fairly unimportant.
    PersistenceManager.makePersistent(domainObject);
    or
    domainObject.makePersistent();
    is really just a matter of taste.

    In practice the domainObject will delegate this task to a specialist like a JDO layer or similar).

    We are dedicating special objects living on distribution boundaries to find, create, delete domain objects.
    (Traditionally, these could be stateless session beans).
    Most domain objects then do not care about persistence, but some do for performance reasons.

    For presentation we use different variants of transport object: read-only presentation objects and DTOs

    Works like a charm and makes changes to the system very easy.

    Cheers,
      Jochen
  4. Oven for persistence?[ Go to top ]

    ...I thought true OO should reflect reality - you know, model your objects on real-world objects.Take for example a Bakery project. The primary objects that come to mind are a Cake, an Oven and a Baker. The Cake is the Domain object. The Oven is the Processor (persistence) and the Baker is the Controller. Should the cake know how to bake itself? What the author is proposing is that we tell the cake to bake itself. Does the Baker call cake.bake()? No, the Baker gets and Oven and calls oven.bake(cake) Why should the cake know about the process?(in this case, persistence) The Cake already has its own set of concerns - data and logic. The Cake is not just a "dumb" data holder. The Cake understands how to combine Sugar, Water, Flour and Eggs. The Cake knows how long it will remain fresh. The Cake has knowledge of the things that make sense for the cake to know about. The Cake should know nothing of the Oven or the Baker. Am I wrong? If I am wrong then what the author is proposing is not Object Oriented programming as I have come to understand it. If a Domain object is to know about Persistence, then why should the Domain object not understand Presentation as well?

    An Oven is the persistence mechanism for a Cake? Is a Cake a Cake before it is baked, or just a mixture of ingredients in a container? I think your example both proved and disproved your point.

    This can easily turn into analysis paralysis, and there are tools like robustness analysis to aid in figuring out what needs to happen and then you can assign those responsibilities to objects and methods.

    But I considr it this way. There is nothing in the real world that "persists a cake." A cake simply exists. This supports the fact that a Cake should not how to persist itself -- but not explicitly -- implicitly.

    Consider if you built your entire bakery system without considering a database -- just a domain object model. Then later you go back and use some marker or aspect to say that you want cakes to survive a server melt down. Well, the syste/framework/VM whatever could make sure your entire object graph is somehow persisted without your system needing to explicitly tell it how. You might start expanding this to support transactions which, upon completion, commit to persistence store. But the end result is that the rest of the domain doesn't know whether or not cakes can persist themselves, nor will they have to worry about explicitly persisting the cake. They'll just know a cake exists when they have a cake and worry about nothing more.
  5. Oven for persistence?[ Go to top ]

    An Oven is the persistence mechanism for a Cake?

    No, I didn't say that. I was merely providing a parallel example. The Oven "bakes" while the DAO "persists" - they are both processors.
    ...Consider if you built your entire bakery system without considering a database -- just a domain object model. Then later you go back and use some marker or aspect to say that you want cakes to survive a server melt down. Well, the syste/framework/VM whatever could make sure your entire object graph is somehow persisted without your system needing to explicitly tell it how.

    This is the kind of egg-headed thinking that makes projects fail or at least go way over budget. The functionality that you describe is unnecessary and impractical. Why is there a need to for an object to persist without explicitly telling it to do so? The object should be saved when the user clicks "save". If the server "melts down" before my user is ready to commit changes, the system should not save the object because that is not what the user intended.

    What is it that Vic says? KISS.




    Every project I have ever been on has some sort of .
    2.
  6. There is a big difference between an explicit need for a user persist and the imlicit need for data to be persisted.

    In the former case it may be a requirement that the user have control over when to commit there changes. Whether these changes are commited to a master copy of the object in infallable memory or written to disk is not part of the requirement. The requirement is rather that the user be able to make changes in a temporary way until they decide to persist. There are many ways to implement this requirement, the most common of which is to keep a working copy of the object in memory (standalone client memory space or web application user session) and when the usser commits, to write it back to a database.

    The latter case stems from the typical business requirement that the data be always available. Since we can't guarantee a process on a machien will run forever uninterrupt, we store the state in a persistent mechanism less prone to failure (e.g. cluster os disks). However, there is no need for some user to explciitly state that the data must be saved, all that's important is that the data is not lost.

    The former is transaction management and the latter is persistent memory. If we had a VM who could ensure that its entire memory is persisted at all times and will never fail, the latter requirement would be fulfilled without affecting the design of the application. However, you would still have some use cases where the user's input is required to decide when to commit a transaction.

    In either case, I argue that it can be a transaction you want to commit, not an entity you want to save. If the transaction happens to involve many entities, so be it. Unfortunately, there aren't many systems which come close to providing this, and none that I'm readily aware of that do it in a mature way.

    So meanwhile, the prevalance of RDBMSs and their ability to expose data in ad-hoc ways combined with the fact that we're so used to explicit persistence because no implicit persistence transaction-based system is prevalent means we're stuck with DAOs for now, and thus we're left to ask whether you call entity.save() or dao.save(entity).

    P.S. egg-headed thinking is what lead us to the world we live in today
  7. Persistent cakes[ Go to top ]

    There is nothing in the real world that "persists a cake."

    Au contraire, sir!

    Simply by adding "fruit" to "cake" creates an indestructible mass that will persist until archaeologists dig the thing up.
  8. Should the cake know how to bake itself?
    Ah, you managed to find an example to deny the concept. But you are forgetting something. Your cake doesn't not know how to bake itself because you modeled it following that notion. But in some other model, in other domain, that might not remain valid. Why? Because it might not be desirable to force the clients of the object model to know how and when to request persistence of an object. By "how" I mean making a call storage.store(object). By "when" I mean whenever the modification of the object is completed and should be persisted.
    With EJB, you don't know or care, beyond the prescriptions of the spec, how or when an entity is persisted.
    I see no problem in giving a domain object the responsability of "persisting itself". Your cake could have a "store" method which could delegate the actual persistence to it's corresponding storage. And THAT is object orientation. Being persisted IS behavior of an object, why not?
    And yes, enough with Spring, already.
  9. Should the cake know how to bake itself?
    Ah, you managed to find an example to deny the concept. But you are forgetting something. Your cake doesn't not know how to bake itself because you modeled it following that notion.

    Sorry, but in the real world cakes don't know how to bake themselves, Strings don't know how to format themselves, etc. If you want to have an object that knows how to persist its data, create a class that delegates the data to the domain object and reserves for itself the ability to communicate with a DAO. There is no excuse for gunking up objects in any model.

    Another object lesson: A refrigerator truck does not extend a refrigerator and/or a truck. Its a class that wraps and delegates to a refrigerator and a truck.
  10. There's no such thing as a String in the real world either, but still, we have tons of then in any given Java program.
    If you had to model everything EXACTLY the way it happens in the real world, then you better get started with a VM than replicates chemistry, phisics, thermodinamycs, biology...
    That is why we have "models" and not "real world object". Unless you have a cake stacked inside your PC (which would explain why you keep talking about cakes instead of programming, by the way).
    And why is the refrigerator truck example relevant to this discussion? FUD.
  11. Congratulations on missing every point.

    String: We don't and shouldn't ask String to know about how the contents of Strings are used. We shouldn't ask domain objects to know about who or what is using its data, including DAO or other persistance mechanisms.

    Refrigerator trucks: An illlustration of how to use delegation instead of gunking up objects with extraneous dependencies.
  12. To me persistence of the data held by an object does not fall into the category of an domain object's behavior. It has nothing to do with the business functionality but with system integrity and performance. The domain model should remain independent of such things.

    In the cake, oven and baker example the behavior belongs in the cake in a method "heat()". The oven doesn't care what its cooking, but the thing that is being cooked changes its state based on the heat in the oven. Therefore, that behavior is in the cake rather than the oven.

    Persistence of a cake object doesn't fall into this same category and makes more sense to be independent of the domain model and behavior of the cake object. The domain model doesn't care how the cake is being persisted. But when removing this behavior I have been guilty of removing all behavior in my domain objects and that's really where the anti-pattern comes in.
  13. To me persistence of the data held by an object does not fall into the category of an domain object's behavior. It has nothing to do with the business functionality but with system integrity and performance. The domain model should remain independent of such things.

    This sums it up nicely.
  14. I wholeheartedly agree. Persistence is plumbing. Businesspeople don't deal with the plumbing in the buildings they work in, so why should "business-aware" objects have to do the same?

    Also, if you're describing the world in terms of objects, a "Customer" might know how to "validate" something or have a "credit balance", but there is no equivalent notion of "saving" itself. That's stepping outside of the abstraction that the objects are dealing with, and the only reason to do so ("save", in this case) is to deal with the implementation details of the solution that contains the abstraction (the data needs to be saved somewhere so that the program can work with it again in the future). In other words, keep this stuff out of business objects.

    I thought this battle had been fought a long time ago against the OO purists?
  15. I desagree. The term "business object" is missused. Being a business object does not prevent it from being other things; in this case, an object that is stored somewhere. There's a semantic inherent to that fact. If you find it confusing, you don't like, you wish someone would PLEASE take care of it for you, well... that's something else. But there's absolutely nothing wrong with an object "knowing" how to store itself. And please, read my hole post. You'll find a place where I state that the actual storing could be delegated to some other object.
    No "store" method? Perhaps; but next, you'll say a constructor does not belong in a class, because NO OBJECT IN THE REAL WORLD CREATES ITSELF. And THAT, my dearest, is purism in the most horrid way.
    (Sigh... I forecast a rain of replies saying the VM is the one creating the object, which is already making me sick).
  16. I desagree. The term "business object" is missused. Being a business object does not prevent it from being other things; in this case, an object that is stored somewhere. There's a semantic inherent to that fact. If you find it confusing, you don't like, you wish someone would PLEASE take care of it for you, well... that's something else. But there's absolutely nothing wrong with an object "knowing" how to store itself. And please, read my hole post. You'll find a place where I state that the actual storing could be delegated to some other object.No "store" method? Perhaps; but next, you'll say a constructor does not belong in a class, because NO OBJECT IN THE REAL WORLD CREATES ITSELF. And THAT, my dearest, is purism in the most horrid way.(Sigh... I forecast a rain of replies saying the VM is the one creating the object, which is already making me sick).

    It is all about requirements.
    People that dont want their domain objects tied to persistence will usually have this as a requirement.

    In a complex server/client application storing an object is
    MUCH more than having access to the DAO.
     
    - You may need to authenticate the current user to see if he/she has access rights to store such objects.
    - There may be business rules that dictate when/where/if/how these objects can and cannot be stored.
    - You may also want to cut down on the number of requests crossing server/client borders.

    Given all these and the fact that they are bound to change during the lifetime of your application a business layer that shields the DAO as well as simple domain objects can be a usefull approach.

    In other contexts ofcourse having Cake.store may make
    complete sense. It is not an option I personally would take
    but it may make sense.
  17. I desagree. The term "business object" is missused. Being a business object does not prevent it from being other things; in this case, an object that is stored somewhere. There's a semantic inherent to that fact. If you find it confusing, you don't like, you wish someone would PLEASE take care of it for you, well... that's something else. But there's absolutely nothing wrong with an object "knowing" how to store itself.

    I think the intent is "domain object" rather than "business object", the difference being that the object describes the problem domain. Take the "real world" example of replacing a paper process where a user fills out a form and puts in a storage cabinet with an application that contains a form that stores its data in a database. The "Form" object shouldn't know how to store itself because the "FilingCabinet" object (database) is the one being changed by the action of "filing a form". What if I want to store that "Form" in a "FilingCabinet" and store copy in my "DeskDrawer". Do I create two store() methods in "Form" or do I create a store() method in "FilingCabinet" and "DeskDrawer"? My point is "Form" needs to know what data to hold and any other actions that may change its state such as crumple() not store(). "FilingCabinet" needs to know how to store "Form"s so that we can find them later.
  18. Following your line of thought, neither FilingCabinet nor DeskDrawer should know how to store a Form; at the most, they know how to "hold" it. But, again, this is modelling issue, not a replicating-real-life one. If you modeled exactly after real life, you should gice User a store(Form) method:
       public void store(Form f, Holder h) throws StorageException
       {
           h.open(this); // exception if locked or user has no access
           h.hold(f); // exception if no room
           h.close(); // exception is whatever
       }
    I don't totally hate this, but of course this (as someone said) a matter of requirements ; sometimes, even one of designer's taste. To me, this would make EVERY "business" operation a responsability of the real world entity operating the system: the user. How long do you think this class would be? And who would store instances of User?
    Funny thing. I've discovered I'm wrong. In EJB the responsability of storing an Entity relies on its Home. You guys are right.
  19. Following your line of thought, neither FilingCabinet nor DeskDrawer should know how to store a Form; at the most, they know how to "hold" it. But, again, this is modelling issue, not a replicating-real-life one. If you modeled exactly after real life, you should gice User a store(Form)

    What is the reason for storing a Form in a FilingCabinet? So you can easily look it up again (and so you don't lose that information). Storing the Form in a FilingCabinet doesn't change what the Form is or does, it is a mechanism to help a User find them easier. As an architect I can't imagine all the ways and places one might store a Form, but when I'm designing my FilingCabinet I know what I want to store it in and how I want to find a Form in it. This is why the behavior belongs in the FilingCabinet rather than the Form itself. In regards to the User having a store() method I think of it this way. As a User, I am filling out a Form, picking it up and placing it in a FilingCabinet. How is the User's state changing in anyway based on this action (except maybe energyLevel decreases by 5, but we don't model all real world aspects in a design only what's pertinent to the business model)? The Form is changing based on the User filling it out, so you attach the fillIn() behavior to the Form. The FilingCabinet is changing based on storing the Form, so you attach the store() behavior to the FilingCabinet. That's how I see that problem. The behavior more belongs to the object that is being changed.
  20. "True OO" != "Real World objects"[ Go to top ]

    Nonsense. I've disagree with this completely. I thought true OO should reflect reality - you know, model your objects on real-world objects.

    The "real world" is a good starting point for classes during Analysis, but during Design, you should modify your classes according to design principles, like the Single Responsability Principle (SRP), the Open-Closed Principle, etc. "Real-world" objects usually don't follow the SRP.

    This page http://www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfObjectOrientedDesign has a nice overview of OO Design.
  21. "True OO" != "Real World objects"[ Go to top ]

    The "real world" is a good starting point for classes during Analysis, but...

    I thank the Lord someone knows what a model is. Thanks for the blow of fresh air, Daniel!
  22. Single Responsibility Principle[ Go to top ]

    How can a Problem Domain class have only a single responsibility if, as well as it's business logic, it also has to know how to persist itself? Or indeed that it is to be persisted? Or even presented?

    Should an Employee class, for instance, know that it has to be persisted and presented as well as containing business methods that calculate retirement plans?
  23. Spring 2.0 vs. the Anemic Domain Model[ Go to top ]

    Nonsense. I've disagree with this completely.

    I completly agree with you, in my opinion that can be named as a DAO antipattern.

    Psique
  24. Streamlined Object Modeling[ Go to top ]

    Cool, actually this article presents a implementation solution for a problem I identified just couple of months ago.

    I will not argue if it´s wrong or right but I can tell you this design fits nicely in my POJOS (c´mom, Javabeans aren´t really POJOS) which follow the modeling and design conventions presented by the book Streamlined Object Modeling.

    Some interesting excerpts relating to this thread:

    Principle 24 - "Do it myself"
    Objects that are acted upon by others in the real world do the work tehmselves in the object world

    Principle 25 - "Do it with data"
    Objects encapsulate data representing an entity together with the services that act on it

    So ya, I do agree with the author. The major problemn i see with OO principles is not related to read and digest it ( thanks for that link, Uncle Bob) but to _apply_ it into a real world software development project. In my little experience with it, SOM can really helps to evict the analysis paralisis while improving a lot my domain models.

    Another side benefit, with some creativity and coding effort, SOM entities can fit nicely into the Active Record persistence pattern Rails implements in Ruby. In part because usualy your domain model (even the bakery) will have much more classes.

    Beside it, the book also finally help me to understand things like object inheritance and bidirecional associations importance in domain models.
  25. Objects don't need to reflect reality.[ Go to top ]

    I think your view is a common misconception. The goal and purpose of an object is to increase the cohesion of common data and behavior and reduce the coupling between disparate parts of your code. The purpose of objects is not to emulate the real world. It's simply a design and coding tool. When you call an object a Cake, it serves no direct purpose to your design make it a strict analogue of an actual cake. You simply call it a "Cake" because it's a *metaphor* for a cake. By changing it's name to a thingamabob is it no longer the same class? Of course it is. It still has the same data and behavior, you just changed its name. If it makes sense in your design (e.g. for encapsulation and abstraction purposes) to have your cake do stuff a normal cake in the real world can't do, such as bake itself, then why prevent that behavior from being definied for the class? To say no cake in the real world can bake itself puts an unnecessary and artifical contrstraint on your design.

    In addition, most objects don't have real analogues in the real world. (e.g. hashtable, strings, streams) Yet, we have no problem defining and using such classes.

    I think if you let go of this artificial rule, you'll see more opportunities to increase cohesion and decrease coupling in your design - the main goal you should be striving for.
  26. Objects don't need to reflect reality.[ Go to top ]

    I think your view is a common misconception.

    Apparently it is common - most people on this page have the same conception.

    By changing it's name to a thingamabob is it no longer the same class?

    No, it’s not the same class. It’s now a thingamabob and developers will be confused as to why it is called thingamabob. The developers will now spend their valuable time unnecessarily discussing what the thingamabob is and what it does. The reason we call it a Cake is to foster communication amongst the development team, including the business analysts and users.

    Like it or not, we are in the communication business. The Physics and Calculus that many of us studied in school don’t come into play when we are developing business applications.

    To say no cake in the real world can bake itself puts an unnecessary and artificial constraint on your design.

    It’s not a constraint at all. It’s an opportunity to model our code on real-world objects. Everyone on the team understands these real-world objects. We will develop a better product which will be much easier to maintain, ESPECIALLY for new developers who are introduced to the team in the future.

    In addition, most objects don't have real analogues in the real world. (e.g. hashtable, strings, streams) Yet, we have no problem defining and using such classes.

    This is an irrelevant statement. The discussion is about domain objects – classes that define the business we are modeling
  27. Your code is not a cake[ Go to top ]

    Race,

    I think you're missing my point. Your code is not a cake. You can't serve it at birthday parties and get fat from it. It doesn't and shouldn't be confined by the rules of a real cake. Cake is a metaphor for a real cake. It's code that you happen to call cake because it's the best name for it, but it's not a cake. If your code says Cake.bake() or Cake.save(), it will not make developers heads spin and say, "Wha wha wha! A cake baking itself. Now I've seen everything!" Maybe this way of thinking is too much for some people to handle, but I think most people realize that it's just code: "I want to save my cake code. Cake.save(). Okay maybe I didn't expect that, but it's not confusing. I just saved my cake data. I get it."

    Paul
  28. Your code is not a cake[ Go to top ]

    ...it will not make developers heads spin and say, "Wha wha wha! A cake baking itself. Now I've seen everything!"

    LOL!!! Now that's funny!

    I see your point but we'll have to agree to disagree on this one.
  29. ...If a Domain object is to know about Persistence, then why should the Domain object not understand Presentation as well?

    I fully agree: Baker, Oven, and Cake are different subjects, Baker know which button to press on Oven...

    However, each theory has it's own area to be applied for, and each one has limitations...

    Should the Cake know about Taste, Smell, and Color? About Presentation?

    Good pattern: Domain Object has methods getDateDisplay, setDateDisplay, which convert from Date to String, from String to Date, - piece of Presentation.

    Another sample: SQL is also the Presentation Layer.
  30. I am with you on this one. I think your analigy of using a cake, overen and baker is excellent! What happened to layering of software?
    Also, domain objects should not know they need to be persisted. They should have no refence, even in the form of a interface persistance in anyway.
  31. missed the point[ Go to top ]

    I don't think the cake analogy is sound. For one, as someone else pointed out, it's not a cake until you cook it. More specifically, a cake doesn't do anything, things are done to it. So in this case, ADM works. But let's use a better analogy to illustrate when ADM is bad: a car. For simplicity, let's say a car has two actions: drive(), turnOnHeadlights(). Let's say you have a service object, travelService (for traveling with the car) you want to implement these actions with: travelService.drive(Car car) and travelService.turnOnHeadlights(Car car). So far so good. But then let's say you have another service object, parkService (for parking the car in the garage). You would also need to implement the same actions; they may be private and only used by other methods in the service, but they would still need to be implemented. So you'd have duplicated code. Of course, you could call the travelService methods from the parkService object, and have all the methods that operate on Car live in the travelService (which you'd probably rename to carService) which would be a better solution. But then nearly everywhere you had a Car instance, you'd need a travelService instance to manipulate it. Separating the logic and data is against OO so why not just put the action methods into the Car object. As far as the Car object populating itselt from a dao, the benefit I see with that is if you have an object with a lot of relationships, you can use lazy loading to load only the relationships needed when they are needed instead of loading an enormous object each time. I wrote this post because most of the posts I saw were pro ADM. But I want to point out that ADM is only an anti-pattern when it's used at the wrong time.
  32. Re: missed the point[ Go to top ]

    In essence, the point of a Rich Data Model isn't that the models themselves decide what they are going to do (in reference to the poster who gave the example of obj.copyAndTweak()). Instead, the objects declare what they can do (through public methods), and the objects themselves handle the implementation of those actions.
  33. Mercy! I'm sick of Spring on this site.
  34. Spring 2.0 vs. the Anemic Domain Model[ Go to top ]

    Mercy! I'm sick of Spring on this site.

    Yes, but if we didn't talk about Spring or Rails, then what would we talk about? ;-)
  35. Spring 2.0 vs. the Anemic Domain Model[ Go to top ]

    Mercy! I'm sick of Spring on this site.
    Yes, but if we didn't talk about Spring or Rails, then what would we talk about? ;-)

    We could fall back to .Net and C# and Mono. Been a while.
  36. The more service-oriented stuff I build, the more I become confident that there is nothing inheritently wrong with this "anti-pattern".

    The trademark of a good service is its ability to be used in a ways service architect did not or could not imagine. Something I build today, may be exposed to VB clients tomorrow (or AJAX, or fat Swing clients, or..). It is much easier to think of a service as a combination of dumb, er, "anemic" objects (no behaviour, just data and inheritance) and service interfaces.
  37. And if you have no logic in your domain objects, it's not always because you have an anemic domain model but your project is just another CRUD application without any business logic. Maybe you didn't need a domain model afterall. Transaction script pattern from Martin Fowler book would have been enough but a domain objet might still be a better idea if you want to keep the application for a long time and makes it scalabe.

    However, I will wait and see where they are going with that approach because Spring folks usually know where they are going. Maybe I didn't get everything...
  38. Still Anemic![ Go to top ]

    Just because a persistence layer has been added to the domain model, it does not mean it is not still anemic. An anemic model, from my point of view, is once where business concepts are missing, and we just have objects stating their attributes. With this type of design once programs in a procedural style, and not sending messages to objects to perform some relevant task.

    To add persistence once can create a generic persistence layer and give an object or a set of objects the responsibility to define the persistence, or if the persistence is related to business concepts then then can be modeled as a Service that can perform the business task and can perform the persistence.

    Obviously this all depends on the problem space and size/complexity of the problem but persistence should not be delegated to the actual domain object (even if it uses a DAO) but rather to a correctly modeled impl.

    Spring is pretty good when used for its core strengths but using it everywhere with loads of aspects may just make your app more complex.
  39. It's sad that the new approach require additional compiling step, which I want to avoid. And another problem is that how do you test below codes without Spring ?

    public class CustomerServiceImpl implements CustomerService {
       public void createNewCustomer(String name) {
           //delegate to dao.save(this) inside Customer:
           new Customer(name).save();
       }
    }
    (1) How to inject realDAO without Spring ?
    (2) How to inject mockDAO in UnitTest ?

    Personally I prefer to write a small static 'hook' if I want to do DI in Domain Object. (I call it Cheap Factory anyway...)
  40. No Additional Compilation Step Necessary[ Go to top ]

    It's sad that the new approach require additional compiling step, which I want to avoid.

    No additional compilation step is required - you can use the Load-Time Weaving (LTW) capabilities of AspectJ to weave in the configuration aspect during application startup.

    Rob
    ---------------------------
    Interface21 - Spring from the Source
    http://www.springframework.com
  41. No Additional Compilation Step Necessary[ Go to top ]

    No additional compilation step is required - you can use the Load-Time Weaving (LTW) capabilities of AspectJ to weave in the configuration aspect during application startup.

    Thanks Rob. I was led to believe that there was a way to do this, but my limited knowledge of AspectJ didn't help to figure it out. I figured that if it were possible that someone would tell me about it after the entry was posted.
  42. It's about the dependencies[ Go to top ]

    The hallmarks of flexible, testable, and maintainable systems are that the individual components have as few dependencies as necessary.

    Why? Because the more dependencies a component has, the more difficult it is to understand the component, the more tests that need to be written to achieve full coverage, and the more likely that small changes will have cascading unintended side effects.

    "Anemic domain models" in the context of service oriented designs usually, though not necessarily, do a better job of minimizing the number of overall system dependencies as compared to "obese domain models".

    I have tremendous respect for the Spring folks, and will wait to see how this fully fleshes out, but my initial reaction to this example of the use of this new feature is one of concerned skepticism.
  43. It's about the dependencies[ Go to top ]

    ...my initial reaction to this example of the use of this new feature is one of concerned skepticism.

    I couldn't agree moore. The addition of AspectJ to the mix seems to hurt Spring's independence. Hopefully the other parts of the Spring 2.0 API won't depend explicitly on this.

    If Spring becomes aspectJ then Spring will go the way of AspectJ.
  44. No additional compilation step is required - you can use the Load-Time Weaving (LTW) capabilities of AspectJ to weave in the configuration aspect during application startup

    This is very good, because I think it would be too invasive to force for an additional compilation step, where can I find some info about how to do this in Spring 2.0?

    Moreover, another thing I'd avoid is the insertion of Spring metadata into my POJO: is there a way to configure this sort of injection via XML configuration?

    Regards,

    Sergio B.
  45. We're working on other approaches to make the configuration simpler and more decoupled.

    Rob
    ------------------------------
    Interface21 - Spring from the Source
    http://www.springframework.org
  46. Over the past 20 years I have actually moved away from the view represented by the idea of telling domain objects to persist themselves. Fowler may say my domain objects are anemic, but they are easy to maintain and keep in synch with various forms of persistence such as databases (relational, object, etc.) and messages. I have found that letting to service or business object act as a controller between the domain object and the interface (or view) object, the DAO, is the best way to go.

    MVC really represents a meta pattern of object specialization where all objects are either controllers, interfaces or domain objects but never a combination. Mediators, adaptors, connectors, MVC itself and other design patterns all work in this way. I've found that it makes the objects simpler, easier to maintain and more reusable.

    What is being suggested here is similar to injecting Strings with formatting objects and then telling them to go format themselves. It sounds nice, except it gunks up String. Why should the author of String have to plan for formatting or any other arbitrary operation that someone may have in mind for Strings? Why should domain object authors concern themselves with a specific DAO interface? There is no DAO interface standard. People can define their own. Do I clutter my domain object with code for each possibility? Domain objects, if done correctly can be used across applications across the enterprise.

    Objects should know all about themselves and as little else as they can get away with.
  47. Over the past 20 years I have actually moved away from the view represented by the idea of telling domain objects to persist themselves. Fowler may say my domain objects are anemic, but they are easy to maintain and keep in synch with various forms of persistence such as databases (relational, object, etc.) and messages. I have found that letting to service or business object act as a controller between the domain object and the interface (or view) object, the DAO, is the best way to go. MVC really represents a meta pattern of object specialization where all objects are either controllers, interfaces or domain objects but never a combination. Mediators, adaptors, connectors, MVC itself and other design patterns all work in this way. I've found that it makes the objects simpler, easier to maintain and more reusable. What is being suggested here is similar to injecting Strings with formatting objects and then telling them to go format themselves. It sounds nice, except it gunks up String. Why should the author of String have to plan for formatting or any other arbitrary operation that someone may have in mind for Strings? Why should domain object authors concern themselves with a specific DAO interface? There is no DAO interface standard. People can define their own. Do I clutter my domain object with code for each possibility? Domain objects, if done correctly can be used across applications across the enterprise. Objects should know all about themselves and as little else as they can get away with.

    +1
  48. Over the past 20 years I have actually moved away from the view represented by the idea of telling domain objects to persist themselves. Fowler may say my domain objects are anemic, but they are easy to maintain and keep in synch with various forms of persistence such as databases (relational, object, etc.) and messages. I have found that letting to service or business object act as a controller between the domain object and the interface (or view) object, the DAO, is the best way to go. MVC really represents a meta pattern of object specialization where all objects are either controllers, interfaces or domain objects but never a combination. Mediators, adaptors, connectors, MVC itself and other design patterns all work in this way. I've found that it makes the objects simpler, easier to maintain and more reusable. What is being suggested here is similar to injecting Strings with formatting objects and then telling them to go format themselves. It sounds nice, except it gunks up String. Why should the author of String have to plan for formatting or any other arbitrary operation that someone may have in mind for Strings? Why should domain object authors concern themselves with a specific DAO interface? There is no DAO interface standard. People can define their own. Do I clutter my domain object with code for each possibility? Domain objects, if done correctly can be used across applications across the enterprise. Objects should know all about themselves and as little else as they can get away with.
    +1
    +1
  49. Over the past 20 years I have actually moved away from the view represented by the idea of telling domain objects to persist themselves. Fowler may say my domain objects are anemic, but they are easy to maintain and keep in synch with various forms of persistence such as databases (relational, object, etc.) and messages. I have found that letting to service or business object act as a controller between the domain object and the interface (or view) object, the DAO, is the best way to go.

    Here when we say "a domain object knows how to persist itself", what we are really saying is "a domain object knows who to delegate to to persist itself". In other words, what Spring 2.0 proposes is injecting domain objects with a persistent layer. It by no means implies to "gunk up the object" with actual JDBC or Hibernate calls.

    There is nothing wrong with using a service object as a controller or mediator over domain objects, but it should control "service" not "persistence". The problem with an anemic domain model is that people tend to end up with relying on the service object to manage the persistence relationships between domain objects. E.g., it's obviously more OO and more natural to call UserGroup.getMembers() to get all the User objects that are members of the group, rather than calling something like UserService.getGroupMembers(UserGroup group).
    MVC really represents a meta pattern of object specialization where all objects are either controllers, interfaces or domain objects but never a combination. Mediators, adaptors, connectors, MVC itself and other design patterns all work in this way. I've found that it makes the objects simpler, easier to maintain and more reusable.

    Yeah, it's easier to maintain and more reusable all right - but that's because there is almost nothing left to maintain, and what's there to reuse anyway? I mean, all you have left in those objects are pass-through getters and setters. :-)
  50. Avoiding client-demarcated transactions[ Go to top ]

    I disagree with injecting a data object with a persistence mechanism. There is a very good pattern that avoids a client-demarcated transaction. This pattern allows a collection of data objects to be saved with one method call to a service. No transaction is required on the client, since the the action is atomic from the client perspective. This pattern cannot be implemented with self-persisting data objects, which must be saved one-by-one by the client.
  51. The fact that an object has a "store" method does not imply that it will be immediatly result in an INSERT or UPDATE. That's a bit narrow-minded of you. How many "connection.commit()" are performed in a given transaction, do you think? Answer: many. How many are actualy executed? Answer: one at the most, when the transaction is over.
    How do we do this? Wrapping the real connection within another "transaction aware" (or whatever you wanna call it) connection.
  52. The fact that an object has a "store" method does not imply that it will be immediatly result in an INSERT or UPDATE. That's a bit narrow-minded of you. How many "connection.commit()" are performed in a given transaction, do you think? Answer: many. How many are actualy executed? Answer: one at the most, when the transaction is over.How do we do this? Wrapping the real connection within another "transaction aware" (or whatever you wanna call it) connection.

    I am sorry. I meant that to save a set of persistence-enabled data objects by a client application would usually require a transaction begin, then a save call to *each* one of the data objects, and finally a transaction commit. A simpler pattern is pass the entire set of objects to one call to a service. The service will start a transaction automatically and save the entire set of objects. Thus, on the client side there is no begin or commit required, only the call to Service.save(Collection dataObjects).
  53. The domain object should not have to know about DAOs. The DAO may need to know something about domain objects - how to ask them to serialize their data for persistence, but since its the DAOs, message writers, etc. that know what they want to do with the data, they should be responsible for knowing about the process, not the domain object.

    I did not say that a service object, whatever that is in your mind, must be the controller from the persistance actvitiy. My service objects sequence and choreograph the work of business objects. My business objects do the work and exchange objects with their subordinates, their callers and with aggregators - or whatever you want to call objects that build objects from data sources. The aggregators in turn get their data from DAOs. If I'm not layering on some mess of a legacy database(s), I can often forego the aggregators.

    On the second point, there is nothing wrong with an object that knows only a few things. Why do you feel compelled to add stuff to an object? Are you worried that you are wasting something? Sometimes the environment and performance requirements force you to reduce the object count and revert to procedural programming inside large grained objects - that is how component-based architectures came into being. Since I assume we a talking about Java, my guess is that is no longer your concern. I keep my object counts low by limiting scope and references and using lazy instantiation.

    Some domain objects have a bit to do especially when their domains do not correspond to the language's data types full range of possible values, which is usually the case. An address, or even a street is not a String. If you want to enforce standardized addressed you would add logic and constraints to insure that the data was a reasonable street name or a complete address. Domain enforcement is a job of domain objects.

    As to getters and setters, if you are auto-generating them or assuming you should have one for every field in the domain object, then you are in error. Getters and setters of fields break encapsulation. Make sure you implement them only when a requirement has been identified and make them accessible only to those with the requirement.
  54. As to getters and setters, if you are auto-generating them or assuming you should have one for every field in the domain object, then you are in error. Getters and setters of fields break encapsulation. Make sure you implement them only when a requirement has been identified and make them accessible only to those with the requirement.

    Exactly. I totally agree with you, and actually feel a bit ironic that you, with your stance in this debate, should bring this up. :-) Let me ask you this: in reality (read: any J2EE application), have you ever seen any domain object that's not wide open with pass-through getters and setters? Why not? Exactly because there is no way to inject things like persistence layer or other facilities into them, so they are not capable of implementing any non-trivial domain logic, other than probably throwing an IllegalArgumentException when setName() is called with a null pointer. Any logic more complex than that tends to, or has to, be extracted and put into a "service". In other words, the domain objects are simply being used as dumb data holders.

    Look, as far as I can see, nobody here is saying that an "anemic domain model", despite the negative meaning of the word, is inherently bad. There may be cases in which domain objects are just not supposed to have logic (as somebody else pointed out in another reply to my post). Or you may be an architect who is sufficiently self-displined to sidestep all the pitfalls. The point here is, an anemic domain model has more tendency to lead to a bad architecture and ultimately bad quality. The problem here is not about the domain model itself, but the same old one that plagued the whole procedural programming paradigm: it relieves people from having to pay attention to how to organize the logic. Since all the domain objects are wide open, and everything is done in the "services" which are stateless, and throwing on the top all the deadline pressure, guess what? developers no longer stop for a moment and try to pick out the right class for that new piece of logic they are implementing. They are not even going to spend time looking through existing services and make sure it hasn't been implemented, because it could be any of the "services", "helpers", or whatever other names - instead, they simply write it up and stick it into one of the stateless session beans, because "it doesn't matter, I can work on any domain object from anywhere."
  55. As to getters and setters, if you are auto-generating them or assuming you should have one for every field in the domain object, then you are in error. Getters and setters of fields break encapsulation. Make sure you implement them only when a requirement has been identified and make them accessible only to those with the requirement.
    Exactly. I totally agree with you, and actually feel a bit ironic that you, with your stance in this debate, should bring this up. :-) Let me ask you this: in reality (read: any J2EE application), have you ever seen any domain object that's not wide open with pass-through getters and setters? Why not? Exactly because there is no way to inject things like persistence layer or other facilities into them, so they are not capable of implementing any non-trivial domain logic, other than probably throwing an IllegalArgumentException when setName() is called with a null pointer. Any logic more complex than that tends to, or has to, be extracted and put into a "service". In other words, the domain objects are simply being used as dumb data holders.

    I don't agree with this statement (but I agree with rest of your reply). Sure some people tend to place everything in services but they are missing the point. The last application I have built was a authentification module able to work with any type of persistent store. To authenticate a user, I had to check a number of security constraints (login disabled, password expiration date, login expiration date, ...) independently of the persistent store used. So I implemented the stack of constraints as a Command pattern and the user had a public method available to check if a user respected all the constraints. It's all depends of your business logic. Like I wrote earlier, a lot of times you are just programming a simple CRUD application where the complexity of a domain model doesn't serve any purpose. Instead for example, you could use the Transaction Script pattern (from Fowler book). But if you think your application is going to live for a long time and therefore have to be scalabe then the domain model is still the way to go. Will the domain objets be just dumb data holders in this case. Yes for the moment but it comes from the fact that there is no inherent business logic in this application. Anemic domain model refers to people putting every bit of logic in the service layer (I have seen that lot of times) even when the logic is intrisic to a component.
  56. Here when we say "a domain object knows how to persist itself", what we are really saying is "a domain object knows who to delegate to to persist itself". In other words, what Spring 2.0 proposes is injecting domain objects with a persistent layer. It by no means implies to "gunk up the object" with actual JDBC or Hibernate calls.There is nothing wrong with using a service object as a controller or mediator over domain objects, but it should control "service" not "persistence". The problem with an anemic domain model is that people tend to end up with relying on the service object to manage the persistence relationships between domain objects. E.g., it's obviously more OO and more natural to call UserGroup.getMembers() to get all the User objects that are members of the group, rather than calling something like UserService.getGroupMembers(UserGroup group).

    Exactly what I meant (but failed to convey). Sure, you *could* muck up the domain object with persistence code (which, as Bill Burke pointed out, would be very BMP-ish and would suck)--But I don't recommend it. I'm not saying that the DAO goes away...I'm just saying that it could move a bit closer to the service layer. Done that way, the service layer could deal directly with domain objects instead of dealing with them via a DAO.

    But as Rob Harrop pointed out, the central point of the blog entry was that I was showing how domain-object injection can be done in Spring 2.0. Certainly, it can be debated whether my example was a valid use of this technique (perhaps my sleep-deprived brain led me to a poor example). But regardless of the appropriateness of the example, it still demonstrates the mechanics of domain-object injection. I leave it up to the greater Spring community (which includes all of us) to muddle through this and figure out the appropriate best practices for injecting domain objects.

    And that's one of the reasons why I write this stuff on my blog: To stir up conversation on what the good and bad uses of a particular technique are...or if the technique itself is even valid. Since this is something new in Spring, no best practices have developed around it. The blog entry and the resulting threads on the blog and at TSS are the first steps toward developing those best practices. Thanks for participating.
  57. I'm not saying that the DAO goes away...I'm just saying that it could move a bit closer to the service layer.

    I meant to say "I'm not saying that the DAO goes away...I'm just saying that the domain objects move a bit closer to the service layer."
  58. Reuse of "anemic" domain objects[ Go to top ]

    I have to question the term "anemic domain model". Besides the excellent points that William Childers made above regarding the simplicity of so-called "anemic" domain objects, I think the value of the definition of such objects is being understated.

    I've worked on a project involving scientific concepts the past few years, and it's not rare that we have domain objects with 50 to 100 properties. In one case, a collection of XYZ objects are generated through a complex procedure that involves invoking methods on several objects that are not related to one another. In such a case, a service object - XyzManager - makes perfect sense and makes things much simpler to manage, especially as new requirements are derived for the procedure that we use to generate XYZ objects.

    The XYZ object, even though it is just a set of properties, is still extremely valuable because it defines those properties. I can think of other applications that would need XYZ as a domain object but wouldn't need any of the business logic found in XyzManager. I'd be very relieved to know that the 100+ properties of an XYZ object have already been correctly defined (it was hard work getting all of them nailed down). And so I wouldn't call such a domain object "anemic" whatsoever.

    There's no doubt that Fowler has good points to make, but everyone should still think for themselves. Don't think your system sucks just because you have a so-called "anemic domain model". There are trade-offs to every decision, and if you feel like such a domain model lends to a simpler, more maintainable system that is easy for other people to understand, then go with it.

    Rob
  59. I've worked on a project involving scientific concepts the past few years, and it's not rare that we have domain objects with 50 to 100 properties. In one case, a collection of XYZ objects are generated through a complex procedure that involves invoking methods on several objects that are not related to one another.

    This sounds like the design of this system went fundamentally wrong.
    Before you implement artificial XyzManagers, I would stronly consider refactoring the mess.
  60. E.g., it's obviously more OO and more natural to call UserGroup.getMembers() to get all the User objects that are members of the group, rather than calling something like UserService.getGroupMembers(UserGroup group).

    It's more OO for sure. And slower as well, because this means that you have performed a query to get up the UserGroup, and another to get the members.
    This can become embarrassing if the dbms sits on another PC, because you have to pay the network latency twice (or more, if you're looping over a set of UserGroup)

    I usually have methods like getUserGroup(boolean fullyLoad) which loads the UserGroup partially or totally, and then then UserGroup does not have to deal with the persistence layer anymore... performance matters...
  61. It's more OO for sure. And slower as well, because this means that you have performed a query to get up the UserGroup, and another to get the members.This can become embarrassing if the dbms sits on another PC, because you have to pay the network latency twice (or more, if you're looping over a set of UserGroup)

    Not necessarily slower. Whatever data caching strategy employed by the underlying persistence layer can be used all the same, no matter you call the persistence layer from the service or the domain object.
    I usually have methods like getUserGroup(boolean fullyLoad) which loads the UserGroup partially or totally, and then then UserGroup does not have to deal with the persistence layer anymore... performance matters...

    Now _that_ I am sure would be frowned upon by a lot of people, including myself. :-) fullyLoad is purely a persistence control flag that should probably not appear on your domain or business service interface. A call like this would force the caller to be aware of certain state of the persistnce layer.
  62. It's more OO for sure. And slower as well, because this means that you have performed a query to get up the UserGroup, and another to get the members.This can become embarrassing if the dbms sits on another PC, because you have to pay the network latency twice (or more, if you're looping over a set of UserGroup)
    Not necessarily slower. Whatever data caching strategy employed by the underlying persistence layer can be used all the same, no matter you call the persistence layer from the service or the domain object.

    With Hibernate in the backend and a business object that must reach a remote reach client it's either that or a LazyInitializationException.
    I usually have methods like getUserGroup(boolean fullyLoad) which loads the UserGroup partially or totally, and then then UserGroup does not have to deal with the persistence layer anymore... performance matters...
    Now _that_ I am sure would be frowned upon by a lot of people, including myself. :-) fullyLoad is purely a persistence control flag that should probably not appear on your domain or business service interface. A call like this would force the caller to be aware of certain state of the persistnce layer.
    It must appear in the business service interface because the client has to specify how much data it needs to work.
    But even in a web app, if you're not the only one that writes on the DBMS caching is of no use, so to get decent performance you have to minimize the round trips to the DBMS...
  63. Persistence proxy[ Go to top ]

    With Hibernate in the backend and a business object that must reach a remote reach client it's either that or a LazyInitializationException.
    Yes, but when you use lazy resolution, Hibernate creates a proxy subclass which has persistence functionality - in effect, it does add persistence to the domain object.

    Whether that "persistence proxy" is generated by Hibernate or in the author's case by AspectJ isn't that important: In both cases, the developer doesn't write it and their domain object remains "pure".
  64. Persistence proxy[ Go to top ]

    Yes, but when you use lazy resolution, Hibernate creates a proxy subclass which has persistence functionality - in effect, it does add persistence to the domain object.

    Which works as long as you don't leave the Hibernate session.
    Once you're out of it, if you try to access that property you get a lazy initialization exception. So, you have to decide what fields you need before leaving the server (I was speacking about a remote rich client).

    Even if you don't leave the server, accessing the proxy will issue another query if you cannot afford to cache beans for some reason, so the number of round trips to the server can become an issue as well (don't tell me you've never seen apps written with Hibernate that perform a ton of queries when a single one could be used, just because the programmer forgot or simply cannot enable the second level cache)
  65. Looking at this the wrong way[ Go to top ]

    From my point of view, this code demo is being looked at in the wrong light. Craig isn't trying to lay out a set of best practices, he is simply doing a good job of demoing a new feature in Spring in an easy to understand fashion.

    As Rod mentioned when we announced this feature, there is still some work to be done in defining the appropriate scenarios for this as opposed to standard service objects.

    Be assured that we are putting a *lot* of effort into this and we will be laying out a complete set of guidelines as to how we see this working. During this process we will obviously work closely with other people in this space and also with the community as a whole.

    Regards,

    Rob
    --------------------
    Interface21 - Spring from the Source
    http://www.springframework.org
  66. Looking at this the wrong way[ Go to top ]

    From my point of view, this code demo is being looked at in the wrong light. Craig isn't trying to lay out a set of best practices, he is simply doing a good job of demoing a new feature in Spring in an easy to understand fashion.As Rod mentioned when we announced this feature, there is still some work to be done in defining the appropriate scenarios for this as opposed to standard service objects.Be assured that we are putting a *lot* of effort into this and we will be laying out a complete set of guidelines as to how we see this working. During this process we will obviously work closely with other people in this space and also with the community as a whole.Regards,Rob--------------------Interface21 - Spring from the Sourcehttp://www.springframework.org

    It now makes sense and by look of things community feedback would be very vital.
  67. Looking at this the wrong way[ Go to top ]

    ... Craig isn't trying to lay out a set of best practices, he is simply doing a good job of demoing a new feature in Spring in an easy to understand fashion.

    Yeah, but the title was about Anemic Domain Models. It seems that we are migrating back to tightly coupled and brittle systems, AOP or not.

    If you look at the example, his Customer could still be considered "anemic". Why not have the Customer load() itself. Hell, why not have it copyAndTweak() itself. Where does it end? Should customer's authenticate() themselves and so on and so on. When does an object stop being anemic?

    Plus, wasn't this one of the reasons to use Spring in the first place vis a vis EJB's was the whole "lightweight" mantra. Just because the interfaces are implicit(setDAO(), etc.) and the Spring container magically injects references, doesn't mean that the object is any lighter than implementing an EJB interface. At least in this example of persistence.

    The problem with "Anemic Domain Models" as I see it is that there is no distinction of extrinsic vs. instrinsic state of an object and the definition of responsibility for each. This is a sticky problem and has been around since day one in the OOD space. (FWIW Eric Evans book is great on Domain Driven Development)

    As far as antipatterns, anything Martin Fowler says is starting to become an antipattern for me.
  68. Looking at this the wrong way[ Go to top ]

    ...As far as antipatterns, anything Martin Fowler says is starting to become an antipattern for me.

    Frank! Be careful what you say. You could be banished from here.
  69. Looking at this the wrong way[ Go to top ]

    I concur with Rob. This is not about where to put persistence, but an example of melding aspectJ with Spring. I'm just glad its not foos and bars.

    OTOH, after listening to Rod, I'll be surprised if the @SpringConfigured tag stays as it doesn't relate to the domain, and couples all the objects to Spring. As the team said at the show, there's still a lot of work to be done in this space before 2.0 final.
  70. Looking at this the wrong way[ Go to top ]

    OTOH, after listening to Rod, I'll be surprised if the @SpringConfigured tag stays as it doesn't relate to the domain, and couples all the objects to Spring. As the team said at the show, there's still a lot of work to be done in this space before 2.0 final.

    Of course, that's something I probably should have pointed out. Rod mentioned that they greatly dislike the name of the annotation and are looking for recommendations for a new name. And since I was working from a pre-2.0M1 build (which is still several months away from a 2.0 final build), anything I said in the blog entry are subject to change.
  71. re: Looking at this the wrong way[ Go to top ]

    Of course, that's something I probably should have pointed out. Rod mentioned that they greatly dislike the name of the annotation and are looking for recommendations for a new name.

    I think it is not a matter of name, but rather a matter of "dirtying" and coupling the domain object with something (an annotation) specific to Spring, whatever its name is.
  72. Looking at this the wrong way[ Go to top ]

    Randy
    OTOH, after listening to Rod, I'll be surprised if the @SpringConfigured tag stays as it doesn't relate to the domain, and couples all the objects to Spring. As the team said at the show, there's still a lot of work to be done in this space before 2.0 final.
    SpringConfigured will be renamed Configurable, and the annotation will be just one choice for identifying where the injection should apply. The other choice will be to write an AspectJ pointcut expression. There may be a way we can bootstrap configuration in XML--for example, parsing an EJB 3.0 Java Persistence API persistence.xml file--but efficient annotation matching usually requires compile-time information. JPA pretty much requires the creation of a child class loader to allow the persistence implementation to do its own weaving, so this will also be an opportunity for load-time weaving, meaning that using the ajc compiler may not be required. Stay tuned.

    Of course, this also has the advantage that you can use this mechanism in Java 1.3 and above, with AspectJ pointcut expressions.
  73. Now correct me if i'm wrong. If you didn't want to have an anemic domain model following the example used in the blog you would move the method dealing with creating a duplicate customer into the Customer class.

    e.g.

    class Customer{
     private Long id;
     private String name;
     
     public Customer createNewCustomerFromCopy(
         Map<propertyToOveride,value> propertiesToOveride){
       // create new instance and override properties
     }
    }

    and the Service class would be something like

    class CustomerServiceImpl implements CustomerService {
      public CustomerServiceImpl() {}
      
      public void copyAndTweakCustomer(Integer id) {
        Customer original = dao.load(id);
        Customer duplicate = original.createNewCustomerFromCopy(
         /*Map with name property*/)
        );
        dao.save(duplicate);
      }
    }

    And if you did go with the save method in the domain object why would it be any different a ActiveRecord?
  74. If it is wrong for an object to know how to persist itself, then is it not also wrong for an object to be able to serialize itself, as is the case with java.io.Externalizable? With systems like XL2, serialization *is* the persistence mechanism, so Externalizable objects are self-persistable.
  75. If it is wrong for an object to know how to persist itself, then is it not also wrong for an object to be able to serialize itself, as is the case with java.io.Externalizable? With systems like XL2, serialization *is* the persistence mechanism, so Externalizable objects are self-persistable.

    This is a good point. I would go as far as to say that
    to strap persistence/serialisation onto the object itself
    is definitely not the thing to do. I also think Java made a mistake allowing objects to be marked as such.

    When you hard-code the persistence strategy onto the
    object you make big assumptions about the context(s) under
    which the developer would want to persist the object: binary, text, XML or other; over a network, to a file or
    a pipe. It's not easy serialising object graphs.
  76. They used an interface because there was no concept of annotations before but I have red sometimes ago that they are going to replace the Serialize interface and all the other markers interfaces by standard annotations. I haven't had the chance to work with Java 5.0 so far so maybe other people can confirm this. The interface has nothing to do with the design because it add no methods. EJB3 does the same but with annotations on POJOs.
  77. Whoops my mistake, you said Externizable not Serializable. Forget it then.
  78. Indoctrination[ Go to top ]

    Indoctrinated as I am into the notion of the layered approach to development, it never really occurred to me what a very hierarchical, command-driven approach it is.

    Backing up, I used to try to introduce managers to the notion of OO via a now long out-of-print book "Object-Oriented Technology: A Manager's Guide" published by a company called Servio.

    In that book, objects were shown not in a hierarchy, but in a mesh, or graph, all sending messages back and forth and happily getting their work done. No hierarchies, just lots of cooperating objects.

    I think the notion of hierarchy is one that's been imposed to manage complexity for single individuals trying to apprehend the full scope of a given large project. The end result is an organization reminiscent of a collectivist command economy.

    There may be help for this. As I was readign the commentary I found the back of my head being tickled. I eventually figured out why. A lot of this sounds a bit liek what the Naked Objects people are doing. Check them out:

    http://www.nakedobjects.org/
  79. Sounds like BMP to me...[ Go to top ]

    Sounds like BMP to me...in other words, this idea sucks.
  80. Sounds like BMP to me...[ Go to top ]

    +1 to that.
    Where do we stop? Using the extreme, we could also swing the other way and make domain objects obese instead of anemic. Personally I think there are tradeoffs that can be made, but in my personal experience, anemic is better. If my cake knew how to do anything, I would throw it away b/c cakes aren't supposed to know anything, unless its left out too long and the mold has become sentient. Even when you model during analysis (for you ruppers ;-) targeting what you are modeling is difficult and is almost a black art to get right most of the time, ie its hard to create a pure analysis model without your subconscious sneaking in how things will really work. And when you do, there are often impedance mismatches with the implementation level design model that require leaps in imagination and translation.

    Personally, taking the tired example of ATM, I would much rather have a service that knows how to debit an Account instance than an Account instance that knows the service to which it should dispatch itself as an argument. There are valid cases IMHO where this makes more sense, but more often than not, it is less straightforward. And procedural? Its never an all or nothing game, there is always a balance point, but just b/c the domain is dumb does not a procedural program make. In fact, I would say that having the code block that orchestrates calls to varying abstractions of controllers and passing around anemic domain objects will lead to less stressful lives in the end, which, as I am constantly reminded, is the end goal is it not?
  81. Missing The Intent of the Example[ Go to top ]

    I think many people are missing the intent of the example. Craig is trying to show that with Spring 2.0 it's very easy to Dependency Injection your Domain Model, even in the case when you use the <code>new</code> operator. He's not necessarily saying "the anemic data model is solved by allowing your domain model to persist itself". Instead, he's saying that it is now very easy to Dependency Inject your domain model.

    Why would you want to do this? Creating an object model with both <strong>state</strong> and <strong>behavior</strong> often requires collaborators and dependencies. And true OOP is creating classes that have both state and behavior, with behavior defined as implementing business rules.

    So, don't look at this example and ponder if a domain model object should persist itself. Look at this example and think about how your domain model can now easily and transparently use collaborators and dependencies. This, in turn, allows your domain model to actually implement true business logic and contain real behavior.
  82. Missing The Intent of the Example[ Go to top ]

    I think many people are missing the intent of the example. Craig is trying to show that with Spring 2.0 it's very easy to Dependency Injection your Domain Model, even in the case when you use the <code>new</code> operator. He's not necessarily saying "the anemic data model is solved by allowing your domain model to persist itself".

    Thanks Seth. You're right...perhaps I chose a horrible example use of domain object dependency injection (or DODI, as I'm now officially calling it) and it seems everyone is focusing on the example and not the core technique (which is what I was really trying to demonstrate).

    My bad...I'll take the blame for choosing a bad example. I originally had a Foo/Bar example, but it seemed dry and boring. Had I went with it, perhaps we could've avoided the discussing that ensued around the example and would've been able to focus on the technique (DODI) itself.
  83. I dont like the example or the annotation thing that much but what is cool is that BeanConfigurer will kind of let you intercept "new" operation in Java and do some post processing.
  84. Anemic is about domain logic[ Go to top ]

    Just to clarify (and I've added a para to the bliki entry too) my definition of an Anemic Domain Model is about the domain objects lacking domain logic. Persistence and/or Presentation logic are an entirely separate issue. I've seen (and helped build) good, rich domain models that have no connections to presentation or data sources and they worked well.

    On the real issue of the article, there is value in injecting service objects into domain objects. Better examples would involve gateways to external systems that would be invoked due to the flow of the business logic.
  85. (noise) Martin Fowler is anti-thinker?[ Go to top ]

    MartinFowler.delete() !
  86. Anemic is about domain logic[ Go to top ]

    I've seen (and helped build) good, rich domain models that have no connections to presentation or data sources and they worked well.
    On the real issue of the article, there is value in injecting service objects into domain objects. Better examples would involve gateways to external systems that would be invoked due to the flow of the business logic.

    Yes, but aren't these two paragraphs contradictionary? If good and rich domain models can be developed without reference to external systems, is there a value in injecting service objects into the domain objects?

    If there is a business process that requires access to the external system, isn't it better to separate that business process in some business service object, resulting in better decoupling?
  87. Just to clarify (and I've added a para to the bliki entry too) my definition of an Anemic Domain Model is about the domain objects lacking domain logic. Persistence and/or Presentation logic are an entirely separate issue. I've seen (and helped build) good, rich domain models that have no connections to presentation or data sources and they worked well. On the real issue of the article, there is value in injecting service objects into domain objects. Better examples would involve gateways to external systems that would be invoked due to the flow of the business logic.

    So would read-only access to a DAO be an example of a service that is necessary to satify business logic?

    Let's take, for example, a fairly immutable object such as a Book. I'll use the BookDAO object to obtain the Book:

    Book book = bookDAO.findBookByIsbn(isbn);

    In a real world application, it may be prudent to not load the entire contents of the book in many cases. Instead, we can rely on the Book knowing how to load additional information upon request (i.e. lazy loading).

    Chapters[] chapters = book.getChapters();

    The getChapters() method itself would be responsible for the lookup of this data. So it would need the DAO as a dependency to perform the lookup:

    ...
    private BookDAO bookDAO;
    private String isbn;

    public Chapters[] getChapters() {
      return bookDAO.getChaptersForBook(isbn);
    }

    Would this be a good example of dependencies necessary to fulfill business requirements?
  88. Anemic is about domain logic[ Go to top ]

    Martin
    Just to clarify (and I've added a para to the bliki entry too) my definition of an Anemic Domain Model is about the domain objects lacking domain logic. Persistence and/or Presentation logic are an entirely separate issue. I've seen (and helped build) good, rich domain models that have no connections to presentation or data sources and they worked well. On the real issue of the article, there is value in injecting service objects into domain objects. Better examples would involve gateways to external systems that would be invoked due to the flow of the business logic.
    Great to see you posting here. I agree completely. It's a valuable mechanism; I would not choose this particular case to use it. A new hammer doesn't make everything a nail.

    Your examples make more sense IMO and I hope you do blog more about the possibilities. I think Craig was trying to illustrate the mechanism, rather than advancing a specific best practice.

    I and Adrian have recently been discussing this topic a lot with Eric Evans (and I remember our chat at Crested Butte in August), and we're excited about the potential to explore a Spring-based realization of DDD.

    Rgds
    Rod
  89. re: Anemic is about domain logic[ Go to top ]

    I and Adrian have recently been discussing this topic a lot with Eric Evans (and I remember our chat at Crested Butte in August), and we're excited about the potential to explore a Spring-based realization of DDD.

    I'm reading Eric Evans' book and his effort to the Spring community would be great.

    There are a lot of doubts (and problems) on how to implement a good designed architecture and follow DDD best practices using Spring and other tools like Hibernate: Evans' direct collaboration would really make the difference.

    My best wishes!
  90. Spring and DDD[ Go to top ]

    Rod,
    I and Adrian have recently been discussing this topic a lot with Eric Evans (and I remember our chat at Crested Butte in August), and we're excited about the potential to explore a Spring-based realization of DDD.RgdsRod

    This sounds really great. Is there anymore you can tell us about Spring and DDD?

    Regards,
    Paul
  91. agree with Fowler's vision[ Go to top ]

    I totally agree with the vision put forth. Infact I've written some framework code that allows one to maintain true domain objects whose persistant calls are delegated to its corresponding DAO. That means one could have operations such as save or update on a business object, without injection of any DAO and at the same time invoke these CRUD methods transparently on the DAO.

    If anyone's interested in the solution, I could elaborate.

    Cheers.
    - Amit
  92. Like others before me, I totally disagree with the statement that CRUD methods should be put on the domain objects. Delegating them in the back to a DAO layer and initializing them through some Spring magic doesn't make it correct! It is also against the idea from M. Fowler as he states on his Website: "It's also worth emphasizing that putting behavior into the domain objects should not contradict the solid approach of using layering to separate domain logic from such things as persistence and presentation responsibilities. The logic that should be in a domain object is domain logic - validations, calculations, business rules - whatever you like to call it. (There are cases when you make an argument for putting data source or presentation logic in a domain object, but that's orthogonal to my view of anemia.)"
  93. Here's what I do[ Go to top ]

    DomainObject contains a reference to a DAOInterface
    DAOImplementation implements DAOInterface

    so the layers go something like this:

    presentation code uses DAOImplementation to retrieve DomainObject. DAOImplementation wires DomainObject with DAOImplementation before returning it. DomainObject then uses its DAOInterface reference to interact with the DAO.

    The domain object is not bound to any specific DAO implementation but rather to a generic DAO interface.

    Presentation
    |
    DAOImpl
    |
    DomainObject
    |
    DAOInterface

    What do you think?
  94. I'm not keen on this design either. It seems like it breaks the "single responsibility principle" and the example given introduces another dependency, i.e. the Domain Object is now dependent, when it is injected, on the service object.

    There are some other issues that I see with this concept.
    - Do I litter all my domain objects that I want to persist with this code? I might as well set up a template or implement these methods in an Abstract Class which I may not have needed to create in the first place
    - What other functions should the domain object be able to perform on itself? Will this lead to a Bloated Domain Model? ;-)

    I'm not a veteran programmer by any means but something tells me there is something wrong with this approach.
  95. I don't like the Annotation[ Go to top ]

    It is a good ideal to inject dependencies into beans which is created out of spring container. It is really helpful.
    But I don't like the Annotation - @SpringConfigured("customer") , which couple class Customer with Spring framework, and cause you can not say the class is a 'POJO' domain object. And it cause difficult to reuse Customer.
    Why not implement this configuration like this - <aop:spring-configured forClass="Customer"/>
  96. Annotations[ Go to top ]

    Going with today's +1 approach ;-)

    A configuration file could get rid of the ugly import and annotation.
  97. To me persistence of the data held by an object does not fall into the category of an domain object's behavior. It has nothing to do with the business functionality but with system integrity and performance. The domain model should remain independent of such things.
    Persistence is often the part of business object lifecycle. For example, you have widget A that contains four widgets B. So you created a database where A is stored in master table and B is stored in detail table. What should happen when you try to persist a fifth B? Whether you verify the rule before INSERT or the database throws an exception from a stored procedure, what you get is not a system exception, it is a business exception that is directly related to business model. Therefore, widgets cannot "remain independent of such things". Everything depends on the model and on the business rules. There is no one proper pattern.
    Creating an object model with both <strong>state</strong> and <strong>behavior</strong> often requires collaborators and dependencies.
    Exactly. This is a great tool to have when one needs it.
  98. Missing the Point[ Go to top ]

    I think many on here are totally missing the point. For me choosing Spring of straight J2EE was about productivity, I get things done with Spring quicker than without it.

    And this proposal is just the next step. I agree with all on here that probably its not the best design and yes it may violate some purests view on OO design and where things should be, but the fact of matter is doing:

    myDomainObject.save()

    Is a hell of lot quicker than writng a Service class, a DAO, possibly a helper, maybe a facade, maybe a business delegate. I mean this is the whole reason many on have opened their eyes to the Rails approach.. you just get more productive.

    This is why Java is seen (and will remain) so much more complex .. call it over design?
  99. Missing the Point[ Go to top ]

    The point is that this new feature actually lets your design be more OO. If you read Martin Fowler's post above, he points out (as Craigs Walls has done several times in this discussion) that persistence is a bad example, because is not something that should be injected into the domain model. Being able to inject domain related dependencies would allow us move away from more procedural Transaction Script/Service type patterns, because the domain objects are enabled to do the work that actual models the domain, without having to pass around a bunch of state in the parameter lists.
  100. Missing the Point[ Go to top ]

    The point is that this new feature actually lets your design be more OO. If you read Martin Fowler's post above, he points out (as Craigs Walls has done several times in this discussion) that persistence is a bad example, because is not something that should be injected into the domain model. Being able to inject domain related dependencies would allow us move away from more procedural Transaction Script/Service type patterns, because the domain objects are enabled to do the work that actual models the domain, without having to pass around a bunch of state in the parameter lists.

    Once again, I apologize for confusing the issue with a really bad example. I've already slapped myself on the wrist for this design faux pas. The next time you see me, you are hereby allowed to scold me with a shaking finger. I deserve it.

    And thanks to Caleb and others for helping me push the real issue of domain object dependency injection (DODI for short). But it seems that my bad example screams much louder than the actual point of the article, so I'm sure much more discussion will follow about how evil it is to let a domain object handle its own persistence.

    I'd much rather see this discussion center around the plusses and minuses of the technique. For example: Is the choice of @SpringConfigured annotation good or would it be better to enumerate the Spring-configured classes in the <aop:spring-configured/> XML element.

    In short, let's refocus the discussion the DODI and move past whether an object should be responsible for its own persistence.
  101. Missing the Point[ Go to top ]

    The point is that this new feature actually lets your design be more OO.

    Ok, if you say so, but I think that depends on one's interpretation of "more OO".
    Once again, I apologize for confusing the issue with a really bad example...the real issue of domain object dependency injection (DODI for short)... let's refocus the discussion the DODI...

    Can you please provide a better example of how this should be used? Until then it is a solution looking for a problem.
  102. Missing the Point[ Go to top ]

    The example that comes to my mind is a class representing a life insurance policy. There is a requirement that certain supporting documentation (medical records, credit check, etc) need to be received before a policy can be issued. Say there is a service which manages the Policies called PolicyService and a RequirementService that has a method to see if all the requirements have been met for a policy.

    Without DODI, the PolicyService.issue(Policy policy) method might look like this:
    - Call RequirementService.requirementsFulfilled(policy)
    - Check the return value of that method to see if it's true or false.
    - Throw an exception or call policy.issue()
    So the logic the decides when it is acceptable to issue a policy is in the PolicyService class.

    If you can inject the RequirementService into the policy object, the PolicyService.issue(Policy policy) can just call policy.issue() and let the policy object figure out whether or not it should be issued.

    That is what I meant by more OO, just that the domain logic can be moved inside the domain objects. I am not making any statments about what is better, it just seems to me that encapsulating the associated behavior with the data is in keeping with the intentions of OO design.
  103. Missing the Point[ Go to top ]

    The example that comes to my mind is a class representing a life insurance policy...
    If you can inject the RequirementService into the policy object, the PolicyService.issue(Policy policy) can just call policy.issue() and let the policy object figure out whether or not it should be issued.

    Yes agreed - inject the Requirement into the Policy so that the Policy can determine its fate (encapsulated business rules) But why call policy.issue()? The policy does not do the issuing. Instead ask the policy if it can be issued and then let the PolicyService do the issuing. This is basically the same code under the hood but is much more meaningful.

    if (policy.canBeIssued()) {
        getPolicyService().issue(policy);
    }
  104. Missing the Point[ Go to top ]

    Yes, that could be more correct, I guess it just depends on how much other logic is necessary and what it relates to. The injection of the collaborators at the appropriate level is what I was getting at (and what I think the point of this whole discussion originally was).

    Caleb
  105. re: Missing the Point[ Go to top ]

    I'd much rather see this discussion center around the plusses and minuses of the technique. For example: Is the choice of @SpringConfigured annotation good or would it be better to enumerate the Spring-configured classes in the <aop:spring-configured/> XML element

    I think Spring 2.0 should provide both ways: annotations, and XML configuration.

    There will be a lot of people who will not like to clutter domain objects with tool specific annotations, in particular when there will be more than an annotation-enabled tool used, like Spring in conjunction with Hibernate.
    As surely, there will be a lot of those people against XML metadata, who will enjoy all these annotations.

    My 2 (euro)cents are that the most important argument supporting the XML configuration way, is that doing so Spring will provide a pure, non invasive, way to inject domain object dependencies, following its widely appreciated way of thinking (and acting).

    IMHO, annotations are an easy and quick way, but too invasive, and Spring should really offer an alternative.

    Same thoughts apply for me to AspectJ compile time enhancement vs. load time weaving.
  106. Missing the Point[ Go to top ]

    By the way, I appreciate the blog entry. I would not have given the persistence in the object thing a second thought had it not been for the excitement that it caused in this discussion. After all, Fowler does describe the Active Record pattern as a "good choice for domain logic that isn't too complex" (PEAA). So maybe your example wasn't so bad after all, it's just a touchy subject.

    I am very interested in the new feature especially being able to have the appropriate behaviour in objects that are loaded by Hibernate. I would lean toward making the feature configurable from xml without the annotations most because I am still ignorant/leary of annotation dependencies. But that opinion is formed just based on looking at the example and my current Spring usage pattern.
  107. No persistence methods at all[ Go to top ]

    No I am not joking.
    I think that the only "real" OOD is making classes without methods that exposes persistence. Notice that I did not say "without managing persistence". I think persistence should be managed by the object itself but not with a naive "save" or "load" method.
    I think that the correct thinking is "how should I design it if I take everything in memory?".

    For instance take an "Order" class:

    public class Order {
      public void setOrderNumber(...);
      public int getOrderNumber(...);
      public void addProduct(Product product, int quantity);
      public void removeProduct(....);
      public void prepareToCheckout(...);
    ....
    }

    Each of these methods can call its persistence code. Anyway the transaction management will be external.
    Just my 2 eurocents....
  108. Or you can just add a DomainObjectDelegate (from the DomainStore J2EE pattern) that always check if the Domain Oject datas are fresh before deleguating the actual work to the domain object. But it can be a lot of work.
  109. I think that the correct thinking is "how should I design it if I take everything in memory?"... Anyway the transaction management will be external.Just my 2 eurocents....

    I concur. The first palce to start is how the objects need to communicate. The fact that you don't want the data to be lost when the server crashes is a technical requirement. The fact that you want several changes to either happen "all or none" is a transaction concern. Now of this needs to infect the API of your domain objects for business purposes (but may for technical reasons).

    When I looked at XL2's object persistence (http://www.xl2.net/odb), I saw how nice it can be to have persistence handled in an implicit, OO manner rather than explicitly using DAOs, etc. Using Xl2, you just think, as you said, "how should I design it if I take everything in memory?".
  110. This is the holy grail I've been looking for.

    Why cannot my persistence be mixed in as an aspect? Or, better yet, why cannot my object be stored by an O/RM layer when the transaction commit begins.

    Essentially, once the thread of execution that has updated my business object reaches a transactional boundary some listener on the transaction should know to call some "persister.save(myObject)" method on my object before the actual "tx.commit()" is processed.

    I'm going to check out XL2...
  111. Think about it as if it were in memory[ Go to top ]

    Absolutely. That's what I'm gonna say. The right way of thinking is to throw away persistence crap and just think as if it is in memory,

    And when we do that, "Customer.save()" appears clearly un-natural.


    interface CustomerDao{
      Customer loadCustomer(String id);
    }
    interface Customer{
      void save();
    }


    In the above design, by semantics, "Customer.save()" should affect the result of subsequent "CustomerDao.loadCustomer()" calls, which means that "save()" and "loadCustomer()" are two operations that are closely coupled to each other. More accurately, "save()" has dependency on "loadCustomer()".

    And having two closely coupled operations in two different places is normally a bad idea.
  112. Think about it as if it were in memory[ Go to top ]

    Gee! I did not think that that clause could have such a success!
    Maybe it could be formalized into a library or a design pattern ;-)
  113. Anemic Domain Model[ Go to top ]

    In one our applications we perform the following with the domain model

    1) Validate it
    2) Diff with another model
    3) Display/Edit it with UI
    4) Serialize it as XML
    5) Persist to Database
    6) Generate HTML docs from it
    7) Export it to other data formats (XMI etc)
    8) Generate code from it (it is a MDA type application)
    9) Search for some text or pattern in the model

     We choose to do 1) 2) & 9 within the model and the rest outside with specialized classes.

    If we do all of this inside domain object it would be extremely messy. The application should run as command line tool as well as in a UI. Most of the features listed above can be used independent of others, and we have command line tool for each one.

    Our domain model fits in with Fowler's definition of "anemic domain model", but we very happy with the approach we choose.
  114. Anemic Domain Model[ Go to top ]

    To use service or to do it in-house?

    Human tom = new Human();
    (i)askAnythingService.makeHimTalk(tom);
    (ii)tom.transplantOwnHeart();

    Both looking funny. Better is:
    (i) tom.talk();
    (ii) medicalService.doHeartTransplant(tom);

    Why not follow business philosophy? Core job do in-house, but for specific expertise call outside service.
  115. Anemic Domain Model[ Go to top ]

    To use service or to do it in-house?Human tom = new Human();(i)askAnythingService.makeHimTalk(tom);(ii)tom.transplantOwnHeart();Both looking funny. Better is:(i) tom.talk();(ii) medicalService.doHeartTransplant(tom);Why not follow business philosophy? Core job do in-house, but for specific expertise call outside service.

    Unfortunately, the only reason you don't do you own heart surgery, is because you are not trained in it. When writing your own software (which is what we're debating here), you are the expert. There is no "surgeon" you can pass it off to (unless you are some manager type). So while your example is true for the real world, it doesn't really work as an analolgy in software.

    The real issue here is encapsulation. If a particular piece of work needs to be done, and it only involves data retained by the object, then it should logically be handled by said object. If it involves mostly data from the object and another piece of data, then that other piece of data should be passed to the object's method doing the work. The goal is to expose as little of the actual contents of the object as possible. If everything is exposed, encapsulation is non-existent (which is, unfortunately, the state of most Java programming today).

    Persistence is really a deviant case here, because it involves all data of the object, and should hence be handled by the object itself. However having a domain object contain JDBC and SQL also seems very wrong. If done by another object, as mentioned before, would make encapsulation non-existent.

    My own solution to this is to use what I refer to as the "Inner Class Strategy" of the DAO pattern. The Inner Class Strategy allows an object to hand off the responsibility of persistence to another object, while retaining full encapsulation.
    It is implemented by defining the DAO as a static abstract inner class of the domain object. This allows the sub classed DAO implementations to access private data, exposed through protected methods of the super class, while retaining full encapsulation for everyone else.
  116. Hi Nils,
    the "Inner Class Strategy" of the DAO pattern. The Inner Class Strategy allows an object to hand off the responsibility of persistence to another object, while retaining full encapsulation. It is implemented by defining the DAO as a static abstract inner class of the domain object. This allows the sub classed DAO implementations to access private data, exposed through protected methods of the super class, while retaining full encapsulation for everyone else.

    This sounds beautifully simple. Can you point me to an example somewhere where I can see this pattern in action.

    Thanks,
    Richard
  117. Hi Nils,
    the "Inner Class Strategy" of the DAO pattern. The Inner Class Strategy allows an object to hand off the responsibility of persistence to another object, while retaining full encapsulation. It is implemented by defining the DAO as a static abstract inner class of the domain object. This allows the sub classed DAO implementations to access private data, exposed through protected methods of the super class, while retaining full encapsulation for everyone else.
    This sounds beautifully simple. Can you point me to an example somewhere where I can see this pattern in action. Thanks,Richard

    I can show you a UML class diagram.
  118. I did a write-up here: Inner Class Strategy.
  119. very contrived in some cases[ Go to top ]

    OO was invented to model real life objects. That is real life objects should dictate the way that OO should be. Now, it seems reversed. In order to make it “real OO”, you should add some behavior to objects that do not have any behavior in real life. This is so contrived.
  120. If a domain model ends up being anemic, that does not mean that it is bad! Maybe the real stuff that this domain model represents is itself anemic!
  121. annotation free solution[ Go to top ]

    Definitely the spring solution is an option, if introducing infrastructure specific annotation and aspectj dependency is not a big deal.

    There are other solutions that are free of annotation and aop though. Absolutely no dependency on the infrastructure is needed in the doain object.


    The technique uses dynamic proxy to wrap around CustomerDao to provide transparent dependency injection into Customer.

    See http://docs.codehaus.org/display/YAN/Simple+Rich+Domain+Injection for details.
  122. annotation free solution[ Go to top ]

    Although the example we showed at the Spring Experience used an annotation to drive the pointcut, this will be just one strategy. We have since refactored to introduce an abstract base aspect with an abstract pointcut; thus the annotation strategy is now just one way of matching. So now it is possible to declare a concrete aspect that uses the AspectJ pointcut expression language to match a set of classes, with no annotations in the picture at all. For example, you could trivially match on all classes derived from a certain base class, all classes in certain packages...

    Introducing framework annotations into core business objects is of course a questionable practice in general, and we will never force folks to do it.

    Rgds
    Rod
  123. re: annotation free solution[ Go to top ]

    Although the example we showed at the Spring Experience used an annotation to drive the pointcut, this will be just one strategy. We have since refactored to introduce an abstract base aspect with an abstract pointcut; thus the annotation strategy is now just one way of matching. So now it is possible to declare a concrete aspect that uses the AspectJ pointcut expression language to match a set of classes, with no annotations in the picture at all. For example, you could trivially match on all classes derived from a certain base class, all classes in certain packages...Introducing framework annotations into core business objects is of course a questionable practice in general, and we will never force folks to do it.RgdsRod

    This is a very good news; I've never used AspectJ and my knowledge is related only to some readings about it, but this sounds great!

    I can't wait to read something more detailed about all this stuff.

    So, my congratulations to you and the whole Spring team, Rod!
  124. re: annotation free solution[ Go to top ]

    Sergio

    Thanks for your encouragement! I'll be committing the refactored version as soon as I have CVS access. The core Spring devs, myself included, are currently at JavaPolis in Antwerp, which is a great event apart from the flaky network access... We will get the 2.0 M1 drop out as soon as we can. In the meantime, nightly snapshots are available from springframework.org.

    Rgds
    Rod
  125. re: annotation free solution[ Go to top ]

    Thanks for your encouragement! I'll be committing the refactored version as soon as I have CVS access. The core Spring devs, myself included, are currently at JavaPolis in Antwerp, which is a great event apart from the flaky network access... We will get the 2.0 M1 drop out as soon as we can. In the meantime, nightly snapshots are available from springframework.org.RgdsRod

    Thank you for your valuable work, Rod!
    I'll be committing the refactored version as soon as I have CVS access.

    Can this improvements be considered as "final", that is, not subjected to other changes and refactorings?
    Or will the new Spring 2.0 DI features change 'til the final release?
  126. re: annotation free solution[ Go to top ]

    Can this improvements be considered as "final", that is, not subjected to other changes and refactorings?
    Or will the new Spring 2.0 DI features change 'til the final release?
    Just now I managed to get to a network connection that allowed CVS access, so I committed the latest changes, with the annotation-free superaspect.

    We're talking about a milestone release--Spring 2.0M1--so we reserve the right to refactor between now and Spring 2.0 final (March). But I and the other Spring devs who I've shown this with are pretty happy with the present solution, so I don't expect it to change.

    Note that the annotation-free approach is totally transparent to your code. So it doesn't matter if we change the aspect itself, even if we change its class...

    Rgds
    Rod
  127. re: annotation free solution[ Go to top ]

    Note that the annotation-free approach is totally transparent to your code. So it doesn't matter if we change the aspect itself, even if we change its class...RgdsRod

    Do you say this because the only thing to do is writing an AspectJ aspect which inject collaborators to domain objects matching a particular pointcut expression?

    If so, is there some sort of additional configuration step?
  128. http://www-128.ibm.com/developerworks/java/library/j-aopwork13.html
  129. The biggest problem I see with the "@SpringConfigured" approach, is not annotation, but the need to specify spring bean name in the domain object. It's a pain that the domain object has to know it is configured by Spring using a specific bean name.
    This is too strong a coupling with Spring IMHO.

    The "AccountOperationValidationClient" interface approach looks better because domain objects are kept almost clean. (I do not love the client interfaces, but I can live with it).

    The problem with that approach is: I need an aspect for every single domain object that I need to inject dependencies.

    I'll have AccountOperationValidationServiceInjector,
    BankOperationValidationServiceInjector, PersonOperationValidationServiceInjector, blah blah blah.

    Out of wild imagination, I'm thinking it will be nicer if Spring can be allowed to inject "pointcut" as well, since the "how-to-inject" and "whom to inject" are closely coupled to each other. Account and Bank has different dependencies to inject.


    What if Aspectj can use dynamic pointcut? Then I can create a real generic aspect that works for _every_ domain object:

    public Injector{
      void inject(Object obj);
    }
    public aspect GenericInjector {
      private Injector injector;
      private Pointcut clientcut;
      public void setInjector(Injector injector){
        this.injector = injector;
      }
      public void setPointcut(Pointcut clientcut){
        this.clientcut= clientcut;
      }
      after(Object aClient) returning :
        clientcut(aClient) {
        injector.inject(aClient);
      }
    }


    Then I can have centralize everything into Spring configuration such that:


      <!--the injection logic for account. -->
      <bean id="accountinjector" .../>
      <bean name="accountAspect"
        class="org.aspectprogrammer.dw.GeneralInjector"
        factory-method="aspectOf">
        <property name="injector">
          <ref bean="accountinjector"/>
        </property>
        <property name="pointcut"> initialization(AccountOperationValidationClient+.new(..))
        </property>
      </bean>


    Things will work beautifully then. Is this possible in AspectJ?
  130. Ben
    The biggest problem I see with the "@SpringConfigured" approach, is not annotation, but the need to specify spring bean name in the domain object. It's a pain that the domain object has to know it is configured by Spring using a specific bean name. This is too strong a coupling with Spring IMHO.
    This is no longer necessary. While the annotation is a convenient place to store metadata such as the bean name, a good default strategy (now implemented) is to use the FQN of the bean class as the bean name. If you don't specify the id attribute of a Spring bean definition, the default bean name is the FQN. This will be sufficient in most cases for injecting domain objects.

    Thus no Spring dependency, no "tight coupling". Just the ability to create a Spring bean definition with the same name (by default) as the class specifying the wiring.
    The problem with that approach is: I need an aspect for every single domain object that I need to inject dependencies.
    No, you don't. Simply extend our generic base aspect to specify an AspectJ pointcut that matches all domain classes you want to inject. With AspectJ type patterns (which have sophisticated wildcarding for packages etc.), the ability to match on interfaces/superclasses etc, this should be straightforward.

    Rgds
    Rod
  131. This is no longer necessary. While the annotation is a convenient place to store metadata such as the bean name, a good default strategy (now implemented) is to use the FQN of the bean class as the bean name. If you don't specify the id attribute of a Spring bean definition, the default bean name is the FQN. This will be sufficient in most cases for injecting domain objects.
    Well. It looks better. But "most cases" is not "always". It is a good practice to save effort when using @SpringConfigured. But it doesn't make "@SpringConfigured" solution to be free of the "bean name" dependency. Occasionally FQN will not work. (For example, two instances per service type)

    This solution is like implementing auto-wiring in AspectJ by using "FQN" naming convention. And when autowiring doesn't work, @SpringConfigured(beanname) comes to rescue as a manual-wiring option. The auto-wiring part is fine, but the manual-wiring option (though typically not necessary) is the weakest link because the domain objects are required to "manual wire", which should be the container's job.

    My ideal solution however, should be total container driving with aspectj as an auxiliary tool to weave injection. This way, we can reuse whatever wiring options already provided by the container without the need to disturb domain objects' peace.

    This is the article I just wrote, any comment?

    http://docs.codehaus.org/display/YAN/All+About+Post+Instantiation
    Thus no Spring dependency, no "tight coupling". Just the ability to create a Spring bean definition with the same name (by default) as the class specifying the wiring.
    @SpringConfigured itself is a coupling to spring too. But Tim Blair made a good point in Craig Wall's blog. The annotation type should be configurable, so that clients can choose to use their own annotation type without dependency on spring. Though I'm still not sure if the whole idea of using annotation is necessary.
    No, you don't. Simply extend our generic base aspect to specify an AspectJ pointcut that matches all domain classes you want to inject. With AspectJ type patterns (which have sophisticated wildcarding for packages etc.), the ability to match on interfaces/superclasses etc, this should be straightforward.
    RgdsRod
    You are right Rod. One generic aspect should suffice. My mistake.
  132. Ben
    But "most cases" is not "always".
    Indeed. Which is precisely why I wrote "in most cases" :-)

    If you look at the present implementation (I get the impression you haven't, and I think we're now at the level of detail where this is necessary), you will note that the BeanWiringInfoResolver interface allows the specification of metadata at a per-instance level if necessary. This won't be necessary with the FQN approach (which is clearly going to be adequate for the vast majority of domain classes). But it allows pretty straightforward approaches to resolving special cases without coupling the domain classes themselves to Spring.
    The annotation type should be configurable, so that clients can choose to use their own annotation type without dependency on spring.
    It is already configurable. Simply extend the superaspect, AbstractBeanConfigurer, and implement a pointcut that looks for an arbitrary annotation. You can then use any annotation(s) you like. An obvious choice would be the JPA Persistent annotation, and we'll probably drop that in out of the box.
  133. This is the article I just wrote, any comment?
    I'm puzzled about the article's assertion that (unless you choose to use @Configurable) there is any Spring dependency in the Spring mechanism. It is a pure POJO.

    Your assertion that "The "new Customer().doBusiness()" is never gonna work without bytecode enhancement" is also off the mark. The class is a pure POJO. If you want you can instantiate it without AspectJ weaving and inject the state.

    As I've pointed out in this thread, there is
    - full control over the pointcut if you wish, meaning you can match on any annotation or any other criteria
    - a BeanWiringInfoResolver interface that resolves the bean name

    You do need a Spring bean definition for each bean to inject if you want to use the Spring mechanism. But that does not constitute a dependence in Java code on Spring. And unless you want to use an external container to do injection, you may as well just call the setters manually or add a constructor.

    I think the article could do with some clarification. However, it's nice to see other containers picking up on the possibilities we've opened with Spring 2.0.
  134. I'm puzzled about the article's assertion that (unless you choose to use @Configurable) there is any Spring dependency in the Spring mechanism. It is a pure POJO.
    Indeed, since the annotation is configurable (not exactly by spring, but a sub-aspect is fine too), this assertion is almost false. :-)

    Is this sub-aspect trivial to write?
    Your assertion that "The "new Customer().doBusiness()" is never gonna work without bytecode enhancement" is also off the mark. The class is a pure POJO. If you want you can instantiate it without AspectJ weaving and inject the state.
    Let me clarify a bit.

    First of all, why do we need to use aspectJ? Is it because we want to be able to write such code somewhere and not worrying about the dependencies?

    new Customer().doBusiness();


    So, now assume I have such code deeply buried somewhere, am I dependent on aspectJ? I think yes. That code is not gonna work without AOP because the constructor of Customer never actually set the depdencies.

    Yes, I can always choose to set the dependencies manually. And that's nice. But what about "new Customer().doBusiness()" I wrote a year ago? Do I dig out the code and add the "manual injection" in?

    I made that point not to criticize Spring's take on AspectJ, rather, it is just some rationale behind using or not using AspectJ.

    As I've pointed out in this thread, there is
    - full control over the pointcut if you wish, meaning you can match on any annotation or any other criteria
    Yes. I see that point now.
    - a BeanWiringInfoResolver interface that resolves the bean name
    I have yet to see this. But I'm afraid whatever it is, it is just another auto-wiring mode that doesn't always work for all cases. If my memory isn't wrong, you prefer "manual-wiring" because it gives greater level of control and documentation. And that's what I see missing in this solution (well, unless we take into consideration the bean name specified in the java code i.e. Spring dependency)
    You do need a Spring bean definition for each bean to inject if you want to use the Spring mechanism. But that does not constitute a dependence in Java code on Spring.
    No, it doesn't. :-)

    And unless you want to use an external container to do injection, you may as well just call the setters manually or add a constructor.
    Again, once I have such "new Customer().doBusiness()" in my code base, I'm stuck with AspectJ anyway. So being able to call setters manually doesn't mean much any more.
  135. Ben
    Indeed, since the annotation is configurable (not exactly by spring, but a sub-aspect is fine too), this assertion is almost false. :-)
    And remember that you don't even need any annotation. However, I like the suggestion of going with a non-Spring (application specific or third party) annotation. I will be sure to include that in the documentation.
    Is this sub-aspect trivial to write?
    Yes. It's a classic AspectJ idiom: an abstract superaspect does all the work, with each concrete subaspect merely implementing the abstract pointcut.

    Here's the implementation of this abstract pointcut for the Spring annotation:

    protected pointcut beanCreation(Object beanInstance) :
            initialization((@Configurable *).new(..)) &&
             this(beanInstance);
    }

    Simply replace @Configurable with the annotation of your choice and you're done. Very straightforward: only thing to note is that you need to bind "this"--the object being injected--to make it available to the superaspect. But of course, that's ensured by the pointcut signature.

    For example, the following implementation would work with all annotated JPA entities. We'll probably ship this out of the box:

    protected pointcut beanCreation(Object beanInstance) :
            initialization((@Entity*).new(..)) &&
             this(beanInstance);
    }

    Rgds
    Rod
  136. Hmm. For some reason my reply did not show up. So re-post.


    Rod,
    Yes. It's a classic AspectJ idiom: an abstract superaspect does all the work, with each concrete subaspect merely implementing the abstract pointcut.
    In Adrian's article, I see such code in the super aspect:

          after(Object newInstance, SpringConfigured scAnn) returning
           : springConfiguredObjectCreation(newInstance,scAnn)
          {
            String beanName = getBeanName(newInstance, scAnn);
            beanFactory.applyBeanPropertyValues(newInstance,beanName);
          }

    which looks like the "SpringConfigured" is hard-coded. Shouldn't the sub-aspect override this advice as well?


    But anyway, Rod, Hopefully you see my point by now. My main concern with the Spring2.0 solution is that it maintains the "domain - bean name" mapping (or contract) in the aspect, which kinda forms a bi-directional dependency between configuration file and aspect. (Cuz spring configures aspect, and aspect mandates a naming convention back on spring)

    I think it is better to maintain that mapping in configuration file so that I can freely choose "by FQN", by specific bean name, by type, etc. There's no coupling or contract between the aspect and the configuration file.

    This, I believe is doable with FactoryBean.

    Similar to Nuts' solution, the dumb aspect is injected with an abstract interface "Injection":

    aspect GenericInjector{
      private Injection injection;
      after(Object newInstance) returning
           : clientCreation(newInstance)
      {
        injection.inject(newInstance);
      }
    }


    Create a few special FactoryBean that create "Injection" instance using bean name, or any other naming convention.

    The final config may look like:

    <bean id="fqn_mapping" class="FQNInjection">
      <property key="types">
        <list>
          <value>com.mycompany.Customer</value>
          <value>com.mycompany.BankAccount</value>
        </list>
      </property>
    </bean>
    <bean id="the_injection" class="AdhocInjection">
      <property key="default"><bean local="fqn_mapping"/></propety>
      <property key="mappings">
        <map>
          <entry key="com.mycompany.Apple">apple</entry>
          <entry key="com.mycompany.Orange">orange</entry>
        </map>
      </property>
    </bean>
    <bean class="GenericInjector" factory-method="aspectOf">
      <property key="injection"><bean local="the_injection"/></property>
    </bean>


    The FQNInjection factory bean specifies a list of types that use the default FQN mapping.

    The AdhocInjection uses FQNInjection as the default mapping scheme, but allows individual domain types to be mapped to any specific bean name we want.

    This design is open and extensible. More factory beans can be created to implement more sophisticated mapping scheme. But anyway, the mapping is now in configuration file and the aspect is dumb with no dependency or contract with the container.

    The syntax could be polished to be more convenient to use, but the point is: "let the container and the configuration file take the steering wheel".

    What do you think?

    Regards,

    Ben.
  137. Ben

    I think Adrian's article relates to an older version of the code. The superaspect in Spring CVS (to go out in M1 today) doesn't know anything about @Configurable.

    I quite like your suggested metadata strategy, for the cases where FQN resolution is inadequate. I think it would be a good strategy for a BeanWiringInfoResolver, and will look at implementing one post M1. If you would like to contribute such an implementation, that would be great.

    Rgds
    Rod
  138. Rod, you are not talking about the "@Inject" marker annotation, are you?

    It just eliminates the need for "one-bean-per-domain-type", but still relies on auto-wiring.
  139. Nuts vs. Anemic Domain Model[ Go to top ]

    More options are provided by Nuts:
    http://docs.codehaus.org/display/YAN/Nuts+vs+Anemic+Domain+Model
  140. Plus, Rod, the FQN solution currently doesn't work with inheritance.

    Suppose I have a bean that injects dependency to Fruit, it will not work for Apple and Orange because they require a different FQN than com.mycompany.Fruit.

    This may or may not be desirable. But what if all Fruit subclasses share the same dependencies? (Or at least most do) In that case, having to declare beans for each subclass is a pain.

    Regards,

    Ben.
  141. Ben
    Plus, Rod, the FQN solution currently doesn't work with inheritance. Suppose I have a bean that injects dependency to Fruit, it will not work for Apple and Orange because they require a different FQN than com.mycompany.Fruit. This may or may not be desirable. But what if all Fruit subclasses share the same dependencies? (Or at least most do) In that case, having to declare beans for each subclass is a pain.
    I think that explicit declaration for each subclass is desirable. It would be easy enough to adapt the present implementation to back up the inheritance hierarchy to find the first match, but I think it's seldom a good idea to err on the side of doing something the user may not expect.

    In any case, Spring offers inheritance of bean definitions to make this concise. Spring's parent bean definition mechanism can ensure that there's zero duplication of configuration in this case. So you get to configure exactly what's required, and not duplicate any of the inherited properties.

    Rgds
    Rod
  142. Rod,
    I think that explicit declaration for each subclass is desirable.
    Well. I'm not so sure about this. Being explicit is surely desirable in some cases, but maybe not always. Anyway, I think the point is that the users should decide what's the best way to go. The infrastructure better not making decisions for the users.
    It would be easy enough to adapt the present implementation to back up the inheritance hierarchy to find the first match
    "first match"? Hmm, I'm not sure if that's a good way to go. I definitely didn't mean it.
    What do you think about the following configuration that works with inheritance?

      <typecase id="the_injection">
        <case type="com.mycompany.domainmodels.Orange" injection="$inject orange"/>
        <case type="com.mycompany.domainmodels.Fruit" injection="$inject fruit"/>
        <case type="com.mycompany.domainmodels.Person" injection="$inject person"/>
      </typecase>


    Using a bean for each domain object type may not be unacceptable. What do you think about the idea of "one bean does it all" then?

      <function id="general_injection" params="domainobj">
        <!-- use abean to auto-wire based on annotation. -->
        <abean component="$domainobj" autowire="bytype"/>
      </function>
      <injector class="DomainInjectionAspect" injection="$general_injection"/>

    However many domain object types are there, only one "general_injection" is needed. autowire and meta-data does everything else.

    Regards,

    Ben.
  143. Why should it ?

    My business object sholdn't need to worry about how it's created or populated with values.

    It needs to know what to do with the values once the business-method's is called.

    ----
    The only thing the cake has to know about the baking, is what condition it's in after beeing processed in the oven for 30 minutes at 200 degrees. And it's the oven that tells the cake what temperature it is, and how long it takes.
    The oven serves back the cake, and does not know wether the cake is totally burned or just fine.
    -----

    In order to make the 'business-side' of the object seperate from the 'persistent/poulation-side' I create two seperate interfaces, where the process instanciating the object only has access to pure get/set-methods for the properties, and the service-process only have access to the business-methods it needs to perform business-logic.

    The object itself is never accessed.

    If the object needs to be persisted, a process deliver the object to a DAO-service with the interface of getters to retrieve all neccesary properties to rebulid the object.

    I could have several different services that creates the object, and each of them would have to know how to transform the input-data and map it to the object's properties.

    The cake could be created from an XML-file

    Cake cake = new Cake();
    cake.addIngredience("Flour",12);
    cake.addIngredience("Milk",1);
    ...
    cake.mix(30); //seconds
    Oven.setTemeratur(200);
    Oven.setTimer(30);
    Oven.bake(cake);

    ....
    the oven calls cake.cook(200,30);
    ...
    Shelf.store(cake);

    ....

    So when should the cake persist ?

    If the process of adding components is done one by one in a manual line-input interface, mabye foe each add.

    This would actually be the responsibility of the service adding those components to make sure the cake doesn't vanish if the input takes too long, and the session is lost or the server goes down.

    If the service was an XML-reader, the persisting could be done after all properties was added, still up to the service creating the cake.

    The cake itself only has a set of ingredients, and doesnt need to worry wether those are stored as a long CSV-string, or in a joined table.
    It might even be neccesary to create a transformer-class in order to persist the cake the way You want for each case, but this should definitely not be any concern of the cake.

    The fridge that stores the finished cakes, should perhaps tell the cakes what temerature it has, and when it changes, it should alert the cakes again. This would the make the cake recalulate it's remaing good days, and perhaps alert the fridge if a threshold-value is reached.

    It should therefore hav access to such method via an interface.
    This way, if the fridge manages the delivery-queue of the cakes, it would rearrange the queue if it got a message from one cake. The later on, if You would install another fridge, the queue-manager shpuld be outside the frige, in a new Queue-manager wich also implements this inerface.

    The cake then gets it reference to the queue-manager instead, and no logic has changed in the cake (as it shouldn't either).


    in short :

    Each b-object should know as little as possible about others (preferably via interfaces), and the service-processes should know as little about the b-objects as possible, preferably via interface (so it has no access to the getters and setters, but just b-methods like add(value), process(value) an so on)

    If the service-process then feels that the object needs to be stored away somewhere berfore using it again, it could deliver it to some persitence-layer.
  144. Has anyone here actually baked a cake?

    I have. Mixing ingredients and baking them make the cake. It is not a "Cake" until mixed and baked. Unless you are making pudding cake. Then it is not cake until you mix the ingredients.

    Time to refactor!

    :)
  145. http://www.nofluffjuststuff.com/blog_detail.jsp?rssItemId=96860