Deciding What Variables to Pass in as Parameters – A Question of Design (OOP)

_config.yml

I faced a somewhat interesting problem that got me thinking:

Consider the code above. We want to print out the message. What is wrong with the method as it stands?

  • It only works if we want to print a Person instance. But what if we wanted to print the name of a street? Then we can’t do it.
  • What then is a solution?

We could do something like this:

But then there are problems with this approach. We’ve done a very great an wonderful thing: We’ve eliminated duplication. “DRY! DRY! DRY!” the pundits roar in approbation! Yet we’ve also introduced a dangerous problem. Can you guess what it is?

We’ve introduced an “axis of change”.

Wait a minute: is it an axis of change?

Well, to answer this question: will we ever need to print a street sign message in a different way to how we print out a person’s ID? Will we need the street sign to be in large bold letters – while the person’s ID in small letters? If there is a possibility that they could vary due to two separate requirements, then employing the one method, to print both Street signs and people is a dangerous idea.

Or let’s ask this in a different way.

  • If we change how we print out a person, do we also want to change how we print out a street sign?

If you want a change in one to affect the other – then there is only one source of change. How ever if you want a change in one to not affect a change in the other – then you have two sources of change. They should be separate. You want this because you don’t want one of your software engineers making a change to how you print out a person – only to find out later that they’ve accidentally screwed over all the people who want their street signs printed out in a certain way.

Examples: Is the SRP violated here. Let’s work through

Let’s say you’re working on an Excel spreadsheet application. You want users to be able to edit:

  1. The style of the spreadsheet and/or
  2. The formulas of the spreadsheet.

Do we have one or two responsibilities here? Start by identifying the sources for change:

Let’s start by asking some questions:

A class should have only one reason to change, and no more.

How many reasons for change does this program have? Well users could make a change to the styling. That’s one. And you could also make a change to the formulas – that’s two. And most importantly, you do not want a change in your formulas to change the styling of the spreadsheet. And vice versa, you don’t want to change the text font colour to red, only to find out that your formulas have gone crazy and are spitting out non-sensical results. In order to avoid these situations, the methods which affect the style of the spreadsheet should be separate from the methods which affect the formulas and values which go into the spreadsheet.

Group together code which changes for the same reason.

Similar to the above, you’d group together the code which affects formatting, from the code which affects the formulas.

What’s wrong with introducing an axis of change?

Think of it like this: every person can only serve one master – he cannot serve two. Now let’s say there is a change in requirements: let’s suppose that we need each person’s ID to be printed twice, instead of once. “For goodness sakes!” you cry in exasperation: “these people can never make up their minds!”

So Start –> Search for VisualStudio and then start plugging away. Here is the result:

You’re pleased with yourself. That was a lot easier than thought. But then you get back on FB only to get interrupted by a Poke from a colleague: ahem: “there’s some repetition there!” she says with a tut, tut, tut, “you’re best off eliminating that!”. Dammit! These code review sessions are really starting to affect my social life.

So then you come up with a more creative solution:

Job well done. All is well. Your colleagues congratulate you with a pat on the back. It’s your shout too.

Then you get a frantic phone call:

“Dudde, why are my streets signs printing double!?!”

Uh-oh!

“It’s gonna cost me $2m to fix this!”

Time to update your Monster.com and LinkedIn account?

What just happened?

A change in one area affected a change in another. You don’t want this to happen. You violated the SRP.

What should have been done instead?

Perhaps you should have implemented a polymorphic solution – that that you can have all the benefits of minimizing the need to repeat yourself, while also allowing you to have different masters – a print message for people. And a separate print message for street signs.

So back to the original question: do we pass in a string or do we pass in a person?

If we pass in a person, we can only use that method if we have a person. If we pass in a string – then we can use it to print anything. But there in lies the danger – do we want to use it to print anything? Just like with creating a base class – we have to be very careful, because if we pass in a string – then any changes we make to the PrintMessage method will affect everything we print – street signs, people, houses, cats dogs etc. Is that something you actually want?

In this case, I am perfectly happy to have every message I want printed – whether it be for a person, or a street sign, to come out exactly the same way. So although there are two sources of change – there really isn’t two sources – because the two sources coalesce to form one source.

Now let’s consider another interesting situation. Let’s suppose that you wanted to print out a person’s ID – but you didn’t have the person object. All you had was this information: “”\nHi my ID is 1234”. In this particular case, how are you going to print the message: you need a person object in order to print that message and you have just a pure string. What are you going to do?

Well the only reason that you are passing a person object is to get the ID of the person. If you have the ID in the client, then by passing in a person, you are needlessly limiting the utility of that method. In other words, I think it justified to make an axiomatic statement – till I find a good reason to controvert it.

An Axiomatic Statement

Pass in the most specific object or type necessary to perform a function.

Summary:

If you are passing in a person object, just so you can extract that person’s ID, then you should pass the person’s ID instead of the entire person object.

Written on October 15, 2017