Domanda

I am working on a standard Spring application where DAO layer returns entities to service layer and service layer returns VOs to other services and controllers.

In a certain scenario, we have a VO that looks like this:

public class MyContainerVO{
    private Integer containerId;
    private String containerName;
    private List<ContainerChild> childList;

    //usual setters and setters

    public Map<String,String> getChildMap(){
        //creates a K,V map from the child list
        //with the key being child.getName() and value being child.getId()
    }
}

I am confused whether this method getChildMap() should be in MyContainerVO or should it be moved to a utility class. I know that there should not be any business logic in the VO, but in my opinion the getChildMap() method only returns the data contained in MyContainerVO in a different format and thus does not qualify as business logic.

I could not find any answers in SO or programmers that deals with such scenario; most are about business logic in VOs that hit other classes creating close coupling which is a bad practice.

Kindly suggest what is the best approach in this scenario, or please point out some link that explains this in detail.

È stato utile?

Soluzione

On the first sight I think it should stay in the Value Object because of cohesion and encapsulation principles - getChildMap() method implementation is intimately connected to the implementation of MyContainerVO object so it should stay inside this object without necessarily exposing the implementation details (childList).

The problem here is that it's not really clear what MyContainerVO is and how is it used. For example, if List childList is commonly used outside of the MyContainerVO and we often need to get its childMap, we could make a case for creating Utility method for the conversion to map and use it everywhere to be consistent ... (or maybe creating Value Object just for this childList which would contain this method).

Altri suggerimenti

Since the childList field is private, a method must be in MyContainerVO somewhere.

However, if the functionality to convert a Collection of ContainerChilds into a Map, based on various keys, is a useful general purpose utility, I would make it a static method of ContainerChild. e.g.

public static Map<String,String> nameIdMap(Collection<ContainerChild> c);
public static Map<String,String> nameFooMap(Collection<ContainerChild> c);

Since this utility is a method of ContainerChild, it knows about the fields of ContainerChild. Obviously, if this function list became extremely large, you might pass the keys as parameters, use new fangled Java 8 closures, some pattern, etc...

Then, your actual code in MyContainerVO delegates all the logic to the utility.

 public Map<String,String> getChildMap(){
   return ContainerChild.nameIdMap(this.childList);
 }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
scroll top