Why Programming skills are Life skills (Part 2)
Dall-E 3 : prompt too long to include here

Why Programming skills are Life skills (Part 2)

In a prior article (Why Programming skills are Life skills), we explored a bit of why common best practices in programming would be useful to apply to other everyday scenarios that do not necessarily involve technology. I ended by stating that I would be revisiting the topic to discuss some more core concepts and their applications as well.

There are basic skills that are comparatively ubiquitous to programmers but which are virtually unknown to most people. These are not best practices, but rather they are things that we utilize in the course of ordinary programming as efficiency measures. Some of these are iteration, conditional statements, recursion, parallelizing, and in-memory operations.

Iteration

Iteration is a fancy word that means repetition with advancement. What do I mean by that? Let's say you have 3 children; Huey, Dewey, and Louie. There's something special about these children. Each time you communicate with 1 of them, the other 2 stop listening. Additionally, you cannot communicate to no one in particular or all 3 will assume that you're not talking to them and will stop listening. This forces you to communicate with each individually. They're playing in the yard, and it's time to tell them to come inside for dinner. What do you do? You call out to each of them in order and tell them that dinner is ready.

Another way to think about this is that you have a list of them in your head.

[Huey, Dewey, Louie]

So, first, you call out "Huey, dinner is ready!" The list is now

[Dewey, Louie]

Then you call out "Dewey, dinner is ready!" The list is now

[Louie]

Lastly, you call out "Louie, dinner is ready!" The list is exhausted.

This is a 'for' loop in programming (or a while loop with pop or a DAG, etc, etc, etc). For each name in the list, you call out the name, and a designated phrase, then move forward to the next in the list.

