It’s all about tech except when it’s not
In this part of the series, I will describe some lessons I have learned on how to balance details and abstractions when exploring new skills, and the importance of getting comfortable with “learning as you go”. I will also provide an overview of the central methodologies and tools that I use in my current work, to serve as inspiration for topics to study.
Details and abstractions
“While a certain proficiency in very specific technical skills is required, it is just as important to not get stuck in technological details”
Part of the process of learning software development is learning to manage the ambiguity of the fact that, while a certain proficiency in very specific technical skills is required, it is just as important to not get stuck in technological details. On the level of the code, this is the classic argument about focusing on abstractions over implementation details, an idea underlying many popular guidelines for good software development (see e.g., Seemann 2021:176).
Remarkably, I have found that the same principle of balancing abstractions and details can be applied to your overall toolbox as a developer. Here at Strongminds, this perspective is reflected in the framing of the field as a craft, as we focus on learning general principles for design and quality even more than we learn new tools and technologies. This encourages ongoing reflection on ways to handle the combined complexity of development tools and conventions, underlying computing details, and domain-specific knowledge. As I see it, the practice of programming consists of working your way through a stream of unfamiliar situations and challenges. In this process, concepts like design patterns and the ability to balance cohesion and coupling will provide you with important stable points of reference to handle the situated complexity of each new task.
So much to learn – how much to learn?
“I recommend learning new things mostly when you encounter a practical demand for that specific knowledge. You could consider this paving the road as you walk”
As David Farley stresses, working in this field involves becoming “experts at learning” (Farley 2022:xxiii), and one of the fundamental challenges of creating software is deciding how much you need to know about a given topic. For instance, the popular version control system Git includes over a hundred commands. Currently, I use four or five of them. Instead of following isolated tutorials and memorizing details, I recommend learning new things mostly when you encounter a practical demand for that specific knowledge. You could consider this paving the road as you walk.
The number of Git commands that it makes sense to know will vary from person to person and project to project, but I always find it useful to distribute my learning in this need-to-know kind of way. It will take some work getting comfortable with this process, but going through it builds confidence that you can enter a project with unfamiliar technologies and get acquainted with them while quickly adding value to the project. When learning a new technology, always consider what general lessons can be derived from the experience.
Beyond the code
Like taking time to think away from the computer, I find it very useful to write text that is not code. Along with weekly craftsman meetings to discuss learning and challenges, developers at Strongminds are encouraged to keep a daily logbook. One benefit of this is to recap where you left your work yesterday or before the lunch break, and the logbook is also a good place to park general lessons that you learn along the way. A final reason to write about your work process is to use it as a critical conversation with yourself about your approach to the task at hand. The best single piece of advice that my master’s thesis supervisor gave me was to write analytical reflections on my material every day in the thesis period, no matter what else I was working on. Now, I have brought the same attitude into software development and use writing to concretize and challenge my understanding of a given problem or technology. I often come up with a better solution just by writing down what I know and what i am trying to do.
While I argued above that I prefer exploring new software development topics only when I encounter a practical need for them, one of the things I struggled with previously was shaping the broad contours of my own curriculum. For this reason, I have decided to include the following overview of the central methodologies and tools that I use in my current work besides conventional programming languages.
Methodologies and principles
“Design patterns make it easy to apply principles like dependency injection or separation of concerns”
Design patterns: being able to apply tried-and-true patterns to your code makes the code easier to maintain, less faulty, and more relatable to other developers. Design patterns make it easy to apply principles like dependency injection or separation of concerns. They also help reason about a program as a collection of larger abstractions rather than individual lines of code, which becomes necessary as the program grows. At first, the number of patterns was overwhelming to me, but I found that learning a few core ones like Strategy and Factory goes a long way.
Test-driven development: this methodology turned the way that I think about software development on its head. In test-driven development, you write an automated test that checks a small piece of the desired behavior of your program, watch it fail, and only then do you come up with a solution that makes the program work and the test succeed. It is perfectly valid to start programming without this mindset, but sooner or later, I find that the perspective and code quality gained from approaching tasks in this way is indispensable.
In terms of project management, concepts like agile software development and Scrum are often lumped together, often misunderstood, and interpreted in a variety of ways. These topics should not occupy too much of your attention when starting out, but reading Manifesto for Agile Software Development (2001) and some introductions to Scrum can give you a feeling for the ways project management is done in many software teams. I also find it useful to know a bit about the historical and ongoing debates on comparing software development to construction engineering and other disciplines, which form the backdrop of the agile principles.
Some acronyms: we have acronyms for many things that are good to remember in software development, including memorable ones like SOLID and DRY, and the less memorable YAGNI. I recommend getting familiar with at least these three, because like design patterns, they can serve as stable points of reference for the multitude of decisions you will be making when coding.
Technologies and tools
The first tool to get is an IDE (Integrated Development Environment), a program used to write code. Any text editor is technically an option, but more specialized IDEs have useful features such as code completion and ways to run your programs within the IDE. Visual Studio Code is a nice, free starting point. If you want something more advanced, I have taken a liking to the user interfaces of the IDEs from JetBrains, such as Rider for C# or IntelliJ for Java.
“Getting comfortable with a couple of scripting and data format languages will also lessen your reliance on any single programming language”
Shells/terminals and scripting: If you have not delved below the graphical user interfaces on your computer before, a shell will be a strange place to go. I recommend getting familiar with Command Line Interfaces (CLI’s) and some scripting in either Bash or PowerShell, which caused a significant shift in my perception of what a computer program is. You will often encounter limitations in specialized CLI’s that can be circumvented by combining humbler ones like grep and awk, and getting comfortable with a couple of scripting and data format languages will also lessen your reliance on any single programming language.
Version control systems (Git being the de facto standard) are used to keep track of changes to a program and undo them if needed. This may seem unnecessary or awkward to use for a hobby project, but I recommend learning and using Git to a reasonable extent. I used to be afraid of merge conflicts in Git. I still am, but somewhat less since my colleagues at Strongminds introduced me to tools like P4 Merge and Sublime Merge, which add a helpful graphical layer to the command-line complexity of Git itself. These tools are great, though they are not a reason to skip learning the Git CLI and the basics of how Git actually works.
“Developer-oriented technologies are often made by people steeped in the same culture and conventions that you will be learning about”
With the spread of DevOps and Infrastructure as Code, tasks that have traditionally belonged to the systems administration/networking field are increasingly seeping into the daily work of software developers. Understanding the basic theory behind virtual machines and containers can be helpful, and Docker is the most widespread tool for managing containers. If you know object-oriented programming, the relationship between a container and its image is similar to the relationship between an object and its class. This exemplifies how developer-oriented technologies are often made by people steeped in the same culture and conventions that you will be learning about, so be on the lookout for such helpful (though sometimes dangerous) parallels.
Infrastructure as Code is closely tied to the notion of cloud computing, which refers to the option to rent computer resources (databases, website hosting, machine learning models and more) over the internet instead of owning physical devices yourself. Common providers of these services include Microsoft Azure and Amazon Web Services, and while cloud computing is often beyond the scale of individual hobby projects, it is integral to contemporary web development. David Clinton’s book Amazon Web Services in a Month of Lunches (2017) provides a brisk but helpful overview, though don’t read it in your lunch breaks. Go for walks in your lunch breaks.
In the third part of this article series, I will provide an overview of the specific books and courses that I have used to build my skills as a developer coming from a non-traditional educational background.
Citations
Farley, David – Modern Software Engineering (2022, Addison-Wesley)
Seemann, Mark – Code that fits in your Head (2021, Addison-Wesley)