Announcement Announcement Module
Collapse
No announcement yet.
Generic User Management conflicts with Rich Domain Model Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Generic User Management conflicts with Rich Domain Model

    Hi there,

    i'm interested on your opinions on this. Maybe it's a trivial question,
    maybe not. At least i did not find satisfying answers for the last two days


    I'm trying to create a generic user management for my app(s). I built a
    domain model (for the user management), a DAO Layer (using
    HibernateDaoSupport), a thin "Service Layer" that basically combines
    cross cutting DAO layer calls (to rolesDao, groupsDao, etc). Virtually
    everything is coded to interfaces (except the MVC stuff).

    I have a central User domain-object that implements IUser and describes
    the very basic user-account of the system (name, password, fullname,
    passwordhint, roles, etc.). So far so good, everything fine.


    Now i want to use the user management in a application that requires to
    have more domain-model data attached to the user object (imagine:
    language, timezone, Contacts, calculateShippingTo() and the like). My
    thinking was to create a interface say "IMyUser" that extends my generic
    IUser. The resulting implementation "User implementes IUser, IMyUser"
    is mapped with Hibernate and represents the domain object User for my
    specific application.


    This approach "cripples" my user management to a set of interfaces
    basically all to be implemented in the appliction. Though that is what i
    don't want to do for each app. Now, my ultimate goal is, that my user
    stuff is totally independent from the domain model of the application. So i
    can store my generic user data i.e. in a different database and the like.

    Any hints of how to approach this? Do i need to externalize the user
    management and communicate via messaging? This would result in sort
    of a shadow user in my app that carries a reference to a real user.

    I'd really appreciate your thoughts and hints.


    Andi

  • #2
    How about this:
    Code:
    IUser <--    IMyUser
       ^            ^
       |            |
    BaseUser <--    MyUser
    (the arrows indicates extends/implements)

    Comment


    • #3
      Hi Andi,

      if you have not read the 'SOA centralization harmful?' thread yet, please check it out, I guess you find it helpfull for your situation: http://forum.springframework.org/viewtopic.php?t=4325


      Any hints of how to approach this? Do i need to externalize the user management and communicate via messaging? This would result in sort of a shadow user in my app that carries a reference to a real user.
      User management/Identification is a very common problem. If you havent' done it yet, you might want to check out some other 3rd-party open source solutions. You may want to start your search with http://www.manageability.org/blog/st...n-in-java/view .

      Also being on the Spring framework page, you might have a look at Spring's solution Acegi Security. I guess if it meets your requirements, you might want to go with this one. (Sadly, I am not yet familiar with the Acegi framework to tell you more, but I guess some others will do it)


      Now, my ultimate goal is, that my user
      stuff is totally independent from the domain model of the application. So i
      can store my generic user data i.e. in a different database and the like.
      This is often desirable but not always necessary. If you simply want to add additional data, you might want to ensure the following contract to your User domain: Every user id is only used once in the entire lifetime of the system. With such a contract you can store additional user informations and need just a very few synchronization steps to react for delete user synchronization events. (I guess this is the natural way).

      But before you breed your own solutions, check out some of the open source implementations. Some allow you to store additional attributes for each user using Maps, property systems or even xml based sources or best of all allow a flexible adaptation according your needs.

      If you already did a look around and didn't found anything usefull, please tell us some more about your application and where the problem emerges and why.

      Comment


      • #4
        hey ml,

        thanks for your reply. yes that was a thought too. but the problem with this is that if i cast to IUser i don't have the business implemented in IMyUser. But IUser should be the holy grail. Plus i'd have to map my persistent BaseUser properties in the application via hibernate. hmm... but that would be ok, i think.

        i came up with a different thing. maybe this works:

        UserAccount implements IUserAccount
        ---------------------------------------------
        basic stuff like certificates, roles and the like. plus a reference to an IUser.

        User implements IUser
        -----------------------------
        application domain model stuff (calculateTax, getAddress(), etc.). Also holds a collection of IUserAccounts assigned to the IUser.


        The problem is that the IUser interface is part of the application's domain model and not known to the user manager. on the other hand if i include the IUser interface with the usermanager, i don't have the business when i cast to it. chicken on the egg...

        It would be cool if i could "shadow" my user managers IUser interface. I mean implement a domain model specific "IUser" extending my user manager IUser and the resulting IUser is also recognized by the user manager... hehe, i know i'm mad


        -andi

        Comment


        • #5
          Hi Martin,

          thanks for your detailed reply. I'm doing this stuff from scratch. It's a project for university it's not a requirement to do it like this but i'm just thinking if it's possible or makes sense.

          Sorry for the fuzzyness of my posts, it's hard to describe what i mean.

          I want to have a rich domain model that i use in my project (it's basically a shop type web application). I assume that in all domain models where user management if used, there is a User object (and related stuff) somewhere (coded to IUser). This is true for my shop application.
          I don't want to implement that user domain model (with roles, groups, etc) with each application domain model (shop application, blog application) . Instead i want a generic user domain model that i can plug in my application domain model.

          Therefore i have a interface IUser. The implementation of IUser should be half generic (loginname, passoword, etc.) and half application specific. In my application i want to have the IUser containing my business methods. The IUser of the user manager does not know about business logic.

          I use acegi security with a authentication dao that is using HibernateDaoSupport. That's not the problem. SSO is also not the problem so far.

          At the moment my IUser + implementation is part of the domain model of the application. So this is no problem and the usual way i did stuff with webapps - being it PHP or java.

          Now i want to go further and refactor out the basic stuff of the user management and having a generic user management for spring (with some SpringMVC controllers to edit/modify the user data like roles, validity enabled/disabled, passwords etc). So i can plug in the user management (with my user domain model) in different spring apps - respectively the relating domain model. (i don't need sso for now, with different i mean totally independent apps that don't have anything to do with each other).
          So i want to code to IUser everywhere. But my application-domain-model-IUser should also contain applications specific business.

          Huh, i hope i'm not telling no bullshit and wasting your time ...

          So maybe i just keep IUser arbitrary and implement it for each application with the concrete domain requirements.

          I'll check those references you gave me....

          -andi

          Comment


          • #6
            Hi Andi,

            reading your last post, I guess using a warper solution might provide you some value. Lets consider this type (interface) hierarchy:

            Code:
            interface IBasicUser &#123; 
                String getUserName&#40;&#41;;
            &#125;
            interface IDomainUser extends IBasicUser &#123;
               Address getAddress&#40;&#41;;
            &#125;
            Now we have a generic solution providing us with a basic user. To create a DomainUser we might use the warper implementation like this:

            Code:
            class DomainUser extends IDomainUser &#123;
                 private final IBasicUser warpedUser;
            
                 DomainUser&#40;IBasicUser warpedUser&#41; &#123;this.warpedUser=warpedUser;&#125;
                 String getUserName&#40;&#41; &#123;return warpedUser.getUserName&#40;&#41;;&#125;
                 Address getAddress&#40;&#41; &#123; ... &#125;
            &#125;
            This is quite a simple solution but I used it once, too (not in the user-domain but for language strings).

            It should also be possible to implement this, using Hibernate's split table mapping. Another idea would be using a split table mapping within Hibernate's mapping files. Therefore using a generic USERS table + a domain specific DOMAIN_USERS table for the application specific informations. Additionally you might also go for hibernate's polymorphism mapping. I guess it enables you, to use a split table version as well. I don't prefer using polymorphism when mapping to relational databases but it should be possible, if I remember it correctly. (never used Hibernate's polymorphism support that way)

            The only thing that might get into your way is the special case where a entry of the USERS table exist, but nothing within the DOMAIN_USERS. But this should be solvable never the less.


            Cheers,

            Martin (Kersten)

            Comment


            • #7
              Hi Martin,

              thanks very much for you input. i guess your propsed solution would work fine but it feels a bit kludgy putting things together like this. i don't like to use polymorphism with hibernate either - i did it one time though (with billing details just like in the caveat emptor).

              anyway, after reading the SOA thread and digging some more resources i think i gonna stick with the domain bound IUser. And just add CAS when i require SSO/Certificate stuff.

              Theres one paragraph of your first post i don't quite understand:

              This is often desirable but not always necessary. If you simply want to add additional data, you might want to ensure the following contract to your User domain: Every user id is only used once in the entire lifetime of the system. With such a contract you can store additional user informations and need just a very few synchronization steps to react for delete user synchronization events. (I guess this is the natural way).
              The contract you mention is clear. But the natural way of store additional info and synch. What do you mean by that? Do you mean the way you described it in the SOA thread? Say username is our natural key that never changes. Then i can keep the generic user info in a seperate database and my app specific stuff in another and use the natural key "username" to look up data? Then when the user, say is deleted, in the user manager datastore i just have to send a message to the application that the user has been deleted. Or vice versea: password updated. Is that what you mean?

              That sounds very good to me. I think it makes sense to use a natural key for the user. This would allow to still display a username (say for an author of an article) when the user was deleted but the article was kept (i mean physically deleted from the database). On the other hand it would be possible to do that with surrogate keys too (by adding a text field "username" to the table). Then again FK relationships are broken anyways. How do you handle this? Do you delete all the FK related rows too? I usually don't delete users but set a "deleted" flag.

              -andi

              Comment


              • #8
                Well to keep things simple. In this scenario we assumed that the user informations are sperated and stored into sperated databases. So you can not impose anythink like a FK constraint.

                Generally I ment that using a primary key, that does not change and never, ever gets recycled (reused) during the lifetime of the entire system is a very usefull and powerfull constraint.

                I think it makes sense to use a natural key for the use.
                I guess, I wasn't that clear about my thoughts then. I don't like to use natural keys. I like the primary key to only focus on the identity problem but having no semantical meaning at all. You know, semantic informations are representations of some real world stuff (not necessary meaning the physical world). And represenations are subject of change during a system's lifetime (for example changing the representation of a username in this case).

                About the natural way, I used it to express, that it is the an natural outcome an analysation of the problem. In world analysis (problem analysis if you mind) there are quite some concepts that drove me in that direction very quickly. Maybe using this term in that particular way, isn't natural after all but we often use it over here.

                One way to think about the given problem might be the use of functional dependencies and the imposed normalized forms:
                ( ttp://www.cs.sfu.ca/CC/354/zaiane/material/notes/Chapter7/node5.html , http://cs.gmu.edu/~aobaidi/spring-02/Normalization.ppt ). And a violation of those normalized forms normally also means: need of semantical and structural synchronization due redundancy, problems related to Atomarity and so on.


                I usually don't delete users but set a "deleted" flag.
                Using such a flag is quite common for synchronization cases or to support undo operations (or to save performance). But there is also time when you have to really delete a user - or better speaking you need to remove the stored informations. And that is the time where you need to synchronize the whole system to maintain a consistent state of your system (also of the database).


                Cheers,

                Martin (Kersten)

                Comment


                • #9
                  Hey Martin,

                  thanks for the clearification After grabbing a copy of "Domain Driven Design" and reading a bit I'm now back to fully integrating the User into the domain model. It's still usable for other projects, by stripping off the specific business logic.
                  I'm also using surrogate keys throughout entities (so username is mutable).

                  However, feeding my brain with so much info the past days new questions arise concerning best practices with layerd structures. At the moment i have DAO Interfaces and Hibernate specific implementations. I have the domain model (User, Role, Group, ...), a UserService and the web tier (Spring MVC).
                  The UserService implementation is quite thin and mostly delegates to the DAOs or domain model. It sends i.e. a e-mail confirmation if a user sigend up successfully (and was successfully created in the database using the dao). This happens in a transcation (applied through spring via AOP). DAOs are unaware of transactions.
                  The UserService is injected in my web-tier controllers, that call the usecases i.e. UserService.signupUser(IUser user). The web-tier uses the model directly to display things, and in simple cases to bind to it.

                  Now my questions:
                  1. Is it fine to do so ?
                  2. Using the model directly in the web tier. Good or evil. I read pros and cons, cons mostly because it's more work in sense of time to invest writing DTOs. I'm interested in the best solution of quality/abstraction/design. So good or evil?
                  3. If DTOs are used, how are they handeled? I mean do i pass them from the web-tier to the service or do i pass them to the model classes
                  4. What about DAO access in model classes. There's a thread where a hibernate interceptor injects dao stuff in the model objects that then again use it to look up things. It feels not very good to me, since the service should do those things.
                  5. The term Business Object seems to be used in different meanings. What is a business object? The service or a model enity class?
                  6. When I'm invoking business strategies on model objects should i do this via itermediate classes like:
                  Code:
                  scs = new ShippingCalculationStrategy&#40;&#41;
                  scs.setDomestic&#40;true&#41;;
                  scs.setExpressShipping&#40;true&#41;;
                  user.calculateShipping&#40;scs&#41;
                  or is this besser:
                  Code:
                  user.calculateShippingDomestic&#40;&#41;;
                  I tend to favour the first one. Should this happen in the web-tier (client tier) or in the service.

                  7. Interfaces. I'm used to code most of my classes to interfaces. Should I do that with my domain model too (an i.e. things the strategy stuff like described above or DTOs). Intefaces for all model classes could end up in many many classes. I've created interfaces for entity model classes only, not for the value object (i.e. TimePeriod would not have an interface since it's only a value object (VO in terms of Evans)). Good practice.

                  Huh, i think that are most of my q's right now. Most of it is basic stuff, but it's hard to find the right way with so much different opinions. Hehe, the more books i read the more questions arise, i should unlearn learning

                  -andi

                  Comment


                  • #10
                    Hi thyrell,

                    After grabbing a copy of "Domain Driven Design" and reading a bit I'm now back to fully integrating the User into the domain model.
                    This is a great book. Keep an eye for the bounded context. If you carefully watch it, you will see this pattern to appear nearly everywhere and on every level - projects/modules/packages/types/methods etc.


                    1. Is it fine to do so ? Wink
                    Sounds good. Watch for any dependency cycles in the type/class hierarchy (especialy in the type (interface) hierarchy). Also if the unit-tests are complicated, you know there is some sort of a problem. So if you extend your domain layer, just watch the unit-tests, they will tell you when you start to have an issue... .


                    2. Using the model directly in the web tier. Good or evil. I read pros and cons, cons mostly because it's more work in sense of time to invest writing DTOs. I'm interested in the best solution of quality/abstraction/design. So good or evil?
                    It depends. It matters what you really want to do with your model objects. As long as you use them for read only access, it is mostly an easy way to use them in a presentation layer (especially in a light weight presentation layer)

                    But if things get more and more complicated or you have co-developers developing the presentation layer on their on, you might want to go for some sort of protection. Protection comes here in form of a more strict separation of the presentation and the domain layers. If you need such a separation depends on the size of the projects and the number of teams, I guess.

                    I have seen such a separation only when there was a complex client application involved. For the client <--> server communication there is always some sort of strict separation and so this can be used by the domain layer<--> presentation layer communication as well.


                    3. If DTOs are used, how are they handeled? I mean do i pass them from the web-tier to the service or do i pass them to the model classes.
                    I don't like to use DTOs (or Data Objects - it doesn't matter for what purpose). If you analyse the scenarios when using DTOs, it often comes down, that these DTOs are only used to formulate a language (inter-module language). There are other ways to formulate a good language. Also there is a reason why we usally don't see the words of a page as being objects - (except when modelling the structure of a page, but this is a totally different task).

                    Other forms of formulating a inter-module language is by using special service interfaces or a special communication format (xml etc.). But DTOs often appear to be the easiest thing to start with, so it isn't that bad to go with DTOs until enough is learned about the certain inter-modul communication requirements and sometimes DTOs get never replaced... .

                    But yet again this depends and there are these nasty non-functional requirements, like performance and memory consumption or time to market etc, which will demand a solution that isn't ideal in terms of design or simplicity.

                    4. What about DAO access in model classes. There's a thread where a hibernate interceptor injects dao stuff in the model objects that then again use it to look up things. It feels not very good to me, since the service should do those things.
                    What is a model class for you? For example implementing a repository or a registry may be also part of the domain model. Check out the dependency graph of all domain types (classes/interfaces) and if there is a cycle you know you have a problem. But there are times a DAO needs to know more about the domain itself. I found that these logical cycles (DAO calles Domain Model Objects) is simply an expression that you don't have a DAO layer, but have several one supporting different parts of the Domain Model (modularization).

                    Also I think there are many possiblities to avoid such 'logical cycles' by using the strategy pattern or stubs or whatever. But I wouldn't consider it to be such harmful.


                    5. The term Business Object seems to be used in different meanings. What is a business object? The service or a model enity class?
                    Normally you can describe the task of an application using a certain language (or a certain model of thinking). For example, if you go for a billing application you may end up using some words like Bill, Customer, CreditCard etc. Such words stand for different concepts of thinking and there is a reason why there are special languages for special domains (physic-scientists may use other terms than therapists when speaking about the same thing).

                    So we may end with such a 'definition': A business object is an object that takes part in a business process. The sum of the required (necessary) business processes may fully describe the problem domain the application applies to.

                    This is how I have learned it, but there may be other distinction and if you speak about a business layer it may get a different meaning, so I am not sure about this.


                    6. When I'm invoking business strategies on model objects should i do this via itermediate classes like:
                    Code:

                    scs = new ShippingCalculationStrategy()
                    scs.setDomestic(true);
                    scs.setExpressShipping(true);
                    user.calculateShipping(scs)


                    or is this besser:
                    Code:

                    user.calculateShippingDomestic();

                    I tend to favour the first one.
                    By removing all the business semantic (generalize the code snippet), I end up with this:

                    Code:
                    strategy=new Strategy&#40;&#41;
                    strategy.setAttribute1&#40;true&#41;;
                    strategy.setAttribute2&#40;true&#41;;
                    object.calculateUsingStrategy&#40;strategy&#41;
                    This is about using the Strategy pattern, alright. The strategy pattern is for providing a plugable or interchangable mechanism to support a certain task of the main object.

                    Now lets remove the unnecessary implementation details:

                    Code:
                    strategy=new Strategy&#40;&#41;;
                    object.calculateUsingStrategy&#40;strategy&#41;
                    Now we apply something very useful. We simply go back a step in the evolutionary development of programming languages. We forget about OOP and do it totally procedural:

                    Code:
                    strategy=new Strategy&#40;&#41;;
                    object=new Object&#40;&#41;;
                    calculate&#40;object,strategy&#41;;
                    (This is a fine trick, I often use when thinking about where to place responsibilities.)

                    Now we have two chances to put the above code snippet back into the OOP world:

                    object.calculate(strategy); vs strategy.calculate(object);

                    Now lets put back our semantics (specialize):

                    Code:
                    shippingCalculationStrategy.calculateShipping&#40;user&#41; 
                    
                    vs.
                    
                    user.calculateShipping&#40;strategy&#41;;

                    So the question is: Should a user be responsible to calculate shipping costs?

                    Another good rule of thumb is: Simple design reduces the knowledge needed to (fully) understand each of its components. (a good indicator are coupling metrics by the way).

                    Trying to remove the necessary special knowledge about shipping from from the ShippingCalculationStrategy doesn't make any sense here. So only the User is left to give it a try. And we are in luck, it works well with the User. Now we end up favouring this one (at least I end with it of cause ;-)) :

                    shippingCalculationStrategy.calculateShipping(user )

                    The typical question after such a restructuring/refactoring: If the strategy now has the responsibility to calculate the shipping itself, is the name-part 'strategy' still sufficient to describe the object? -> No. So we have to rename this type.

                    Since objects should be named by their functionality (what) instead of the way the functionality is achieved (how), we abstract the semantic of the name. -> calculationStrategy.calculate(object) -> A better name would be calculator.calculate(object) -> Now we specialize again -> shippingCalculator.calculateShipping(user).

                    So everything ends with having one or more shipping calculators and a user object knowing nothing about shipping after all. (also we solved a dependency cycle here I guess).

                    (Calculating the shipping cost may be now considered to be part of the business logic (business (sub)layer) rather than the domain model.)


                    Should this happen in the web-tier (client tier) or in the service.
                    What do you exactly mean by 'Should this happen in the web-tier' ?


                    7. Interfaces. I'm used to code most of my classes to interfaces. Should I do that with my domain model too (an i.e. things the strategy stuff like described above or DTOs). Intefaces for all model classes could end up in many many classes. I've created interfaces for entity model classes only, not for the value object (i.e. TimePeriod would not have an interface since it's only a value object (VO in terms of Evans)). Good practice.
                    I use interfaces for value objects, too. I mostly find it preferable to stick to the factory pattern - using mostly static factories in terms of the value objects. I also simply like to refer to abstract types rather than concrete implementations. But this is a habit and there are other schools of thinking out there :-).

                    Comment


                    • #11
                      Hi Martin,

                      first thank you for taking the time to answer my questions in so much detail. Things are clearing up now. Most of the things i did before were database based where the model basically was a mirror of the tables. So i don't have experience with a rich Domain Model.
                      I also realize that he structure of my quick and dirty application (make it work first) was not soooo far from what it's becoming now again So I guess it's part of the learning process.

                      Regarding the DTO issue i have is basically the following. I use the domain model classes directly to display data, no DTO. That's not a big deal and I see that it does not make sense to create them.
                      But what about edit-cases. I have my web forms, realting controller and view. I started out using FormBeans to grab the inputs validating the from against a FormBeanValidator, when everything was OK modified my domain object in the controller, passed it to the service to save it. To my understanding the FormBean acts as a DTO in this case. Right?
                      Then I removed the form beans and bound to the model directly. After refactoring the model to be more OO-like (i.e. fromDate, toDate fields became a class TimeInterval and the like), i faced the problem that i needed public getters/and setters i just removed. Instead i intruduced "business logic" like i.e. updateValidity(TimeInterval). Now I can't bind to the model directly. So i reverted back to my FormBean that does that for me. In the controller i get the form bean and execute use cases through my service providing it with data from the form bean.
                      So my next thinking was to make the FormBean a generic DTO to bind to and use it. I need it anyways so why not make it generic and prepare to being able sending the data via SOAP or something . Hmm, now as I write this, the FormBean is form specific... so it makes sense to have it seperate. Hmm..

                      What is a model class for you?
                      A model class, for me, is a class that is part of the domain model and. either a entity or a value class used to describe the heart of my business. i persist my model classes feeding them to daos (hibernate using access=field).

                      The service as i understand it would handle all the business that i think does not belong to the model classes. i.e. sending a confirmation email via for example.

                      Dao(s), Model, Service(s) are part of the domain layer. whereas the model describes the heart of the business "mirroring" the real world, the dao is responsible for persistence and the service(s) do "workflow" and application realated tasks.

                      The client layer contains the user interface i.e. web application that interacts with the service(s).

                      At least that's how it feels most natural to me.

                      -------------

                      Strategy. Thanks for working this out! So in essence:

                      Now we specialize again -> shippingCalculator.calculateShipping(user).
                      woud be called in the business service, right? This is strange, caus when i did it first last week to get it work (before thinking about it to do it better), this was basically the way i did it.

                      What do you exactly mean by 'Should this happen in the web-tier' ?
                      I meant should shippingCalculator.calculateShipping(user) be called in the web-tier (in a controller). But that question is answered. It should go to the service in the use case that handles the "display shipping details for shippment" usecase or similar use case, right?

                      Thank you very much for your thoughts and insights. This brings me a step fruther in all those architecture questions.

                      -andi

                      Comment


                      • #12
                        To my understanding the FormBean acts as a DTO in this case. Right?
                        I would say right. Here is a quote I found at http://www.scioworks.net/camino_doc/...rmBeanDlg.html regarding to Struts FormBeans: "A FormBean (also known as ActionForm) is a JavaBean used by Struts to encapsulate and pass request parameters." But you can see it differently. Remembering the MVC? Try to apply the MVC pattern for a special form. You end up with the FormBean being the model of the form sub-system (module, unit or whatever). So is it really a DTO? Or is it just a model object of the form being reused as DTO? Is the model object is simply appearing as a DTO, because the form doesn't have additional knowledge to be put into its model object? Isn't the model of the form, the domain model of the form's domain? Isn't the FormBean an expression of the high abstractation level of the form solution?


                        But what about edit-cases.
                        Thats what always should be done by the domain layer (business+model). The domain layer knows best about the domain (and the used model). So if there is a need to modify the domain model the domain layer should be responsible, regardless wether a special service or a model object takes care for it.

                        So if you have a domain model protecting itself (do validation / not an anemic one), there is not much of a problem using the domain model object directly.

                        But you shouldn't develop anything doing a domain model modification without the domain layer being able to ensure validity and consistency (which is often similar). If you can ensure validity and consistency by calling the domain model object directly, it isn't that much of a problem.

                        Example:

                        user.updateAddress(Address newAddress);

                        -> Now the user is responsible for doing all the validation stuff.

                        If the user is anemic and we have a plain setAddress method, calling the anemic user.setAddress method becomes a trouble maker. That's why I would suggest to never expose anemic setter methods to another layer and to push logic as far in the model as possible. (If you want to reuse the parts of the model you may apply the onion model, and this is when thinking in model object vs service object tend to makes me crazy)

                        Using such an anemic setter involves the following contract: "Only set valid values, and after a 'transaction' is done the domain model (or better speaking the domain layer) should be in a consistent state.". This contract is a written one. Unless you can ensure consistency of your model by the datastore used, you are just hoping for every developer taking care for the contract. Mostly this complicate the user's use-case and makes you introduce a object taking care for the user. And this object becomes a domain object (since it is domain related) itself. At the end you end with domain model objects and other objects and the other objects only provide service for the user and do not represent data itself (session beans anyone?). -> So you see everything follows naturally by doing some very basic considerations: Who is using what and in what way? How I can ease the use for the user? (hiding informations, limiting the knowledge needed to understand the system) etc.


                        Hmm, now as I write this, the FormBean is form specific... so it makes sense to have it seperate. Hmm..
                        The FormBean is existing because of design decisions related to the architecture (the user of the implementation use it, so it is an architectural issue). If your domain model objects are smart enough, you may even survive with using the domain model objects as FormBeans (directly or using an adapter).

                        But now your form must be able to understand business exceptions in case of a validation problem. To make a form understanding business language, you have to put business knowledge in it (adapter, bridge etc). So you complicate the form logic. But if you did a good work on abstracting the business knowledge, hey you can go with it. It is a special form you are implementing anyways.

                        So this is a design decision you should make under the complexity control aspect. -> your unit-tests will tell you, just watch the language you use to formulate your unit-tests.


                        A model class, for me, is a class that is part of the domain model and. either a entity or a value class used to describe the heart of my business. i persist my model classes feeding them to daos (hibernate using access=field).

                        The service as i understand it would handle all the business that i think does not belong to the model classes. i.e. sending a confirmation email via for example.
                        Don't bother yourself with the distinction of service object vs. model object that much. Every model object can be seen as declaring a very limited service by itself. (remember you can extract an abstract class from a concrete class, thus you can extract an interface from it as well). Where to introduce a 'true' service is mostly driven by other design decision like hiding details, reduce couplings and dependencies (and therefore hiding special knowledge) etc.

                        A little example:

                        A domain requires the exisitence of a User object. The User objects are stored in a collection. To access this collection we define an object called UserManager. Now is the UserManager a domain model object or a service object? If (business) service object is your answer, does your answer change, if we rename the UserManager to UserRepository or UserRegistry? How about UserStore?

                        But when to introduce a business interface? Every time you want to abstract and simplify the use. Remember the 'Hide 3rd party libraries behind fascades' idea. Also who is implementing that business interface? A domain model object? Maybe... .

                        I don't design a system by thinking about service or model or anything like that. That is something that forms quite natural when packaging is done. And there are rules (or better advises) of how to package a given collection of objects (classes/interfaces). And doing so - guess what - at the end you see the separation of domain model objects vs business objects. It comes really natural. No need to think about it, when doing a design. Even thinking about domain layer, persistence layer, presentation layer or talking about any tier is something that is related to concepts of simplifying a design (except you fiddle with a framework imposing strict requirements like EJB's session vs CMP beans).

                        When I got familiar with Hibernate for instance, all my knowledge about JDBC and DAO etc. was a burden. It had lead to something the unit-tests told me to be wrong (unnatural). And when I looked at the dependencies and the knowledge involved in each object, I had to admit that the unit-tests were right.

                        The client layer contains the user interface i.e. web application that interacts with the service(s).
                        Well first of all I wouldn't use the term 'client' in conjunction with 'layer'. I like presentation layer instead, but this is also a problem since a presentation layer involves more than just presenting something. So it is really a matter of language terms anyways (maybe a presentation layer would be better called user-interface layer).

                        The problem with the above statement is interacting with services. It is better to say 'web application that uses services'. I like to say 'use' to indicate the dependency direction. The application may depend on the used service but the service does not (or better should not (yet again check out the packaging rules). Using the term interaction is not that specific and may lead to a thinking that might be cause a restructuring.

                        But you are right here. The question is if the service is s real business service object or if it is something realised by a domain model object. It is tricky and just depends on the situation. Often you can push this service functionality even further towards the domain model objects (Onion model helps you here).


                        woud be called in the business service, right? This is strange, caus when i did it first last week to get it work (before thinking about it to do it better), this was basically the way i did it.
                        I wouldn't call it a business service. You know the question is, who uses the calculator? Is the calculator exposed to the outside of the domain layer? The calculator encapsulate knowledge of the business domain (how to calculate shipping costs), and therefore abstracts this knowledge - you only have to think about a calculator and not about shipping cost calculation details.

                        But who will use it and in what situation? Using the right calculator involves additional knowledge. You have to be aware about the situation where to apply the different calculators. So I guess the users of the domain layer are not much likely to face each of the existing calculators.

                        It is even questionable if the other parts of the domain layer will use calculators in a special way. (watch for dependency cycles between the parts/modules of the domain layer here). So I guess there will be a special object abstracting encapsulated knowledge of the different calculators.

                        Thinking more about this, I guess this whole service object vs domain model object comes from the EJB world. I would simply call it a domain object and a domain object may be a special one, being called domain model object. But service vs model is a bit more to strict and not everything that is not about model is a service in my opinion. So there is something in between.

                        Again this all is related to complexity management. It isn't something that exclusively applies to OOP. You find this in assembler programs, too. ;-)


                        It should go to the service in the use case that handles the "display shipping details for shippment" usecase or similar use case, right?
                        Use-cases are cases of use. Therefore a use-case imposes requirements toward the system (or better a part of the system). Also a use-case of a domain layer can be a use-case where the presentation layer is the user... . So this is something, where you might stumble if you do not watch it carefully.

                        By the way using UML you see that a use-case can be described using the 'includes use-case' term. So you can compose a use-case by using other use-cases.

                        Decomposing use-cases gives you a great opportunity to formulate the particular responsibilities of each layer /part /object of your system. (and from there you can derive the needed inter-layer/inter-part/inter-module/inter-object/inter-method interfaces (don't get tricked by the word interface here, it does not mean the Java interface concept. I really don't like tp use the term interface in Java terms).

                        Use-cases are just a way to think about the tasks and the involved sub-tasks for the system (each sub-task comes in form of (sub) use-cases of cause). Use-cases are one of the most abstract views you can have about a system. From the use-case analysis you can derive the achitectural requirements (therefore the architectual design). From architecture you can derive the implementation requirements (therefore the implementational design). And so on.

                        So even if you implement a method (or a field), ask yourself the following questions: Who is the user? What use-cases exist? Can I put additional knowledge in this method to simplify the use-case from the user's point of view? (Answering the last question this is a point when type hierarchies are born in a natural way).

                        Thank you very much for your thoughts and insights. This brings me a step fruther in all those architecture questions.
                        It is a good training for me to answer questions in a more detailed manor (often I end up writing to much, since this keeps me also thinking...).

                        Also I try to get as far away from design-pattern as possible. I don't like thinking in design patterns. It tends to make me blind for other possible solutions. (and like other people already reported, this is something others experienced as well). And answering questions gives me a great opportunity to control myself and force me away of design-pattern thinking.

                        And of cause it makes me happy if I can serve you while doing this. :-)


                        Cheers,

                        Martin (Kersten)

                        Comment


                        • #13
                          Hi Martin,

                          Thats what always should be done by the domain layer (business+model). The domain layer knows best about the domain (and the used model). So if there is a need to modify the domain model the domain layer should be responsible, regardless wether a special service or a model object takes care for it.

                          So if you have a domain model protecting itself (do validation / not an anemic one), there is not much of a problem using the domain model object directly.

                          But you shouldn't develop anything doing a domain model modification without the domain layer being able to ensure validity and consistency (which is often similar). If you can ensure validity and consistency by calling the domain model object directly, it isn't that much of a problem.
                          Agreed. That's how i want to have it. But therefore I need a FromBean to collect the values that are set on the model via, say updateAddress(). There's no other way, unless i provide anemic setters so i can bind to the model directly. But i don't like that. So i need to process the FormBean in the MVc controller setting the new address on the model and saving it (or present errors to the user to correct things).


                          A little example:

                          A domain requires the exisitence of a User object. The User objects are stored in a collection. To access this collection we define an object called UserManager. Now is the UserManager a domain model object or a service object? If (business) service object is your answer, does your answer change, if we rename the UserManager to UserRepository or UserRegistry? How about UserStore?
                          No it would not change. If the functionality would be the same. But it UserManager would execute business specific logic (like calculating shipping or the like) and UserRepository would not, i'd not go so far calling UserRepository a business service.

                          Well first of all I wouldn't use the term 'client' in conjunction with 'layer'. I like presentation layer instead,
                          yeah, my bad. let's call it client application.

                          So even if you implement a method (or a field), ask yourself the following questions: Who is the user? What use-cases exist? Can I put additional knowledge in this method to simplify the use-case from the user's point of view? (Answering the last question this is a point when type hierarchies are born in a natural way).
                          I'm usually writing story cards that are non-technical at all. from this point on i find the solution for the problem to get it work (that's an oversimplification of the process, but thats my basic mode of working).

                          but i realized i was building anemic domain models built on clean normalized RDBMS tables. and doing validation and all the stuff in the web-application.


                          ...
                          And of cause it makes me happy if I can serve you while doing this. Smile
                          hehe, glad to hear i'm not buggin' you.

                          -andi[/quote]

                          Comment


                          • #14
                            There's no other way, unless i provide anemic setters so i can bind to the model directly.
                            So it comes down that you are adapting your implementation to meet some framework constraints. So you can are not free to choose freely.


                            But i don't like that. So i need to process the FormBean in the MVc controller setting the new address on the model and saving it (or present errors to the user to correct things).
                            Now that's what I ment with forming natural. You always have some choices where to put responsibilities. The FormBean seams like a representative. The FormBean seam to have diffrent responsibilities than a domain object would have, right? So you protect your domain object from mutating into a jack-of-all-trades. So in this case, a domain object would just not fit the picture.

                            So I wouldn't call the FormBean a Data Object at all. I guess you just failed to add required logic to it. Does you extend your FormBean from an abstract class by the way?


                            No it would not change. If the functionality would be the same. But it UserManager would execute business specific logic (like calculating shipping or the like) and UserRepository would not, i'd not go so far calling UserRepository a business service.
                            What is business specific logic for you?


                            I'm usually writing story cards that are non-technical at all. from this point on i find the solution for the problem to get it work
                            Nice. Would like to see your story cards. Also I guess you put quite afford into your story cards. So it wouldn't be unlikely that you can reuse them.

                            I also use something not that common I guess. I go for pattern languages. (not design pattern, just generally what a pattern is etc). It serves me very well.

                            (that's an oversimplification of the process, but thats my basic mode of working).
                            Nope, I do not think you are oversimplify the process here. You know every minute you spend on thinking, is an hour less of writing code ;-). People sometimes look me straight in the face, when I say: "lets make a pattern language". So if it helps you, just stick with it as long as you are open-minded. I am currently using a mix of use-case analysation and pattern-languages, but this might change sometime, too.

                            So it is nothing wrong with it, really! :-)


                            Cheers,

                            Martin (Kersten)

                            Comment


                            • #15
                              First, sorry for the delayed answer. I had no time for the private project the past days... anyway...

                              So it comes down that you are adapting your implementation to meet some framework constraints. So you can are not free to choose freely.
                              Not really. I can choose. It's a not a money project or something. I'm doing this mainly for personal research and as a project at university. The only "frameworks" i'm using right now are spring, hibernate, acegi running in resin.

                              So I wouldn't call the FormBean a Data Object at all. I guess you just failed to add required logic to it. Does you extend your FormBean from an abstract class by the way?
                              No, not at all, it's a simple getter/setter bean that collects form values. Can't post ist since i'm at work and i don't have the code here.

                              My story cards are nothing special. They're mostly user orienend and read i.e. "A web user can log on the system by clicking on a log on button/topic. he must provide his username and password. if the user authenticated successfully a additional menu iteam "myXYZ" appears in the main navigation. also, a log-off entry is displaying." Priority: 2, Due: may, 5th 2005.

                              Stuff like that. I'm not going for reusabilty, but for simple descriptions what the software should do for this specific case. though, the above example is sort of reusable, at least the text - i'm writing on real paper cards btw. wich i found much more effective than doing it in files or something. you virtually see the progress.

                              nope, I do not think you are oversimplify the process here. You know every minute you spend on thinking, is an hour less of writing code Wink
                              yep, that's true. usually the cards are just implemented without thinking much about the architechture up front. resulting in heavy refactoring all the time. most of the php projects were database based and the controller was basically executing most of the business logic.

                              So it is nothing wrong with it, really! Smile
                              That's fine

                              One more thing. The DAO abstraction spring provides, and how it is commonly put to use with a data mapper (especially Hibernate). Too me it actually sounds exactly what Evans describes as a Repository. A object that is responsible for reconstructing and persisting entities. I'm just courious.

                              -andi

                              Comment

                              Working...
                              X