Thoughts about Thinking

·

19 min read

Something you'll come to note is I'm a sucker for structure, preparedness, and forethought. While I both enjoy and see the value in jumping into a project and hacking together an MVP, it's fair to say I prefer to take some time to consider what, how and most importantly, why and for whom. Often, in small, iterative cycles. Here are a few tricks I store up my sleeve you might find useful.


Why do we plan

If someone asked me what's the one certainty of software development, I'd answer that nothing stays the same for long. But don't confuse this as certain technologies or methodologies becoming a cold and barren wasteland the moment they turn 6 months old. Numerous languages, tools and workflow methodologies developed decades ago are still in heavy use and refinement today. Why? Because they work.

A building may be functional without solid foundations, but it can crumble when subjected to high pressure. In other words - I like to learn the basics before taking advantage of the tools available to use which speed up development. I made sure I had the foundational knowledge in JavaScript before attempting to use AngularJS, for example. So I have a set of methodologies I find rather useful for enabling this. Everyone is different. Different groups of people learn in different ways. But I'm of the mindset where I enjoy the constant learning curve of my work, both professionally, academically and personally. I rarely feel unchallenged and that's my life force.

Now, you could liken these processes to BDUF, which we're told is unspeakable. You could call it 'big learning up front'. Regardless - it enhances my learning styles. I must say, however, that the important part is making the distinction between when you can afford to BLUF, and when you just need to get the ball rolling with a framework for rapid prototyping and stakeholder demos. So, even when we BLUF, it's useful to have a structure to follow but it's not always the answer. Sometimes, experimentation and hands-on is more suitable. That's where the techniques in this post come in handy for me. Maybe they will for you, too.

It does not do to leave a live dragon out of your calculations if you live near him.”

― J.R.R. Tolkien, The Hobbit

The Methods

I categorise these methods as below. Most of the category titles are fairly self-explanatory, but I'd like to elaborate on some. Feel free to skip around between them as per your needs.

  • Learning
  • Problem Solving
  • Blockages
  • Debugging
  • Productivity
  • Time and Project Management
  • Documenting
  • Reflection

Learning

What better way to attack the learning of a new concept than with the Feynman Technique. The philosophy behind it is remarkably simple - so much so, it's easy to overlook or undervalue.

To me, the philosophy of the Feynman Technique encapsulates 'the great explainer', himself. Although this quote wasn't spoken by Feynman, I feel it captures the essence of this technique perfectly:

“If you can't explain it to a six-year-old, you don't understand it yourself.”

- Albert Einstein

Videos: Sprouts, Scott Young, Thomas Frank.

Articles: Linkedin, Scott Young (Transcript).

All of these sources have a slight variation on the structure or content, but I think that's okay. The important takeaway is the conscious decision to structure your approach to learning in such a simple manner that you could teach it - that's the power of it.

The structure tends to follow this format, however:

  1. Identify a subject area and the concept within it which you wish to understand, or understanding deeper.
  2. Explain and example the concept as if explaining to someone less experienced than yourself. Sometimes in many forms or representations.
  3. Should you find yourself blocked, refer back to resources and study up on that section of the concept. Revisit step 2. Otherwise, onwards to step 4.
  4. Create analogies for the problem as a memorisation shortcut and to abstract the concept for summarising it to others. Make it relatable.

Feynman was a wonderful Physicist who had a famous ability to see the world with such curiosity and excitement, and he was wonderful at communicating that. I don't have enough time or space to list all those men and women of the STEM subjects whose work have changed the course of history and have been so influential on my outlook on life, the Universe, and my work. But Feynman is one of the most influential communicators with his simplistic but accurate explanations.

The real problem in speech is not precise language. The problem is clear language.

- Richard Feynman

Problem Solving

I shan't spend too much time here, as I've covered it before. You can check out that post here. Another handy resource for a more succinct model to adhere to is the IDEAL model.

Blockages

We've all been there. Regularly, in fact. Getting stuck on a problem is frustrating, particularly when it's your bread and butter. For when a problem-solving framework just can't help or takes too long, fear not, there are always other options.

Initial Exploration - 10 Tab Rule

Something I discovered through Ken Mazaika's post on dev.to, I find it integrates rather well with the next method - RSA(E). The method being - when you get stuck, craft a good question to exercise your Google-fu, and open the first ten tabs. Read those. Go back to your problem. This can also be used as a research technique.

Something Ken writes in his post which really struck a chord was:

It’s a subtle mentality switch, but it’s important. Beginners often have the mentality of:

“I don’t know, and I feel stupid because of it.”

However, experienced developers have an entirely different mentality…

“I don’t know, let’s figure this out as quickly as possible.”

Subtle, it is. I can't pin down when it happened, but I see this switch in my own work, now.

RSA(E)

