As I develop as a programmer, I take on certain habits that are helpful when planning a program. These could be summed up as taking a step back and thinking straight before getting to the thick of code.
Compartmentalizing the two creates a space of focus solely dedicated to logic. When the time comes for programming, I have a clear-enough map of the territory ahead. A clear-enough idea of what I’m trying to accomplish which in turn facilitates the search for specific solutions built-into the language. This, it turns out, can be a helpful antidote against trying to memorize every method in a language – a shift from what to how.
When giving it all some thought, some themes emerge:
1. Breaking things down
Any problem or challenge is made of parts. The first question is to determine what these parts are; and then what parts those parts are made of. Answering this question pulls me away from trying to solve everything at once.
In the case of a simple calculator, for example, I can break it down into first, getting user input (numbers and operator); then performing the operation; and finally displaying the result.
The broad idea of a calculator is broken down into three more granular procedures; and to each, the same question can be asked. What parts is it made of?
Cultivating this mindset is not only helpful in programming, but it trickles down into other areas of life. It creates a stronger sense that things can be achieved if properly broken down. Having said this, I recognize that knowing what to break something into is, in itself, a skill.
2. Writing before coding
In essence, writing pseudo-code before getting into the thick of programming. Being an experimentalist myself, it can be hard sometimes to find the patience to plan before doing. Personally, instruction manuals don’t stand a chance to the joy of figuring it out.
But, writing pseudo-code can be to programming what prototyping is to design. Prototyping the logic of a program in advance makes it so that by the time I’m coding it, I’m already working on a more sophisticated idea of the solution. This is helpful!
So, my version of a helpful yet doable pseudo-code is one where I’m already writing programming logic, despite it being in a more human-friendly language. Pseudo-code is most helpful to me, personally, when I can strike a balance between the two.
3. Prioritizing imperative problem-solving
At this stage, there is a helpful distinction to keep in mind: that of an imperative versus declarative approach to problem solving.
John V. Guttag of MIT puts it clearest, in Introduction to Computation and Programming using Python, when he states that imperative knowledge is “how-to” knowledge; a recipe for deducing a solution. Whereas declarative knowledge is made of statements-of-fact about said solution.
This translates to pseudo-code in that taking an imperative approach to problem solving is akin to focusing on the logic without using any specific constructs or tools of a specific programming logic.
To put it clearest, to manually go through an array of numbers:
Even though, at times, it’s helpful to jump straight to a declarative solution, in the overall context of problem solving, taking an imperative approach and actually figuring out the recipe makes for better thinking.
4. Using programmatic keywords
Now that we’ve made this distinction between imperative and declarative thinking, we can look at the syntax of actual pseudo-code. At its core, it's meant to be unconstrained by the syntax of programming languages, while still using certain keywords and constructs that map to the universe of programming.
Some keywords lend themselves more to imperative thinking by virtue of being non-language specific programming constructs. These are primitive concepts akin to directions such as: move, left, right, turn back.
Other keywords are declarative in that they mirror existing methods in a given language and can encapsulate a series of procedures into one single word. The real world example of this is to tell someone to go from Venice to Santa Monica – a lot is implied in that simple direction.
In the example of the calculator mentioned earlier, I can write pseudo-code to explore the first step of getting input from the user. This combines an imperative approach to the overall design with some declarative tools such as the use of a function with an argument, and a RegEx test to check if the input provided is indeed a number or an operator.
5. Visualizing to reduce complexity
In cases when the problem is more complex and / or a whiteboard is at hand, there is a form of visualization through flowcharts. Just like in written pseudo-code, I learned (at Launch School) that there is a method to the madness in the form of visual keywords.
So if I take the pseudo-code from before, I can also plot it visually, it goes somewhat like this:
I wrote this to organize my thoughts, but if this is of help to you out there, awesome. Any improvement suggestions are welcome!