Using Objects as Parameters in C#

Hands up, how many of you create monster functions and methods in your projects? And no, I'm not on about routines that are a million lines long, what did you think I meant? I'm actually talking about those functions that have signatures that could easily span over two lines if word wrap were turned on.

In Today's Nuts & Bolts post, we look at why functions like this cause a problem, and what you can do to keep yourself from getting into these kinds of messes.

It's not about any special thing that is specific to .NET but a general programming technique that makes your code easier to read, and begins to help you understand IoC (Inversion of Control)

Starting with the Problem

We've all seen them, those functions & methods that seem to go on forever:

public Class1()
{
  public myMethod(int age, string name, string surname, int yearBorn, int weight, float xlocation, float ylocation ......)
  {
  }
}

You can see that even my example is hard to read, and it's not even in a full blown project with many other lines of code. Imagine, trying to navigate a source file that had masses and masses of function prototypes like this; I think finding a needle in a haystack would be much easier.

Why is This Bad?

Well we've already seen one reason why coding like this is bad; readability.  You might be okay with it when you’re writing this code, but what happens when you come back six months later? Imagine you’re the maintenance programmer who has to take over looking after this thing, and answering inbound support calls from customers out in the field using the software. These are just a couple of reasons to consider. There are many other reasons too.

What if during development your specs get changed, and you suddenly find that you need to add a parameter to pass in a value of how much food is eaten in a month. What about if you need to rename a parameter?

Going one step further, what about optional parameters? You know the ones where you can add a default value:

public myMethod(int age = 20 ......)
{
}

Imagine if you had to update that “20” to a “40” in all instances.

Very quickly this becomes something that's very likely going to lead to mistakes being made in your project, and if you’re under any doubt about how easy it is to miss a parameter like that amongst masses of other code, take some advice from me, it's stupidly easy.

I like many professional developers have been there and made these mistakes, and it's no fun spending a Sunday afternoon trying to hunt down something you just can't quite put your finger on.

How do You Solve This?

As it happens, it is quite easy to solve this. Instead of adding all your parameters in one go, use an object.

Now before we go any further, notice I'm using the term 'Object' here.  To me this will generally mean a class, some people however prefer to use structs, some prefer generic objects, it really doesn't matter what you use, the principle is still the same, and I have no desire to get into a religious war over which type is best.

One thing I will say is each type has its advantages and its disadvantages, and if any of you have ever read my posts in Lidnug, then you'll know already that I'm a firm believer in looking at all your options and using the correct tool for the job.

Moving on.

Let's take our example above:

public myMethod(int age, string name, string surname, int yearBorn, int weight, float xlocation, float ylocation ......)

We can see that we have at least seven items of data we’re using, so let's flesh this out into a class.

public class myMethodParams
{
  public int age { get; set;}
  public string name { get; set;}
  public string surname { get; set;}
  public int yearBorn { get; set;}
  public int weight { get; set;}
  public float xlocation { get; set;}
  public float ylocation { get; set;}
}

And then change our function signature:

public void myFunction(myMethodParams theParams)
{
}

Immediately it looks much more readable.

But now we have other benefits too.

Because a class is being used, you can add methods that can act just like parameters, and in fact this is one of the underlying concepts of object orientated programming, making objects self aware and expose only what they need to.

Encapsulation is a very powerful thing when used correctly, to 'myMethod' all it sees is what it needs to see, nothing more.

What about Defaults? Well, you can easily add an extra field, and then some code to initialize it to a known value:

public class myMethodParams
{
  public int age { get; set; }
  public string name { get; set; }
  public string surname { get; set; }
  public int yearBorn { get; set; }
  public int weight { get; set; }
  public float xlocation { get; set; }
  public float ylocation { get; set; }
 
  public myMethodParams()
  {
    age = 20;
  }
}

If you never set 'age' to a value, you can guarantee that it'll be set to '20' and not have to worry about it.

Is This Just a Quick Tutorial on OOP?

If you've done any formal programming language training in the past ten years then this stuff will be (or should be) second nature to you. If you’ve not, then this might be new to you. Regardless, having a refresher never really hurts anyone.