It's an easy method to remember thanks to its abbreviation. While it's not particularly pneumonic, at least it's short! It's somewhat tailored to development, but can be adapted and applied to other areas. I have an inkling it was an episode of the CodeNewbie podcast which first led me to this FreeCodeCamp post on the method.

The process is simple: when you get stuck, read the documentation. If that's a little wordy or unclear, search the internet for simpler explanations and example use cases. Still a little unsure? Ask. Whether it be online, or in person, the crucial thing here is to show your previous efforts - give sources and explain your current understanding and misunderstandings.

Failing these 3 things, this is where my adaption of the model comes in. Experiment. Realistically, this one is entirely flexible. It can be placed at any index in the model. Wherever you chose to do it, however, it's still just as powerful. Play around and see what you can figure out then find the 'best practice' way to do it.

Rubber Duck Debugging

To most initiated and experienced developers, hearing about this technique is like hearing the sky is blue. Jeff Atwood wrote a great post with an example scenario back in 2012. The idea being that you vocalize your thoughts. The duck (or any other object, including yourself) acts as a listening sponge. By getting no response, we instinctively continue to discuss and explain.

Asking questions of yourself and detailing your thought process aloud gives an instant feedback loop. Often, you end up looking at the same problem from a new perspective or find a solution before you've finished explaining it. By having to explain it aloud and vocalize each thought, you're sure to understand the problem domain fully.

It's not suitable for all. Some people aren't comfortable with vocalizing their thought process. Some work in offices with colleagues who like the quiet. Some of you might even work in open spaces where you can barely hear yourself think. You can try to find alternatives or a workaround to suit your situation, by all means. I'm interested to see how effective it is as a non-vocal method. I prefer to vocalize, but, again, your mileage may vary.

The 5 Whys

It's difficult to fault the simplicity and effectiveness of this technique. A great starting point for this technique is the StackOverflow Podcast #107 (48m30s). For a quick summary, check out Matts SO Meta answer here. This episode has a great section on making mistakes in development work and in general. If this is a fear that holds you back, I highly recommend you listen to it. Once you hear some of the mistakes the big names in that podcast made, you'll feel much better. Highly entertaining! For those who need a visual source, have a read of Joel's blog post at 'Joel on Software'.

And for those who have neither the time or ability to listen to a podcast currently - here's the gist of it. We identify a symptom of a problem, and ask "why?". Once you formulate a cause from thinking or evidence ask it again. Ask it 5 times. The benefit being that by asking this question recursively 5 times, we end up performing a simple form of root-cause analysis.

Debugging

Some might consider this area a necessary evil of software development. I consider it one of its wonders. Why? Because a bug indicates something we thought was right, or didn't think of at all in some cases, is fundamentally broken or flawed. And this leads to discovery - nothing drives exploration like the unknown. We've witnessed it throughout the last few centuries in Scientific development. When a Scientific theory or law is fundamentally flawed, we don't patch it up to make it work - we use that lack of understanding as an opportunity to discover something previously unknown to us. Why should software debugging be any different?

In fact, maybe the question we should be asking is; why is it different?

We're all guilty of putting a plaster (aka. 'band-aid') over a bug at 5 pm on a Friday. Don't mistake me as being starry-eyed - we all have deadlines. And sometimes, you just don't have the time or mental effort to think of a bug as anything more than a pothole in the road where filling it in with leaves is effective enough. We shouldn't excuse ourselves with that "grand refactor in the sky". But, should we not strive for better? Should we not take influence from the giants whose shoulders we stand on and use it as a chance to explore a new mystery and discover something new?

Scientific Debugging

That's my take on it, anyway. After all, computing is Science and Mathematics. We may interact with it at a higher abstraction, but why should that mean we think about it at that same high abstraction level when things go wrong?

That's why I use the scientific method when debugging. For me, debugging is an entire mindset change. Instead of asking "what is stopping A from working?", try asking "considering the inputs, what might lead the output of A to this state?".

Here is the Scientific Method:

  1. Make an initial observation
  2. Question your observations
  3. Develop a hypothesis from those questions and observations
  4. Develop a prediction about the hypothesis
  5. Design a method of testing said prediction
  6. Test the hypothesis and gather data
  7. Evaluate the effectiveness of the test, and results with respect to the prediction and its hypothesis
  8. If it doesn't confirm the prediction of the hypothesis, we adjust and re-test, or develop a new hypothesis and prediction.

In practice, it's an iterative cycle. For a more in-depth view, take a look at its Wikipedia entry. Specifically, the wonderfully simple graphic from ArchonMagnus, which shows a variation of this cycle.

Applying this to Software Debugging

I'm not suggesting every step must be explicitly ticked off. And maybe you already follow a similar structure. Maybe this is glaringly obvious to you. But to some, it isn't. And to some, having such structure gives them a mindset to approach the problem with.

