13 Dreaded Disasters in Software Development
1 Coding without a Proper Analysis
You can start coding without any analysis and succeed. However, it is like a lottery - chances of you losing are much bigger. If you do it regularly, it is gambling with your project, and you may get into trouble.
A proper analysis is important to understand the essence of the developing project or its extension. You should communicate with the client a lot to understand what issues must be solved, what is their nature, how they relate to each other and what will be their impact on the existing solution. Various kinds of diagrams as flowcharts, simple UML diagrams or wireframes may be useful in this stage. The natural language may be very ambiguous - make sure you and the client are on the same page.
Brainstorming is a very useful way of getting another point of view on an issue. Speak about possible solutions with your teammates, let your imagination work, do not fear crazy ideas and avoid any mockery of the colleagues’ thoughts, even though they may sound silly. The most important rule is to free your mind and let the ideas flow freely. You will separate the grain from the chaff later.
In case the project is bigger, do not try to resolve every little aspect in the beginning. Outline the solution in larger contours and continue with partial analyses later. Do not forget that waterfall development has been overcome, one big analysis followed by the rest of the development process is not sufficient and any mistakes made in it would become very costly later. Software development is a dynamic and complex process and that makes it also very unpredictable in long terms.
2 Wrong Estimation
The estimation is a tricky thing, which may easily get wrong and thus endanger the whole project. Estimation of software development can never be absolutely accurate. Software development is not a routine matter, it is a creative process with many possible hurdles and unpredictable complications. However, it does not mean you should retreat on estimation completely. On the contrary, you should do your best. The key is to divide larger tasks into smaller ones. The task should not take longer than a few hours or a day. Start with big tasks and break them down gradually into smaller ones. Do not count only with implementation and programming, think about analysis, prototyping, testing, and deployment.
If you identify tasks that are too uncertain and it is hard to predict the time to complete them, mark them. You may try to make a lower and upper estimate for uncertain tasks.
3 Unknown Target Environment, Infrastructure and Scaling
The development environment and the production environment can be diametrically different. The developer’s machine could be more powerful (with a better CPU and a larger memory) than an end-user’s computer. Or, the target system may be missing an important service or framework, the versions may not be compatible, the change of a component or module on a target machine can be restricted. An external web service may be inaccessible from the given infrastructure or through a firewall. A security module may block some features. There are countless possibilities of how it can go wrong.
That is why knowing the target environment and its infrastructure is crucial for the development of software. Especially a new one, but the extensions of an existing system are no exceptions. The behavior may change and the external dependencies with it.
Try to identify the software external dependencies, the allowed versions and the differences between development and production environment. Find out the average and maximum system load in operation. How many concurrent users will access it? What is the reliability of the target environment? What is the bandwidth of the internet connection?
4 Wrong Technology or Framework
The same framework may be good for one software and still completely inappropriate for another. A framework may be perfect for game development, but totally unusable for a business application.
It is important to know whether the chosen technology or framework is reliable enough for your solution. The latest framework may be too buggy, the older one may get deprecated. Do your research about the technology you are planning to use, know its limitations as well as its strengths.
5 Unclear Naming Conventions
Using various naming conventions within a single data model or code of a project module may lead to errors that could have otherwise been prevented. Choose one notation you will use (preferably one that is standard for the respective area) and instruct the whole team about it.
A clear naming convention speeds up the development. Once it saves time to a developer when trying to find a desired entity because they know the rules, and again when they name the new entities. They do not decide which naming convention to use when there are many of them.
6 Reinventing the Wheel
Do research about existing solutions before you start to code to prevent doing a thing that exists already. Understanding, configuring and integrating an existing component may be time-consuming, but still less than developing the same thing again and then fixing similar or same bugs and problems that have been already resolved in the existing solution.
You should use components whenever they fit your requirements about functionality, reliability and performance. In case you have not found any suitable component, you should implement your custom solution. However, even in such cases, you should not reinvent the wheel. You should utilize the design patterns and proven software architecture concepts.
7 Copy&Paste Programming
Copy & paste programming is a bad practice in software development. Copying a part of code to several places is never a good idea. If a bug is in this code, you must fix it several times. If you want to implement some improvements in the copied code, you must do it again and again. There is a high chance that you forget about a copy that will be not fixed or improved and it makes the development even more expensive.
A good way to avoid the copy&paste programming is to follow the DRY (Don’t repeat yourself) principle. It states that every piece of knowledge must have a single and unambiguous representation within a system.
8 Undocumented Core Concepts, Missing Comments
Missing documentation for core concepts and important parts of software is hazardous. New team members spend more time trying to figure out how the given code works and asking the other colleagues about things that are not clear to them.
Documentation is important on two levels:
- Project, modules and higher concepts – in text form and the form of explanatory diagrams. UML diagrams, flowcharts or any informal diagrams of important parts and core concepts are a great addition to text descriptions.
- Source code – in the form of comments, method and argument description. The meaningful and self-explanatory names for fields, properties, methods, functions, and classes should form the necessary base.
Especially complicated and unintuitive parts of code should be documented and commented thoroughly.
9 Underestimating Impact of Changes
The world changes every day – what was perfect yesterday may be obsolete tomorrow. The software depends on external changes; they are the engine of the development. The new requirements must be incorporated into applications and systems to be relevant in a changing environment. Every change affects how the software system works overall. Before implementing a change, we should analyze it to know its impact. Even a seemingly small change may have unexpectedly unpleasant consequences. Know the relevant dependencies of a changing module and the impact of the change to them.
10 Overgeneralization and Silver Bullet for Everything
The assignment is to design a cottage, but you end up with a two-story villa with a pool and a large garden with many benches and fountains. Or you should create a table knife, but you will offer a swiss knife to your customer in the end because what if he also needs scissors or a corkscrew during his dinner?
When developing software, you should be careful not to think more about possible future purposes as an addition to the actual ones. Remember that the future is highly unpredictable and if you come with a solution B, which should be better and more universal than solution A (which was actually requested), the future will bring the need for solution C most likely and your solution B will be pure wasting.
11 Insufficient Testing
Even the simplest software is a complex beast. If we want to tame it, we will need testing. A lot of testing. Whereas things can go wrong at various levels, we also need tests on these levels – unit tests for the testing source code, its functions, and procedures, integration tests when assembling the modules, manual tests, usability tests, regression tests, and deployment tests.
If you do not provide enough time and resources for testing, you risk releasing a faulty product. Count with at least 40% of implementation time for the testing phase.
12 Lack of Communication
Things can go wrong easily without communication within a team and outside to external teams. One team may not know about the obstacles of another team. If it does not communicate the blockers to the other team, it may not adjust the plan and this may have an influence on the common delivery. Another team may also help with resolving blocking issues if communicated properly and on time.
The team members should speak about their decisions, progress, and problems in the project on a daily basis. It will help them to proceed more effectively.
13 Fixed Deadline
Deadlines are important and estimation should allow us to deliver the final solution in time. However, as we know, real-life brings hurdles that can break even the best estimates. The tests can reveal problems that will need more time to fix them. If the deadline is near, there may be tendencies to underestimate the severity of the remaining problems and hurry up the release of the project. In these situations, be extra careful and rather postpone the delivery than to release a buggy product.
Define the deadline but be prepared to move it if the product does not fit the quality criteria.