A popular phrase over the decades has been “Build it and they will come”. In software, that simply isn’t true. Let’s make sure we’re building software “Just-in-Time” instead of “Just-in-Case”.
The terms “Just-in-Time” (JIT) and “Just-in-Case” (JIC) may seem familiar to you in the context of manufacturing and inventory management, but they apply equally as well (or even better!) to software development.
In short, make sure that whatever the heck you’re building has a known need and well-defined scope! It’s way too easy, and often even a bit of fun, to try to build a product or program that you think meets or exceeds every possible present and future need. The problem there is that typically nobody cares!
There are no awards given for systems that do more than they need to. And more importantly, there’s often a significant amount of sunk costs that go into over-engineering something.
As an example on the extreme side, let’s reference this little company you may have heard of named Amazon. In 2014, Amazon launched its new Fire Phone on which they eventually took about a $170 MILLION-dollar loss. In hindsight, the numerous post-mortems describe a product that had no distinctions other than extra features that nobody particularly cared for. (Read more here: The Inside Story Of Jeff Bezos’s Fire Phone Debacle) Amazon had clearly lost their way when it came down to building something that the end-user actually wanted and/or needed.
On a much smaller and more personal side, imagine the following scenario. What if you aren’t much of a “techie” and on a whim, you decide to build yourself a website from scratch to promote yourself. Most likely, you would casually spend months learning the rudimentary technical skills, slap something together that seemingly sufficed and then moved on with your life. It’s unlikely that your finished product would be as perfect and presentable as you’d like, and the skills you learned would likely diminish quickly over time.
On the other hand, if you suddenly became unemployed, and your prospects of landing your dream job hinged on having a website to promote yourself, the outcome is likely much different! In this scenario, you would have a driving motivation to produce something to be proud of in a fraction of the time 😊
In the first scenario, you were building something “Just-in-Case” that you didn’t particularly want or need, and the output reflected it. In the second scenario, you built something “Just-in-Time” at the moment of greatest need and you nailed it! Not only was the finished result better, but so was the time and effort involved to get there. IOW — it was a lean operation.
Whether we’re talking about one of the largest companies in the world, or the smallest “solopreneur”, to anywhere in-between, this concept is often easier said than done. Let’s take what most would think is the simplest of concepts and see how quickly we can go South.
Image Source: Psychology Today
Most of the applications we write these days need some sort of user login and authentication. In the “old days,” the options were limited and fairly straight-forward. You gave the user a place to enter their username and password, and you gave them the ability to reset their password when it was forgotten. This basic approach was adequate for many systems, but not all.
Today, our options for designing the login workflow are many and varied and include (but are not limited to):
Image Source: Medium.com
So…we haven’t written a single line of code yet, and we already have to decide if we’re building a mountain or a molehill. Think about your user audience and their need for complexity and sophistication. For example, is multi-factor authentication really necessary? Are you protecting government secrets or is it somebody’s list of favorite recipes? What do your users actually want and need? Is it possible that you start out small and then add to it as your user community suggests?
This brings us to our first solution to over-engineering which is user feedback. No matter how hard you try to guess the desires and intent of your user base, you’re likely to never have the full picture. That is simply the nature of the beast. The opinions that you have, along with a comparatively small team of “experts” can rarely capture user sentiment as well as hearing it from them directly.
Think about it — what’s a more representative example of user opinion? Is it your small group of subject matter experts, or the feedback from potentially dozens, hundreds or thousands of real-world users?
As with anything else, gathering user feedback can take many forms, but here are a few things to keep in mind when doing so.
Ask the Right Questions
The feedback doesn’t have much value if you aren’t asking the right questions. Make sure the feedback you gather is structured in such a way that it will help you to take meaningful steps toward improvement. For example, asking somebody an open-ended question such as “What do you think of my app?” may not provide as much valuable insight as asking them to rank 3 very specific features or benefits on a scale of 1 to 10.
Ask the Right Questions at the Right Time
Capture user feedback when it is most relevant. For example, don’t ask your user what they thought about the login process right after they finished checking out and making a purchase. In that case, asking them about the checkout process will probably produce better feedback as the process is fresh in the user’s mind.
Collect Feedback in the Most Appropriate Manner
There are many ways to collect feedback, and you need to determine which is best for the situation. For example, asking a user what their favorite color is for a “Submit” button is hardly as effective as doing a split test with multiple button colors and seeing who the “winner” is based on actual user interaction. User feedback doesn’t always have to be verbal to be valuable.
Run it Through Your Common Sense Filter
As a last line of defense, it’s always a good idea to make sure that any feedback you gather at least passes the sniff test for common sense. Make sure that your questions and tests don’t have any built-in biases that may skew the results. And this also leads us to our next point…
Ok, so maybe the customer isn’t always right…right? Even though our aim is to build software Just-in-Time, that doesn’t mean that the smallest scope possible is always the correct path to take.
For example, in our scenario above about login functionality, it’s entirely possible if not likely that the user has no idea what type of solution is most appropriate for their needs. Just because they can’t detail the difference between two-factor authentication and multi-factor authentication, doesn’t mean those aren’t valid options for their needs.
There are many cases where the opinion of an industry expert has to be given priority even if that means expanding scope and budget is necessary. In those cases, you’re still building JIT, because it is functionality that is minimally needed in order to have a viable product. So…this is all a long way of reminding you that simply because your aim is to build JIT, doesn’t mean you limit scope at every opportunity. It just means that you build what must be built when it must be built.
Over the life of any project, there is always ample opportunity to over-think and over-engineer almost anything. Here are a few common areas to be aware of.
Too Many Features (Scope Creep)
This, of course, is the most common cause of JIC engineering, but that doesn’t mean it’s the easiest to avoid. This can only be avoided by having an almost fanatical obsession with building a product that meets the definition of Minimum Viable Product (MVP). A minimum viable product is a product with just enough features to satisfy early customers. These early adopters can then provide you with valuable feedback for future product development. (Wikipedia)
For example, extending our login scenario above, that means that you likely have to manage users. One of the goals of your application may be that you want it to automatically generate a nice gender-specific birthday message to a user on their birthday. The team thinks that would be a nice touch and may increase user engagement a tiny tick or two.
In order to do so, you need to capture a user’s birth-date and gender at a minimum. Then you need to create the process to produce this message, which itself probably went through multiple rounds of design and revision to come to an agreement on a final presentation.
Image Source: Ganttpro
So…what seemingly was a simple request ends up creating a nice chunk of design, development and QA time for what is anticipated to be a minimal return. Unless your product is extremely mature, and you’re down to nit-picking ways to increase engagement, then a feature such as this doesn’t meet the criteria for MVP, nor JIT development.
Aiming to Perform Like a Ferrari When a Bicycle Will Do
Let’s face it…engineers simply love to engineer things 😊. What some folks may consider to be over-engineering, is just doing the best job possible in an engineers viewpoint. Is your application like a Ferrari in the sense that it needs to operate at the highest level of performance and reliability? Or is it more like a bicycle in the sense that it needs to be dependable enough to get the job done, but without any undue complexity?
Photo by Marc Kleen on Unsplash
Does your application really need any or all of the following?
Or are you simply creating an application for people to store their favorite wines along with pictures and tasting notes? In either case, it’s imperative to have very specific requirements defined ahead of time so that you know you’re spending time and effort on building for the right circumstances.
Sure, everybody wants a highly performant app, but if you build an app that has way more capacity than will ever be needed, then you’ve just thrown away a pretty penny.
Focusing on Compliance Issues When the Need Does’t Exist
This one can often be a bit of a tightrope walk. Complying with various regulations can be a necessary evil, but it can also lead to JIC development when not well defined or understood.
For example, are you wasting time in discussion about PCI compliance for your website when in reality you don’t even store any user payment data?
Are you worried about being GDPR compliant when you don’t capture or store any personal identifying information about your users?
Are you sure you’re not wasting any resources on any compliance initiatives that aren’t specific to your type of business or need?
In summary, simply ensure that you’re not sinking costs into compliance efforts that truly aren’t needed.
Building the Perfect Mousetrap
To pick on engineers yet again…the best ones want perfection 😊. Now, that in and of itself is an admirable goal and can often pay huge dividends. However, there is a time and place for everything.
Are you at a stage in your project development where you simply need to prove a concept? Is a quick and dirty prototype the way to go? In those cases, and others it can often not only be acceptable to write “less than clean” code but actually preferable.
As a quick aside though, beware of the Proof-of-Concept (POC) trap! Sometimes these POC’s go so well, that it’s instantly transitioned into production code. Now, all of a sudden, your quick-and-dirty code makes it into a production build, and you come out of the starting gate with built-in technical debt!
[Technical debt (also known as design debt or code debt) is a concept in software development that reflects the implied cost of additional rework caused by choosing an easy (limited but often quicker) solution instead of using a more robust approach that would take longer. Wikipedia]
Again, there’s always a balancing act involved here. Sometimes building JIT means also taking the time to do it right the first time and not incur unneeded technical debt that will bog you down in the long-term. Other times, JIT means building quick-and-dirty where the needs and outcomes allow a short-term focus. Always be cognizant of how much of your valuable resources are being invested in creating or fixing technical debt.
My last piece of advice to ensure that you’re creating software Just-in-Time instead of Just-in-Case is to keep your development and feedback cycles short whenever it makes sense to do so.
There was a time in the past where software development was built on a bit of a “Big Bang Theory”. In other words, requirements would be gathered, specs are written and then the dev team would disappear for a number of months, returning with a “finished” product to show the customer. The biggest problem with that was that by the time the product was ready to be released, requirements had already changed…sometimes significantly.
This all, of course, lead to the increased adoption of the myriad agile methodologies used these days to create software.
[For more details on how we accomplish this at my company, click here]
The point is that you can not create JIT software if you’re relying on the subject matter experts to know every detail of what they want to be built from the onset of the project. Software development projects each have their own life and personality. And like a child, your project must be allowed to grow and mature over time. Keep your focus narrow and concise and laser-focused on precisely what you need at this time. Knock that out, gather feedback, prioritize next steps, and start the cycle again.
I’ll say that one last time as it is the entire gist of this article in one sentence:
Keep your focus narrow and concise and laser-focused on precisely what you need at this time
Start there, and you’ve won most of the battle to building JIT software.