Page 1 of 4 123 ... LastLast
Results 1 to 10 of 39

Thread: Generic User Management conflicts with Rich Domain Model

  1. #1

    Default 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. #2
    Join Date
    Oct 2004
    Location
    Herndon, VA, US
    Posts
    648

    Default

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

  3. #3
    Join Date
    Aug 2004
    Location
    Germany, Magdeburg
    Posts
    279

    Default

    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.

  4. #4

    Default

    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

  5. #5

    Default

    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

  6. #6
    Join Date
    Aug 2004
    Location
    Germany, Magdeburg
    Posts
    279

    Default

    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)

  7. #7

    Default

    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

  8. #8
    Join Date
    Aug 2004
    Location
    Germany, Magdeburg
    Posts
    279

    Default

    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)

  9. #9

    Default

    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

  10. #10
    Join Date
    Aug 2004
    Location
    Germany, Magdeburg
    Posts
    279

    Default

    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 :-).

Similar Threads

  1. Problem with HibernateInterceptor
    By prane in forum Data
    Replies: 5
    Last Post: Oct 16th, 2007, 08:01 AM
  2. Replies: 2
    Last Post: Oct 10th, 2005, 05:12 PM
  3. could not satisfy dependencies
    By springuser in forum Container
    Replies: 4
    Last Post: Apr 26th, 2005, 01:15 PM
  4. Replies: 1
    Last Post: Apr 25th, 2005, 07:37 PM
  5. Content Provider vs View Model
    By Martin Kersten in forum Swing
    Replies: 21
    Last Post: Mar 10th, 2005, 02:25 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •