Good habits of productive software developers needed for great coding

Branimir Hrzenjak

There is no structured step by step manual for coding. If two programmers are asked to code a program for the same task, the two pieces of software they come up with will have very few similarities.

They will be siblings, but not twins, achieving the same end objective but with some substantial differences.

Similarly, there are habits and strategies that each developer can either adopt or ignore when coding, which will greatly affect the look of the finished code.

Nevertheless, despite the fact that there is room for individual preferences when creating code, there are certain practices all developers are likely to adopt, simply because they guarantee better results.

This article explores beneficial habits that help developers code more efficiently and hopefully transform their coding from good to great.

Planning the code

What happens when developers go into a project blindly?

They begin, the code doesn’t perform as expected, they rework and troubleshoot, only to realize hours later that the feature could have been done with a framework and an API.

When coding, planning can take developers a long way.

Consider grocery shopping.

People don’t buy whatever food catches their eye when they’re at the supermarket because they’d wind up with pasta, sunflower seeds, and ketchup—nothing to make a meal out of.

Instead, they create an ingredients list ahead of time and follow it so that the end result is lasagne.

Coding isn’t dissimilar: developing an action plan beforehand helps point developers in the right direction. Roy Carlson quipped about this phenomenon:

Source: Shake

The takeaway from the above is that the preparatory work done before they start coding can save developers a significant amount of time.

Developers can benefit significantly from sitting down and writing out a general outline and the main specifics of their project.

They do this by asking themselves questions about the task, which compels them to formulate solutions by self-interrogation.

Some helpful questions to ask are:

Source: Shake

Think of these questions as a springboard for the project.

For instance, “What does the app look like?” often translates to “What type of wireframe do you want?”

From there, it’s time to investigate CSS examples for ideas. Consider the framework options—what features will you have to implement?

Bug and crash reporting tool for your app

Try Shake SDK for free.

The answers to these will help developers construct their plan.

Once you have those answers, visualize them somehow. Sketch a flowchart, or use Trello boards.

Ensure that there is a roadmap for achieving all of the goals defined by the answers to the questions.

For instance, below is an example of a flowchart for a translation app.

Source: ResearchGate

Such a flowchart helps guide developers through the necessary steps towards those predefined goals.

With these two tacticsùa Q&A session and a specific roadmap—they have a detailed plan to follow while coding.

Thinking about code organization

Code organization is not a must. The computer doesn’t care if the code is full of single-letter variables—it will still run.

Nevertheless, organization is vital for productive developers to maintain code.

For example, what happens if one day a developer realizes they can’t find the correct method or class?

What if a colleague takes over someone’s work, only to find 8000+ lines of code in a single file?

The authors of the famous “Wizard Book” commented on this.

Source: Shake

That being said, one of the prerequisites for reading programs is for the code to be easily navigable.

Breaking up the program into several files is one of the most common organizational procedures. Thousands of single-line code do not constitute an elegant solution.

Every recompilation will affect the entire file, which impedes finding a specific function or statement.

However, with multiple smaller files, developers only need to recompile the modified files, and it’s easier to find specific parts of code.

For larger programs, those files can then be sorted into separate folders for a clearer overview.

Ruby on Rails even comes with a default directory structure, with a folder structure already recommended. Take a look here:

Source: Medium

Here, files are grouped according to the function they serve in the bigger picture, which might be useful for developers building their own structure.

It’s also worth keeping an includes folder handy. That is a folder containing all code that will be re-used in the project, such as headers and footers.

Therefore, if a source file needs access to a global variable already present in one of the header files, no changes are necessary—the header file is already included.

Therefore, critical thinking plays a prominent role in coding, as it dramatically facilitates work processes. In fact, it’s not uncommon for recruiters to test organizational skills, as seen below.

Source: Twitter

As demonstrated, knowing how to organize code is a skill crucial for any efficient software developer—it makes the lives of everyone on the team easier and is guaranteed to improve productivity.

Not overdoing features

There is such a thing as doing too much.

An eager developer can sometimes take things too far, implementing features that are not yet in the pipeline simply because they assume that these assets will be needed later.

Assume is the key word. The developer hasn’t been instructed to design these functions. They just think it’d be wise to have them—a tendency called overengineering:

Source: Shake 

In other words, overengineering refers to thinking too far in advance or too laterally—building just in case where there is currently no need to do so.

A classic example of overengineering is Bugzilla.

An is_active column was added to the codebase, which was supposed to one day enable the administrator to disable selecting certain choices.

Three years later, those choices remain to be disabled, yet the column is still there in the codebase, accomplishing nothing.

Therefore, developers must keep their main goal clear and focus on one objective without veering off into side quests and wasting both time and resources.

There is a simple acronym that can help them stay on track: KISS.

Source: Shake

KISS stands for keep it simple, stupid or keep it super simple—either phrase works.

It’s a reminder for developers not to dive into any needlessly complex trappings of the code, as one of Sagitec’s Software Engineers reminds us.

Source: LinkedIn

If developers keep the KISS principle in mind, they can become much more productive without wasting energy on unnecessary things.

Keeping consistent naming conventions

Naming conventions are similar to code organization—the computer doesn’t mind how code is named, but people certainly do.

Software developers rarely work alone, and naming readability is a crucial component in a team—it makes it easier to find files in a project and helps with predictability.

Nomenclature is so essential that Netscape’s Phil Karlton said the following:

Source: Shake

There is, however, one trick that helps—making sure the names are consistent. Pick one method per operation, and then stick with it.

There’s nothing to be gained from inventing multiple names that ultimately all refer to the same thing.

For example, if it’s agreed that fetch will request information, a rogue retrieve or import cannot be inputted into the code haphazardly.

Take a look at the middle row in the below image for a visualization of the idea.

Source: AppWorks

Similarly, it doesn’t hurt to name with a standard format in mind. In the screenshot above, an underscore is used as a space between groups of words, and a lower camelCase naming convention is in place.

If these distinctions have already been decided, don’t go using Kebab Case or any others.

Helpfully, several languages have their own naming conventions that serve as a guide for developers.

Rust’s conventions are in its official documentation, whereas Kotlin follows Java’s footprints, also summarized in the official Kotlin documentation.

Before starting a project, it would be productive to double-check the language recommendations—there might be some pointers.

Android projects used to be particularly tricky, as they had their resources defined in XML but inconveniently without namespaces.

Thankfully, the XML naming convention can solve this problem, as depicted below.

Source: Jeroen Mols

This Android naming logic, developed by Jeroen Mols, is a great resource to have bookmarked and should cover the most common naming pain points, making for a cleaner project.

Debugging the code regularly

Periodically debugging while coding is perhaps the most helpful habit for developers. They will save themselves countless hours by doing it as they go along.

Debugging the code once the entire project is complete, as it can be time-consuming and exhausting.

Simply put, no one wants to comb through thousands of lines of code to find errors.

Checking for bugs in regular intervals is much more productive, as they routinely verify if everything is running smoothly.

And, if it’s not, they know precisely which block of code to investigate for the error.

Once they have found the bug, they should try to recreate it. Replicating the error will make it easier to understand what precisely is causing the issue.

If that doesn’t work, there’s always the tried-and-tested rubber duck method. Who better to help work out a complex problem than an inanimate plastic object?

Source: Duckly

The rubber duck method involves explaining the problem in the code, line-by-line, in plain language to a rubber duck.

By articulating the issue in natural language, developers walk through all the particulars of their code and, hopefully, realize their mistake.

A similar, only slightly more technical technique is print statement debugging.

While the program is executing, developers will use print statements to generate output, which helps identify the program’s errors.

This procedure is one of the more basic debugging techniques, but it’s stood the test of time.

Paul Graham, List extraordinaire and Y Combination co-founder, is an advocate of this approach.

Source: Twitter

