perspective Technology

Crossing the Line

There’s always a line waiting to be crossed. Morally, technically, physically. With whatever we do, or can do, there will be a line. And some of us will cross that line just because we can. It doesn’t mean though that we should.

We can cram a plethora of features into any software product. Doesn’t mean we should.
We can add layers of indirection into our architecture to push the boundaries of decoupling. Doesn’t mean we should.
We can implement [insert pattern name here]. Doesn’t mean we should.
We can deprive ourselves of sleep and turn a 4 day project into a 2 day delivery. Doesn’t mean we should.
Just because we can, it doesn’t mean we should.

Too many decisions are implemented based on what we can do. Usually there is some discussion about what is possible and what is not. Wether or not it makes sense, is not beside the point but can certainly be diluted by confusion amidst emotional rhetoric. And then after all is said and done, there being no obvious agreement, a public opinion poll is held. Oh behold the saviour of our modern thought process: public opinion. It has been said that public opinion is no substitute for thought. Behaviour beg to differ.

Of course, the problem with lines is that we often don’t know what the other side is like or where that line was actually drawn. It’s only once we’ve crossed it, do we realise that we’ve crossed it. At such times, realization and prompt action can help alleviate any problem caused by being on the wrong side. It does take some courage; different to bravado which is usually what crosses the line in the first place. Itself, another line: bravado and courage.

Recognising where the line is and if it’s worth crossing is a valuable skill. It’s the difference between profit and loss. Value and gimmick. Genius or just clever. Working hard or working smart. If there’s one soft skill your team can encourage, it’s line detection.


Parameter Guardians

With most methods that are called, procedural or OO, there will be (a) parameter(s) passed in. The parameter itself can be a relatively “simple” type [eg. int] or a more complex reference type [eg. string]. The degrees of simplicity referred to here are related to the degrees of state which a parameter can have.

In the case of an int, the value must be set and the range is within an established, and ususally guarded, boundary. In other words, an int has a set size limit and cannot be null. A string, however, can be null and can be of *mostly* any length [physical memory aside]. There are other examples of the relative complexities of parameter types, but these suffice for the discussion. Which is to say, there are relative degrees of complexities in dealing with various parameter types.

In dealing with the various types, there is a responsibility, somewhere between caller and callee, about ensuring the state of the more complex types. In defensive programming, the responsibility lies more with the callee. Should a callee accept a reference type [eg. pointer, string, object reference] it is the responsibility of the callee to validate the state of the parameter before using it. Consider…

public void foo(string param)

Here, foo must check for:

null == param


param.length > 0

or any other explicit constraints about the contents of param which are not essential to the function. In doing so, not only is foo concerned with doing what it needs to do, it also needs to check what it receives before it can function. On the plus, foo documents it’s assumptions about the state of the parameters it functions on. On the drawback, foo also has the responsibility of dealing with bad parameters, in addition to its designed function. In fact, what does foo do if param is NULL. Throw an exception? Conditionally process the function?

If it throws an exception, why check for the state of the parameter anyway since using the parameter in a null state will generate a more reliable[?] exception. Is a system generated exception more accurate than the programmer’s interpretation of a bad parameter. And which is more liable to remain accurate for the lifetime of a function?

Conditionally processing a function can be ambiguous and overloading functions might be a more explicit way to dealing with “conditional” parameters, depending on your design. Also, simply returning from a function because the parameter is not what is expected can also be a design
issue and not completely within the scope of this discussion. The main issue revolves around why should a callee guard against the state of the parameters it receives?

Wether the callee throws its own exception or lets the system throw, the caller is still responsible for handling the exception- or ignoring it. Either way, the caller has expectations about the state of the system [and the parameters] before and after making the call. Those expectations cannot be met if the caller itself is not aware of the state of the parameters it is passing on. If the caller is aware that the parameter it is about to pass is NULL, it shouldn’t pass the parameter unless it knows that itself and the callee both assume NULL is a possibility.

I maintain callers have the responsibility of passing “good” data [garbage in, garbage out] to any method. This makes for a cleaner design in the methods since they work within reasonable assumptions and their code is not dotted with “unneccessary” checks which should have been proactively made further up the call stack [read: closer to the actual problem]. By burdening the callee with the responsibility of not being “open to abuse” is relegating the problem because then i would ask the question: why is the callee being abused to begin with? Surely the real problem lies somwehere else?

But then again, does it hurt that much to put the extra checks in on the callee, as per good defensive programming techniques suggest? Certainly for security reasons, there are certain methods which simply must check their data because they don’t trust anyone calling them. And that too is only by way of design. So in addition to callers being responsible, there are times when the callee has more of the responsibility. Combining the two views, and after a brief, no less passionate debate about the matter with Eugene…

as soon as there is enough information available to make an intelligent assumption about the data you are working with, you should. Be it caller or callee.