Software people love challenges and want to exercise their brains by tackling difficult problems. Our nature is to understand complicated problems, become familiar with various business domains, and generate a solution that helps the world become a better place. Nirav Assar explains four techniques to wrap your head around complicated code.
Software people love challenges and want to exercise their brains by tackling difficult problems. Our nature is to understand complicated problems, become familiar with various business domains, and generate a solution that helps the world become a better place.
During our journey, we may have to look at complicated code (or “spaghetti code”). If we don't understand the dilemma or code, we risk solving the wrong problem and wasting time and money. This article offers some techniques I have used in the past to muddle through complicated problems and wrap my head around complicated code.
We Are Intelligent
Most of us in software are intelligent. When trying to understand a complicated problem, intuition kicks in and we work our way to a solution in a free-flowing fashion. An example of this is just browsing through code and clicking around an application until we understand what is occurring. By doing this, we are forming a picture in our heads of how a system is working. After a while, we “get” it. This is our natural ability at work, and we may find it hard to explain how we arrived at our destination.
However, this technique is not scalable as the problem complexity increases. Relying on intuition has limits. Sometimes, you can look at code all day in bits and pieces and still never get a clear picture. This can be not only unsuccessful but also wasteful. We need a more disciplined, efficient, and effective approach.
Below are four useful techniques. They start with lightweight and intuitive and gradually trend towards more heavy and formal. Each approach has its own context, and you should use it where it is most effective.
1. Use Your Intuition
The best approach is to trust your intuition. This technique simply requires looking at the code and browsing until you figure it out. Don't jot down any notes. Just wrap your head around the issue. It is basically the “dig around and find out what’s going on” approach.
In my experience, this is the most common way that developers try to solve problems. It is beneficial for straightforward, simple issues. The domain of the problem should be understandable, the code should be readable, and the time taken with this approach should be minimal. The “intuition” approach is good because it is hands free, requires no discipline, and is the quickest in some situations. The drawback is that sometimes it doesn’t scale or just doesn’t work.
It is important to time box how long you work in this manner. Since using “intuition only” is the fastest and simplest method, it often is the correct first choice. However, if progress stops, you should use alternate methods. A common mistake for programmers is to spend too much time using this method before transitioning to a more formal method.
2. Document the Known, the Unknown, and Formulated Questions
When looking at a lot of complex code, your brain tends to jumble knowledge. Research has shown that brain comprehension decreases when processing more than three things at a time. Most people can only retain seven things in working memory at a time. How do we get past this limitation? Document your knowledge.
Taking notes is effective when trying to understand a complex domain, which could be code or even a sophisticated business process. While you are perusing code, jot down your ideas in a free-flowing manner. If you are listening to a business person explain a process, jot down the process in a free-flowing manner.
Now, here is where the novel idea comes in. After you have logged notes, take a step back and analyze them. Organize and structure the notes in a more disciplined manner. The most effective way is to create three sections: Known, Unknown, and Formulated Questions. Write down concepts that you understand clearly as bullet points in the Known section. Following this process, you will derive things that are unclear or not well understood; document these in the Unknown section. From this known and unknown information, you can formulate questions that you will direct at subject matter experts or research yourself at a later time.
This method is lightweight, fast, and extremely effective when you are wrapping your head around something complicated. It helps organize your thoughts, and the output is very direct, containing specific pertinent questions that get to the heart of the matter and eventually lead to a clear understanding.
3. FBI Board
The FBI board technique comes in handy when the previous, lighter techniques fail. It comes from watching some really good detective shows on television. In the television show, Flash Forward, the FBI is tasked with solving who caused a global blackout. In the other show, Dexter, a forensic specialist hunts down serial killers and is a serial killer himself.
In both shows, the protagonists set out to solve complicated crimes with a multitude of variables and circumstances. While thinking about the problem, they post all the facts and suspects on a bulletin board with thumbtacks. As more information relating to the crime comes through, they draw associations and possible outcomes.
How does this relate to software? You can use the same technique when you hit a brick wall and can’t figure out a problem. Take everything you know and lay it out in front of you on a whiteboard or some scratch paper. Stare at it for a while, and draw some relationships between items. Trust your intellectual powers to process the information in front of you, and let your creative juices flow.
On a government project that processed checks, I ran into a race condition issue where several transactions processed data concurrently. It seemed like the data entry disappeared into thin air after it was persisted to the database. I used the FBI board to enumerate all the moving parts. This helped me to qualify the scenarios, run some tests, and discover the problem.
4. Formal UML Diagrams
Unified Modeling Language (UML) diagrams have their purpose. When the goal is to communicate the structure of a system or a defined business process to many people, UML can be very valuable. UML is especially useful for understanding a large code base, even if it’s only to enhance the system with a relatively small change.
The most useful diagrams are sequence diagrams, class diagrams, and activity diagrams. In tandem, they offer both the structural and behavioral aspect of the system. Once you’ve taken the time to generate these diagrams, developers and business members can have a common visual depiction of the system to use as a base to solve problems.
Because generating these diagrams sometimes requires significant time and effort compared to the previous techniques, I recommend the UML diagramming technique when the lighter tactics come up short.
I had to resort to UML diagrams when working for a client that developed its own custom model view controller framework. The assignment was to add a simple upload page for a multimedia file. However, the framework had up to seven different layers with delegation and unnecessary code handoffs. It was so convoluted that it was difficult to understand the behavior without creating sequence diagrams. Every class was similarly named, and classes had unclear responsibilities. Drawing diagrams provided the structural and behavioral understanding necessary to make the changes easily.
Solving problems is at the heart of software development. When your head is spinning because you’re doing something very complex, it’s always best to take a step back and rely on some disciplined approaches. The above tactics are helpful to clarify the problem space and pave the way to solutions.