Remember the scientific method? You probably first learned about it in elementary school when you had to apply it to create a lovely tri-fold backboard science fair project. If that was not only the first time you used it but also the last, it went like this: ask a question, do background research, formulate a hypothesis, test the hypothesis, draw a conclusion and determine next steps. While this might bring back memories of long, drawn-out research projects, I have found that this exact method creates a great framework for solving many problems I run into at work.

Sometimes, the right approach to take when solving a problem can be opaque. When is it right to ask for help? When does it make sense to power through and find the answer alone? If asking for help, how does one do that while still maintaining co-workers’ high esteem? The scientific method can help guide this process: it will provide some direction on how to start solving the problem, and lead to the ability to ask intelligent and thoughtful questions. I will walk through both the basic principles as well as how I applied them to a real software engineering problem that I had to solve recently.

Ask a question — Start with a problem. Figure out what the component pieces of the problem are.

Using Go, a language I am still pretty unfamiliar with, how do I take in a generic payload and truncate its fields to make viable JSON, while allocating minimal memory and time?

Background Research — Think about what pieces of knowledge might be needed to solve the problem. Use Google, company docs, and similar code that already exists to build a foundation of knowledge to work off of.

I looked at the Go concepts that seemed the most relevant: empty interfaces/(interface{}/), switch statements, some of the finer details around pass by reference vs. pass by value for how Go handles specific types when passed into a function as parameter (answer: technically always pass by value, but this can be confusing depending on the type), slices vs. arrays. I also knew that my team had made an attempt at this problem in the past but it was not as memory efficient or fast as we needed, so I made sure I was familiar with that code.

Formulate a hypothesis — This could be the full answer to the problem or a theory that tackles only a portion. The answer might still seem far away but it is important to do this step; it forces a thorough understanding and is a good exercise for problems in the future.

After looking at the previous version of the truncator, doing my Google research, and sketching out some ideas, I came up with a possible solution that involved walking through the interface{} and encapsulating information in a variant on a linked list type structure. This preserved the order I wanted, limited memory usage, and kept track of what information to include in the final output and what was to be truncated.

Experiment — Take the hypothesis and test it out. The controlled, repetitive style of tests used in real scientific research are not necessary here, but the idea of finding components of the hypothesis that are easily testable is important. Some simple problems, like determining how a specific language handles the rounding of floats to ints, lend themselves to a simple experiment. For more complex problems try to find components that are clearly testable like above. In order to write an “experiment” for the larger picture, there may not be an experiment in the classical sense, draw logic diagrams or write the method signatures the hypothesis would require.

I could have sat down and cranked out my complete project but that would very likely have led to my being confused and writing less than perfect code. So, as a way to examine my hypothesis, I wrote out a simple scaffolding including all the public methods, a number of the private methods with quick descriptions of what they would do, and the data structure I wanted to use. I filled in some of the structure with very basic code just to make sure I could create and use my modified linked list in Go the way I thought I could.

Conclusion and Next Steps — At this point there should be more clarity around the problem. It is possible that the solution is now fairly obvious, and thus now solvable. If not, then what were once open-ended questions are now more targeted and concrete, and can be posed to a colleague. Going to a colleague at this point means that there was a chance to learn, develop a more solid idea of the problem being tackled, allows for smarter question and a more thoughtful dialogues to be had as well as being a demonstration of self-reliance and of respect for the co-worker’s time.

I now had a complete plan, and a few basic assumptions that I tested out. It looked like my approach was going to work, but since this was a fairly complex solution I wanted to run my ideas by my colleague and mentor. I walked him through my thought process and showed him the scaffolding that I had written. We ended up needing to tweak my idea a fair amount, but the scaffolding and POC were extremely useful. They provided something tangible for my mentor to look at and provide feedback on and the scaffolding provided the start to some code that I could quickly iterate on.

When I was first presented with the task of writing the truncator I felt overwhelmed and not certain how to proceed. Using the scientific method made the project more manageable. It made certain that I had a firm grasp on the high level problem I was trying to solve, which made it easier to understand the finer details. I still went to my mentor, but I was able to present a solution and engage with the feedback on a much deeper level.

Once I started employing the scientific method in this way I found that I was able to wrap my head around problems quicker, made the help that I received from my co-workers more valuable, and has helped to guarantee I continue learning. I find myself solving mini research problems everyday.

Originally published at lightstep.com.