Is it okay to use Value Object that cross layers?

Discussions

EJB design: Is it okay to use Value Object that cross layers?

  1. Is it okay to use Value Object that cross layers? (8 messages)

    Hi,
    I have a design issue here. I understand that Value Object pattern is used to minimize network calls to send and retrieve data to and from the Entity Beans.

    My current architecture has 3 layers:
    - Presentation - JSP/Servlet
    - Business - Session Bean
    - Domain - Entity Bean

    Currently, my application's packages goes like:
    com.mycompany.ejb.myejb1
    com.mycompany.ui.myui1
    ...and so on..

    The Value Objects resides in the EJB packages. I found that, if I do this, I'll be coupling the Presentation layer tightly to the Business/Domain layer, even though I have Business Delegate to separate the Presentation to the Business layer.

    My team brainstormed and came up with a few suggestions:

    1. Have an exact Value Object that resides in both the Business/Domain layer and also the Presentation layer. For example:
    com.mycompany.ejb.myejb1.VO1
    com.mycompany.ui.myui1.VO1

    Use the Business Delegate to deal with it. Should there be any changes to any of the layers, the other layers are shielded from changes and also package dependencies.

    However, there is duplicated work and duplicated codes to maintain.

    2. Create a totally new package as below and place all these Value Objects under it.
    com.mycompany.general.vo.VO1

    Using this method tackles the duplicated codes and maintenance issue. However, now the Value Objects are vulnerable to misuse. For example, if someone change the values in the Presentation layer, it could cause some undesirable result if the Business/Domain layer requires the same values again.

    Any suggestions?

    Thanks.

    Wing Hoe
  2. You hit on the two main ways to package value objects:

    1) put the VOs in a parent package, com.mycompany.VO1
    2) put them in a sibling package, com.mycompany.vo.VO1

    where the technology would be, com.mycompany.ejb.EJB1


    I would also add that, when designing your package hierarchy, you avoid detailing the technoloogy packages (ejb, ui, etc.) until you have completed your domain packages (see example below). This method allows for a cleaner package structure later on when you need to expand or add new business domains.

    Example:

    /* ejb that is applicable to the whole company */
    com.mycomany.ejb

    /* ejb that is applicable to Business Domain One (can reference things in com.mycompany.*) */
    com.myComany.domainOne.ejb

    /* ejb that is applicable to Sub-Domain One (can reference things in com.mycompany.*, com.mycompany.domainone.*) */
    com.myComany.domaintOne.subdomainOne

    /* ejb that is applicable to Sub-Domain One (can reference things in com.mycompany.*, com.mycompany.domainone.*, but NOT Sub-Domain One) */
    com.myComany.domaintOne.subdomainTwo
  3. Whoops! that last one should read:

    /* ejb that is applicable to Sub-Domain Two (can reference things in com.mycompany.*, com.mycompany.domainone.*, but NOT Sub-Domain One) */
    com.myComany.domaintOne.subdomainTwo
  4. Hi Justin,
    Thanks for replying.

    I have another package that is not tied to any technology packages such as ejb,ui,etc. It looks like:

    com.mycompany.general.vo

    where I'm thinking of placing these VOs into this package.

    I have another library jar that should contain base classes, like exception superclass, formatting classes, utilities and so on, in:

    com.mycompany.base.exception
    com.mycompany.base.format
    com.mycompany.base.dbsupport
    com.mycompany.base.util
    ....

    Back to the VO question, as you have suggested,
    --------------
    1) put the VOs in a parent package, com.mycompany.VO1
    2) put them in a sibling package, com.mycompany.vo.VO1
    --------------
    Which one would you use? I believe either one will separate these VOs from either layers right? Thus, I'm able to use it from Presentation layer all the way to the Domain layer yes?

    Thanks.

    Wing Hoe




  5. I would create a sperate class which does the mapping between entity and the VO.This class could act like a factory and create value objects.
  6. Neeraj,
    Are you talking about the Data Transfer Object Factory pattern?

    Do you think you can provide some sample codes? I'm kind of lost about this pattern.

    Oh, we still need to create specific VOs with specific setter methods to store the data acquired from the Entity Bean and specific getter methods to retrieve the data by the client right?

    Wing Hoe
  7. I'm not quite sure what Neeraj is talking about either. Since there is a tightly coupled relationship between a VO and it's EntityBean, I really don't see the applicability of a mapping or factory system.

    Though I would suggest that if you find you need to replicate the basic structure of your data in multiple implementations (i.e. EntityBean, VO, Struts ActionForm) then you might want to have all of them implement a common interface.


    Example:

    package com.mycompany.accounting;
    public interface Invoice
    {
    //method signatures, mainly getX() and setX() methods
    }


    package com.mycompany.accounting.ejb;
    public class InvoiceBean
    implements javax.ejb.EntityBean, com.mycompany.accounting.Invoice
    {
    ...
    }

    package com.mycompany.accounting.vo;
    public class InvoiceVO
    implements com.mycompany.accounting.Invoice
    {
    ...
    }

    package com.mycompany.accounting.ui;
    public class InvoiceForm
    extends org.apache.struts.action.ActionForm
    implements com.mycompany.accounting.Invoice
    {
    ...
    }
  8. I prefer to have to VOs in a siblng package:

    com.myComany.ejb
    com.myComany.vo
    com.myComany.ui

    com.myComany.domainOne.ejb
    com.myComany.domainOne.vo
    com.myComany.domainOne.ui

    com.myComany.domaintOne.subdomainOne.ejb
    com.myComany.domaintOne.subdomainOne.vo
    com.myComany.domaintOne.subdomainOne.ui
  9. I Strongly agree with Justin on package declaration

    Raj