This post is written for non-technical stakeholders, executive leadership, and other decision-makers who want to better understand the world of software development and realize why their asks and mandates don’t always end up as they might expect.
There is a common misconception that I see all over in the software engineering profession. The misconception spans industries and most commonly presents itself in job interviews and code reviews but also in the minds of product managers and especially non-technical stakeholders from clients to executive leadership. I have seen how, on far too many occasions, this misconception has served to sabotage projects, bankrupt startups, and contribute to overly stressful and sometimes hostile work environments.
The misconception is that coding is just a process. It’s something that, if the programmer knows what they are doing, should be straightforward (though not necessarily easy) to do.
In all fairness, it’s easy to see how this misconception has propagated over the years. Programming is a complex and sometimes mysterious process that all-to-often elevates the programmer into a magician-like status to their non-technical peers. After all, programmers often solve stakeholder’s difficult problems with elegant systems that may seem like magic. Unfortunately, anytime we elevate people into a mythical status, we run the risk of forgetting that they are, of course, only human.
Programming is a science, coding is its expression
Computer science as an academic discipline is most certainly a science. Rigor in both application and research are required and nobody would argue otherwise. Solutions to computer problems in this space require as much validation, process, and proof as any other discipline. Here, there is typically one best way to accomplish something and if there is no one best way, then there likely is a strictly defined process for achieving the most optimal one. Much of computer science involves the act of programming and in this context, programming is a science.
Yet from a more practical and dare I say professional perspective, programming as a science is not something that is frequently done. In the world of commerce, doing something strictly optimal is far less of a concern than doing something generally effective. Now, I’m not speaking of globally-dependent services like Google or AWS services which, yes, had better be programmed the absolute best way possible. I’m speaking of the far more common applications written and used by countless small businesses and organizations around the world. While most would love to think that their application needs top-level performance or 99% training accuracy or nine nines of availability, the brutal reality is that the vast majority of them don’t.
Herein lies the problem. There is a palpable practice gap in most organizations between the expectation of programming as a science and the reality of coding. I distinguish programming as simply the practice of telling a computer what and how to do something. It is objective and pure. There are right and wrong answers when programming. Coding, on the other hand, is an art. It is subjective and contextual. It comprises the act of programming within the contextual realities of the coder, the requirements of the project, and the expectations of the customers (company leadership included). While the end result may appear to be the same, the process of getting there, and the implications for the application’s future, is anything but.
Coders Don’t Simply Program, They Create
Let’s take, for instance, the difference between imitation and creation. When someone recreates a painting, either for mass production reprint or even just to practice techniques of the original artist, the imitation here is procedural and objective. The replicator’s intention is not to take liberties and extend on the original work. Rather, it is to replicate it as faithfully as possible. This is akin to a programmer taking known-best methods of solving an algorithm or problem and simply applying them as faithfully as they can. Sure, they will typically need to augment the implementation in a contextual manner if only to make it fit within their existing application but their subjective liberties are largely curtailed. From a practical perspective, this is largely an exercise in copy/paste.
Now, let’s juxtapose that against an artist who has been commissioned to paint a mural on the wall of a building in an ethnically and socioeconomically diverse neighborhood. This artist doesn’t just ask what the city wants, they make every effort to engage with the community and discover what they think the community would like. They take into account factors such as community pride, struggles, cultural histories, accomplishments, setbacks, dreams, and points of pride. They speak with numerous locals. They internalize as much of this as they can before they set out to create a piece of art that they feel captures the essence of the community. This, my friends, is what coding is.
Does this mean coders don’t use established programming tools and techniques? Of course not. The artist acquires a lifetime of skills and techniques that they bring to the table and are expected to execute on faithfully, but there is the additional layer of context and choice of application methods that transform the fundamental skills into what we call art. This is no different for the coder. In place of community members, coders have product managers, designers, Sr Engineers, and quality assurance engineers to speak to and get context from. Programming provides the tools and basic techniques; coding is the contextual application of those techniques.
What Implications Does This Have for Engineers?
From an engineering perspective, this approach can be both a blessing and a curse. On the one hand, when customers and leadership approach software development in this way, it takes some of the stress off the engineer for needing to find the one “correct” way to do something. It also lets the engineer have more liberties in how something is implemented. It helps form the basis of a conversation about the why rather than just the how…which is often ignored by non-technical stakeholders anyway.
However, with this liberty comes responsibility. In many ways, by treating programming as an art, it places more of an emphasis on the engineer needing to be a well rounded and thoughtful artist rather than simply a mechanical implementer. While a good engineer usually tries to code with guiding principles like DRY and SOLID (which are tools to the code is art approach), approaching code as art means knowing when these kinds of principles are proper and necessary to implement…and when they can be ignored.
Above all else, code as art requires the engineer to have good judgment and a honed ability to know the when and why as much as the how. Jr engineers will generally stick with the procedural and mechanical task of imitation. This is perfectly fine and expected in the early years. True art is as much about the artist’s maturity through experience as it is their acquired techniques, and the same holds true with software engineers.
Now, where a lot of engineers falter is that they get stuck in the imitation mentality. I see this happen for two main reasons: 1) they get comfortable with imitation programming as it seems to work fine for them or 2) they are never given the opportunity to grow into the code as art mentality.
Reason number one is solely on the engineer. As a practitioner of any craft, it is your responsibility to continually learn new methods and ways of working. No growth occurs in comfort, and as such, a good amount of your professional life should be trying to grow your craft from as many different angles as you can. The key to this is having the mental and social attitude that you can and need to grow. I can’t tell you how many potentially good programmers I have seen keep shooting themselves in the foot because they either think they already know enough or they shun the collaborative and social aspects of growth as a coder. Don’t be that person!
Regarding opportunities to implement code as art, this is where the role of stakeholders comes in.
What Implications Does This Have for Stakeholders?
Organizational stakeholders have just as much of a responsibility for promoting and enabling the code as art mentality as software engineers do; if not more so. As the people who set the expectations, requirements, timelines, and working conditions; stakeholders…especially executive leadership, are uniquely positioned to promote this idea.
I think the biggest implication for stakeholders is the need to understand a software engineer’s continual struggle between coding something “right” vs getting something done. In this case, the “right” generally means approaching the solution from a code as art perspective and implementing a well thought out, contextualized, and technically correct solution. All too often, engineers are forced to program a solution that simply gets the job done. They know it’s not proper. They know it’s going to mean problems down the road (aka technical debt). Yet, they often have no choice. Deadlines set by stakeholders necessitate the bypassing of crucial steps like UI/UX, QA, or proper software architecture implementation…all of which take time.
As a stakeholder, it is critical that concerns from engineers are taken seriously. Can they simply code it to just, “get it out the door?” Absolutely. Can we just, “circle back and fix things after this deadline?” Absolutely. Can you just, “use your best judgment?” Absolutely. Sure, engineers can do all of these things but here’s the consistent problem that I have seen over and over for the last 15 years: engineer judgment when it comes to UI/UX and product decisions is notoriously bad and no, there is rarely, if ever, time cut out to circle back and do things right without client or financial pressure to do so.
Now, this doesn’t mean that deadlines and client promises should go out the window. Rather, it simply means that more care, and in particular, more communication pursuant to deep understanding, needs to happen to get stakeholders and engineers on the same page. Some of the things stakeholders can focus on include:
- Consult engineering, UI/UX, and QA departments before making client promises or setting deadlines. If their estimate seems long, work towards understanding why. The disconnect could be a lack of understanding of the feature, a systemic problem with a proper implementation (tech debt or legacy problems), or just a misunderstanding on the stakeholder’s end regarding the feature’s complexity.
- Inquire about and promote the discussion of resolving tech debt incrementally during new feature development. When given the opportunity, I guarantee you that engineers will raise existing problems related to the requested feature that they’d love to fix (sometimes, they’ll need to) in order to get the feature built in the best manner.
- Don’t run roughshod over-engineer concerns; it will always come back to bite the product and organization. Seek an understanding and work on a compromise. This will go a long way in helping relationships with engineering and will significantly benefit the product in the long term. A pattern I have seen consistently over my 15 years in this industry is stakeholders ignoring design and implementation concerns in preference of a timely deliverable or client demand. It typically goes like this:
- Engineering or QA raises concerns about taking shortcuts.
- These are ignored or belittled by stakeholders (usually executive leadership in my experience) because of timeline promises or a lack of genuine desire to understand the problem.
- The product or feature is built and delivered but it is built on a shaky foundation.
- Six months to a year or so later, new features or client demands are made to expand that original feature and the original tech debt issues arise as a blocker.
- Stakeholders blame engineering for not building it right the first time around and/or the original stakeholders have moved on from the organization, reaping the temporary success but leaving debt in their wake for someone else to repay.
- Compromise. Like artists, most good software engineers never feel like their work is “done” or good enough. There’s always more tweaking, abstracting, or refactoring that can be done. This doesn’t mean timelines and deliverables can be ignored. Work with engineering to come up with a compromise from both sides that is fair and helpful to everyone.
The practice of coding is an art form and as such it can be easily misunderstood. Yes, it has technical and scientific roots. Yes, programming can be done objectively and to solve immediate and specific problems. However, for products that have any kind of shelflife or stakeholders foresee any kind of ongoing benefit for maintaining the software, it benefits all parties to view the process of software engineering as a creative process with all that it entails.
Good engineers will leverage contextual input from design, QA, and product management teams and frame their input against business requirements, like deadlines and cost constraints, to craft software that adheres to good software engineering principles and fits the needs of all stakeholders. They will make their concerns known regarding technical debt and unwise shortcuts being imposed on them.
Stakeholders will understand the creative nature of coding an application or feature and provide as much context to the relevant teams as possible. They will take engineering concerns seriously and understand that, as with most craftspeople, engineers take pride in their work and want to do things right. Communication and compromise are the keys here. Continually asking for shortcuts and bypassing best practices belittles the engineer’s craft.
Need help implementing great coding practices in your engineers or stakeholders?
We offer training and consulting, based on decades of experience, to engineering teams as well as stakeholders and ELTs on the best ways of approaching software engineering challenges. Great software starts with the right mindset. Let us help get you there.