Ask yourself this question though:

How often do you pass full classes/objects as parameters to regular methods?

I'm willing to bet not very often. In fact I'll even go so far as to say that most of you probably do something like this most of the time:

public class HomeController : Controller
{
  public HomeController(myDataObject theObject)
  {
  }
 
  public ActionResult Index()
  {
    return View();
  }
}

And leave it at that.

Well what your actually practicing here is 'IoC', which means 'Inversion of control'. Essentially what you’re doing is your passing an object that's responsible for its own state, has its own processing methods and likely quite a chunk of other functionality.

Why 'Inversion'?

Well it's because you’re giving the data object the control of its lifetime within the 'Controller class' it's used in above, rather than the traditional way of having the controller class 'new' a copy of the data object, and control it.

You’re taking control away from the class that's using the data object, and inverting that control, so that the data object is in charge.

In Summary

The point I'm trying to make here though, is why only restrict yourselves to the scenario above?

ASP.NET MVC enforces this paradigm by default, but there's absolutely no reason why you can't make your own code/projects easier to manage and easier to read by adopting similar methods.

If you have any ideas for posts for this series, please reach out to me on twitter '@shawty_ds' or come and find me in the Linked .NET users group (Lidnug) on the Linked-In social network. Until next time, code happy.



Related Articles

Comments

  • Nice to be reminded of.

    Posted by Gavin on 09/30/2014 01:20pm

    In most of the code I've been working on, I rarely come across such method or constructor with so many params. But doing the above is certainly a good option, especially to keep things readable. When I'm looking for a problem in my code I like to scan over it, an then zoom in on a potential problem area. If I have huge lines of code spanning 3 pages to the right; it kinda makes doing that harder.

    Reply
  • named parameters

    Posted by Yves on 06/12/2014 11:47am

    Do you know named parameters? I have just overlooked the article and named parameters may solve the issue you describe. If not, I need to read it in detail...

    • RE: Named Parameters

      Posted by Peter Shaw on 09/26/2014 07:25am

      Hi Yves, Yes I do know named parameters :-) and yes at times they can be useful. Cheers Shawty

      Reply
    Reply
  • Bad idea

    Posted by Karsten on 06/11/2014 08:52am

    it creates dependencies on all source files and classes. One change and a lot of work. Try this at home - NOT at work...

    Reply
  • Really bad ass idea

    Posted by Karsten on 06/10/2014 02:02am

    if objects and classes are parameters to others classes it creates dependencies on interfaces. If the class interfaces are changed - a lot of code is to be maintained. Stay native - big interfaces are an architectual problem. One task = one class. If code is shared between projects or companies it will BREAK AND KILL.

    • RE: Bad Idea

      Posted by Peter Shaw on 09/26/2014 07:24am

      Hi Karsten, Thanks for your comments here, but I have to say I wholly disagree with you. Your comment sounds to me like some one who has a VERY SINGULAR vision of a way to do things. This article is not designed to serve as a "This is how you do it article", it's designed to serve as a nut or a bolt or another little bit of hardware that you put in your .NET toolbox knowing that at some point in the future it may be of use. There are indeed many, many, different architectural patterns in software development, as someone who's been writing for best part of the last 30 years I've seen and used a great many of them. If there's one thing that I've learned in all this time, it's this: There is no ONE singular correct way to do things in this industry. While you might disagree that this is a good fit for the work you do, it does not mean that this is a bad fit for everyone. There are many instances where this pattern may indeed be useful and help with the design, but there are just as likely to be many instances where it will indeed break things. In my own honest opinion, this is one of the biggest issues facing developers these days. Far too many are trained directly from a text book to follow a singular vision, this text book then becomes a rule book and as a result we have a great many devs who NEVER think outside the box or explore new concepts and ideas. This in turn leads to a workforce of robot 9 til 5 developers who will repeat ad-infanatum the exact same patterns and methods of their predecessors, which eventually will kill innovation and thinking and the art of Software Engineering.

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: December 18, 2014 The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this webcast and join industry experts as …

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

Most Popular Programming Stories

More for Developers

RSS Feeds