Discussions

News: Updates to "New Life for EJB" Critique of EJB 3.0

  1. We received a lot of feedback on the first release of our document "New Life for EJB, version 1.2". We have made changes to our model in response to this feedback, and the changes are in the following areas:

    1.The DTO mechanism has been overhauled and simplified.
    2.The interfaces have been further rationalised and simplified making the model extremely simple (POJOs and POJIs).
    3. Testability outside the container is possible for all bean methods which do not require container services.

    We believe we have reconciled four concerns – architectural soundness, performance, security and ease of use. In the process, we also show why the EJB 3.0 approach to the use of data is wrong.

    Interestingly, our model does not require explicitly declared local or remote interfaces for any bean, because we have resolved the pass-by-value/pass-by-reference issue more fundamentally. This makes it even simpler and friendlier than EJB 3.0.

    The updated document can be found here:
    http://today.java.net/pub/a/today/2004/08/05/ejbnewlife.html

    This document is a much smaller one that describes only the changes we have made since the earlier version. A revised version of the full document will be released soon.

    Feedback, as always, is welcome.

    Rajat Taneja
    Ganesh Prasad

    Threaded Messages (26)

  2. Ease of use will be reconciled when the spec is used easily. Real projects in the real world will flush that out.
  3. I think the authors sacrifice ease (developer-friendlyness) of use a lot.

    I work with a framework which forces me to make a interface for every business object. I cannot simply use a implementation. Because methods are added or removed to the implementation, the interfaces changes too. I think this is not the sense of an interface, to frequently change. Besides this, we use these business objects in different components, so we have exactly the same implementations of lets say Article in many components. This violates the DRY principle (don't repeat yourself).

    Its nonsense what the authors propose: to create a Buisness Data Interface AND a Data View Interface, which are in most cases identical. Again we have a violation of the DRY principle.

    Furthermore they want to built in security into the domain model. Thats a reason why the use the Data View Interface. But these things should NOT be hardcoded but configured by an adminstrator. We use a bad framework, but this framework at least has a feature which makes the Data View Interface pattern obsolete and bad. One can simply adjust which usergroups are allowed to get certain data. Its not hardcoded but simply configured! So the security aspect is realized in a much better way, more dynamical, not requiring any recompling or redeploying!

    Compared to Hibernate I think their proposed EJB 3.0 is still much more developer-unfriendly und unproductive in most cases.

    They say certain objects need not to implement this or that. But in fact they do, its just not visible. This is a strange, unnatural concept to me, like the abstract methods in the bean.

    Another big criticism against the use of interfaces for the data model is that in UML the relations cannot be reverse engeneered. It requires instance variables for UML to recognize relations and cardinalities. But interfaces should not contain instance variables. Relations and cardinalities need to be set manually for interfaces. If the implementations are shown together with the interfaces (which corrospond completely with the implementations) on the diagram then the diagram gets double as big and is useless.

    Still EJB (heavyweight enterprise framework) seems to me like Pentagon is forcing its soldiers to carry 100kg of weapons with them, just in case they need them. Its heavy, you can hardly move, and it makes no sense.
  4. Very impressive analytical work, indeed!

    At the end of the day, the fundamental disagreement I see with this report is the incorrect assumption that tight coupling, by virtue of passing domain objects across tiers, is *universally* bad. This topic has been beaten to death in the original thread.

    SOA, and by definition loose coupling, makes sense for inter-application interactions. It is *not* optimal for intra-application scenarios. UI-Biz Layer interaction is WITHIN the application boundary, therefore DTO-izing biz layer encourages duplication of a significant portion biz logic in the UI. On the other hand, DTO solution is a perfect fit for app-app interactions. But even in that case we don’t need to build that abstraction into the EJB model.

    Here's an example to illustrate this:
    An order management app might have 15-20 JSPs to incrementally build the Order object. Each page *applies relevant biz logic* and proactively warns users of biz logic issues. This can immensely benefit from having the domain object itself as the model object instead of a dumb DTO/struct.

    Contrast this with an app-app interaction. A third-party storefront may be submitting Orders to our app which may be consumed by our biz logic layer receiving it through a service interface. It would be disastrous to have the third-party depend on our "domain object" let alone the technology issues (maybe its done in .Net).

    In the latter case, the overhead of loose-coupling is justified by the maintenance advantages it gives the respective application owners – these applications can evolve relatively independent of each other. In the former case it is not so.

    By having the biz layer expose domain objects, UI can take advantage of reusing the domain biz logic. For app-app interactions, a thin Service Facade layer will be built on top that will *expose* out biz layer API through DTOs or the equivalent. In any case, we don't need developers to deal with the DTO abstraction. For example, the Service Facade could include tools to adapt from an XML Schema (the DTO-equivalent in Web Services) to the domain object itself.

    As regards to knowing whether you have a reference or a copy, it comes back to the architecture. You biz layer façade should always expose detached copies of domain objects as there shouldn’t be a transaction context outside of biz layer. This will also work consistently for interactions between biz layer objects also.
  5. At the end of the day, the fundamental disagreement I see with this report is the incorrect assumption that tight coupling, by virtue of passing domain objects across tiers, is *universally* bad. This topic has been beaten to death in the original thread. SOA, and by definition loose coupling, makes sense for inter-application interactions. It is *not* optimal for intra-application scenarios.
    Raman,

    It is very limiting to take such a "single-application" view of EJB.

    Remember the original design intent of EJB:

    We were meant to be able to buy EJBs from some vendor in the market, deploy them into our container, and thereafter applications in our organisation would be able to selectively use subsets of their functionality as appropriate.

    What happened to that vision? Why was it never realised? Not because there was something fundamentally wrong with the concept itself, but because the EJB architecture was so clumsy it was just not practically feasible.

    If you step back and look at the original design intent of EJB, you will see that the natural corollary should have been a Service-Oriented Architecture.

    That's why we emphasise decoupling so much, because it's directly linked to the potential for reuse, which in turn is what EJBs were always meant to be - reusable components for the Enterprise.

    Even if you build an EJB application today with a dedicated web front-end, you will find many potential uses of the EJB tier within future applications, provided you have designed the service contract well. You as the EJB developer cannot foresee all the uses to which your beans will be put, and so your best bet for reusability is to standardise your Service Contract and hide your Domain Model.

    Anything less fails the Enterprise test, and what you then have are plain JavaBeans.

    Regards,
    Ganesh
  6. SOA has not really achieved loose coupling nirvana. What happens, if the service interface changes (because change is the only thing that is constant,) to the clients that are not interested in the new interface? WIth Web Services or DTO (implementations of SOA) the clients are forced to update themselves even if the change is not directly related to them - it is a compile time tight coupling.
    Dynamic DTOs can be an answer?
  7. Coupling seems to be the fundamental issue[ Go to top ]

    This is not entirely true. One of the advantages of separating Service interfaces from core application components is to support multiple versions of Service interface to exist. In the Web Services context, you could have multiple WSDLs, or use a Service Broker to initally receive the request and transform and/or route it to the actual biz logic service.

    Of course this can fail if you are making a drastic change that can't be kept backward compatible easily.
  8. Coupling seems to be the fundamental issue[ Go to top ]

    Well, we have seen a similar solution already and it's universally bad as in "DLL Hell!"
  9. Raman,It is very limiting to take such a "single-application" view of EJB.Remember the original design intent of EJB:We were meant to be able to buy EJBs from some vendor in the market, deploy them into our container, and thereafter applications in our organisation would be able to selectively use subsets of their functionality as appropriate.What happened to that vision?
    I'm assuming you are referring to the reuse of business components. If so, the main technical hurdle, I think, was the sub-optimal Entity Bean design. Beyond technology there is a fundamental business modeling issue - the issue of being able to model components that would be applicable *across* Organizations. ASPs (I work for one such company) face that issue today. How do you create a common model of, say, a Order management workflow, across companies in the *same* vertical space.
    Even if you build an EJB application today with a dedicated web front-end, you will find many potential uses of the EJB tier within future applications, provided you have designed the service contract well. You as the EJB developer cannot foresee all the uses to which your beans will be put, and so your best bet for reusability is to standardise your Service Contract and hide your Domain Model.
    Your argument seems contradictory to me. In majority of the cases, a service contract is targeted to a particular usage scenario / use case. So for building a Service contract, you need to all the more, foresee potential usages in the future. If you argue that this is not the case, then your DTOs are just an exact mirror of domain object, sans behavior.

    Domain objects model the business without *application logic* in them. If we follow such a definition, then the domain object model is the core reusable piece. Domain objects are POJO Entity beans containing application-independent reusable domain biz logic. Session Facades are a thin layer of EJB Session beans that expose and consume domain objects that provide transaction and remoting. The direct consumer of this is UI which by nature requires this tight coupling. One will build Service Facades on top of Session Facades for each potentially distinct *client application* that expose and consume DTOs specific to the use case being modeled.

    This is separation of concerns - Session Facade provide coarse transactional, remotable interface. Service Facades encapsulate *adaptational* logic specific to each client app/use case. Entity beans are POJO domain objects.

    If one were to sell biz *components*, they will most likely be Entity bean clusters modeling the business in question, NOT Services. The buyers would build Facades on top of it and use it.

    On the other hand, if one were to sell biz *services*, they will most likely be coarse-grained in nature suitable for collaboration, NOT for composing tight applications from such services.
  10. DTO oxymoron[ Go to top ]

    Java that espoused clean OO has introduced the ridiculous concept of "Data Transfer Objects." Why don't you just called them structs?

    J2EE has done enormous damage on OO principles. I recently found myself dumbfounded when a sr. j2ee developer told me that objects in my j2ee model should not have business methods and that those belonged to the session beans!

    On a side note: Has anyone actually used the bean pooling feature of session beans to effect?
  11. DTO oxymoron[ Go to top ]

    I recently found myself dumbfounded when a sr. j2ee developer told me that objects in my j2ee model should not have business methods and that those belonged to the session beans!
    You know, there is definitely something to be said for crosscutting concerns to group common business methods. Inheritance only gets you so far, sometimes it is just easier and cleaner to break 'functions' out of the model.
  12. DTO oxymoron[ Go to top ]

    Java that espoused clean OO has introduced the ridiculous concept of "Data Transfer Objects." Why don't you just called them structs?
    Yes, they are structs, but there is nothing wrong in struct.
    J2EE has done enormous damage on OO principles. I recently found myself dumbfounded when a sr. j2ee developer told me that objects in my j2ee model should not have business methods and that those belonged to the session beans!On a side note: Has anyone actually used the bean pooling feature of session beans to effect?
    Yes, he was right. You do not need to care about "business logic", this is job for business analyst. You just need to transform model, as more this model abstract as better, OO model is not abstract (it is too domain specific) and it has many problems related to performance. There are more reasons to transform model to structs for RPC and messaging systems, this transformation doe's not need to be cool, it must work in the best way.
  13. DTO oxymoron[ Go to top ]

    Yes, he was right. You do not need to care about "business logic", this is job for business analyst.
    What was he right about ?
    This is surprising. If I understand this right, it flies in the face of domain driven development and domain modeling. Are you talking about requirements gathering or OOA/D ?
    This is one major problem. There should be business objects in the form of a OO model whether we use session beans or not. How can these be in the session bean ?
  14. DTO oxymoron[ Go to top ]

    Domain driven development makes sence, I see no way to make business people think in terms like "record" and "procedure" (abstractions from developer point of view) and developer doe's not need to think in "customer", "P/E", "stock", "order" ... terms to transform this stuff to records,attributes, tables ... . Business methods is a mokey code, it is transformation from paper or diagram to java code and it is not important for system architecture.
  15. DTO oxymoron[ Go to top ]

    Java that espoused clean OO has introduced the ridiculous concept of "Data Transfer Objects." Why don't you just called them structs?
    Yes, they are structs, but there is nothing wrong in struct.
    J2EE has done enormous damage on OO principles. I recently found myself dumbfounded when a sr. j2ee developer told me that objects in my j2ee model should not have business methods and that those belonged to the session beans!On a side note: Has anyone actually used the bean pooling feature of session beans to effect?
    Yes, he was right. You do not need to care about "business logic", this is job for business analyst. You just need to transform model, as more this model abstract as better, OO model is not abstract (it is too domain specific) and it has many problems related to performance. There are more reasons to transform model to structs for RPC and messaging systems, this transformation doe's not need to be cool, it must work in the best way.
    I have used and written business objects in the past which had transparent (to the user of the objects) remoting, it's not a valid argument for removing object orientation. The original poster had a fair comment. I have seen the least object oriented code in J2EE, it isn't justifiable in terms of remoting or persistance. If you have to pass value objects about fine; but their life span should be only at the interface between systems and don't dumb them down uneccesarily. All too often they are used through out the system and all business logic remains in 'helper' classes. So we have a perfectly non-OO design.

    We should go back to basics every now and again and remember why we moved to OO. Because I see a lot of code duplication and overly complex code in J2EE because we are not making use of the advantages we get from OO design. Hence also the push for frameworks like Hibernate and Spring - as they help us get back to the halcyon days of OO :-)
  16. DTO oxymoron[ Go to top ]

    I have used and written business objects in the past which had transparent (to the user of the objects) remoting, it's not a valid argument for removing object orientation. The original poster had a fair comment. I have seen the least object oriented code in J2EE, it isn't justifiable in terms of remoting or persistance.
    Well, transparent remote OO fell flat on its face with Corba. EJB was not least an attempt to get around the performance and management problems that proper location transparent OO remoting made all to visible...
    If you have to pass value objects about fine; but their life span should be only at the interface between systems and don't dumb them down uneccesarily. All too often they are used through out the system and all business logic remains in 'helper' classes. So we have a perfectly non-OO design.We should go back to basics every now and again and remember why we moved to OO. Because I see a lot of code duplication and overly complex code in J2EE because we are not making use of the advantages we get from OO design.
     
    Yes the helper class is not the best design. On the other hand a helper class might well be a valid abstraction. Consider (see below) one of the ultimate "helper classes", the Spring BeanFactory.

    If I remember correctly the main push for OO was not because of reuse (it was in the GUI layer), but because it enables a certain way of thinking about things. As it turned out, this is not an easy way to think about things. I still find a lot of people who are uncomfortable with "programming by interface" or who have not yet grasped what polymprphism is.... So maybe the amount of non-oo we see everywhere is nothing but a lack of understanding and training, while the adoption of things like AOPish interception is not because of the concept itslef but because of the (seemingly) simple, straightforward and procedural way it actually works....
    Hence also the push for frameworks like Hibernate and Spring - as they help us get back to the halcyon days of OO :-)
    What these frameworks do is enable you to build a more OO like layer. They will not give you OO-remoting (in a way, for example when bound to JMS, they heavily rely on "DTO").
  17. DTO oxymoron[ Go to top ]

    If I remember correctly the main push for OO was not because of reuse (it was in the GUI layer), but because it enables a certain way of thinking about things. As it turned out, this is not an easy way to think about things. I still find a lot of people who are uncomfortable with "programming by interface" or who have not yet grasped what polymprphism is.... So maybe the amount of non-oo we see everywhere is nothing but a lack of understanding and training, while the adoption of things like AOPish interception is not because of the concept itslef but because of the (seemingly) simple, straightforward and procedural way it actually works....
    Do you think "programming by interface" or polymprphism are related to "OO domain model" and "business methods" in some way ? I prefer to think about things in the way I understand, many things in business I do not understand in OO way because I am not this business expert, but I understand it as records without problems. Do you think it is better to train me for all business problems I work with or I need to look for problems in OO way ?
  18. DTO oxymoron[ Go to top ]

    Do you think "programming by interface" or polymprphism are related to "OO domain model" and "business methods" in some way ? I prefer to think about things in the way I understand, many things in business I do not understand in OO way because I am not this business expert, but I understand it as records without problems. Do you think it is better to train me for all business problems I work with or I need to look for problems in OO way ?
    If you are serious with OO you need to transform the business problem in a OO space and be able to communicate that back to "business" in business terms. If you can't do that then there is no bloody way you can come up with a model that is flexible and maintainable not from a system architecture point but from a business point. So, yes I do think OO concepts of domain objects like "customer", "contract" and of business procedures like "create account" or "sell shares" are important.
  19. Object concepts are related to business[ Go to top ]

    Do you think "programming by interface" or polymprphism are related
    to "OO domain model" and "business methods" in some way ?
    Of course, yes!

    The problem is what does "business model" means. I've been teaching OO analysis, conception, dev, and coached programmers, analysts and architects for over 15 years. And a recurrent question is what is a business object ?
    Well, I should say everything is a business object, it depends on what business we are talking about.

    Say, your business (or domain) is manipulation of collections, data structures and so on, the business concepts related to your domain are maps, lists, stacks, sets theory, etc. How you decide to implement these concepts is a problem to solve but how these concepts are consistent one with each other is another one. And when implementing your full-featured-collection-framework-OO model, we don't consider in one hand the "business data" and on the other the "business logic". We don't consider one is affaire of business analyst and the other is for hardcore techies. Why ? Because we consider ourselves as business experts on this domain and also because in the OO paradygm (as in the systems theory), information without responsability, internal states without action is useless. We can't decouple these two aspects without loosing consistence and undertanding.
    I prefer to think about things in the way I understand, many things in business I do not understand in OO way because I am not this business expert, but I understand it as records without problems.
    Ok, you understand the procedural/relational paradygm and you do not understand the OO paradygm. The fact is that UML models are far more expressive than relational data models. And thinking about a problem, a domain or whatever just with a relational point of view is non sense.

    There is something funny when talking with technical architects (well, I am), we often consider that there are two worlds : the technical issues and the business domain with big problems. As if, in our world there are only two businesses : our (IT business) and the reste-du-monde business wich is very complicated.

    If we talk about n-tier architectures, it's not just because it is beautiful nor because we have n computing nodes to load-balance, it is also because we isolate in a tier/layer a domain with its own concepts. And saying the business is located in the Business Tier is not sufficient as a business domain may be seen as a multi-tiered architecture involving multiple businesses. When we simplify the problem by saying : "a domain (wich is in fact multiple interconnected-domains) = a database" then we are getting in trouble.

    Regards
  20. J2EE not for business ?[ Go to top ]

    You do not need to care about "business logic", this is job for business analyst.
    This is a kind of thinking that made sure J2EE did not enter into enterprise computing. Peoplesoft, SAP, Oracle Apps, Siebel - none are written in J2EE.

    It is _only_ business logic that matters, the rest is just the plumbing (frequently overengineered).

     You just need to transform model, as more this model abstract as better,
    Hashmap ?
  21. DTO oxymoron[ Go to top ]

    Not got much time, so I'll be brief. Emphasis on re-useable enterprise components, was how ejbs where pitched back in the day (I remember I was there). This doesn't sit so well with the current Agile Trend towards building the "simplest thing possible", and not betting on the future.

    The question as I see it is what do you want? Re-use is difficult but potentially rewarding. Otherwise you can build monolithic standalone apps, that may have a database in common (if that), and choose to live with redundant code across the enterprise (possibly redundant data too!).

    Looks like back to the future then!

    I was beginning to think I was the only person who remembered the original goals. Good work
  22. DTO oxymoron[ Go to top ]

    +1 on that (sigh)
  23. DTO oxymoron[ Go to top ]

    I recently found myself dumbfounded when a sr. j2ee developer told me that objects in my j2ee model should not have business methods and that those belonged to the session beans!
    I'd probably give you the same advice mainly due to the fact that business logic often accesses the persistant store and by having this code within session beans you get the full benefit of the container handling transactions for you.

    Ian Purton
    Website and Server Monitoring | Email Marketing | Website Analysis
  24. Yeap, DTO makes a lot of sense and CORBA rules.
    Even with presence of DTO there is room for nasty errors in Java: consider this DTO (or business object )
    Class MyDTO implements Serializable{
      List values;
      String name;
      ..getters and setters
    }

    This travels seemingly fine via RMI between client and server till another day server side Hibernate library gets updated and client connection fails with incompatible class versions error.
  25. DTO oxymoron[ Go to top ]

    I recently found myself dumbfounded when a sr. j2ee developer told me that objects in my j2ee model should not have business methods and that those belonged to the session beans!
    What he should say is that business objects should be represented by beans, either entity or session. EJBs were supposed to be business objects, ehanced with remote access, transaction control, instance management, roles, etc.

    EJB 2.1 spec, Chapter 4.1.1:
    The essential characteristics of an enterprise bean are:
    • An enterprise bean typically contains business logic that operates on the enterprise’s data.
    • ...


    EJB 2.1 spec, Chapter 4.1.2:
    The enterprise bean architecture is flexible enough to implement components such as the following:
    • An object that represents a stateless service.
    • An object that represents a stateless service and that implements a web service endpoint.
    • An object that represents a stateless service and whose invocation is asynchronous, driven by the arrival of messages.
    • An object that represents a conversational session with a particular client. Such session objects automatically maintain their conversational state across multiple client-invoked methods.
    An entity object that represents a business object that can be shared among multiple clients.
    • An entity object that represents a fine-grained persistent object that embodies the persistent state of a coarse-grained business object.
  26. DTO oxymoron[ Go to top ]

    +1
    DTO is a just a workaround, nothing to be proud of ...

    I would agree with J2EE impact statement too. I have seen quite a few project where multiple layers play "data ping-pong".
    Data goes just back and from through n+1 layers and from business perspective nothing happens to it. What are these layers for ? Look good on the picture for sure, make us techies feel good, but where is business value? Is customer getting getting any value from the fact that we have clean separated boxes on the picture ? Code is slower, codebase is larger, validations are far away from the UI (or they are duplicated in UI and deeper layer).
  27. I'm not a fan of DTOs[ Go to top ]

    They push too much client knowledge into the service layer and usually force every application to behave like a web app for DTOs are often modeled as universal transfer objects. Take for example a list of auto parts that are being updated. The client could display hundreds or thousands of them and update one of them. The DTO will contain a list of all the parts listed, transfer the updated item to the service layer, and then receive a fresh copy of the list after the update. This works in a web app, but a client server application may only need to update the single part and not refetch the entire list. Yes you can break the view into two calls, one to get the original list and one to update the single item in the list. But then the client is responsible for synchronizing the list with the update and I’ve seen this problem enough times to realize engineers are often too lazy to break the view into two separate components or are afraid of suffering the serialization penalty twice in the same screen. This creates coupling between the screens and the service layer.

    DTOs also limit the ways the service layer can be used. In the example above, I could have an entirely new client that only needs to see one part (for the sake of the example, lets assume that their isn’t an existing view that retrieves a single auto part) so the developer must either design, implement, and deploy a new view with the single auto part, or use the existing list view and search that list for the desired part. Modifying the service layer to give me this new view may not be an issue if my team owns the service layer, but it can be an issue if they don’t. I also don’t believe the service layer should need changes to support a new client data request.

    DTOs also escape the object pool. Using a technology like JDO, the domain objects are pooled and cached and so optimize memory usage as well as garbage collection. Using a DTOs, the developer will make for the most part an exact copy of the underling DTO into an entirely new object, serialize the new object, and destroy it. This could temporarily bump memory usage (not a problem in most systems), but will work the garbage collector. So is the extra overhead of creating new objects worth the penalty of serializing potentially larger and or deeper objects? In some cases yes and others no.

    Also with DTOs, you get into the game of finding the right definition of the DTO for similar objects. Take for example a person object. There are often at least two versions or flavors of a person, a person light with just a name and a person heavy that has the name, address and phone number. There are also often use cases where the client needs the name and phone number only and other frequent use cases where only name and address are used. Do you use the heavy user in the later cases or create new versions with one having the name and phone number and another with name and address? If you create new versions, then you’ve significantly added to the complexity of managing views for not only will you have create new readable views, but also a more elaborate means to persist changes to the object(if you don’t so this, then you could end up retrieving the same information twice, once to get the light version for display and once to get the heavy version for updates). And if you don’t create a new version then in most use cases you just end up using the heavy object and so receive no benefit in pairing down the size and depth of the object.

    I’m a much bigger fan of the composite object pattern in most cases for it allows greater flexibility in client implementations for the client has more data exposed by default and doesn’t cause the service layer to be modified when the client needs new data or changes in the data it receives. It does couple the client more tightly with the domain layer, but I’ve rarely seen changes in the domain model that were not the result of a change in the client layer or visa versa. The two layers are coupled together in most real world applications for one doesn’t store data in the domain that the client doesn’t need. There are situations where the DTO pattern does make sense such as exposing services to entities external to the organization(web service is probably a better technology in this case, but you’ll most likely still end up creating intermediate objects similar to DTOs), or in cases where the domain model is very large and the client only needs small pieces of it, or in cases where extra security is needed.

    So my point here is I don’t think the DTO is a universally applicable pattern as the article suggest. In a lot of situations, it’s reasonable to expose the domain objects to the client directly to avoid the time to mange the decoupling layer and the DTO often are clones of the domain model itself so you just end up creating new objects that looks and behave the exact same as the domain at the expense of creating new unmanaged objects with the same depth and size as the domain objects themselves.