6 + 1 Tips to Write Easily Extensible Code

Disclaimer: the following tips apply to programs
more complex than this
As promised some weeks ago in the post The 0 Ohm Resistor, here there are some tips to follow while developing a new project that will make your life easier when someone will ask you to add some features in a short time.

If you are working in a team, these suggestions will also help your colleagues to understand your code and make changes autonomously.

1. Use Defines

This is a quite common suggestion but, believe me or not, I've seen several programs using numeric constants. Basically, every time you declare a fixed size array or set a limit, you should create a define. In this way it'll be faster to change it when requirements evolve. Unfortunately, not every programming language supports defines or constants; in such cases, the fastest way is to use variables with all uppercase names.

2. Use Getters and Setters

For object oriented languages, it's not a good idea to directly expose members. Even for simple things it's preferable to use functions to change a member or to retrieve a value in order to hide the implementation of your classes. So, in the future, you may change an integer to an iterator without impacting the existing code. The exception is Python, where properties should be used, but only because they do the same thing: implementation hiding.

3. Write Small Functions that Do a Single Thing

There's nothing worst than having a function one-thousand lines long. It's hard to understand and almost impossible to change it's behavior without rewriting it. With small functions it's easier to change some details or add something in the right place without being frightened of hidden side effects.

Corollary: unless a heavy optimization is needed, don't write code that is hard to understand for an average programmer. If you cannot avoid tricky code, remember to comment very well what it is supposed to do.

4. Prefer Text Files Where Possible

Unless you are working on systems with limited speed or storage, consider using text files to save (and load) configurations, logs and everything else. Binary structures are faster to read and write but every time you'll change the format, you need to update several part of your code. Moreover, the debug is easier and, in case of troubles, an handmade change can save you time and money.

5. Use Names Not Related to the Solution

It is easy to call a class ArrayValues, and it seems reasonable, too. But it's wrong. Again there is a problem with implementation hiding but not only. If one day the array has to be changed in a hash table, what would you do? Keep the name even if it's wrong or change it everywhere in your project? The key point here is that the solution you have found to solve a problem may vary in the future, so it's better that names of variables, functions, classes, etc. reflect a something that will never change: the problem to solve.

6. Avoid Code Duplication

Trivial tip, don't you think? But you won't believe how many times I've seen two (or sometimes three) functions doing almost the same thing in the same project. The reason is simple, who added the second function didn't know (or didn't remember) that a task is already performed by a function already present. In some cases it's the fear that makes someone say: "Maybe if I add this little feature I can add bugs to something that it's working. No, it's better to create my own function". The result is that for every subsequent change there is the risk to not consider every implication.

Bonus Tip - Do the Refactoring

This is something that is (hopefully) not necessary at first, but as the modifications start to accumulate, take some time to review the changes and harmonize them into the structure of your program. In this way, in the future you can keep adding features on a structure that is stable and well implemented.

We Have an Opportunity!

Speaking about my developer job, to me the word "opportunity" means only four things:
  1. with few changes to a project, we can sell something to a customer - the Company will earn a lot of money;
  2. with a fair amount of modifications, we can sell something to a single customer and possibly also to many others - the Company will earn many, many money;
  3. with a huge but well defined modification, we can sell something to a single customer - the Company will earn a massive amount of money;
  4. we can drive a rover on Mars.
Unfortunately, what salesmen usually mean with "opportunity" is:
There is this big firm that wants to start a partnership with us and they said that, if the first test project is OK, they will leave their current provider and start to buy from us. The forecast is a very huge amount of money. You don't have to worry about the modification: they just need a couple of changes and they'll provide a specifications in few days, then in a couple of weeks we do the work and problem solved!
Opportunity sign in front of a wall
This opportunity seems a dead end

Translated this means:
  • the current provider of this firm asked too much for the same modification;
  • the modification will be a total pain and the specifications will be incomplete and provided in late;
  • there will be a lot of work to do in a short amount of time;
  • the Company will provide your work for free;
  • the firm will not switch to our Company.
Do you recognize the situation?

Image generated with www.redkid.net

Power and Control


This video is a perfect representation of the Pirelli's slogan "power is nothing without control". You can have the fastest car in the world but if you are not able to manage it, you'll crash.

With the development languages it's the same. Some languages are (sensed to be) more powerful than others: some say that C++ is more powerful than C.

Please stop laughing and keep reading.

Small Digression on the Most Powerful Language

Programming language textbooks
What is the meaning of "powerful" related to a programming language? Try to ask Google. Excluding Richard Stallman (that seems to love LISP), the majority of the results will say: "Every Turing-complete language is at the same level of the others."

Someone else points out that a language that needs less code to do the same thing is more powerful and probably I could agree, but... would you say that Assembly is less powerful than Pascal?

The answer that I like much is the following (from here):
C is powerful, because it is low level and gives you access to hardware. Python is powerful because you can prototype quickly. Lisp is powerful because its REPL gives you fantastic debugging opportunities. SQL is powerful because you say what you want and the DMBS will figure out the best way to do it for you. Haskell is powerful because each function can be tested in isolation. C++ is powerful because it has ten times the number of syntactic constructs that any one person ever needs or uses. APL is powerful since it can squeeze a ten-screen program into ten characters. Hell, COBOL is powerful because... why else would all the banks be using it? :)