So, how do we translate into debugging? Well, it turns out it's incredibly similar. For a short, visual representation of this cycle, Udacity has this video on YouTube which explains it with an example. I also highly recommend the "Debugging with the Scientific Method" talk given at ClojureConj by Stuart Halloway.

  1. Make an observation using actual input and expected output, and note the actual output of the unit suspected as faulty.
  2. Question the components involved within the domain of the unit, and determine which might be involved when leading to the erroneous output.
  3. Define a hypothesis for the cause of our error or misbehavior which is consistent with our observations.
  4. Define a prediction for the hypothesis, when eventually testing.
  5. Design a test using our hypothesis and assert our prediction.
  6. Gather the results and determine whether they meet the hypothesis and its prediction.
  7. If correct, reverse engineer the solution from the test. Else, amend the test, prediction, or hypothesis, or create a new hypothesis and begin the cycle again.

I use a reduced version of this when I do whiteboard problems often encountered in interviews. When redefining the problem, I find it helpful for myself (and the interviewer) to make an observation of the problem by identifying the input, and the expected output and ask a few questions about the constraints. From this, I can define a hypothesis and prediction on which to assert in a logical manner, when designing and evaluating my solution. There is a similar visual example of this approach to a whiteboard problem in this Example Coding Interview video from Google.

Can we avoid Debugging?

Short answer; no. Not until our all-mighty AI overloads achieve self-development capabilities [citation needed]. But, we can reduce the amount we have to do with tests. Test Driven Development and Test Last Development, are amongst the most popular industry adopted practices for reducing errors, at the developer level. By thinking and coding defensively at the level of small code units, we reduce the number of bugs when running that code as we consider edge cases. We can then further test the integration of those units and ensure they play nicely. And so on.

I'll cover testing in greater depth in a future post so I shan't say much more on the subject. If you're new to testing or want to pick up some new ideas about it, a great place to start is Robert C. Martin's blog - Clean Code Blog where you'll find numerous articles on testing, from different viewpoints. Another is Martin Fowler's 'Unit Tests'. A great beginning post being First-Class Tests. As always, there is an abundance of resources, opinions and best practices out there so search around, discuss it with others, and try it out.

Productivity

Optimal productivity can sometimes seem elusive - often desired, but rarely obtained. There is no fix-all solution to obtain ultimate productivity which can be put into practice for an overnight result, I'm afraid. It's something that takes time and a large amount of conscious effort on our part to begin to reap the benefits.

By optimal, I simply mean well-balanced against life and other responsibilities. We're all aware that life doesn't revolve around work. It pays the bills, sure, but life has much more to offer than a successful career which, all too often, end up being treated as blockages to our progress and productivity. Step one is recognizing when you're guilty of this. Working through a lunch break; working multiple weekends; working way past your work-day end time; missing family events; missing out on bonding opportunities with colleagues. These are just a few things we are all guilty of at some point. I know I have been in the past. I'm not suggesting we relegate our work to a permanent position as number two, but perspective and optimal focus of our time are how we achieve productivity.

Family and social lives begin to suffer. Sleep becomes sacrificial or optional. Exercise becomes a waste of valuable time. Your procrastination monkey persuades you that watching a motivational movie is more beneficial to start a new project than sitting down and kludging together the first iteration. Pushing harder on a task rather than addressing the opposing constraints or blockages. These are just some causes of poor productivity, but they're also symptoms of greater despair. Addressing them is often as simple as acknowledging them, and formulating a plan to attack them.

So here are a few resources I've used in the past to reduce stress by adjusting and refocusing my efforts, time, and priorities to improve my productivity. As always, there's plenty of great stuff out there so I encourage you to treat this only as a start line, not the finish line.

Let us start with a quick listing of negative influences on Productivity. I find as much value in understanding what to avoid, as what to aim for. That's why I find posts such as 5 Ways to Destroy your Productivity by John Sonmez over at SimpleProgrammer, are a great place to begin.

For more on the impact of inadequate sleep, kick off your search by reading A Good Nights Rest by Raymond Bryant Jr.

To dig into your procrastination problem and sideline your procrastination monster, view Tim Urban's Ted Talk here.

Are your fears or anxieties holding you back? Tim Ferriss has a unique and inspiring perspective on stoicism gained from personal growth which he delivered at Ted 2017. His pen and paper technique called 'fear setting', described in the above presentation, is an excellent place to start acknowledging and reducing those fears.

For those of you with a keen interest in Physics, I highly recommend The Physics of Productivity: Newton’s Laws of Getting Stuff Done by James Clear. James explains and applies Newtons Laws of Gravitation to a productivity setting, outlining three core rules for improving your productivity in a Newtonian manner.

