I recently appeared on Dave Rael’s Developer on Fire podcast. The show focuses less on technical minutiae and more on the developer as a person, and their approach to adding value. I got to talk a little bit about how I think a developer can add value, and wanted to elaborate a bit more.
When talking about software, “adding value” is a nebulous concept. There’s many ways to add value, and many ways to think you’re adding value, even though you’re actually creating drag or adding cost.
A Matter of Perspective
Developers love to focus on code and code hygiene. How the code looks, how it’s abstracted, how dependencies are managed, how many tests surround the code, what frameworks are used, etc etc. Without deadlines, a development team could probably bikeshed minor issues for years before releasing anything. Like a painting, software is never finished, only abandoned.
Developers often assume that fighting over dependency injection frameworks or entombing code in unit tests is adding value. Delaying a feature until the code coverage metrics are hit, or the abstraction is just right, feels like it’s a benefit to the company. Surely everyone cares about maintainable code and using best practices? If a month-long refactor could clean up some of the “gross” code in the system, it must be worth it? Especially because you wouldn’t want to build new features on a shaky foundation! I know I’ve made these arguments plenty of times.
But you know who doesn’t care about any of that? The sales team. Those folks just want to sell the software. More features means more angles to sell it. Code quality is approaching last on their list of priorities. Whether you use IoC or just new up the damn class, it’s all the same to them. When you tell sales you’re stopping new feature development for a month to focus on a refactor, they’re going to be incredulous.
And they’ll probably be right. It’s easy to slavishly follow best practices and do “everything right” while still being a net loss for your company.
Inmates Running the Asylum
Part of the problem is that developers are rarely empowered to make meaningful decisions in a business. What to build and how to build it are usually decided above their pay grade. The design team spits out some wires, business signs off on exactly that design and the developers are left to implement it. So developers focus on the things they can control, namely the code and everything surrounding it. This is how we end up with neverending wars over coding style.
But what happens when the developers run the business? That was the position we found ourselves in when we started TrackJS. We had full control over every aspect of the company - not just which DI framework to pick. All at once there were a slew of new priorities. Discussing which test runner to use, or the exact difference between a unit and integration test, was no longer worth talking about. Much more important was how to get people to pay us, which features were mandatory for release, and how to keep the infrastructure alive.
Once we were responsible for every business decision, the code itself became less significant. Instead of being the main focus, it became a means to an end. Writing code for the sake of it was no longer a clear value adding proposition as there were myriad other factors to consider. It turns out this is the case at every corporation, big or small, but it’s hard to see the bigger picture sometimes.
You Don’t have Time to Fight With Technology
Everyone pays lip service to simplicity. Most developers agree that, all else being equal, a simpler solution is usually better. The problem is, I’ve often heard “let’s keep it simple” in the same breath as things like “and use Kafka to feed a Spark Streaming cluster” or “bring in event sourcing and do serverless microservices.” Developers aren’t very good at gauging simplicity it turns out.
But when you’re the one who’s money is on the line, and time is critical (and time is always critical), you really start to understand what simple means. Simple means not having to fight your technology choices. It’s more fun to learn something new than to use something old, but it’s almost always the wrong choice. New things fail in unpredictable ways. New paradigms appear better at first, but after 6 months of development you’ll discover you’re in a worse place. Developers keep re-inventing the wheel, but each new wheel has some as-yet-undiscovered defect, and sometimes they’re catastrophic. Adding value usually means avoiding the bleeding edge in favor of predictable infrastructure, proven languages, and stable frameworks.
The Best Code is No Code
Sometimes the best way to add value is to do nothing. Developers want to write code to solve problems, it makes them feel productive. But there are myriad problems that either shouldn’t be solved with code, or shouldn’t be solved right now with code. I see developers rush to their editors and start banging out lines of code the minute they encounter a problem. But it’s frequently the case that they don’t fully understand the problem, or the solution. Sometimes “issues” will even solve themselves if you wait long enough or requirements will change entirely.
Consider the clamor around everyone switching to HTTPS. The TrackJS documentation is hosted on Github Pages. Google warned everyone that they would start penalizing search results that were HTTP only, and Chrome would start flagging HTTP sites as insecure. We really liked Github Pages for hosting our static content but they didn’t support custom domain SSL certs at the time. Changing would mean writing code, spinning up new infrastructure etc. So instead of doing any of that - we just waited. We figured everyone else on Github Pages would be clamoring for HTTPS support too. Sure enough, a few months ago Github partnered with Let’s Encrypt to get every hosted Github Pages repo an SSL cert. Problem solved, with no work required on our part.
Code is Costly
If you have to write code, write as little as possible. Every line of code has a cost. Heck, it’s called “code” for a reason. There’s the maintenance costs, the cognitive costs to understand the code, and the complexity costs as the system as a whole is now more brittle. Writing less code might mean changing the UX to something “less optimal” that is easier to develop. It might mean repurposing existing infrastructure for a new task. It might mean making a manual process easier instead of fully automating it.
At TrackJS we are always balancing our user experience and design with the cost to build it. We will pick a “good” user experience over a “perfect” user experience if the time to develop it, and the lines of code written, are meaningfully less. The same goes with infrastructure. We’ve built plenty of features where getting 100% of the functionality we wanted would require new infrastructure, but we could get 80% of the functionality by re-using existing hardware. Everything is a balancing act.
When confronted with “gross” code, most developers will have a strong desire to clean it. They’ll insist they can refactor it to something better. Nevermind that most of this is subjective, and as a profession we still can’t agree on tabs vs. spaces. The problem is refactors are risky and are constant sources of new bugs. (And I don’t want to hear about unit tests making refactoring safer, that’s nonsense. Any significant refactor worthy of the name is going to break APIs and render most tests useless. You could make an argument for functional tests though).
Risk needs to be balanced with reward. What is the advantage of cleaning this code? If it’s code that’s rarely touched, or if it’s a mission critical part of the system, usually it’s better to leave it alone. And anyways, the end result of a big refactor is almost always code that is still gross, but in a different way. Many times adding value comes in the form of choosing to leave something as-is, or bolt your functionality on while touching as little as possible.
Value is Hard to Measure
There’s no one-size-fits all approach to adding value when it comes to software. It takes experience, empathy, and self introspection to get better at “knowing it when you see it.” But it’s always worth considering your problem from the perspective of the business as a whole, rather than your small slice of the world. Software is a powerful lever, and as a developer you can make an outsized difference if you come at problems from a holistic perspective. The flip side is you can crater an initiative with a poor decision, or cost the company millions of dollars or thousands of hours with a wrong choice. It’s up to you to choose wisely.
While we’re on the subject, another thing you should do is install TrackJS on your web apps. Proactively monitoring and solving front-end issues is a great way to add value!