Every Introduction to Programming class starts with a programming language, introduces various concepts like variables and functions and leaves with an understanding of some simple algorithms. Mine was no different. We used C and spent a lot of time trying to make students comfortable using Linux.
This leaves a lot to be desired. Software engineering is hard and laying out certain principles at the beginning can help tremendously. This is a short list of supplemental resources I would have liked to have when I started programming. They do not require any knowledge of programming or computer science. The intention is to setup a framework for thinking about programming. Some of them point out common flaws students will encounter throughout their careers while others lay out basic principles to follow. Remember that exceptions make the rule.
Fred Brooks’ No Silver Bullet - essence and accident in software engineering lays out the challenges of an entire field. Every software developer should read this once every year. It is so readable, and software so relevant to our lives, that every person should read it once. One quote is particularly useful for beginners:
I believe the hard part of building software to be the specification, design, and testing of this conceptual construct, not the labor of representing it and testing the fidelity of the representation. We still make syntax errors, to be sure; but they are fuzz compared to the conceptual errors in most systems.
The most important idea is that software is an attempt to model the real world. Unlike physics or math, software may not remove complexity as that destroys the essence of the model. Complexity introduced by these (often human imposed) “business problems” is essential complexity. Real computers have finite limits; a lot of complexity has to be introduced in software to fit this real world model into the trade-offs necessary for it to work on real computers. This is incidental complexity. Brooks suggests that incidental complexity is reasonably easy to solve, but essential complexity can only be managed. Software programmers must be gardeners more than builders.
With a basis for what you are getting into, you are now ready to start programming. You will spend the first few weeks learning a lot of new words. Engineering is about precision. This extends to definitions. Ambiguity prevents sane discussions and leads to confusing requirements. Computers take everything literally, so precision in programming is more important than most disciplines. Despite this, the field doesn’t even have most basic terminology nailed down. eevee does a good job of laying out common ambiguities.
An important software engineering skill is to frame your problem correctly; another is to calibrate your intuitions about likely reasons for incorrect results from programs that seem to be correct. eevee provides rough guides in Architectural Fallacies.
As your programs grow bigger and start doing useful things, you will spend a lot of time inter-operating with other software and communicating with other engineers. RFC 2119 precisely defines key words to indicate requirement levels when software must communicate with other software.
For all the good things software has done in the world, our tools are surprising primitive and software engineering in the real world is hardly science. Greg Wilson has a great talk on striving for engineering discipline and evidence based decisions in software development. It is entertaining and has useful trivia. Don’t believe everything the experts tell you. A lot of “best practices” in software engineering are decided by who can shout the loudest.
Mid-term, you will realize that anything beyond simple programs needs some thinking. The bureaucratic waterfall models of earlier times have today pushed us to be spontaneous and start hammering out code. Unfortunately, people don’t get the part where you don’t ship the first prototype to customers. We should try to find a middle ground. Rich Hickey makes a modest case for this in Hammock Driven Development.
Finally, understand that software is a) used by humans, but more importantly b) created by humans. Humans are squishy, organic computers distracted by fatigue and boredom. We don’t do a good job of thinking for the long term either.
The data are clear that humans are really bad at taking the time to do things that are well understood to incontrovertibly reduce the risk of rare but catastrophic events. We will rationalize that taking shortcuts is the right, reasonable thing to do. There’s a term for this: the normalization of deviance.
Acknowledge this and watch out when you yourself make the same mistakes. Design your code so that the easiest way to use it is also the right way. The Emperor’s Old Clothes is worth reading for this one sentence alone:
The price of reliability is the pursuit of the utmost simplicity.
Less is more, none is better, null is a bad idea. Everything from your CPU up guides the quality of your software. Some of these things are easier to change than others. Use languages that catch more errors at compile time, but remember that errors caught in the design are even cheaper to fix.
Everything from the The Zen Of Python is always applicable.
I’ve intentionally left out programming paradigms, tools and software engineering practices. If you feel a certain resource deserves a place here, please email me.