Solving Problems & Saving Time through Software and Crushing Entropy
Powered by Cecil & Hyde.
I’ve had the good fortune to be able to volunteer some of my time to mentoring a few folks at Resilient Coders who are in the process of becoming Full Stack Developers (It is a fantastic organization, and if you’re in Boston you should take a moment and check them out). Working with people who are at the beginning of learning to code has been immensely refreshing.
First, I am old. And that means I really don’t remember when I “learned how to code”. I know that it happened. Over a long period of time. And I know that if I were able to look at work I did a decade ago I would be ashamed. That is a good thing in my view—it means I’m growing, I’m still walking forward on the road. (There were definitely times I took a “break” and sat down on the roadside for a while without growing.)
As my mind wandered onto my own learning-to-code journey, I wanted to write down my signposts that marked my periods of growth. Your mileage may vary—and I would love to hear your experiences in the comments.
This is the first critical step, and its something I talk about with those I’ve been helping. When you’re stuck, you start searching for answers. Rarely will you find something you can truly copy & paste into your editor and it just works. There comes a moment when you know: “Hey, this isn’t exactly what I need, but, it taught me something and now I know how to fix it.” That is a moment every engineer needs to have. We’re not built with it, even if you don’t remember when it happened to you.
It signals that they can fully learn by themselves. Without that ability its very hard to grow.
It’s one thing to hack something together and make it work. And then clean it up and refactor it after the fact into something you’re comfortable attaching your name to for general consumption. But it is something different to be thinking about abstraction, cleanliness, separation of concerns, and enter any-of-the-things-you-find-most-important before you’ve made it fully work.
It signals that they are comfortable in their environment, confident in their ability, and can break down a problem into its constituent parts.
When you have a job as an engineer at some point someone brings you either a written spec or has a requirements meeting. As you’re talking about all this new information, and before imagining what code you’ll need to write looks like, you’re thinking “What is X, really?” and “How does it relate to Y?” You start assigning concepts (like Dictionaries, Lists, Graphs, Trees, Enums, etc) to real world requirements.
It signals that they understand what we’re really doing here; attempting to contain and transform the real world into digital relationships. Their focus at this level is an understanding that making a poor choice here results in greater catastrophe down the road.
When we stare at a blank editor, unable to type—or we just start moving code around like peas on a dinner plate you do not want to eat—we’re not sure what is next. It is a magical feeling when you can just sit down, open the editor, and start typing and the program unfolds itself before you. You’ve already got the next 20 lines in your head ready to go as you’re finishing your function. As you tweak one part of the code, you instinctively fly over to another part to make a required corresponding change so that it all works together.
This is a second level of development in breaking down the problem into smaller parts—it signals that not only have you broken it down, but that you can also hold all the parts in your head, together, intimately aware of their relationship to one another.
There comes a time when we are looked to for optimizing performance. We go back over our code, measure it, trace it, and profile it, using various tools and come up with changes to make it faster, and better. We make the changes and whoever came over whining about a spinning pinwheel, or waiting for the browser to load something is happy again.
There comes a time when we start working on bigger systems; with more data, and with more users. Where you can’t just ask someone to delineate how many things your system is responsible for—because no one could know all of that. Where changing a behavior in one part of your system has drastic effects on another part. This is when the systems you’re working on greater resemble a living organism; because it is not merely a determinative system anymore, the actions of the users have a greater effect on what happens.
This is an area in my career I am happy to have entered. I am realizing that as these systems get bigger we have to start worrying about smaller and smaller things. When we are designing and coding systems I find that I am exploring how I can leverage the power of processes and threads, and choosing where the computing work is done. I find that I am choosing different techniques in order to not spend memory I do not need to, rather than what would come naturally. I’m doing this because I have a big system, with lots of data, and limited resources. A bottleneck, or even sluggish performance, in one area will have a greater effect on the system as a whole.
I can’t wait to see what the next signposts on the road are.