четверг, 24 июля 2014 г.

Teach your code to speak genteelly, nil is country speach

Imagine you ask a person something, but he just stares at you in response. Or even worse, you tell one to do what you want, and he seems to get your command, but turns his back to you and you can't tell if he did what you asked him to or not. Did you imagine it?
Congratulations! You have just got nil/null, whatever represents nothingness in your programming language, in response to a function call.

The same way you think a person who doesn't react appropriately to your questions or requests is an ass-head, the same way function returning nil is a moron-function.

I do know that there are cases when you have nothing to return, but this is either a Special Case or an exceptional situation. Let's consider two examples for query and command. Yes, to be genteel your code have to comply with CQS principle. 

First - query. To be honest whether a special case or an exception is better depends very much on a context. Let's consider two query categories: query for data (information, data structure) and query for behaviour. First case is easy, you just fill your data structure with whatever it turns it to an empty state if it has a meaning or you raise an exception if you can't fulfill a query. Easy peasy. The second case is a little bit more complicated. Lets say, you write a polymorphic query function which is supposed to return objects with state and behaviour that may be used to do something. As long as it is polymorphic it is to change a behaviour when you work with descendant classes i.e. return different objects with different behaviour, but not every descendant alters a default behaviour. Oh, and there is no default behaviour. Natural choice? - Nil. But if I put it another way: to do nothing IS a default behaviour, it becomes obvious that your best bet is a Special Case with no op strategy, rather then nil, completely nothing. 

Now a command. I'd separate two kinds of commands: those that you do not expect to return a result and those you do. The first type is naturally implemented by procedures. Some programming languages have a void return type built in. This is probably the only valid case to return nothing. However, if your language of choice has no built-in tools to mark the function as a procedure then treat all commands as those that return result. In this case you'd probably return nothing in case you've failed to accomplish request, which is the worst way to do. Rather use an exception to inform a caller that his request puts you into an exceptional case when you can't process a command request.

All in all it is very easy to be polite to those who use your code and to those who read it. 

To be little bit more convincing I'll again reference one of the best programming books ever: Clean Code, and a very good discussion.

And as if that was not enough already I'd quote Sir Charles Antony Richard Hoare:
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. [...] More recent programming languages like Spec# have introduced declarations for non-null references. This is the solution, which I rejected in 1965.

P.S. Should I mention that passing nil/null as a function argument is even worse for very obvious reasons? 
P.P.S. I'd like to try a programming language without nils. Without nothing. You got it.

Cheers.

Комментариев нет: