This article describes some of the key traps software developers often fall into when working on numerous client projects and provides tips on how to avoid them.
Imagine falling into a dip that's 10 feet deep and trying to crawl out of it by clinging to the edges and scrabbling on the surface. The chance is high that you'll eventually get out of the dip on your own. The same is happening in software development; however, the more traps you'll get caught in when working on a software development project, the deeper your dip and the slimmer the chance you'll get out of it without external help.
Metaphorically speaking, avoiding traps in software development is like walking along a very narrow pathway with challenges on the left and solutions (most of which are really absurd) on the right.
Trap #1: Code optimization
"Smartass" type of developers often gets trapped by paying too much attention to code optimization.
"Premature optimization is the root of an evil," Donald Knuth.
Their knowledge of efficient algorithms or processor's firmware makes them think that the code should be optimized in the best possible ways. As a result, they spend too much time on code optimization, and the code becomes nearly unmaintainable, unscalable and unstable for errors.
How to understand you're getting trapped?
- You're attempting to write a fast code that doesn't require a lot of resources to run
- You're trying to squeeze everything from your code no matter how it'll affect other parameters
- You believe if you use bitshifting instead of multiplying all operations by 2 you'll make your code sexy
However, when trying to avoid premature code optimization, some developers actually forget about it until the final stages of development. So, when trying to avoid falling into a trap of over-optimization, you may fall into a trap of under-optimization. When you shift your code optimization to the final stage, you're at risk of facing the following challenge: in order to increase efficiency up to an acceptable level, you'll have to re-write at least 1/3 of your already written code instead of just running a profiler and fixing a couple of isolated algorithms.
That being said, if you don't provide for code optimization upfront, brace yourself for having to delete a lump of your beautiful and clean code at a later stage.
How to understand you're getting trapped?
- You believe any code optimization is premature
- You postpone optimization to the final project stages
- You refuse to design some tiny architecture solutions for future optimization
The Way Out:
- Don't try to optimize your code from the very first days of the project; instead, create opportunities and plans for timely optimization at later stages
- Don't postpone code optimization for no reason
- 20/80 is your rule of thumb - spend most of your time on 20% of code that will ensure 80% of the final result (and yes, use profilers!)
Trap #2: Abstraction
In software engineering, abstraction is one of the best features. At first there were binary codes, then there appeared processor mnemonics, followed by imperative, structured, procedural, modular, object-oriented and functional programming.
Now imagine you still have to use goto to arrange a cycle. As such, you still need to generate similar functions that only differ in data types. And you can't just take and modify the size of your collection; you have to highlight a new memory chunk, copy your old collection in it, add a new element and release memory not in use.
Excessive complexity
Let's start with a trap when developer's attempt to abstract everything becomes absurd. Abstraction evangelists normally clutter 20+ classes, use 12 different patterns, create own DSL to parse another DSL, build a cross-platform framework for visualization of cyclic graphs and do other messy things.
How to understand you're getting trapped?
- You start building a universal framework prior to implementing core functionality (and 30% of code will be used at most)
- You believe you can solve any challenge by using some pattern
- You create a generic, not a specialized feature, even if you know its functionality will never be used in real life
Too much of simplification
While experienced software developers normally like abstraction, rookies often ignore it and the best developers balance somewhere in-between.
Amateur developers are oftentimes unaware of many types of abstraction used in software engineering in general and their programming language in particular. Therefore, they usually write a very inexpressive code that would be easy to re-write using built-in tools or external libraries and frameworks. They think simplification will make project development easier and more effective.
How to understand you're getting trapped?
- You ignore abstractions that would be able to significantly improve your code (e.g., C++ iterators, Haskell monads, Python generators, Java interfaces, etc.)
- When you switch to a new programming language, you refuse to learn its abstractions because you think it's a waste of time. That said, you don't learn iterators when you're shifting from C to C++, nor do you learn monads when switching to Haskell.
- You believe that programming language features that you don't use are actually useless
The Way Out:
- Don't use abstractions for the sake of abstractions
- Use available / known abstractions appropriately and don't use them where they shouldn't be used
- Learn all possible abstractions provided by your chosen programming language
- Before implementing a feature, think twice if you really need it (You aren't gonna need it (YAGNI) principle)
- Use Keep It Simple, Stupid (KISS) principle, i.e. don't use abstractions if there're other easier ways to fix your issue
Trap #3: Perfectionism
That's probably the most popular trap most of smart software developers fall into.
How to understand you're getting trapped?
- You believe in beauty, readability and supportability as the top 3 features of a quality code
- You never stop refactoring and re-writing your code
- You search for bugs in every code snippet you see
- You spend too much time thinking about architecture, even for the simplest elements of your project
As we know, chaos is reverse to perfectionism. What if you completely ignore your code cleanness, refuse from refactoring and turn off your common sense and critical thinking when solving issues? You'll most likely fall into another trap - messy coding.
How to understand you're getting trapped?
- You don't think your code's readability and scalability really matter
- You don't think critically about your own code
- At least some acceptable result is OK for you as well as a totally unacceptable result
- You never re-factor your code
- You don't ponder over complex parts of your architecture
- You can't even imagine you'll ever have to re-write your existing code or part of it from scratch
The Way Out:
As always, it's somewhere in-between.
- Accept the fact that both your code beauty and its ability to help attain goals are equally important (the latter may be even twice as important!)
- Accept the fact that re-wrtiting code from scratch is the last resort, but still it can be unavoidable in some cases
- Identify maximum time you can afford to spend on code refactoring. It may account to 20%, 50% or even 80% of your entire work time. Yet, never exceed this time not to get stuck.
- When you spot a bug in the code, think whether it's really critical enough that you should start fixing it right away
- Use 20/80 rule, i.e. focus mostly on 20% of work that will bring 80% of a positive result at the end.
Trap #4: New tools and technologies
Software programming is a dynamic and a rapidly developing space that currently provides thousands of tools, plugins and libraries aiming to simplify your work. However, some developers are taking advantage of them, while others are still inventing a bicycle. Let's take a look at these two cases:
Laziness
Of course, using existing frameworks and tools is a sign of laziness to a certain extent, but sometimes it can have crucial subsequences. For instance, simultaneous use of boost, Qt and STL when writing "Hello World" isn't the best idea, but such things do happen quite often.
How to understand you're trapped?
- You connect a 30+ MB library for the sake of Mersenne twister (MT)
- You believe all you need has already been coded
- You never believe inventing a bicycle can be a better idea than using pre-built components
- You can't write a single line of code without using IDE autocomplete
- You use a lot of tools, but don't quite understand how they work (e.g. you're using Qt Creator, CodeGear Rad Studio, MS Visual Studio and other tools for visual editing of GUI without getting in-depth understanding of how each performs)
Workaholism
As the practice shows, fully ignoring programming legacy makes more harm than good. And it's perhaps one of the most dangerous traps for developers.
How to understand you're getting trapped?
- You keep inventing more and more new bicycles for no reason
- You believe your programming language features and standard libraries would be sufficient for any operations
- You believe autocomplete is only for those who have weak memory
- You're creating your own library, no matter how robust it is, that doesn't supplement functionality already provided by existing tools
- You believe troubleshooters and profilers are needed by those who don't understand how their own code works
The Way Out:
- Familiarize yourself with all of the tools available to help you complete your task, but don't use them here and there
- Evaluate all pros and cons carefully prior to choosing between using an external library and inventing a bicycle
- Try to improve your productivity by using modern tools, but make sure you don't fully depend on them
- Accept the fact there're many exceptions to the above rules when you're working on pilot projects.
Trap #5: Magic Pill
Remember using a non-trivial solution on your project and literally falling in love with it? It's another trap many developers are at risk of getting into. Magic pill is referred to a habit of using a favorite method everywhere, even where it obviously wouldn't work. None of us is insured from falling into a magic pill (aka silver bullet) trap: someone may fall in love with object-oriented programming and create classes for every sneeze, while the other one may use design patterns and build a whole program with singletons and factories. For some, their programming language is a magic pill, for others - a favorite paradigm or a development methodology is a magic pill. The main distinguishing feature of this trap is an attempt to use the same tool always and everywhere.
How to understand you're getting trapped?
- You use the same programming language / technology for all tasks and challenges across your project
- You believe that one paradigm can solve all of your issues
- You use the same methodology on all projects regardless of their conditions and prerequisites (e.g. your use of test-driven development on all projects can go crazy)
- You use a specialized feature as a generic one (e.g., you only pass all arguments by const reference; you only use one type of collections across the program; you use immutable objects everywhere; you use one indent style in languages with a different syntax like Java and C, etc.)
However, avoiding this trap is no rocket science.
The Way Out:
- If you know just one programming language, make an effort and learn one more or even two new languages to better sense the difference in approaches
- If you have one favorite language, but know more than one language, try to use other languages on your non-critical, or pet projects
- If you only have experience with object-oriented or imperative programming, try to acquire functional programming skills for differentiation
- If you're used to using one development methodology, learn and try to use a different one on your project
- Always think about alternative solutions prior to using methods you're accustomed to!
To be continued...
In part 2 of this blog post we'll address such software development traps as cross-platform development, secure and insecure programming, multitasking and more! Stay tuned with us by subscribing to our blog updates below or following us in social media!
[subscribe2]