Controlling your software surface area
One of the most important parts of crafting software is making it focused and light enough to deal with. In this post I try to capture some details that might help you to keep in mind when considering software.
Data can represent a lot!
Even when software was hand-assembled punch-card and sticky-tape, representations within a single addressable unit were comprised of many bits. I'm not going to cover fundamental computer-science or prerequisite learning. Often the type systems we build on to digitally express ourselves using, at a fundamental level allow for a large number of possible representations within a single unit.
- A Character you see on screen may be backed by 1-4 bytes
- Depending upon the number-types you use they may have 256 - 9,223,372,036,854,775,808 unique values in 1 - 8 bytes
A consequence of this is that it's very easy to have software that doesn't fit inside your head.
Features do not grow linearly
"It's just 16 things". Later it will be "Just another 16 things". The combination of 4 bits + 4 bits is not 32 outcomes, but 256. There are 16 outcomes of the above, and even when considering unique one's, we can agree I hope, just 4 more things lead to a multiplicative effort in reasoning.
|Feature 1||Feature 2||Feature 3||Feature 4|
|You get the point I hope...|
If something does not need to do more, consideration should be given to containing the extra and leaving it as an option, instead of a third-wheel that won't go away. I've seen businesses literally lose everything because of a cast-iron grip on unnecessary data and complexity at a fundamental level.
Some strategies to reason about state
Mapping invalid state
If you know that someone entering your offices on a Tuesday, on the fourth week of the 12th month will cause a fire. Give that person a holiday and maybe yourself too! I'm being characteristically flippant and choosing fantastical analogues, but the point is that knowing what you need to support and trying to restrict to that means you have less to think about.
You've thought of, does not mean We need to
I find myself constantly arguing about premature storage of data. We want a user, but they can't login and may not be able to use the app until such time as... STOP.
You need a place to store information maybe. Does that need to be your app? Probably not
Ever since I became a programmer, I noticed there is a bizarre fetishization of data. I was on a call yesterday when I was asked "Can we just store this data we purchased from clearbit?". I must seem like such a grump. My immediate answer was a question. "Have we got a place to surface it or a result of it?". "Well no, but..." There is no need for any what-if. We purchased something I'd imagine anyone else with a trivial amount of revenue could purchase. It's worthless without a place to show it or make decisions based upon it.
Putting off homework is good
If any teachers read this I'll be in trouble but I'm right.
If you took on the complexity of building the lunar lander during the age of bronze, you probably would not have got to the moon faster. Sometimes nobody more than me needs to be told to ship a thing as-is, get feedback. It might be thrown away anyway.
Far from laziness or lack of diligence this enables you to ship faster, experience pain that will shape the best products.
Nearly 8 years ago I used to argue against this because I had a problem visualising the outcome. The thing you gain by letting go of that picture, or that idea of a picture is the need to be right. If your goal is to put 4 video's on a page and you do that in a day, then finding out people don't want video at all helps you to focus on delivering what they do want.
We might need to
Just stop. There are benefits to being pro-active. Imaginary conversations and situations are not the place, they won't provide a benefit most of the time.
Sometimes those I work with will say "Aha, you're doing a thing we've not yet got a situation for". The goal is to make things simpler. There are still ground rules. Making things simpler doesn't mean plaintext auth, it doesn't mean serially storing imported data one-record at a time.
I remember when. Or this is so that (near-term need); or third-party will require / has found. Form a much better basis for decision making.
Things that are too comprehensive, AIO themes and libraries, frameworks and apps; annoy the heck out of me. Not only do they make it harder to reason about what they do, but they generally break in unison or unexpectedly, functionality that didn't need the all or nothing approach.
Standards are a wonderful thing, and proprietary or siloed knowledge is the harbinger of doom. If you have a thing that talks to WordPress but not Drupal, Magento and not BigCommerce or Shopify, ASP.NET but not PHP then it loses its flexibility. It could be the best tool in the world but NIH, or I'll charge you forever for this one thing frustrates me. I'm not arguing for flying cars here, there will and should be enough natural boundaries to constrain even the most connective software. Drawing lines in the sand seems such a pity.
One smell that comes with strong things is that they only work a certain way. They infer a perfect garden of connective systems. To some extent we cannot entirely eliminate this, but we should not presume that it's free, sensible or desirable.
This might be my largest pet peeve. Perhaps you have a syntax or language feature that you find attractive. Good for you! Now think about how essential it is. What the cost of not having it vs having it and try to think about others.
I've worked with some truly amazing people. The ones I remember fondly was not for their mastery of prose or ability to express things using the latest terminology, or to pull things into their own domain. They tried to remain as open as was practical and not negligent.
The startup I work at selected ruby on rails as it's new development stack some months before I started a job as a python software engineer and API specialist. Ruby is wonderful, I've used projects written in ruby for years, but honestly I'm not a fan. The rails methods which do not exist are as large a burden as C pre-processor statements and I believe are why arguments are present to materialize code from pre-processed C. Trivial flourishes such as unless built into the language have not been welcomed by me.
In past roles I've worked with PHP, Java, C, C#, C++. I had one rule for the language features I'd use formed about 7 years in. I don't want to fight with legal or compliance; I don't want to fight with steep cost of adoption. I used runtimes which were supported, well tooled for and within serviceable life. Please try to build things that people without gigabit ethernet connections and the latest intel CPU's can use and afford.
Writing software is hard. Please try to make it easier. This is a bit long so I may write more elsewhere. I welcome your new techniques; your input and the fact we all think differently. Please be as welcoming and patient as you'd like me to be.
- Identify and tackle complexity
- Deal with the tangible & reasonable
- Try to shape software so each part does one thing well
- Accept that your way may not be the only, or best way for the context
- Pick your battles, know when to fight legal & compliance
- Use standards, and speak to people about living within them
- Consider if you really need the shiny new thing
- Try to help others use your software
- Don't just listen to me. Think problems through contextually