This post is a follow up to my earlier posts on so called fragile or spaghetti code where I made a point about reading code - not the most fun part of anyone's day, but it generally makes code a lot less 'fragile' if you do it.
This idea is the equivalent of taking the time to read the instructions - you're a lot less likely to break something if you know how you're supposed to operate it.
This post is still about code fragility, but it is about code that actually is fragile, only it is fragile on purpose.
There are a number of reasons why this can happen, I will illustrate them from some recent work I've been doing, as well as some client projects. But first I am going to focus on what people mean by 'fragile', so it is clear what this means.
You may hear the phrase 'this code is fragile' and think that that means that it doesn't work, or that there are purposes to which it is not suited. As in, 'This vase is fragile so I probably shouldn't fill it with chunks of broken concrete.
But this is really not what 'fragile' code means. Usually it means:
This code is hard to work on and it is likely to break if I do something to change it.
This code may break in the future if the conditions in which it runs change.
This code may break if any of our integration partners alter their API.
This code does not fail gracefully.
This code is not commented well and that makes it hard for me to read and understand what it doing.
As it pertains to number 1, this is just the scenario from the other article where you aren't working hard enough to understand it. Said differently, you are really saying, "My understanding of this code is fragile."
I put 1 and 5 at opposite ends of this list for a reason. Because 5 should not be an obstacle to reading code. It is a better excuse, than 1 for your lack of progress, but it still an excuse. Poorly commented code simply means you have to spend more time reading, testing, debugging the code to understand it. No code is ever commented well enough in my opinion, so you can't let it stop you from working on it. Code can be readable or unreadable, it can be commented or not, but that should not stop you from understanding it if you know what you are doing and that is your job. You can get a different job, but chances are you will be in the same situation there.
5 is only worth noting separately, because you should plan for and avoid that situation. Try to avoid committing this sin if you can.
For both 2 and 3, a significant portion of what will happen in the future is unknowable, and so how much time you spend dealing with 2 and 3 should be carefully callibrated. You can know that a partner is going to publish an API update in 6 months if they tell you, but if you need to go live now you may simply have to deal with that change when they publish it or make it the new API available for testing.
Of course with failures and crashes (number 4) you should avoid these things and use defensive coding practices to avoid exposing your users to failures, even if they originate outside of your systems. A few examples:
A good NoScript section of your website.
A graceful handling handling of offline operation.
Handling nulls, empty strings, and other straightforward data situations.
Use exception handling properly to deal with unexpected situations
But be careful of swallowing problems within the system - you may protect users and also hide them from yourself, only to have them come back and bite you later on.
OK, so here we are. We need to do some development work. We have coding practices to deal with number 4 and 5. We're working on a new system, so hopefully number 1 is a non-issue. What, if anything should we do about 2 and 3?
My answer is: it depends.
Truthfully, you can't predict the future or what your integration partner will do to update their API until they publish a specification.
We were recently working through updating a Dialogflow implementation for v2, but we couldn't have changed anything or done anything until they published their v2 specs. It would have been guesswork.
As I've been working on my side project Pricekite.io, I am dealing with the billing APIs for AWS, Azure, and Google Cloud, each of which is in varying stages of development. I am faced with 2 challenges:
What are they going to do in the future to update these APIs?
What additional features am I going to want to add in the future?
My decision for both is to do nothing. If/when I decide to add a feature that requires me to improve code, I'll improve it. I had to add some data storage in order to have data on hand for 1 provider (cough Azure cough) because their billing API is not the most efficient thing in the world.
I had not intended to add data storage until phase 2, but my hand was forced by the 6 seconds it took to pull and process the data. So, I call the 6 second method every 30 minutes and store the values, which can then be pulled at any time. It introduces latency to the data, but that does not matter at this juncture at all. If it turns out to matter, I simply can crank up the frequency of the polling.
So, the code is fragile. But it works, and it was able to be written by 1 person quickly, and it will be very easy to read as, for the most part, you have absolute line of sight readability in the code.
This is why Amazon doesn't get prosecuted for monopolistic practices, but Apple did for price-fixing on books. Amazon lowers prices (good for consumers, bad for competitors) and Apple was trying to raise them (bad for consumers).
The European Union would look at this differently. They say that one company possessing too much market-share is inherently bad for the marketplace.
Can you really trust an Amazon to keep having a focus on low prices? What about when there is no more competition?
To answer that question I found one more article. You have to dig, but it's there at the bottom of the top paragraph of page 4:
Basically, you can trust them if their anti-competitive (but pro-consumer) price lowering has to stay low because any raising of prices will result in new players immediately entering the market.
What does all this have to do with technology? Well it helps explain some differences between the US and Europe.
The other thing that is related is that there isn't really a software or online business that isn't susceptible to a new competitor.
To create software you may need software developers and servers, but you don't need other raw materials or a factory, so the cost is much lower than in analog industries.
Software business are inherently winner take all because world-wide delivery is so simple, there are no geographic restrictions on products, therefore the best will win and when they win they will win very big.
But they can only stay on top if the innovate relentlessly or buy companies who do.
Otherwise someone will find away to come along and eat their lunch.
Those are rockets and they hold up the cloud. Those black hash-mark areas are patches in the cloud where things didn't work right. Because of these flaws someone needed to sew the cloud together. The patches are comprised of 81% code and 22% duct tape.
Why don't the cables burn up in the rocket exhaust? That is because of trained monkeys wearing asbestos suits. When the cable breaks or one monkey burns up, a monkey is added to the chain.
This concludes our brief tutorial on the cloud.
Here's the deal. This was inspired by a discussion with a client about a large cloud service provider. The service provider informed the client that the hardware that their instances ran on was bad and needed to be replaced. This is not the first time this has happened.
To me this revelation of 'hardware problem' feels tone deaf because everything about the cloud (which I mostly love) is predicated on us (the customers) not caring about hardware anymore: pricing structures, product offerings, marketing materials, billing. It seems wrong to then blame the hardware when it is convenient. My client didn't ask for you to tie their instance to some faulty hardware. My client had previously been entirely oblivious (and rightly so) to what hardware the instance ran on. Why don't they just quietly move the VM and fix the problem themselves?
Even if it was totally manual, it would give me a lot more faith in the magic and that they have their stuff together.
Truly, I love the cloud. Even if it is imperfect, it powers a lot of the modern world (including this site). I love it mostly because it is a technical marvel and it empowers business, but this customer service flaw makes me doubt the technical greatness. Why do that?
I really believe that cloud, IoT, and mobile technology are job creators in the long run, because there will just be so much of it.
Just, please, don't blame the hardware when the rest of the time you don't want me to think about it.
I've posted this article recently, but it got me thinking about why code is harder to read than to write. So, I will post it again, to make your life easier and explain why I think that code is still harder to read than write, even all these years later. Here's the article:
The title of this post seems counter-intuitive because we think of reading and writing in relationship to human language, but programming languages are not like human language.
What are the important differences? Here is the main one:
Programming languages can't be read aloud.
So when we talk about 'reading code' we're using 'reading' in a purely metaphorical sense. When you 'read' code you don't actually read it - you're looking at it and trying to make sense of what it does.
This is nothing like reading a book, paragraph, or sentence written in human language.
When you review code you study, you re-read, you look things up. You jump around from file to file. You may consult web pages. Even in programming languages you are familiar with and with a business domain you know, these tasks can be time consuming.
You're trying to 'read' something that can't be read, across many files, and trying to ascertain the author's intent not just comprehend a sentence.
An equivalent would be trying to read in a language where you had to look up every third word, every time you read something because:
Every author used the language in a novel way. AND
Every page of a book was put in a different file and they were constantly referencing each other and not in order.
It would be hard. And it would not really be reading. That's what 'reading' code is.
If you are a developer what code are you accountable for?
Is it only your own? Is it your own plus that of a system that you've worked on for some period of time? Is it your team's? Is it every project ever worked on at your company?
I ask this because I've seen a lot of different answers and I will share with you my own approach to this and why that has been my approach.
When I approach a code base I did not create, my first question is to ask, "What can I learn from this code?". This question can and should consume you for some time. You won't know the answer right away, if you think you do, you probably aren't listening closely enough.
Once you know what you should be learning and have begun to learn you can ask how you can make it better. There are always ways to make improvements and to meld your learning with what you already know.
At no point during this process do I use the phrase 'spaghetti code', precisely because it places the source of misunderstandings outside the self onto an inanimate object: 'the code'.
Code is, at one level, a tool to communicate to a machine what you want it to do. It can't be 'spaghetti' if the machine understands it and does what the humans in the room wanted it to do.
On another level, code is a tool to communicate between one developer and another the intent to make a program and what that program was supposed to do. You may choose to blame the previous developer (who completed their assignment), but I don't see how that helps any business situation you happen to be in.
My approach was to be accountable for all code that I touched.
For code written, from scratch by me, I am accountable for all of it, no matter how long ago I wrote it.
As a boss or manager, I don't necessarily expect every person to have that level of accountability, but I expect them to be on a journey that moves in that direction.
And I hate, hate, hate the term 'spaghetti code' (if that wasn't already clear) because it is such a victim phrase. Are you the victim of code? I certainly never wanted to be. I wanted to win and make the code do what it was supposed to do.
Think of the great developers you know. Do they use that phrase? I've never heard one do it.