Software engineers switch between two modes: painful perfectionists and band-aid stickers. During the start of a project, software engineers discuss things to painful detail on whiteboards, Post-It notes, restaurant napkins and even glass doors. This eats away precious time that could have been spent on actual development. But as the deadline looms, the whiteboards and glass doors are rubbed, Post-It notes are torn apart and restaurant napkins are trashed. The plans are chucked in favour of anything that makes the application work.
Often, the released solution has plenty of duct tape code that holds the functionality together. After all the over-planning, duct-tape coding is the only thing possible in the limited time that the programmers leave for themselves. Software teams hardly release anything during the early phase of a software project as everything is put in meticulous detail on paper only. But as the deadline approaches, frenetic releases are made everyday or even every few hours, causing confusion among the developers, project managers, testing teams and the clients.
A flipped approach
What if I tell you to do the opposite? During the start of the project, you should stop thinking too much and instead quickly write some solution – a functional software application which is a proof of concept. You should learn things as you go. Get this put-together version in front of the world to try and give feedback on. Instead of planning an architecture at the start of your application, you should plan everything to detail after your crappy first version is written and released.
After the dust settles on the first release, you should slow down. Your subsequent releases should be made slowly and carefully. The closer the application is to the deadline or higher the version of your software, the slower and more careful your releases should be. Software engineering best practices such as clean architecture and SOLID principles should be applied meticulously to the subsequent versions, allowing the application to grow smoothly.
Instead of a grand architectural plan at the start of your project, your plan should be to refactor your already written and working solution. Remember that you are not constructing a building with a set plan. This is software, where plans can change any time and it is possible to change the code healthily through a disciplined approach called refactoring.
Here are 6 things that keep your software in the development stage for too long and prevent you from releasing and getting meaningful feedback as soon as possible.
1. Over-planning the architecture
Software teams love the idea of long meetings, drawing diagrams on whiteboards and looking at software like LEGO building blocks. Yes, you need all those, but at a much later stage when your software really warrants breaking things down into components. Your program will become a union of really tiny components as you add new forms of customisation and connections to other software applications.
But do not break a program into too many components on day 1. In fact, I am advising you against something that the world of software takes as common sense and sacred. Do not apply software models like clean architecture, model-view-controller, model-view-presenter or the hundreds of frameworks that are recommended as ‘best practices’ on day 1. Despite what they claim, the best practices complicate a small application beyond necessity. These models are extremely useful only when your application starts growing with multiple scenarios, more inputs, more outputs and more code repetition.
So what do you do on day 1? Just pick one or two scenarios that you know should be part of your first release, probably as proof of concept. Identify the main inputs, outputs and the steps to convert those inputs to outputs. Then write one or two big monolithic pieces of code that will achieve your target. It is okay to hard code numbers and strings. It is okay to keep all the code inside one file. It is okay to do anything that software pundits will look at with disgust. Relax. It is only in the first few versions where all the disgusting things should be. The aim is to get a fully functional application as quickly as possible. Since most of the best practices take time to conform to and slow us down, you should avoid them in your first version. We are looking for a short cut to a working solution.
2. Over-emphasising the choice of programming language
This is another area where software teams love to waste time. Discussing which programming language should be used for their application. iOS does a wonderful job of shutting this argument by allowing only Swift. Android used to allow only Java, but now has opened up an argument for Kotlin. Suddenly, we also have the option of creating web apps / native apps / hybrid apps. The options for desktop apps and servers are staggering.
Stop arguing and just pick one language for now. Simply pick one that you are most confident about delivering your first version. The winner of the argument should by default be the programmer who has been assigned the task of writing the program. In today’s world, programs written in different languages can easily inter-operate with each other by using inter-process communication. A program written in Python can easily call another written in PHP. Such programs are called microservices, which we shall see in another post.
3. Giving too much importance to the user interface
User interface plays an important role for sustained usage of a software application. Usually, applications with substandard UI are dropped in favour of those with a smooth and pleasing UI. A stable program must have a polished UI which the user is happy to keep coming back to.
That doesn’t mean that the first version of your program must have a world-class UI. The first few versions of any application must fully focus on getting the functionality completely working. UI should be a peripheral requirement. All requests to improve the UI must be put into a backlog for later implementation.
The first version of your program can use the basic UI that comes with the operating system. The UI can be made of simple widgets such as text boxes, check boxes, radio buttons and buttons. You don’t need even sliders or date pickers. Yes, it is okay to ask the user to enter the full date in dd/mm/yyyy format or to prompt him/her to enter a number in a text box, specifying the acceptable range as a foot note. The output doesn’t need to be animated charts. Simple text data inside tables will do. As long as the user has something working and his/her bigger problems are solved, he/she won’t create an issue about having to type too much or about the UI looking crappy. He/she will wait for you to catch up.
4. Overemphasis on programming rather than making a solution
Lets say that your application needs the current temperature in your city so that it can set the temperatures for the various plants in a vegetable-growing green house. During the first iteration of your software, it is okay to prompt the user to enter the temperature every six hours or so. You don’t need to make the application so complete that it uses a temperature sensor or fetches the temperature from the world’s best weather API. The biggest headache for the green house maintainer is to reach the temperature control systems inside a green house and set each of them to be suitable for a specific plant. Your software takes away that larger pain for the user.
Even for a little inconvenience, such as having to key in the current temperature every six hours, either through a touch panel or online via a web interface, the green house owner will gladly use your solution that takes care of automating the temperature controls inside the green house.
In your earlier versions, try to solve only the biggest pain point for which your application is being built. All other things can be taken care of outside the program.
5. Putting too many people to work
As mentioned in the 1st point, the first version of an application should be a monolithic program, put together at a fast pace as you learn how to solve the problem by converting input to output. Since the number of components is to be kept to a minimum and each component will not be made flexible enough to speak to other components, it doesn’t make sense to assign a huge team to work on the application.
One or two dedicated programmers should be used to develop a quickly assembled proof of concept. These dedicated programmers should ideally be left alone to work on that application only. They should not be shuttled between projects. The idea is to use a limited number of fully dedicated programmer(s) to put together a solution as quickly as possible, without getting tied down into the overhead of following best programming practices or creating a full-blown application architecture.
6. Putting too much effort on configurability
Sure, your application needs to be configurable. Users should be able to control as many aspects of your application as possible. Right from how many devices should be supported, the time zone to use, the currency format to use, right down to the font face and font size shown in the footnotes.
But your first version should make assumptions about certain inputs and avoid configuration. The aim of the first version is to solve one or two scenarios for which the user is willing to use even an imperfect application.
E.g. let’s say that you are making an alarm clock application. It is okay to allow the user to input just TWO timings, one for weekdays and another for weekends. That’s it. This will usually cover 80 – 90% of the user’s alarm needs. Why, I would even recommend you to drop the weekend alarm, having just one alarm timing in the application. Surely, the user can wake up to the alarm on weekends, switch it off and go back to sleep. In our first iteration, we are interested only in the success of the alarm in waking up the user at the time he/she desires to wake up most often. We can even restrict the program to have just one alarm tone.
With your alarm app succeeding at one particular time everyday with one tone, you can then switch your focus to expanding the app to have multiple tones and support for as many alarms as the user likes.
Conclusion
Software best practices, architecture design, frameworks, automation and configurability are definitely some features that must be part of polished and mature applications. But you must not focus on them on day 1. Your focus during your first iteration should be on building a rigid application that defies all engineering practices and displeases engineers and architects. But software is about users and solving their problems. The quicker you are able to deliver something for the users to see, the faster you can receive their feedback and validate if what you are building is really what they want. Once the user is happy, you can go back to your code and refactor it to match the best practices.