Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method Parameters vs Parameter Object

I'm trying to build a framework that allows people to extend our core functionality by implementing an interface. Below is a dumbed down example of this interface.

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3);
}

Recently, we've decided to modify this interface (I know I shouldn't break dependent code, but the truth is we don't have any 3rd parties implementing this interface yet, so we have a chance for a "do-over" to implement this interface correctly).

We need to add 2 more parameters to this interface for our software to work correctly. Two ways we're thinking of are just adding them to the signature like this:

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3, bool p4, DateTime p5);
}

or by creating a parameter object like this

public class MyParameters
{
    public bool p4 { get; set; }
    public DateTime p5 { get; set; }
}

and adding them to the end of the method like so:

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3, MyParameters p4);
}

I'm looking for some sort of guidance on which way is the "most" correct way to proceed. I can see pros and cons in both categories, but I don't want my biases to lead me down the wrong path.

Some of my main concerns are:

  • Extensibility of the software - I want the user to be able to do things I haven't thought of yet by implementing the interface
  • Maintainability - Ideally, I'd like to never have to touch the code that is responsible for calling GetData() again
  • Clean API - I don't want the solution I arrive at to make a 3rd party developer cringe

I don't even know what question to ask online to get guidance for this issue. I have a feeling that the answer is "it depends" (on things like how related p1-p5 are to the purpose of the GetData() function), but can someone point me to a list of questions I should ask to help me evaluate whether one solution is better than the other?

Related: Post 1 Post 2

like image 811
Michael Avatar asked Dec 19 '12 05:12

Michael


People also ask

What is the difference between parameter and method?

A parameter is a variable in a method definition. When a method is called, the arguments are the data you pass into the method's parameters. An alliterating mnemonic that may help: Arguments are Actual. ;) "You define parameters, and you make arguments."

What is a parameter object?

The Parameter Object is simply a wrapper object for all parameters of a method. It is nothing more than just a regular POJO. The advantage of the Parameter Object over a regular method parameter list is the fact that class fields can have default values.

Can a method take an object as a parameter?

You can use any data type for a parameter of a method or a constructor. This includes primitive data types, such as doubles, floats, and integers, as you saw in the computePayment method, and reference data types, such as objects and arrays.


2 Answers

Let me try to answer this. Let's evaluate your options:

1) If the below interface

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3);
}

is broken:

a) and shouldn't be used at all, then you should force the implementors to rewrite it. So change the method definition.

public interface MyInterface
{
    IData GetData(something else);
}

b) but you only need to encourage the users to use new definition, then you can create a new overload telling them the first one is obsolete.

public interface MyInterface
{
    //xml to tell them this is deprecated.
    IData GetData(string p1, char p2, double p3);
    IData GetData(string p1, char p2, double p3, and whatever);
}

About your new definition, there's no one stop solution that anyone can give without knowing about the model, but you ask yourself,

I) "Can the parameters themselves represent a single entity if combined? Does it mean something in real world to have one unit of your parameters?" If so, make it so. If not, do not. I think you should rely on thinking in such abstract levels when you're in this sort of dilemma. I'm not sure what's the point in clubbing bool p4 and DateTime p5. You should be clubbing those parameters which themselves represent something in real life. If no combination of those makes sense, then leave it as such. You will have more success in leaving such clubbing to such logical way of thinking. Mind you, you're leaving your definition to other programmers, and to ease their job your method signature should be very very logical.

II) Can the class do more things as opposed to merely holding a set of data? Class should be option here.

III) Do I need to control only the class definition and not the implementation of it? In that case just define a public interface of your inputs, and leave the implementation to customer.

IV) Should future modifications to my interface not break existing implementation? Overloading is your way to go.

Lets say you have two choices, leave the signature flattened out, or to club.

1) Without clubbing:

a) Less code, reduction of another layer.

b) No need to expose another class to public.

2) With clubbing:

a) Gives a better understanding of the model to go into the function - your intention is clear.

b) Easy to scale in future if you need to add optional details for constructing the newly formed class. Lets say you have a class

class Input {
    string p1; char p2; double p3;

    public Input(string p1, char p2, double p3){
    }
}

and interface

public interface MyInterface
{
    IData GetData(Input p1);
}

Now you might want to add optional details like a bool and a DateTime. Since they are optional you dont have to force it int the constructor. You can still have the same constructor, and give the user the privilege to modify if needed outside the constructor.

class Input {
    string p1; char p2; double p3; bool p4; DateTime p5;

    public Input(string p1, char p2, double p3){
    }
}

Interface can still be the same. As I said the impetus to derive anything of this sort is sadly dependent on your model. In short, if a grouping can mean something, make it a class or interface (depending upon who will control the logic).

like image 198
nawfal Avatar answered Oct 10 '22 16:10

nawfal


Why not go all the way:

public Interface IParameters
{
    string p1 {get; set;}
    char p2 {get; set;}
    double p3 {get; set;}
    bool p4 { get; set; }
    DateTime p5 { get; set; }
}

public interface MyInterface
{
    IData GetData(IParameters p);
}
like image 43
BlackICE Avatar answered Oct 10 '22 15:10

BlackICE