1

I have a helper class which has a method that perform some checks against a field in a model. I have two models, ModelA and ModelB, they have some similarities but not all. One of them is they both have a field, lets say string ProductCheckField. The ProductCheckMethod returns back the Model, because of that it has created duplication of methods which does the same thing but returns a different model. Even the extracted methods are duplicates. Is there a good design pattern or any other good practice/technique I can use to eliminate duplication of having to create two methods?

N.B I can't use a shared Interface as the models are not the same.

Currently I have..

public class ModelA
   string blah..
   int blah
   .....
   string ProductCheckField


public class ModelB
   string xyz
   int xyz
   .....
   string ProductCheckField

public class HelperClass
{

    public ModelA ProductCheckMethod(ModelA model)
    {
       /// do somthing
       performX(model);
       checkY(model);
       return model;
    }

    public ModelB ProductCheckMethod(ModelB model)
    {
       /// do somthing
       performXDuplicate(model);
       checkYDuplicate(model);
       return model;
    }
}
  • Why does check return the model? – Telastyn Jan 14 '15 at 17:40
  • @Telastyn Because as part of the check it updates the model and returns back – user4453701 Jan 14 '15 at 17:44
  • Okay, so if ModelA and ModelB have duplicate checks, why are the duplicate bits not shared in some third class? – Telastyn Jan 14 '15 at 17:48
  • @Telastyn Because you will be passing in the model to perform those check. Therfore, even if they are in a third class it will still need a model passed in. And as mentioned, these models are different apart from some of the fields – user4453701 Jan 14 '15 at 17:50
  • 1
    Sure, but if "some of the fields" are put into a common class, they could be checked using the same function, instead of duplicating check(modelA.X); check(modelA.Y), check(modelB.X); check(modelB.Y) and the such. Without more concrete examples, it's hard to say. – Telastyn Jan 14 '15 at 17:53
0

What you have shown of the Models shows the same interface. So your protestations of differences are unsupported by the example you give. I suggest you wrap the fields you check in performX and checkY with accessor methods that are commonly named across model A and B and extract a common interface for the use of your Helper class.

public interface CheckModel
{
    public String getStringValue();
    public void setStringValue(String blahs);
    public int getIntValue();
    public void setIntValue(int blah);
    public String getProductCheckField();
    public void setProductCheckField(String productCheckField);
}

public class ModelA implements CheckModel
{
    String blahs;
   int blah;

   String ProductCheckField;

   public String getStringValue()
    {
        return blahs;
    }

    public void setStringValue(String blahs)
    {
        this.blahs = blahs;
    }

    public int getIntValue()
    {
        return blah;
    }

    public void setIntValue(int blah)
    {
        this.blah = blah;
    }

    public String getProductCheckField()
    {
        return ProductCheckField;
    }

    public void setProductCheckField(String productCheckField)
    {
        ProductCheckField = productCheckField;
    }

}

public class ModelB implements CheckModel
{
    String xyzs;
   int xyz;

   String ProductCheckField;

public String getStringValue()
{
    return xyzs;
}

public void setStringValue(String xyzs)
{
    this.xyzs = xyzs;
}

public int getIntValue()
{
    return xyz;
}

public void setIntValue(int xyz)
{
    this.xyz = xyz;
}

public String getProductCheckField()
{
    return ProductCheckField;
}

public void setProductCheckField(String productCheckField)
{
    ProductCheckField = productCheckField;
}
}

public class HelperClass
{

    public CheckModel ProductCheckMethod(CheckModel model)
    {
       /// do somthing
       performX(model);
       checkY(model);
       return model;
    }

    private void checkY(CheckModel model)
    {
        // ...
    }

    private void performX(CheckModel model)
    {
        // ...
    }

}
2

You seem to have some sort of mental block going on. If you want a design that eliminates the duplication, you're going to have to change your design somehow, which you seem resistant to do. You need to look past your current design.

Some ways to eliminate the duplication, some of which are better than others:

  • Put the common stuff of the models into a common class, with your models containing a reference to that object, as Telastyn suggested in the comments.
  • Reverse of Telastyn's suggestion, where you have a ProductCheckStuff class, with pointers inside it to one of the models.
  • Use generics in HelperClass or its methods, with the model as the generic parameter.
  • Have each model implement an interface with getters for the fields you need.
  • Extend the model from a base class that implements the ProductCheckMethod.
  • Put the product check fields and methods into a mixin (if your language supports it) that is mixed in with the other fields of your model.

You can't make an omelette without breaking some eggs. You have a ton of choices here. Keep trying them until you find one that works.

0

It's hard to understand fully what you need done here. It looks like you MIGHT have a case for the Visitor pattern but you said you can't use the same interface.

The only other alternative would be the Strategy pattern where the CheckMethod would be implemented in a strategy class for each Model and instead of the overloaded methods you can use generics to map the Model to the strategy.

public class HelperClass
{
  public T CheckMethod(T model)
  {
    var strategy GetStrategyFor(typeof(T));
    var result = strategy.Execute(model);
    return result;
  }
}

You could use an IoC container or other methods for determining how a type maps to a given strategy. But once you've done that, you can add new models and matching strategies to your heart's content.

0

With the constrints you having (unable to use a common interface) for ModelA and for ModelB, there isn't a lot of things you can do from the Models. However you could generalize the helper class.

One way to do is,

public class RequestDTO
{
   string xyz_blah;
}

public class ResultDTO. 
{
   string ProductCheckField; 
}

public class HelperClass
{
    public static ResultDTO ProductCheckMethod(RequestDTO request)
    {
        //do something
        ResultDTO result = performXUsingRequestData(model);
        checkYUsingRequestData(model,result);
        return result;
    }       
}

Here the data you currently sending to the methods performX,checkY are added to the RequestDTO and whatever the data you want to update on the model are added to the ResultDTO.

In your model you could call the helper class like this,

public class ModelA
{
   string blah..
   int blah
   .....
   string ProductCheckField

   public void ProductCheckMethod()
   {
       RequestDTO dto = new RequestDTO { xyz_blah = blah; }
       ResultDTO result = HelperClass.ProductCheckMethod(dto);
       ProductCheckField = result.ProductCheckField;
   }
}

Same goes for the ModelB

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.