- The Starter Version of Delphi is currently 100% off. I.e. Free as in beer.
- “The proper use of comments is to compensate for our failure to express ourselves in code.” – Uncle Bob Martin
- I continue working hard on my materials for Delphi Developer Days. If you haven’t signed up yet, do it. I’m really looking forward to seeing you all there.
- I’m really looking forward to attending TechBash 2016 at the end of the month here in the Poconos in Pennsylvania. Not only will there be a great lineup of speakers and a great venue, there will be some old friends there that I’m looking forward to seeing again. It’s nice to have a world-class event like this so close to where I live – it’s so close that I’m driving, as well as taking advantage of the water park. 🙂
- And while we are on the topic of conferences, I’ll be at Philly CodeCamp this year as well, on October 21-22. It’s at the Microsoft Malvern office. Friday is a pay-for-it all day session, where Saturday is hour long talks and is totally free. If you are in the area, you should go. It’s always been very good, and they give away a lot of prizes.
- The new book is drawing closer. I know I keep saying that, but I only so because it is true. It will finish sooner rather than later. As always, you can sign up to be kept abreast of things.
Yesterday I made the following tweet:
Never pass nil to a method, and don’t let your methods accept nil as a parameter value.
— Nick Hodges (@NickHodges) January 19, 2015
and it started and interesting little discussion on Twitter. (I was actually honored that the great Mark Seemann himself entered into the fray…) Naturally, the conversation tried to point out why I was wrong, and all the ways that it was fine to use nil. That’s okay – if there it is one thing developers like better than making pronouncements, it’s finding exceptions and arguing against other developer’s pronouncements.
Well, I remain unconvinced and stand by my statement. No surprise there, I know.
There are two parts to what I said and I’ll argue them one at a time.
First – “never pass nil to a method”. Now people freak out about “never”, but it’s Twitter and you don’t have a lot of room for caveats. First, sometimes I guess you have to pass nil to some methods — ShellExecute comes to mind — but I’d argue that those methods are poorly designed (as I’ll talk more about in a minute), and that you should pass nil only very, very reluctantly. Again, I’m talking about your code, not other’s code. You should never send nil to a place where a valid object will be accepted. Never do that to someone’s code. Returning nil is always a bad design decision.
The Robustness Principle states, in part, that you should be very precise in what you pass, and passing nil is not precise. It misses the mark by as much as you can miss the mark. The target is a valid, working instance of whatever the method is asking for, and passing nil is like turning 180 degrees around and firing your arrow away from the bulls-eye. Nil should not be used as a “signal”, leaving the class you passed it to in a state where they can’t make use of what you’ve given them. You should avoid like the plague allowing a class to be in a state where it can’t do what it is designed to do, and if it asks for a object in a method or constructor, you are obligated to pass a working, constructed object that it can use without error. To do anything else is to invite an exception or worse, an access violation.
The second part is this: “Don’t let your methods – especially your constructors — accept nil as a parameter value”. Your classes should never let themselves get into an unusable state, and blindly accepting nil as a parameter will do that. Instead, your classes should carefully guard against being passed nil and quickly – no, immediately – fail if passed a nil reference. There is even a pattern – the Guard Pattern – that is employed to ensure that a program won’t continue unless things are acceptable. Getting nil is not acceptable:
procedure TMyClass.constructor(aSomeClass: TSomeClass);
if aSomeClass = nil then
raise NoNilParametersException.Create('Don''t you dare pass me a nil reference. Pass only valid instances');
FSomeClass := aSomeClass;
Every single time you accept an object as a method parameter, you need to use the Guard Pattern to prevent your object from being placed in a bad state where it can’t do what it is supposed to do. Fail fast and tell the user exactly what they did wrong and what they need to do to fix it. In fact, if a nil reference sneaks in, you’ll eventually get an access violation when you try to use this nil reference, right? Sure, it’s work, but it is time well spent. Knowing that your references are always valid makes for easier code, and actually can reduce the amount of nil checking that you have to do. Who wants to check for nil every time you use an object?
Don’t pass nil references. Don’t accept nil references. This seems obvious to me and I confess I don’t understand objections to this aphorism that only results in cleaner code. Why would you ever want to accept a nil object? Why would you want your code in a state that is begging for an access violation to occur? Insist that your objects are valid, and never impose invalid objects – nil – on others. Seems blatantly obvious to me.
So I am going to guess that this will not make some of you happy. So here is my challenge: Show me code that you have written where nil is acceptable. Don’t show me code that calls the Win32 API or the VCL, show me code you have yourself written where nil is acceptable and useful as a valid method parameter. I’d love to see it – and then point out the problems that it will cause. 🙂
An important step to writing Clean Code is the notion of separating “commands” and “queries” by using the Command Query Separation Principle. The notion was first discussed by Bertrand Meyer in his book Object Oriented Software Construction. This means that the idea is not new. In its basic form, it means we should separate the things that read data from the system and things that write data to the system.
The Command/Query Separation Principle means that there should be a clear separation between the updating of information and status in your program and the way that you read information from the program. Commands and queries should be separately declared (though you’ll find that commands can call queries but not vice-versa.) It can be a complex as ensuring that reading and writing take place in completely separate object, or as simple as ensuring that commands and queries are simply done in different methods of your objects.
Of course, the first question you’ll have is “What do you mean by ‘command’ and ‘query’?” Well, I’ll tell you.
A query is an operation that returns a result without effecting the state of the class or application. In Object Pascal, this is typically a
function. Queries should not mutate the state of a class. They should be idempotent. That means “denoting an element of a set that is unchanged in value when multiplied or otherwise operated on by itself.” (I had to look that up, by the way….)
As a general rule, queries should return a single value, and “asking a question should not change the answer”. They should be referentially transparent; that is, they should be perfectly replaceable with their literal result without changing the meaning of the system.
What this means practically is that your functions shouldn’t change the status of the system you are working on, whether that be a class, a framework, or an application. You should be able to run a query, i.e. a function, a hundred times in a row and get the same answer back each time. The function, because it doesn’t change the status of the system, can be safely called at any time without repercussions.
Now this should be a general rule — there are certainly cases where your query will change the state of the system (a dataset’s
Next call comes to mind). But generally, it’s a good idea to have your queries not change state.
A command is any operation that has an observable side-effect. It is any code that changes something in your class or application. Typically, in Object Pascal, a command will be a
procedure — that is, code that takes actions without returning a value. Commands can call queries (but queries should never call commands, because commands change the status of the system).
Commands should not in general return values. Thus, the use of
var parameters should be discouraged if not down-right banned.
Don’t Mix the Two
All your methods and routines should be easily identifiable as either a command or a query. Commands and queries should be separate entities in your code — with the exception that a command can call a query if need be. The use of
out parameters in a
procedure will confuse this issue, and thus should be discouraged. If you follow this rule, your code should be more “reasonable” — it should be easier to understand and easier to modify.
CQRS also encourages you not to violate what I consider to be a bedrock of sound development technique: Don’t try to make one thing do two things. For instance, here is some code that does exactly that:
procedure ProcessWidgets(aCollectionOfWidgets: TWidgetCollection; var aNumberOfProcessedWidgets: integer);
This method is a clear violation of CQS [NOTE: I orginally had this as CQRS] as it obviously is trying to be a command and altering the state of the system by processing widgets, but also tries to be a query by “returning” through a
var parameter the number of processed widgets. Instead, the system should have a simple command to process widgets and a separate query to return the number of widgets that were processed. The procedure is trying to be two things at once, and all kinds of mischief comes from making one thing do two things.
Following the CQRS principle in the design of your code will help to ensure the proper separation of concerns, resulting in cleaner, easier to read and easier to maintain code.
Jon Postel was a guy that wrote an early specification for the Transmission Control Protocol (TCP), one of the core protocols of the Internet protocol suite. You use it every day to surf the web, send emails, etc. One of the guiding principles that he used when writing it was this:
Be conservative in what you do, be liberal in what you accept from others.
This idea is also call the Robustness Principle, and is sometimes rephrased as “Be conservative in what you send, be liberal in what you accept.” When applied to TCP, it means that the sender of data should be strict in what is sent, ensuring that it is accurate and precise. It also means that the receiver of data should be forgiving and understanding of data to as large a degree as possible. If you send data, be as clear as possible in what you send. If you can accept the data sent, then you should.
Any application programming interface (API) should follow this principle. Thus, the same principle should apply to your code. The public interface of your class should be viewed as an API, and it should be conservative in what it sends, and forgiving in what it receives. When calling another API, your code should send out data in a completely conformant way, following the rules laid down by the receiving API. But it should be willing to receive input in a non-conformant way as long as the input can be understood.
For instance, if passed a string, you might be happy to accept strings with blank spaces on the beginning and end, and use the Trim function to clean things up for the sender. Your classes might provide overloads for input methods, accepting both and integer and a string as input, providing a way for your class to be as forgiving as possible.
But when you call another API, your code should be strict and always send data in the correct, expected form. You should trim your strings before they get sent along to the API you are calling. If the system expects integers, you are going to send integers. You should meet the specification completely.
Another example is the use of nil. First, your code should never pass nil to a method that you are calling. Always provide a valid instance if the API calls for one. Second, your code should accept nil, but “fail fast” if passed nil and raise an exception. You should never let your internals get into the state of nil, and while you should accept nil, you should immediately raise an exception at any attempt to set one of your internal references to nil.
Postel’s Law – a small but important way to write better code.