Key Takeaways
- The ability to effectively analyze a problem, evaluate different options, and engineer a solution requires the skills taught in the liberal arts.
- Many problems with software projects are caused by poor communication. Studying effective language and communication can lead to more successful software.
- Great communicators always remember the importance of context–know your audience. This applies equally to discussions of requirements and to designing interfaces between microservices.
- The best engineers blend a knowledge of computer science with good critical thinking and problem solving.
- The liberal arts teaches the skills necessary to be a lifelong learner, which is vital to keep up with the ever-changing world of software.
The education of most software engineers involves a heavy focus on STEM subjects: science, technology, engineering, and math. Other subjects, especially those under the umbrella of liberal arts, are often thought of as less important, or just an annoying requirement to graduate. However, much of what helps you become a great software engineer, and create outstanding software that people want to use, comes from outside the world of STEM. This might sound like great advice to give to a freshman computer science student, but it's equally helpful for the 20-year software veteran.
Computer science is the study of algorithms, data structures, and operating systems. Programming is the practical implementation of computer science. Software engineering is the use of software to solve problems. The ability to effectively analyze a problem, evaluate different options, and engineer a solution requires the skills taught in the liberal arts.
What Does "Liberal Arts" Mean?
I think it's important to first clarify what is meant by the terms liberal arts or a liberal arts education. A pithy, but not very useful, definition could be anything that isn't STEM. While technically true, it doesn't really tell us the benefits or expected outcomes from studying the humanities and social sciences. Clearly, if you get a degree in biology, you will probably be qualified to be a biologist. But the purpose of the liberal arts isn't to train directly for a specific profession.
Liberal is sometimes, incorrectly, assumed to only mean the opposite of conservative, as in politics. Rather, it shares a root with liberated, meaning free, in contrast to imprisoned or subjugated. A liberal education provides the skills necessary to function successfully as free citizens in society. According to Syracuse University's Gerald Greenberg, "It teaches them [students] how to think critically, communicate clearly, analyze and solve complex problems, appreciate others, understand the physical world, and be prepared to learn continuously so they can work with others and on their own to meet the challenges of the future."
Software engineers are expected to think critically and analyze and solve complex problems. Greenberg’s other lessons (clear communication, appreciating others, and continuous learning) may seem less important for software development, but those skills are what make the difference between just a good developer and a great software engineer.
The Importance of Language
When the musical Hamilton came to town, I noticed my co-workers were divided into two groups: Those trying desperately to get tickets, and those with no interest in seeing the show. One of the latter said he didn't like musicals because they were unrealistic–in real life, people don't spontaneously break into song and dance. While that is true, the purpose of a musical or play isn't to be 100% realistic; it's to tell a story, convey emotion, and make the audience think, all in a limited amount of time. Songs incorporate music and rhythm to grab the audience more intensely than just spoken words. The bandwidth of the theatre is constrained, and music is the data compression technology.
A similar comment that "people don't really talk (or sing) like that" could be made about software code. When creating instructions for the computer, there are severe constraints on the syntax. That makes code closer to poetry than prose. I don't expect software engineers to start describing themselves as code poets, but they clearly are writers. And every writer must know their audience.
Know Your Audience
If there is one message to be remembered from English Composition 101, it is "know your audience." When teaching students how to be better writers, one of the first steps is acknowledging and understanding who you are writing for. The style used for a children's book is vastly different from a college thesis, and also varies between a history of the Roman empire ora lab report for biology.
In her presentation on readable code, Laura Savino pointed out that programmers are writing for two audiences: the compiler and other developers. One of these is very opinionated, and will tell us loudly when it doesn't understand. That skews a lot of code to favor the compiler as the primary audience. However, since humans must maintain the code, it's vital that it remain readable for the audience between the keyboard and chair.
The idea of ubiquitous language, from Domain-Driven Design, aids in communication by clearly defining terms as they apply within a specific context. In such a situation, constraints liberate – by focusing on a small audience, you are better able to express your intent. The words and phrases in your ubiquitous language may have a different meaning outside your context, but that concern goes away because your audience is not everyone.
At the code level, DDD recommends the use of value types over native data types. Passing around an AccountNumber carries more meaning than passing a simple string or integer. The rules for checking if an AccountNumber is valid can be clearly defined, and invalid values could be prevented from being constructed. Once we have agreed on a ubiquitous language, it can be used to prevent many common errors that could arise from unclear communication.
Every Problem is a Communication Problem
Whether providing requirements from customers to engineers ("I'm a people person!") or sending requests to an API, communication is present throughout the application lifecycle, and at every layer of a software system. When something doesn't go as planned, the solution usually starts with improving the communication.
Waterfall projects are based on discrete, significant points of communication. The requirements are gathered, written up, and handed to the developers. The developers write the code and hand it to QA to test. If the software doesn't meet expectations, everyone starts pointing fingers and assigning blame. An agile approach hopes to solve that by creating more frequent, smaller points of communication. This makes it easier for everyone to understand what is being discussed, identify any issues, and fix them before they become major obstacles.
In an n-tier, monolithic codebase, you have a limited number of communication points. (The front-end talks to the back-end. The back-end talks to the database.) Within any single layer you don’t think much about the communication path because you're making direct function calls. However, when the monolith becomes too cumbersome to deploy frequently, you start breaking it up into separate services. Now you have a lot more communication pathways to worry about.
If those services are managed by different teams, then you need to make sure every team understands the behavior of their related services. Conway’s Law states that "organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations." Therefore, to be able to improve the communication between services, we cannot ignore the communication between people and teams.
Model Software Communication After Human Communication
The department of communication studies at a liberal arts college researches and teaches about interpersonal and intercultural communication. Studying how people communicate, whether to share knowledge, tell a story, or simply get to know one another, can help us gain an appreciation of common communication challenges, methods for overcoming them, and more empathy for those we try to communicate with. The lessons can be adapted and applied to many aspects of software engineering.
As distributed systems become more common, we have to start thinking differently about the communication throughout the system. Instead of looking for a great architectural pattern, start by looking at how people communicate and you’ll find a wide variety of successful techniques, some of which may serve as a model for your system. Humans are able to have real-time conversations, either in person, over the phone or video chat, and either one-on-one or in large groups. They also use asynchronous and distributed communication patterns, such as sending emails or text messages, or leaving a voicemail. In all of them, translation occurs at different stages.
The next time you order a coffee at Starbucks, watch as your request is translated (through an anti-corruption layer) into a concise message (in the ubiquitous language) describing your command, and written on a paper cup (the transport layer). When your drink is prepared, they call your name (raising an event), and you retrieve it from the counter (reacting to the event).
Software patterns such as Command Query Responsibility Segregation (CQRS), Event-Driven Architecture, and reactive programming all put an emphasis on messaging. In CQRS, you send either a command or a query where the intent is clearly understood, and the message conveys all the necessary information. EDA and reactive both approach a problem in a way humans prefer to behave - when something happens, then I respond accordingly.
Since human communication predates computers by millenia, we have evolved to expect certain patterns of behavior. When creating software, your system will be far more successful it it embraces those patterns, rather than trying to present something new and disruptive. Knowing what your users expect, and designing it into your system, requires a certain level of empathy.
The Importance of Empathy
Studying the humanities teaches us that the world is far more complex than what we can sense around us. While the same sense of perspective can come from astrophysics, the humanities explore how small changes in location, environment, or historical background - a different kind of perspective - can produce dramatically different outcomes for two groups of people. While it may not be possible to literally put yourself in someone else's shoes, taking the time to understand their situation can create more empathy towards them.
The Agile Manifesto is comprised of only 68 words, but it could be greatly simplified to "practice empathy." Preferring individuals and interactions over processes and tools, and customer collaboration over contract negotiation are about creating shared understanding and empathy. When you encounter software that has an intuitive user experience it's not because the developers know the best sorting algorithm to use – it's because the software was designed with empathy towards the people who will use it.
Practicing empathy goes beyond the user interface. When debugging and troubleshooting, it can sometimes become frustrating to the point of declaring everything broken and just giving up. Instead of fighting a bug as a mano a mano battle, use empathy towards the computer to try to understand why the software isn't working as expected. After all, it isn't doing anything you, or another developer, didn't ask it to do. (And if the computers do really start thinking for themselves, it's sure to start a lot of philosophical discussions – another time when a liberal arts education will be beneficial.)
Critical Thinking and Problem Solving
Every great developer I've worked with has excellent problem solving skills. I've participated in many technical interviews, on both sides of the table, where the goal wasn't to determine coding ability as much as it was to demonstrate how a person approaches a new problem. In STEM subjects, the scientific method is often employed as a logical set of analytical steps.
At the core of the scientific method are the steps of creating a hypothesis, testing the hypothesis with an experiment, then analyzing the data and drawing a conclusion. It may be easy to forget that the process begins with asking a question and doing background research, and ends with communicating your findings. Coming up with a question, determining if it is the right question to ask, and doing background research, all require critical thinking skills which are the focus of the liberal arts.
Effectively reporting your findings comes back to knowing your audience. If you wrote a simple prototype application to test performance improvement, how would you communicate the results to your non-technical product owner? Showing the raw code is probably no more helpful than writing a 50-page report. A better approach could be demonstrating new functionality using the prototype, or creating a simple chart to summarize improved performance metrics. Good communication depends on knowing who you're trying to communicate with, and what you're trying to communicate to them.
Lifelong Learning
The liberal arts teach us that the amount of available information is too vast for anyone to know everything, and there are always ample opportunities to learn more. The importance of learning over knowing is a view echoed by agile coaches who emphasize having a growth, and not fixed, mindset. Because technology evolves so quickly, good developers already know they must constantly learn about new programming languages, frameworks, and platforms. However, great engineers realize that continuing to learn about non-technical aspects of software development improves their ability to work with a team and deliver better solutions.
A liberal arts education teaches how to use a broad knowledge base to analyze new and unfamiliar topics. Subjects that may seem completely unrelated to software development can provide new insights and perspectives that shine a light on technical tasks. Studying interpersonal communication can lead to a better microservices architecture. Reading a novel and studying social sciences both lead to greater empathy. Empathy helps you know your audience and create great software that delights your customers.
About the Author
Thomas Betts is a Principal Software Engineer at IHS Markit, with two decades of professional software development experience. His focus has always been on providing software solutions that delight his customers. He has worked in a variety of industries, including retail, finance, health care, defense and travel. Thomas lives in Denver with his wife and son, and they love hiking and otherwise exploring beautiful Colorado.