Spicy spaghetti or how to avoid spaghetti code

28 October 2015, Monika Mitura

– You can’t name a  function “udpate_counters ” which does something else. The name should describe  program’s  functionality. The program increases a  counter, that’s  great, but apart from that it does also DELETE.  Which has nothing to do with these counters. Let’s move it to another procedure.

– Sure, sure .. The name should reflect the functionality …

– What about changing  the name to update_counters_and_delete_tmp_tbl?

Spaghetti Code

What is “spaghetti code”? It’s quite obvious. Each developer has seen it. Of course the author is always someone else, not me.

According to the definition on Wikipedia:

“Spaghetti code is a pejorative phrase for source code that has a complex and tangled control structure, especially one using many GOTO statements, exceptions, threads, or other “unstructured” branching constructs. It is named such because program flow is conceptually like a bowl of spaghetti, i.e. twisted and tangled.  ”

Spaghetti code is associated mainly with long, tangled procedures written a long time ago (“in a galaxy far, far away …”;). Nobody writes spaghetti code anymore, or do they?

How can we check if we are dealing with spaghetti code?

FACT: spaghetti code is long like spaghetti

The first symptom of spaghetti code is code length. Long programs are difficult to understand and analyze. Extremely long programs can contain several hundreds or even thousands lines of code. Number of branches or logical paths in such programs is practically unlimited. Getting around such code is very difficult and every change in it can cause errors in the other modules in the application. Finding the location of a bug in such a program is very time consuming.

Short programs are much easier to use, understand and develop. The standard length of one program unit should not exceed the screen. It is important that the procedure can be quickly embraced with eyes. It is easier to understand the code when you see  the whole of it. Best practice is that procedures should be built of about 50-80 lines of code (only  body, without the declaration section and exceptions). Short programs are easier to understand, test, detect  and fix errors. Since the procedures are isolated from each other there is less chance that amendments in one software unit will influence other procedures.

MYTH: Only long code is a spaghetti code

Surprisingly this is not true. The code can be considered as a spaghetti code even if it is very short and contains recommended 50-80 lines. Sometimes 50 lines of code could be so complex and implement so many different functionalities that it is enough to name it spaghetti code . In the above anecdote the function has not more than 10 lines. In one line counter is increased. Next line DELETES some data, which is  not  related to the counters. Although code is quite short, it deserves to be called spaghetti code because of the confusion of various functionalities and invalid separation of concerns. In this situation, program should be revised and both functionalities should moved into separate procedures.

FACT: The complex process

Another symptom is the large number of different loops and conditional clauses. If the procedure contains  lot of IFs and loops, interrupts the performance of the process – GOTO return, exit – we can say that we are dealing with spaghetti code. Procedures should have clear and simple flow.

Complicated conditional clauses, calculation or loops should be hidden in specialized functions.

Procedure or function should have only one exit.

RETURN clause in functions is frequently overused. How many times  should it occur? Count how many times the RETURN clause occurs in your function. Is it more than one? Should be one. Just one. Instead of using RETURN all over our code we can set a value to a variable and exit the function once returning this variable as an out parameter  at the end of code. Thanks to that the process will be easier to follow.

Loops are often interrupted using EXIT or RETURN clause. One can say that it is sometimes necessary to exit the loop before fetching all records? The solution is to use proper kind of loop for specific problem: e.g. instead of while loop we can use for z in 1..10 etc.

Another overused break is using RAISE exception. Instead of calling RAISE in an unexpected places in the code it is better to define the specific exception in declarations section and RAISE the local exception in the code. Thanks to that we have procedure exits defined in one place and also all our exceptions there. It is easier to understand the process when similar things you have in one place.

MYTH: When the process is divided into small software units it is not spaghetti code

Can we assume that process divided into small program units will never be a spaghetti code? Not necessarily. The process should be divided into units according to the principle “from general to specific”. Each program implements one specific task. Unfortunately programmers, while trying to use these principles, are applying them randomly. In this case we are still dealing with spaghetti code. This time it is split into smaller spaghetti codes.

The division of the process into smaller program units makes sense when it provides a better understanding of the process, the easier analysis and better readability. When a split is random or incorrect – none of these advantages are obtained. Many small spaghetti codes are not easier to understand or analysis than one large spaghetti code. What is more, a lot of small spaghetti codes can be frustrating. Jumping from one function to another in unexpected places really irritates.

Example 1.

Package: generate_file

Procedures: Main_file, Start_file, Run_file, Gen_file

How much we know after reviewing package specification? Honestly little. We know only that procedure generates a file. But which does what exactly?

Example 2.

Package: generate_file

Procedures: Main, Get_filename, get_data, Open_file, Create_line, Save_line, Close_file

In this package it is much easier to get around. At first glance we know which procedure is responsible for which functionality.

“Soczewica koło miele młyn” – the final spaghetti code test.

During the reign of Władysław Łokietek (King of Poland in the XIV-th century ) they tested whether you are a Pole by asking you to repeat the words “Soczewica koło miele młyn” (if you’d like to try it out play it in Google Translate and repeat – lots of fun for readers who are not Polish native speakers ;).

It appears that we can also perform one simple test to verify whether we have a nice code or spaghetti code.

This test is “try to name the procedure”. But not like a programmer in the anecdote using the connector AND. But by finding one short phrase that defines the essence of the process. If we have a problem with that, then either we do not know exactly what our function does or it does so many things that we are not able to identify them. In both cases we probably are dealing with the spaghetti code. In this situation, you should review the code, split it into smaller units implementing one (and only one) functionality, check loops and interrupt processes, hide complex algorithms behind specialized functions. Repeat the process until you are able to give a nice, short name to each program unit.

Avoid spaghetti code, even in small portions

Everyone knows that spaghetti code is wrong. No one wants to write spaghetti code. But few people realize that due to time pressure or misconception that the code, if it is short, is not spaghetti code, they fall into the trap. I hope this post will encourage you to look critically even at small procedures and encourage you to avoid spaghetti code, even in small portions.

Good Practices

1. The names of program units should be precise and reflecting the functionality
2. The code should not exceed the screen.
3. Programs should be divided into smaller units according to the principle “from general to specific” and not at random
4. Number of outputs from the program should be 1.
5. Complex algorithms should be hidden behind the specialized functions
6. Avoid loop interruption- better fit the type of loop to the problem

This post was published originally at my blog, which you can find here how2ora.blogspot.com.

Tagged with: , , , , , , , , ,

Hire us!

Pretius is a software development company.
We create web applications using: Java, Oracle DB, Oracle Apex, AngularJS.
Contact us to talk about how we can help you with your software project!