Time Management

I've found myself losing touch with this area of late. Simply because I've had a lot on recently, which makes dividing and managing your time much harder. But under normal circumstances, when I'm able to get into my flow state, I find the Pomodoro technique a great way to record and manage my time. When the workload is manageable, it helps re-balance the work-life ratio. Think of it like hourly Sprints.

You can find the 6 easy steps to follow at the link above. The core of the Pomodoro is:

  • Work with time, not against it by scheduling time periods to work within
  • Eliminate burnout with short, scheduled breaks and rewards
  • Manage distractions through task prioritization and going offline (headphones, close your door, close your email client)
  • Improve your work-life balance by logging your achievements and track their progress

For something more general and less task-focused, consider the following areas:

  • Create an overall plan of action, and per task
  • Prioritize your tasks however you see fit
  • Log your tasks and time spent on them
  • Review your progress at the end of the day, and week.
  • Take regular breaks and reward yourself
  • Avoid Distraction and procrastination

You can view this model in greater depth on the University of Kent's website. That last one is easier said than done in most cases but I feel it's there to serve as a reminder for recognizing when you are distracted or procrastinating.

It's always good to have a plan. Daily to-do lists are useful for having a source to refer to as to not have to remember all the things you need to do, but, if they're not structured in a goal-oriented and prioritized manner, I find they can add to my stress.

To address this, I use Trello to log all my work tasks into a backlog. From this, I build a list of the goals to achieve throughout that day. I like to identify the main goal for each day which goes at the top of my list - something I've not done before. How you structure this is entirely up to your needs. You could rank by:

  • Tasks by their importance and urgency
  • By the amount of time required to do them
  • Tackle the harder problems first
  • By those tasks which return the most value.

Try a few and evaluate what suits you best. Personally, I like to tackle the more difficult problems earlier in the day when I'm at my most productive, before fatigue sets in around 3 - 4 pm.

Project Tracking

There's a helpful post to give more structure to project planning and management by mistermocha over at dev.to. It's a manageable starting point for you to begin your journey to project enlightenment. This is less of a discussion of the extensive list of Project Management Types as found on the Wikipedia page. It's more about how we track our time and work, specifically.

A great tool for managing our project workload is Trello. There are others, of course, such as Asana, but Trello is my personal choice. It takes the established methods of Kanban, Scrum, and collaboration to a new level. They've done a great job of making it accessible to the masses for all walks of business and life with some innovative enhancements to those concepts and a great free feature suite while remaining a useful tool for industries such as production and computing where tracking projects in these forms are proven to be highly beneficial.

Documenting

This one is fairly obvious. Methods such as logbooks are well-known but undervalued. Having a record of the more complex problems you faced, their specifics and solutions are a pain to keep - until you need them. Time and effort get wasted searching the internet to piece together an answer a second time.

wisdom_of_the_ancients.png

Of course, documentation will eventually begin to rot. Whether it is shared technical documentation or user documentation - keep it as up to date as possible. The only thing worse than having no documentation is having out of date documentation. But how detailed should it be? My answer: as much as needed. That may sound fuzzy, but it's the reality of the situation. Do you want to document every mouse movement and click to achieve a goal in your software? That depends - who is your audience? What are their average ages and technical abilities? Has the UI been designed with the goal to reduce cognitive load through intuitive recognition and reuse, or is it slightly complex requiring recalling of the 'whys' and 'hows'?

For personal logbooks, however, I practice the reverse. I don't feel obligated to update them with every change that happens. Technology moves fast, as does my development. The most important thing is capturing the initial exploration or key points to reflect on later, or use as a point of reference to quickly find my way back into a topic.

Would you release a critical application without logging or auditing? We should have the same approach to the development of the application, and development of ourselves.

Reflection

I'll wrap this up with reflection. Where you've been is just as important as where you are and where you're going. So why not take some time to reflect one in a while?

At one of my previous jobs, we'd send out a weekly update email. It was a time for reflection and logging of our progress and achievements as much as it was to inform each other of it to encourage collaboration and limit the work of one person negatively affecting another. We'd also take some time to list a few goals for the next week.

For those developers on the team, daily stand-ups, sprints, and retrospectives were commonplace. Other than the usual benefits to developers and the business of wrapping up one portion of work and before defining the next, these are great for getting perspective on the challenges you faced, your team faced, and the progress you all made.

A model I use is LELSA. LELSA helps reflect on any experience - not just work. It's a quick way to prompt thinking about where you've been, and where you're going. It helps you understand who you are, how you work, and the inward progress you make. It's as simple as pondering on each point. Give it a try. It's short, simple, and effective.

  • What did you Learn?
  • What did you Enjoy?
  • What did you Loath?
  • Identify a Shortfall.
  • Identify a future Aspiration.