How to Write Software: 5 Lessons Learned from Running Businesses
I used to write software for a living. I did that for a lot of years, as a matter of fact. And, in doing so, I learned a lot about how to write software.
But I learned this from the perspective of, well, a wage software developer. Today, I’d like to reflect on how my view has evolved over the last number of years.
Software as a Software Developer versus Software as a Business Owner
As longtime followers of this blog know, I’ve had a meandering career. I started this blog as a software developer, new to moonlighting. Eventually I moved into management and then started doing developer training activities. From there, it was a number of years of consulting. And finally, these days, I’m mostly running a business that is growing rapidly.
I say all this not to treat you to an unsolicited autobiography, but rather to set the scene and to help explain what I’ve been doing between my last full time software development gig and now.
These days, for Hit Subscribe, I’ve started writing software again. I don’t do it full time, by any stretch. But I am building a line of business app used directly by four of us and indirectly by something like 30 people. So it’s not my primary living, but it’s not trivial either, in terms of importance or scope.
Dedicating some time to this has caused me to reflect on how my perspective has changed. Don’t get me wrong. I never stuck my head in the ground pretended “the business” didn’t exist or didn’t matter. But then again, I never was the business, either. It was never my money in play.
Now that it is, here are some musings. And please bear in mind that I’m not teeing these up as lessons you learn. They are simply how my perspective is different.
1. I Ask, “How Does This Not Exist?!” A Lot.
I won’t go into a ton of detail about the app I’m building. It’s no secret — here’s the github repo, if you want. It’s not interesting enough to folks outside the business to describe in detail.
What I will say, however, is that you could argue that there’s a COTS out there I could use instead. I’ve researched this a bit and punted because of cost and because I’d prefer a degree of extensibility that would probably be impossible.
So I decided to build instead of buy. But I didn’t decide this lightly.
And that philosophy carries down to more granular levels. In my software pro days, I’d have snapped my fingers and said, “aw, shucks, I guess the perfect client-side grid thing doesn’t exist, so I’ll just build my own!” These days, not so much.
Whether it’s a framework, an architectural construct, a library, or a user control, I find myself thinking, “someone has to have built this by now. It’s friggin’ 2018 — how does this not exist yet?!”
I want to spend my time building out business logic and serving the app’s specific value proposition. I don’t want to write the world’s 183,663rd date picker.
2. I Don’t Think Building Things Yourself Builds Character
This next point builds logically on the first. I don’t want to build yet another date picker because it’s a waste of time I could spend on other things. I’d rather one just exist.
And consequently, I also don’t think building my own somehow builds character for me as a programmer.
There’s an understandable desire to know how everything works under the hood. If you write web apps, you’d better yourself by writing your own web server to really understand how your web apps work. Do you write web servers? Try writing your own kernel logic or your own operating system.
This is kind of extreme, but it reflects a sentiment. And I remember sharing this sentiment. Building something of questionable business value might not help the bottom line or your immediate situation. But it would give you a broader base of generalist knowledge to use in your career.
Well, it’s no secret that I’ve soured on genearlism in the extreme. I don’t think that writing a date picker improves my prospects short term or long term. Might it make me a slightly better generalist programmer? Sure, maybe. But why not build something that actually serves your career, instead of miscellaneous “practice?”
I’d rather get better at automating and solving deep problems in my chosen domain, and make myself increasingly marketable as a specialist.
3. Don’t Speculatively Abstract Anything
Moving away from the idea of your own skill set and from reinventing wheels, let’s talk about actual software design. My take on that has changed a lot, too.
Back in the heady days of obligatory N-Tier architecture in enterprise Java, I was a believer. Want to build a toy app to sort the music files on your hard drive? Well, the first thing you need is your data access layer, domain layer, service layer, presentation layer, and markup, of course.
And interfaces. Interfaces everywhere. Sure, today you might want it to sort MP3 files on disk, but maybe tomorrow you’ll want it to be links in a relational database or blobs in a document store. If you interface all of your layers, you can swap out your entire persistence model without ever touching anything else! Would you ever want to? Who cares! You can do it!
Before I left the world of wage software, I drifted away from this and toward YAGNI along most others during the late 2000s. But I still fretted over architecture from the get-go. You want interfaces because unit testing. You want at least some conceptual layering.
These days, not so much. I want to test drive my code, and if I can do that, fine. So I don’t interface anything until I’ll have multiple implementations. I don’t layer things until I have an actual use case for varying things above and below independently. I don’t create abstractions until they solve problems.
So I use Entity Framework and manipulate a context right there in my controller, and I keep doing it until I have a persuasive reason not to. I don’t have time for speculative best practice design.
4. Technical Debt Can Be Technical Leverage
Are you familiar with the difference between debt and leverage? It’s not just “debt is what Millennials have and leverage is what wealthy Boomers have.” It’s about the reason that you owe money.
If you borrow $20 from me for a pizza that you subsequently eat, you have debt. You’ve taken that pizza and turned it into… well, let’s just say something that probably has no monetary value. You owe me $20 and you’ve used the money you borrowed in a way that gives you no head start on repayment.
But let’s say that instead of buying a pizza, you take $20 from me and buy a share of stock. You still owe me $20, but you now have an asset worth (for the moment) $20. You could pay me back at will. But what’s more, you have an asset that might appreciate. It might even appreciate more aggressively than the interest you pay me on the loan. This is leverage.
Leverage is a more strategic play than debt.
This is true in finance, and it’s true in your codebase.
In my younger days, I viewed technical debt exclusively as “slapdash design” and a failing of the team. I didn’t distinguish between tech debt and tech leverage.
But now I do.
I was using a library recently whose untestable design bleeds into the code using it. So I confined use to an isolated area at the edge of my codebase. This worked, but a series of events started to force business logic into these untested little methods.
I went with it for a bit because we needed a series of relatively quick changes to facilitate work that couldn’t wait. As I did this, I understood that I needed to think about an isolation framework or a wrapper for the library I was using. I understand that each commit where I didn’t do that would make things more time-consuming later.
But for a while, I went on anyway. And then, finally, when there was downtime on a weekday, I paid the piper.
This was tech leverage. I’d created the aforementioned downtime by incurring technical debt. I’d saved more time than I’d cost myself, and I got the code back on track so as to keep the feature delivery curve flat.
5. My Pride in My Work Product is Irrelevant
And finally, one last evolution in my thinking. You could probably call this “lean” or use a pithy phrase, like, “if you’re not ashamed of it, you waited too long to ship it,” or whatever. But I have a different take.
I think of it as a pragmatic recognition that “pride in the code” is irrelevant to the goals we have with this business.
Oh, don’t get me wrong. I do take some pride in delivering something quickly or coming up with a compact, readable way to refactor a method. And, I’d rather push something into production with a snazzy UI.
But those are vanity concerns — not business ones. For the business, my pride doesn’t matter. So I can’t think things like “if I were a good programmer, I’d do this best practice, or defensively code against that, or have a diligence checklist.” Instead, I have to frame all of those things through the lens of business value and return on investment.
To circle back to an earlier theme, is it embarrassing to push something into production that requires us to hand-type dates instead of using a date picker? Sure, kinda. But will I omit the date picker if the people using the app tell me that it would save them almost no time? Yes, absolutely.
I guess, in the end, this detour from programmer to business owner and back again has created an important distinction for me. For hobby projects, I sharpen saws while I automate, hone my skills, and make things I’m proud of. For projects with a commercial interest, I code like an economist.