children = [Huey, Dewey, Louie]
for child in children:
   print(f"{child}, dinner is ready!"        

(That's what that might look like in Python)

Sounds pretty simple, self-explanatory, and therefore useless, right?

What is interesting about Iteration is that it forces you to think about how you can consolidate the many moving parts in a system into simple archetypes and groupings. For example, it's easy to remember 3 children's names and hold them all in your mind while you call out to them. What about 10? What about 100? If you had to do it for 100 children, there's a good chance you'd use some sort of method to break those kids down into smaller, more easily memorable chunks. Like, for example, all kids who were born in February. All children older than the age of 10. All children whose names begin with "N". More on this when we cover in-memory operations and conditional statements.

When we think about iteration, we're thinking about how to create simple interactions out of complex systems. One project I had was working on documenting workflows. A line that kept coming up in process interviews was "There are too many scenarios to name. It's just complex and murky." (or some variation therein). My response was simple. At each step, tell me all of the possible things that could happen here. While variability is infinite, variation at any particular moment is finite. While there may be quadrillions of potential ways a chess game can proceed, there are only 24 openings. We can simplify it further. There are 2 types of openings, those involving a pawn and those involving a knight.

Why do categories matter? Because they cut down on cognitive complexity and allow us to grapple with extremely complex realities using very simple models. In HR, we have the responsibility of onboarding new employees. There are 19 forms, plus additional documents that we have to collect depending on the category of staff. Each form or document can be unacceptable in a number of ways. There are a near-infinite number of approaches to onboarding that will not reach success. I use the approach outlined above to simplify. Firstly, each item is a binary. Either it's acceptable or it's not. This allows us to focus only on those that are unacceptable, lowering the total cognitive effort. From there, we can subdivide unacceptable into a few categories.

A. Unsigned

B. Incomplete

C. Incorrectly completed

Each of these has a treatment and some require more effort than others, but all of them beat sending it back and saying "You did it wrong. Do it again." Ultimately, this reduces effort and energy for both parties.

When we interact with others, and also with ourselves, abstracting variability into discreet categories to perform simple operations on them is a net benefit.

Conditional statements

Conditional statements in programming are "If" statements. As in "If I'm talking to Dewey, I use ye olde English".

In discussing how we categorize and quantify infinite diversity, I touched on how we handle variation. Conditional statements are largely how this operates in programming and in the real world. This is not something novel. The real difference is that when programmers implement conditionals, we have to worry about priority order.

When a conditional statement is written for a situation with many different possibilities, we must account for them, and we must account for them in a way that does not create errors. Most new programmers have problems with If, elif, else, end statement blocks due to the fact that there are unexpected consequences from not considering priority.

The way that this shows up in real life is more difficult to notice. It takes us many iterations to figure out that we have a better morning if we have our caffeine before we brush our teeth rather than the other way around, or if we sacrifice one step in a morning routine rather than another when we're late. The way that most people deal with sort order obstacles that they encounter is with rules of thumb or heuristics. These heuristics aren't always easy to verbalize but everyone has them.

There are a few differences that understanding conditional statements and sort order for them makes. First, it forces you to formalize what you want. In language, we don't tend to structure our conditions well, which leads to confusion. For example, the phrase "take the leaf garbage out the first and third Wednesday of the month, except for a holiday in which case it's a Tuesday and Thursday respectively." seems relatively simple to understand but there are several problems with it from a programmatic standpoint. If a computer were to parse that, the first conditional check would be some flavor of

if weeknum(date) in [1,3] and daynum(date)==3:
   take_out_leaves()        

In language, we kind of do this spooling and unspooling thing. Like, there are many sentences, paragraphs, or even books that must reach the end of before you understand the beginning. We also naturally tend to sort things in descending order by the probability of occurrence (think of the order a helpdesk asks questions in). Computers don't work that way, so it forces you to rethink your expression of these conditions. In the example code above, checking that this is every other Wednesday should not be the first condition because it doesn't apply uniformly and will lead to the need for nested if statements (like 'is it every other Wednesday? and is it a holiday? and is it the first or the second of the eligible weeks?').

The correct sort order checks for the most exigent circumstance first, so that it can safely discard the possibility and move on toward the base case, which should be the else statement at the end. The lesson to take away here for everyday life is not that we must make everything procedurally executable in such a way that proceeding through linear binary conditions, we cover all the bases. Rather, we should keep in mind how we're formulating the ideas themselves.

Second, it forces you to separate out and discretize overlapping conditions. Is there a slight variation in the way that two similar cases must be handled? Then that needs to be stated explicitly. I wrote earlier about a work project that I had where I was doing process interviews. A lot of the work done was not about nuance but about getting rough-edged details. I would say things like "I don't need to know all the details, just give me what happens 85% of the time". Thinking in conditions is about that last 15%. What is the difference between these cases and what difference does it make? It's about drilling down from large chunky concepts into fine-grained observations and models.

In-memory operations

You're not a real programmer until you've crashed a computer by using all of the available memory. Memory management is incredibly important when writing code. Not just to prevent the worst-case scenario of using all available memory (and effectively bricking the machine until you do a hard restart) but also in terms of the efficiency of programs that consume relatively small amounts of memory.

In real life, we don't think much about memory management. Memory is one of those things that most people don't work on and don't think about too hard. For example, I have a spectacularly bad memory. People are constantly telling me about things that I did, said, or that happened and I was present for. Instead of addressing the core problem, like most people, I've come up with heuristics for dealing with it. I have quick comebacks when people make fun of me for it. "This is for processing, not for storage," said while pointing at my head. I also have methods of dealing with the externalities associated with bad memory. I have a much more precise model of my own behavior than many people since I often have to predict what I've done in some past scenario rather than recalling it. "that sounds like something I would do" is an oft-used phrase for me.

Most people I know work pretty much the same way. "I'm great with faces but terrible with names" or "I'd forget my head if it wasn't connected to my body" or "if it's not in my planner, it's not getting done" or "Send me that in an e-mail so it doesn't slip my mind, please". You hear these things all the time.

The real difference with a programming mindset on this subject is that you begin to recognize and differentiate different sorts of memory objects, retrieval patterns, and storage locations. In programming, when you have an object too large to hold in memory, you have to break it apart into chunks small enough to be handled easily with the amount of memory that you have and then work over the whole thing iteratively from beginning to end (or using map-reduce... whatever). When you see a flat data file that's 2 GBs, you already know you'd better be building the process around it to stream it rather than opening it. The human mind works much the same way but we often don't consider these operations. We read a book and, when we're done, we expect to remember what was in it with a level of fidelity that would be absurd if we were considering any other recording surface.

What we can learn from programming here is to be careful with our memory (working memory) versus our storage (long-term memory). The average human can hold between 3 and 7 distinct objects in their mind at the same time without losing any, with most people falling around 4. You can actually train this (using the game dual n-back) but it makes more sense to work around it since you will never be able to train it well enough to keep everything at the front of mind at the same time. It's much more effective to develop routines for storage and retrieval as needed than to chase the grail on that one (for those of you studying to become memory champions).

So, how do we effectively use this understanding? First, always break things up into smaller and smaller clusters no larger than 4 distinct objects or categories in size. For example, there are 12 zodiac signs, but they can be broken down into groupings of elements (fire, water, earth, air) and modalities (cardinal, fixed, mutable). Either way you break it down, you get 4 items or less per grouping, which makes it arbitrarily easy to think about the things in that category Sagittarius, Pisces, Taurus, and Gemini are the mutable signs in the order of the elements, for example. Cancer, Scorpio, and Pisces are the water signs in the order of modality. In essence, these categories act as containers and each container brings a workable number of objects into working memory, like following a breadcrumb trail. It requires less energy to open successive categorical boxes in storage, even with mistakes, than to go through the entire ungrouped list looking for the one you want. This is also usually referred to as chunking.

The second way that we can effectively use this information is to do things that reduce strain. For example, there is a human equivalent to streaming. it's called rhythm. Rhymes, songs, and stories all have rhythms and are all devices we use for remembering more information than we can normally store in memory at one time and in the correct order. For example, one of the first songs many of us learn is the alphabet song. We are able to store 26 discreet objects in memory by handling them in smaller groupings in a set order that reduces retrieval energy requirements by leveraging a pattern of intonation and timing. "abcd" in a rising lilt, "efg" in an even tone, "hijk" in a descending tone, and so on and so forth. Go through the song quickly for yourself and count how many groupings have 5 letters.

{Are you someone who has to sing the alphabet song in your head to know which letter is a particular number in the sequence? Don't worry. So am I.)

The third, and most important way, that we can leverage memory operations is using external storage. I always ordinate external processing over external storage but more on that in another article. So, what do I mean? I don't mean putting all of your appointments in your planner, though that is external storage. In Scrum Sprints (and many other systems for coordinating thinking and effort among multiple people), you use sticky notes on a surface visible to everyone to work things out. There are several reasons to do this but the one that's important to us is that it gives you a similar level of access, at a similar cognitive cost, to creating a mnemonic device. Instead of retrieving information from storage in a sequence, you can call items into memory using your senses (sight) in any sequence you want and however many times you want. This enables new, easier operations, such as a random walk.

This is important because so many problems that we have are issues of perception and framing. Goldratt's theory of constraints tells us that all conflicts in processes are the result of human misunderstanding because no paradoxes exist in nature. de Bono's work on lateral thinking reveals that our brains are built to get stuck into ruts with existing patterns and often the solutions that we want require an almost arbitrary rearrangement of existing parts. In other words, operations like the random walk, either done by passing your eyes over random locations on a board or by scrambling things written on index cards, allow us to reconfigure without the massive cognitive cost that this would normally incur (insurmountable for some).

In conclusion

The big takeaway here isn't that we should treat our brains like computers. Brains aren't computers and computers aren't brains, or so everyone has learned in the last year while having hair-pullingly frustrating conversations with ChatGPT. The thing to learn here is just that domain-specific knowledge and methods are almost always cross-applicable if you'll take a little while to consider how they can be. For people who are concerned with mastering multiple subjects, that's a shortcut. I think I wrote in a prior article that I was able to ace the Azure fundamentals certification by imagining the Azure environment as sort of a medieval castle with various areas associated with the typical needs of a self-contained society (security, resource generation, storage, resource transformation, excutive control, communication, etc). This is a generalizable 'skill'.


要查看或添加评论,请登录

Shane Ayers - SPHR, SCP, MS的更多文章

  • The Problem of Choice: A Speculative Exploration into the Roots of Evil

    The Problem of Choice: A Speculative Exploration into the Roots of Evil

    I’ve been thinking a lot lately about what drives what we perceive as evil behavior. I believe the core issue might not…

  • Problems of Insufficient Resolution

    Problems of Insufficient Resolution

    Those of us who spend a great deal problem-solving have a process, an algorithm, a way. Writers have the writer's room.

    1 条评论
  • AI as Concept-proofing vehicle

    AI as Concept-proofing vehicle

    As part of my ongoing work in feeling out the capabilities of popular Large Language Models, I've taken to validating…

  • Comprehension Check

    Comprehension Check

    As some of my connections may know, one of the ways that I function at work is as an SME for digital platforms that…

    1 条评论
  • 100 lessons

    100 lessons

    As part of my preparation efforts for the next book I intend on writing, I'm writing a list of 100. As the book is…

    2 条评论
  • On the Importance (and Unimportance) of Tactile Work

    On the Importance (and Unimportance) of Tactile Work

    In creative endeavors, I find there to be two major modes of approaching the work. Creating and editing.

  • Self-Healing Data Project 2 - Exploring Alternatives

    Self-Healing Data Project 2 - Exploring Alternatives

    This is the second installment of my brief "ride-along" series where I'll be walking you through the innovation process…

  • On Languages

    On Languages

    [Please note that I'm not a linguist and I'm not attempting to step on Linguistics' collective toes in writing this…

  • Self-Healing Data Project 1 - Ideation

    Self-Healing Data Project 1 - Ideation

    This is the first installment of my brief "ride-along" series where I'll be walking you through the innovation process…

  • Silver Linings (an inexhaustive list)

    Silver Linings (an inexhaustive list)

    In my life, as in the life of every person, I've had problems and obstacles. Some of these I created and some were…

社区洞察

其他会员也浏览了