Time for a classic rant again; yeah it’s always good to express thoughts and hear about the feelings of others – a good way to learn.
Lots of people think the most difficult aspects of software development revolve around engineering themes like:
- Writing elegant pieces of code that are a joy to extend and scale beautifully
- Crafting brilliant algorithms that can land rockets on small floating platforms (yup, SpaceX, I see you…)
- Inventing new cryptographic systems (please don’t attempt this at home…)
- Building and maintaining massively parallel computation systems
Agreed, these are extremely challenging and sometimes it is difficult to find a perfect solution. However, since most of these deal with code and systems, the required skills can be learned and there are usually workarounds available.
There is more to software development than engineering and these other facets can spawn tougher (or even impossible-to-solve) challenges.
Here are three of those difficult areas:
1. Exponential Chaos
The combinatorial complexity of code grows exponentially. It’s well nigh impossible and also futile trying to exercise all possible execution paths of a program. Equivalence class partitioning helps a lot to cut down the test space but invariably, we still miss out on a few.
A single if statement with one condition has two paths – the condition is either true or false. Let’s assign the simple one-condition if check code above a theoretical complexity value of 1. If that if statement is nested in another if statement, the number of paths explode to 4; ditto for two conditions in the if condition check. Re-using our complexity model, this comes to a value of 2 or so.
Most codebases have loads of conditional branching, loops, multi-threading, various components and what have you. So we can safely our complexity values for such code bases in in the high millions or thereabout. Scary? Not yet.
Now imagine what happens when there are hundreds of developers working in that same codebase and making a few hundred check-ins daily? Maybe the complexity value should sky-rocket to the high billions? Trillions?
Given the rapid rate of change and inherent complexity, how do you ensure that quality is maintained? How do you enforce consistency across large groups? A very difficult problem to solve – there are approaches to mitigate the risk but I do not know of any foolproof method that works all the time. If you know of a way, do let me know.
2. I’ll know what I want when I see it
We all think we know what we want – alas, we typically don’t until we see the finished product. Let’s take the following series of interactions between Ade who wants a new dress and his tailor.
Ade: I want some beautiful dress that fits me, is wearable all year round and casual. I want it in 2 weeks.
Tailor: Aha, so you want something casual that fits you, is wearable all year round and need it in 2 weeks.
Ade: Yup right on point
2 weeks later
Tailor: Here it is! (Beaming proudly)
Ade: (Not impressed); I like the fabric and design. But I don’t like the colour, the sleeve length and it doesn’t fit me quite right. Can you change it to black?
Tailor: here, it is in black
Ade: On second thoughts, black would be too hot, could you change it to brown?
Tailor: here it is in brown
Ade: Great! Could the sleeves be shortened by 2cm?
Ade: Hhmm, could you revert the sleeves to their original length? I think I now like the earlier design.
Tailor: Done!! (getting annoyed probably)
Ade: Great! This is becoming awesome, could you please reduce the width of the dress? It’s too wide…
Most people usually don’t have physical products tailor-made to their desires. We go to the store (to meet a car dealer, a tailor or an architect) and choose one of the several options there. We can take a car out for a ride, walk through a building or try on a new dress. This helps a lot as we know if we want that product or not.
In software development, it’s a different story – we want something tailored but we cannot express that need accurately until we see the product. Invariably, our descriptions do not match what we desire. To restate: it’s highly probable that you wouldn’t like a dress you described in its entirety to a tailor when you try it on.
Figuring out what users actually want is a difficult problem – probably why agile methodologies are popular. Less difficult way? Do the minimum possible thing and allow users to play with it. For example, the tailor could have given Ade a paper dress to evaluate all the styles and all that.
Let’s play a simple game: when you start your next project, make sure you document all user requests, also record every update as you go along. I am pretty sure the new requests will significantly differ from the original one. The end product might be totally different from the initial ask even.
3. No laws – it’s the wild wild west out there
If I release my grip on an apple, I expect it to fall down – why? Gravity of course. Most interactions in the physical world are bound by these models. Imagine that a car manufacturer has to design a new super car for some super-rich guy. Mr-rich-guy asks for the following:
- Must be drive-able by adults, teenagers and infants
- Must work on Earth, Venus and Mars
- Can run perfectly on gas, water or coal
The manufacturer can tell him it’s impossible since the current physical models make it extremely difficult to achieve the three impossible orthogonal requirements; maybe if he wants a movie though…
Let’s go to the world of software; consider the typical AAA game, to capture the largest possible market share, products have to be usable on:
- Multiple consoles (XBox, PlayStation, Nintendo etc)
- Other architectures (e.g. 32-bit and 64-bit PCs)
- Operating systems – Windows, Linux
- Various frame rates
There are also limitations in software (hardware limits, processors, memory etc) but we often have to build ‘cars’ that can be driven well by people in various age groups living in multiple planets!
The support matrix explodes all the time and generating optimal experiences is an extremely difficult task. In fact, most times, the workaround is to have a limited set of supported platforms.
Alas, it’s the realm of 0s and 1s, so software engineers have to conjure all sort of tricks and contortions to make things work. Maybe some day, cars would run everywhere too…
So apart from the technical challenges, there are a few other just-as-challenging (or even more challenging areas) in software development. These include
- Ensuring your requirements match hidden customer desires
- Working to meet various regulations and ensuring proper support across platforms
- Managing technical debt and reducing risk in heavily changed code bases
16 thoughts on “The difficult parts of software development”
“Volatile. Business. Priorities”
A tad similar to “I’ll know what I want when I see it” above but on another level of insanity.
So you and your team are working on this new feature business requested. Cranking out insane man hours to beat the stupid deadline some dude whose only credential is that he got an MBA from Harvard set. And then all of a sudden, the Harvard MBA dude says, neeh, let’s dump that feature, let’s do this instead. Nothing bad with that really. I mean, it’s just the business “reacting to realities of the market”, right? However, when you have things like that happening 3-4 times, maybe you should look for another job.
I mean, you’re a software engineer. Just wave your wand and make it happen. I need the feature last week. No, I don’t like dealing with non-technical business people. My honest opinion, I think they are stupid. The least you can do is learn about the business you’ll be working with before trying to “run the show” Harvard MBA guy, I see you.
Rant over. I need more coffee.
Lol! This is one heck of a rant – someone must have really gotten on your neck. Take am easy oh.
Have you thought about educating them? Am pretty sure they would back off if you make visible to the them the cost of switching and all that. Example below (learnt from one of my former managers).
Product Guy: Yo rockstars! It’s time to pivot again!! We’re gonna build the best-est awesome-est baddest (add more superlatives…) feature this time.
Engineer: Sure. This would be the 7th pivot in 7 weeks; we’ve not shipped anything, our customers won’t get any value since the newly-proposed one-of-a-kind feature would take 4 more weeks. However, we could ship pivot 6 in about a week; how about we ship that and then jump on the new boat?
Product Guy: But feature 6 is so old; this 7th thingy is the coolest raddest thing out there.
Engineer: Do you have some customer metrics to back this up? Have you done surveys? Do you have users requesting this? How do you know? Tried A/B testing?
Product Guy: Err… I know because I can feel it…
Engineer: Just a week and we’ll ship the 6th cool thing; then we can move on. If 6 fails, we can learn from it and also pull the plug. At least customers get some value while awesome-est is in the works…
Making the cost of such volatile changes very visible to management helps a lot; educating them too helps a lot. Thoughts?
Yet another well written and articulate piece. Yeah, the ‘Exponential Chaos’ is real and it is quite hilarious how often we downplay the implication of exponential functions. we know the first ‘if’ statement splits the code path into 2paths. We stay conscious that the first level of nesting is 4 paths. We just see the third, 4th,… ones as ‘minor” edge case failing to realise how explosive exponentials can be. Analogous to this is the headache of crafting integration tests for these ever increasing code paths.
Thanks for sharing once again, always a pleasure reading.
Thank you very much Pelumi; glad you enjoyed it. Have you heard of the broken windows theory? Pressure, deadlines, sloppiness and a lot of other issues contribute to the demise of code quality. Having a very strict attitude helps a lot and code reviews too.
There is a technical cure to volatile business requirements. It is called BRM and has little side effects.
Thanks Maurice; do you use BRM a lot? What has been your experience so far?
I use BRM to get the spaghetti code (like having several if/else/for/whiles layered together) out of my imperative code base. It is a declarative approach and needs to get used to, but makes Rules more readable and editable because one is not subtracted by all the different layers of code that you would get in a imperative code base. Drools from JBoss is a good starting point.
Nice article. Murphy puts it this way: Users never know what they want, but they always know what they don’t want (when you deliver it to them). Plus, once they see a new product, it is often immediately obvious what it should do or be differently (and that they “obviously” meant when they asked for it in the first place.) ;)
That’s why prototyping is great when it can be done.
Thanks a lot Joseph!
I really like the description you shared: “Users never know what they want, but they always know what they don’t want (when you deliver it to them)”. Going to use it all the way now :)
I typically try to push back nowadays until I am sure that everything is clear; next I try to build the smallest high-value feature possible to validate the ‘obvious’ intentions, lol.
Nice piece my brother! Jazaakallaahu Khayra!
How about users wanting you to support an obsolete technology when it is very obvious it poses risks such as (security, scalability or performance) just because they fear the unknown while the engineer is quite sure such technology is not sustainable in the long run? A very good example is “I want the db in Ms Access 2003 format and the application to run on IE6 as we don’t want to upgrade our OS now but I also want a responsive design that requires no plugin to run so my users don’t have to keep downloading flash, silverlight or Java plugins”.
Simply put, users sometimes push for two extremes just because they trust a technology version they are used to than others. Although, educating them and making them realize the cost implications works a lot, but there a few nostalgic guys out there. I know occurrences of this kind are more likely in the “technological disadvantaged terrains”, but they also need to be considered in the big view since users are always users.
My paradigm may be questionable, please feel free to point it out.
My years in startups are not without the lessons.
I call them Parables:
1) “I don’t know what I want. But I know I don’t like that.”
Lesson: The root of all genesis in things new, is the dissatisfaction with what we have today. WE DREAM OF SOMETHING BETTER and then
manifest in matter and thought, our design of a new era, a new way of life.
2) KISS – rinse and repeat.
Lesson: Too easy to get lost in the complexity; the more you think it down to something easy to comprehend, communicable
and manageable, the more it will help you manage the complexity that will otherwise make you fail. Find your common denominators
and build upon them. To abandon them is either further simplify or fail.
Lesson: It sounds so cliche but it’s true.
To invest too much into any one version, is to fail to fail fast, and to find what people like.
Find what you like.
Don’t be afraid to invest your passion and let people see it, even if they tell you to do it like UX said in the first place…
People respect those with the move vision and imagination, to just let it shine and develop it.
4) “I want it to look like this” ( and points to a 10 year old mature software product with millions of dollars in development behind it).
Lesson: EXPECTATION MANAGEMENT
Cut that shit off at the stem fast. Make damn sure some MBA type with little technical knowledge doesn’t set you up to fail, and
doesn’t get the deciding vote without a fight.
When they point to a mature product with millions in design and development behind it, point out that is a mature product with millions of dollars
in development behind it, and that it will take a real leapfrog of effort to counter it. Indirect moves only; you can’t fight it directly with a small team.
5) CEO leading technical meetings
Lesson: Wait for the CTO to get back from vacation or business trip. Duck and cover.
6) Stay on top of the food chain.
Lesson: Study and Find ways to be lazy and work smarter. Don’t take on fire with fire. Take fire on with Halon gas.
LikeLiked by 1 person
That’s why developing software is NOT engineering, it’s mostly an art. To build a bridge, we know exactly what we must do, pick the bridge type, determine the amount of materials required to span the area to be crossed, and select the appropriate machinery to actually build it. Software has a million variables you can consider to implement your piece of software. Each piece of software is kind of like Michelangelo’s Sistine chapel. Nobody knew exactly how he would paint it, or what it would look like, but they were in awe when they saw the completed project. This is ultimately the job of the software developer, no matter what type of development methodology you wrap it in.
LikeLiked by 1 person
For software I have come to realize, writing good software takes time and great discipline.
Software has three main functions, it needs to solve customers problems, it needs to work, and it needs to be maintainable (extendable).
So you’ve got three problems.
Q. How do you know what you have is what the customer will want? Answer talk to customers, feel their pain and rapidly iterate. Do you do this with production code or lots of little prototypes? I would say rapid prototyping and lots of A/B testing is not a culture at MSFT.
2. How do you ensure your product works. Answer tests. Tests with code coverage. Ensure you are hitting 80%-100% of your branches. This is hard and requires a lot of discipline. I’ve seen some teams do it. It takes time. However time not spent implementing failed prototypes can be used here. You can only afford to do this when you know the product has good market fit and not undergoing crazy re-writes.
3. Maintainability – this I would say would be a combination of documentation, tools and a keen eye to code quality metrics. Usually great code has great semantic compression. It usually undergoes refactoring as new requirements come in. This is why I think open source projects at times have better quality. Code needs to be written both for developers and its users.
But this takes time and discipline. Problem is worsened by fact that there is a lot of middle management who don’t write / review code therefore don’t understand the pain. Some became managers to escape the coding bit.
The other issue is devs are super isolated from customers. PM’s do most of it. But PM’s sometimes fail to realize what is easy and what is hard.
So you’ve got a group of people who are trying to globally maximize customer satisfaction + good code, but end up locally maximizing their personal reward.
How do you tie local maximizing (promo + rewards) to global maxima. That’s an interesting question on its own.
LikeLiked by 1 person
The quality of these comments shows what a great following this blog has!
Here’s a simple summary article on good code: https://sourceforge.net/blog/is-that-really-good-quality-code-youre-writing/ .