Power and Control in C++

That having been said, we can go back to the control part. No matter the language you are using, you have to use it well. Are you still determined to use C++ because you think it's more powerful? Please go on. I'm not interested in a religion war. I love C++ too. But I know that mastering it is way more difficult than C.

And no, "mastering C++" doesn't mean using the iterators to scan a std::vector containing your fancy objects. Mastering C++ means understand OOP and understand template meta-programming.

Now you are able to start to design your class hierarchy. Design. Not code. The design part is the most important in a C++ project. If you fail it, your software will be a total failure. And when you have finished your design, take some time to simplify it.

The risk with C++ is to fall in love with your architecture and forget that the main purpose of every program is to run in a decent time without saturate the hardware resources.

Good Old Dirty C

So now you think that C is easier, right? Wrong! Probably the design part is faster and shorter but the risk to create something that is buggy, leaking memory and unmaintainable is just around the corner.

With C you can let all your perverse ideas to run free: cast madness, mixed usage of integers and pointers, long jumps like there is no tomorrow, etc.

The fact that you can do almost everything in C doesn't mean that you should. And remember, you don't have to demonstrate that you are a good programmer. Other developers don't care about you and your fancy hack; if it takes more than one minute to be understood, it's surely wrong.

Conclusions

You should have understood that the programmer is much more important than the used language. Poor developers will only write bad software. And programmers that don't think about the design before starting to code are doomed to write and rewrite and rewrite again.

Missing Things

People talks about things they consider important to communicate and not about what they think is implicit. This is normal: life is too short to lose time speaking about things that everybody knows, right?

Unfortunately, in the Developers' World this behavior leads to big mistakes and missed deadlines. Usually things go this way:
  • someone (most of the time the Project Manager) writes the specifications and sends it to the Dev Team;
  • the Dev Team asks a million questions about what is written on that specification;
  • the PM answers;
  • the Dev Team do the work and pass it to the Quality Assurance Team;
  • the QA Team, guided by the specifications, tests the product and finds a 2 or 3 (billions) bugs that the Dev Team quickly fixes;
  • the PM looks at the product and screams: "what is this crap?!"

What Has Gone Wrong?

Probably the PM has taken for granted something that for the developers wasn't. I'm not pointing my finger against Product Managers. It's not (only) their fault if their wonderful specifications are focused on few aspects (that they consider fundamental for the product) and everything else is left unsaid.

Another thing that often happens is that the specifications are providing us a solution instead of explaining the problem. So we are forced into railways tracks that usually are leading us to the wrong place.

And if this happens with people working in the same company and building, try to figure out how the situation can go worst when you have to deal directly with a customer that belongs to a completely different application field.

Saving the Project

How can we solve this? As my boss usually says "we simply don't know what we don't know" (no, I do not work for Monsieur de La Palice), so it seems that we are in a cul-de-sac.

something is missing and I dnt know what it is

But let's see the whole thing from a different point of view: we know that we don't know (to cite Socrates) so we must ask the PM or the customer to explain not only how he want a certain feature to be implemented, but why he needs it.

We must understand in deep the application field and its critical aspects in order to create a better software that fits the requirements (also the implicit ones). We have to become users, to play the customer's role.

In addition, we should schedule periodic meetings with the PM to check the direction and make sure that misunderstandings are solved as soon as possible. Only following these two suggestions we can avoid situations like the one described above.

Conclusions

It would be wonderful if we could have a document that describes everything is needed (well, sometimes simply having one document would be great) without knowing anything else, right? Unfortunately we live in a real world... or so we think...

Recommended complementary readings: this post by Seth Godin and Estimation is Evil?

Think More and Work Smarter

The Thinker Musee Rodin
Sometimes I work with the autopilot on. It happens when there is a series of simple things to do in a small amount of time. The priority become to mark all the items of the to-do list before turn off the PC and go home.

Since the tasks are quite trivial, there is no need to think about a fancy way to solve them: it's just code to write. But sometimes it happens that, after accomplishing everything, I ask to myself: "why the hell did I do that?!"

Usually the answer is: "because I was thinking about a fast solution, not a good solution". So I have to rewrite and spend more time in something that could have been done better the first time.

[ By the way, the philosophy "just make it run" is something that I consider totally awful. ]

But right after reading this article, I felt like a door was opened in front of me. Now I know what I have to do: spend five minutes in thinking before, instead of one hour after to rewrite.

You know, thinking is always a smart thing.