Moving forward to more recent tactics, a useful modern debugging tool is Shake. Shake streamlines the process of reporting bugs in mobile apps dramatically.

All users need to do is shake their device once they encounter an issue, and a detailed bug report will be sent to the development team. There is an example of this below.

Source: Shake

When submitting the report, users can also include screenshots, screen recordings, and markup notes – elements that help the report be as comprehensive as possible.

Avoiding repetition

One of the golden rules of software development is—you guessed it—another acronym: DRY. DRY stands for don’t repeat yourself and advocates that no two pieces of code look exactly alike.

The phrase was first coined in the 1999 book “The Pragmatic Programmer” and defined as follows:

Source: Shake

The reason for that insistence is that having multiple identical lines of code makes it harder to maintain.

The problem arises as soon as developers want to make changes. Instead of adjusting one single piece of code, they must now edit all that code they had repeated earlier, increasing code churn.

Nick Lockwood, founder of Charcoal Design, articulates this pain point below.

Source: Twitter

Besides being uninspired and bland, repeated maintenance is also a painstaking and detailed process where developers can easily lose focus, making it an ideal environment for possible bugs to creep in.

Instead of blindly repeating code, it is much more productive for developers to create functions to perform these tasks.

Functions have several benefits over repeated code, but their main strength is their modularity. Namely, functions written for particular individual tasks can be used over and over.

This, in turn, makes them easier to maintain than identical code, as developers are only editing one function instead of multiple pieces of repeated code.

Once a function is edited, every location where that same task is performed is automatically updated.

Another two popular methods are efficient as an alternative to DRY. The first is abstraction, utilized for designing classes.

If several classes have some business logic in common, developers can then abstract this logic into a superclass, subsequently inherited by each class. A model of this practice looks like this:

Source: Plutora

The image should nicely illustrate the difference in quality between plain repetition and abstraction.

Besides abstraction, another common technique is normalization. Often used for designing databases, it allows developers to extract the replicates into a distinct entity.

The source will then reference that same entity. The process is depicted below:

Source: Plutora

This flowchart outlining normalization is a superb alternative to simply repeating code; hopefully, it will assist developers with implementing DRY.

Leveraging comments to explain the logic behind the code

The final tip is perhaps the most tedious but invaluable—comment on the code. While coding, this might seem unnecessary and exhausting.

Why should developers comment on their own code? They know exactly what it does, they wrote it, after all.

The thing is, they understand the code at the moment while writing it. What about when that same developer comes back to the code after a few months? They’ll be completely lost.

This is why comments are invaluable. They explain the reasoning behind the code, the why behind the how. Donald Knuth, Professor Emeritus at Stanford, also remarks on this approach.

Source: Shake

As per Knuth’s appeal, code must be digestible not only for computers but also for human beings.

One of the easiest ways to achieve this is by keeping code meticulously annotated through comments, to express the logic behind it.

Below are examples of typical helpful code comments taken from a Quora thread.

Source: Quora

All these explanations are vital for future maintenance and embellishment, as it warns future developers of what can and cannot be meddled with.

Such comments are invaluable when working on the code at a later date.

Another essential type of comment is those that include resources such as legal notices, copyright information, provenance, etc.

An example of a comment containing license information, for example, is shown below.

Source: Red Gate

These comments are valuable as they contain particulars that are absolutely impossible to be expressed in code.

As to where comments should be placed, developers spend a great deal of time in the editor.

It isn’t a bad idea to notate your comments there, as this should make them both easy to find and create.

There are even free JetBrains and VSCode extensions designed for this very purpose, amongst countless other productivity tools.

Conclusion

Good coding is nothing to scoff at. It gets the job done, and at the end of the day, the program runs as envisioned.

However, great coding is one step above—not only does it function smoothly, but it is also easily read and understood, providing elegant solutions for tasks at hand.

Habits that seem small and insignificant can actually make a huge splash in one’s productivity, at least when it comes to coding.

Hopefully, we’ve inspired developers to pick up at least one of these habits; they can truly form the defining line between good code and great code.