简体   繁体   中英

How can I refactor a JAVA method that returns a nested MAP?

public Map<product, SortedMap<Date, ServiceInterval>> getServiceInterval(
            Contract pContract, BillCycle pBillCycle)
    {
        Map<product, SortedMap<Date, ServiceInterval>> returnMap = new HashMap<>();

        List<product> productList = getAllproducts(pContract);

        for (product product : productList)
        {
            Date billingDate = getBillingDate(product);

            createReturnMap(
                    product, returnMap,
                    billingDate, pBillCycle);
        }

        return returnMap;
    }

I was asked to refactor this method (simplified here) because:

Such complex type should not be used in interfaces. Besides it makes the code difficult to debug. The implementation should be hidden in the class.

I am not sure it makes sense to refactor this.

Do you agree that is worth refactoring this method?

If yes, what approach would you use? How can one make this easier for debugging?

Thanks

You could replace the nested Map with your own class, eg Services that offers the methods the callers need. This class will most likely use or extend a Map. The signature then becomes

public Map<Product, Services> getServiceInterval(Contract pContract, BillCycle pBillCycle)

It makes the code a little easier to read but you are spending development time and effort on it, while most likely not adding much functionality to it. Might make sense if the Services class could be extended with additional logic. Really hard to say without knowing more details.

public Map<Product, SortedMap<Date, ServiceInterval>> getServiceInterval(
            Contract pContract, BillCycle pBillCycle)

Such complex type should not be used in interfaces. Besides it makes the code difficult to debug. The implementation should be hidden in the class.

I agree. If the service is provided to another client class, it may be cumbersome to use the returned object which is a map of map. So, you could use wrapper for your maps by providing a basic way for client classes to retrieve a ServiceInterval instance matching to input parameters : so containing a getServiceInterval() method in the returned object : public ServiceInterval getServiceInterval (Product product, Date date)
I propose product and date as input parameter as it's how you set your map of map :

Map<Product, SortedMap<Date, ServiceInterval>>

It's pseudo code written on the fly, just to show the idea:

public ServiceIntervalByProduct getServiceInterval(
        Contract pContract, BillCycle pBillCycle)  {
    ServiceIntervalByProduct  returnMap = new ServiceIntervalByProduct();

    List<product> productList = getAllproducts(pContract);

    for (product product : productList)
    {
        Date billingDate = getBillingDate(product);

        createReturnMap(
                product, returnMap,
                billingDate, pBillCycle);
    }

    return returnMap;
}

// First level Wrapper class
public class ServiceIntervalsByProduct{

  private Map<Product, ServiceIntervalsByDate>> mapByProduct;   

  public void add(Product product, Date date, ServiceInterval serviceInterval) {
   // add in inner map
  }

 public ServiceInterval getServiceInterval (Product product, Date date){
   // get from inner map
    return mapByProduct.get(product).getServiceInterval (date);    
 }
}


// Second level Wrapper class
public class ServiceIntervalsByDate{
  private  SortedMap<Date, ServiceInterval>> mapByDate;

  public void add(Date date, ServiceInterval serviceInterval){
   // add in inner map    
  }

  public ServiceInterval getServiceInterval (Date date){
   // get from inner map
    return mapByDate.get(date);
   }

}

I provide add() methods in the wrappers but you can gather all needed data in a constructor if you want to protect data modifications from client classes.

Looking on provided example I don't see any reasone to have nested map at all. As I see from code you have only one billing date per product, so your nested map will have only one element for each product. To make things simpler just create one more class wich wll hold billing date and ServiceInterval , let's call it BillingServiceInterval and return Map<Product, BillingServiceInterval> from your method. Hope this helps

In case for each product you get one Date and one ServiceInterval you could create a simple bean. The method would return a collection of your choice of such beans.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM