kenfreed1

 

What Makes Application Code Maintainable?

Coding isn't about just making things work.

Maintainability largely isn't about coding style items like how many spaces one indents, or whether one avoids i,j,k in their simple loop counters.
Following a style guideline does not insure understandable code (any more than the rules of grammar insure clear writing).

Coding is about making relationships and dependencies as clear as possible, given how generalized/abstract the code has to be.

Following someone else's code is harder than understanding your own code.

The basic problem is that programming often involves knowing where (in a haystack full of code and indirect references) the pieces that relate to each other are located. In large systems, race conditions, unforeseen critical sections, buffer overruns, deadlock and state dependencies (e.g. did this get set before we started using it?) can get knotty. Without the right foresight, a bunch of little pieces of logic can easily add up to a great big confusing mess.

Code is unmaintainable when it takes longer to understand it - than it does to rewrite it.

The ultimate test of code maintainability is whether it lives on (to be used, useful and enhanced) well past its originators.


1. Debugging Capability:

It is impossible to understand a flow of logic performed on variables - without visualizing examples of data within those variables.

In fact, it's impossible to learn any (e.g. math, physics, ...) generalization, without familiarity with the concrete examples upon which the generalization was induced.


2. Variable Scope and Type:

How a variable is scoped and typed is just as important as what it represents. Try to make it apparent where, what type of data is being changed.


3. Language Usage:

Some view software primarily as a mathematical construct. I view it more as language.

Granted that programmers make dozens of little micro design decisions in a typical day, and you can't be productive if you vacillate over each one. But there are a couple of places where a little more pause and thought have big effects on maintainability:

Try to use consistent naming.

It's incredible how little thought goes into consistent naming - yet this has a HUGE bang for the buck in making code and end user functionality understandable. Some common examples are:

From what your POST variables are called (it's helpful if their names correspond in some way to the database table columns that they will update), to having a button labeled "Copy to Cart" named "copy_to_cart" in the POST, to programmers who call a stream or file handle one thing on Friday and choose another name for it somewhere else on Monday (and yes, I admit I have done this too. But knowing this is bad, I usually catch it and correct it) - it really helps make code understandable to (at least) think about how to be as consistent as possible in naming variables, table columns, tables, etc.

Once again - everyone's code has inconsistencies. But if one has experience picking up other people's code, they will realize how much they detract from maintainability - and will be on the lookout for them. They will revise them whenever they get the chance to view their coding with a fresh eye (which is usually on Monday morning).

 

Think out warning and error messages.

e.g. "Invalid Input" or "Communication error" does not cut it when the problem is Unrecognized user" or "Invalid password".

 

Knowing the programming language isn't enough to develop good software (any more than being good at crossword puzzles means that one can write well).

Program logic has analogies to language prose, e.g.:
Readable Obscure
 if (can_machine_start(user_id) ) then   -vs.-   if (check_conditions(2, user_id)) then 
 start_scan(row, column, length, direction)   -vs.-   start_scan(product[lineno-offsetY], product[lineno+offsetX], sizeof(buffer1[lineno]), read_io(control34[lineno])) 

I believe those who can write straightforward, salient prose to boil down a complex situation - are also good at designing and writing straightforward, understandable code to solve a technical problem.

The more intelligent you are, the easier it is for others to follow your code.

The more you struggle to learn new things outside of your comfort zone, the more you will appreciate how to structure code and end user features so that others can more easily understand them.

The most common mistake I've seen is when management tries to address (difficult to follow, "high entropy") code support by looking for an expert in that programming language (rather than someone experienced in that type of application).


4. Commenting:

 

5. Don't Over Generalize.

The LESS a programmer understands the application domain (and its likely paths of change), the MORE generalized they tend to write the code.


6. Don't Over Reuse Code.

There is a (rarely recognized) tradeoff between code reuse and code cloning:


It is the tradeoff between using more if-then-else statements throughout a single module
vs.
repeating some of the code (among separate modules) to keep their flow of control simpler.

Less code (squashed down to the nth degree) does NOT always equate to simpler, easier to follow code.

Variations of this tradeoff:


7. Code Cleanup Can Be Overdone:

Cleanup can encrypt and overly fragment the code, making it harder to understand.


A Common Scenario:

Cleaning up code by localizing variables and creating common modules is great, but cleanup refinements can be overdone. Doing things like replacing text strings with enumerated variables (for performance), compressing code down too tersely, and eliminating all repeated code - often act to fragment a narrative flow and/or encrypts code. This is somewhat akin to effectively semi-compiling it after development to reduce its bulk. While the result is still far from a reduction all the way down to machine language (which is indeed compressed), prior knowledge of the unencrypted development source code holds a definite advantage (and is a common way for programmers to appear exceptionally intelligent) - yet

the code wasn't like that just after development because it had to be simple and straightforward enough for the originator to understand it.

Reasonable code cleanup and clean modularity aside,

the next person shouldn't have to tease it back apart to unencrypt it (or recombine it from various modules) - in order to re-understand it.


Least Favorite Software Engineering Philosophies:

Given the above, it should be fairly apparent that I disagree with some of what's out there. Two main counter philosophies are:


Finally:

Getting people to agree on what "good software" is - goes a long way towards being able to cohesively work together.

Finding help can be difficult when code is not easily understood by others.

kenfreed1