Tradeoffs In Coding: No Objectively Better Solutions
Tradeoffs In Coding: No Objectively Better Solutions
So this is a pretty difficult one to tackle and it is going to draw on yesterday's theme of toasters - but it's going to incorporate tradeoffs as a main theme and a main topic of this blogpost.
A review of yesterday:
So there are two times in our code when toasters are useful. What is a toaster, you may ask? A toaster is something that inputs and outputs something.
A toaster in code is very often a function - but not always.
It can also very often be a couple of lines of codes - often inside of a function, but not always.
When in our journey as a software engineer can toasters be useful?
Toasters can be really useful at two points in our journey:
When we are READING code
And
When we are WRITING code.
- So, when we are READING code we should look out for the toasters and how we can use them.
- And when we are WRITING our own code we should also look out for our own toasters, and how we can use them, and how we might be able to incorporate them into our own code!!!!! ❤️
Tradeoffs
Every decision in software involves tradeoffs. This includes decisions about how the code is structured. There are potentially infinite ways of how to structure solutions to coding problems.
We can come up with multiple potential solutions to structure the code
And then we can compare them against each other and look at the tradeoffs between them.
One thing to look out for is good function signatures.
This makes the interface of the function much quicker and easier to understand and is good for reducing cognitive load and understanding what each toaster does very quickly.
Especially if we just want to know what the function does but don't need to worry about how it does it, or if the logic is super complex and complicated, then we might want to put our code into a smaller function or "toaster" if we possibly can.
Avoid Duplication
Avoiding duplication can be good as when something changes within the business logic of a codebase, then that means we only have to change things in one place and/or we don't have to worry about forgetting to change things in other places.
However, duplication can sometimes be better than over-engineering things.
The Main Main Point About Tradeoffs
Different ways of structuring the code will have different tradeoffs.
One way of structuring the code isn't necessarily objectively better than the other.
Crucially:
Even if we were to measure against certain metrics like performance metrics, cyclomatic complexity score (??!), (I read up about this but, NO, it's too late, that's definitely a post for another day), then still nothing could tell us whether objectively one coding solution is better than the other. And so - no quantitative metric can tell us whether one solution is either more readable or more suitable to the problem at hand than others are.
A Lot Lot More About Toasters
So, a toaster should ideally follow the single responsibility principle.
This means that the toaster should be responsible for just one simple thing.
For example, the toaster should just make toast; it should not be responsible for making eggs as well. That way, if it breaks then we can still make eggs in some other way.
I cannot believe I'm doing this but my mentor encouraged me to put this MONSTROSITY into my blog post (cramping my style).
However, these are just guidelines
This is what my mentor says.
He says that real problems are not simple and the guideline helps us know if we're at least benefitting from this ideal or not. However I disagree with him slightly.
I think it is often quite easy to stick to the ideal - and even if we get it slightly wrong, putting 2 or 3 small bits of code into a function (instead of having just one) is still better than having 500 bits of code loosely flying around in one function! But basically we want to make sure that the function is not responsible for more than it has to be.
My mentor says this is a guideline that we can and will break
However I don't think that there is anything wrong with that anyway.
What is wrong with breaking a guideline? After all it's only there to help isn't it? I like this idea anyway - this idea of one functionality per, well, function - and if it has to be two or three small bits then there's nothing wrong with that, right??!
Some basic guiding principles behind tech tradeoffs
On the whole: simplicity is good and complexity is bad. It's the same with appliances.
We want them to do one thing, and not ALL THE THINGS.
That way, as we said above, if one breaks: THE OTHERS CAN STILL KEEP ON WORKING.
"THE SIMPLER THE TOASTER IS THE EASIER IT IS TO FIX."
Little Toasters
We NEVER WANT TO LOSE SIGHT OF THE BIG TOASTERS THAT WE ARE WORKING INSIDE OF. So even if we are working on lots of tiny little toasters with lots of smaller functionality, we want to keep the big toaster in mind. This will help us to keep the end goal in mind, and not to lose sight of the functionality.
I'll repeat that: this will help us to keep the end goal in mind, and not to lose sight of the functionality.
"If we stay focused on the big toasters, we don't get lost for the little toasters."
A note on return types
A good thing to do when going through a codebase is to think about return types.
This will allow you to not get bogged down in the details of every little tiny bit of code.
Better reduce your cognitive load. Far better to just focus on functionality.
Don't focus on every tiny little bit of the implementation details - think about the bigger picture.
Summary: One More Thought About Tradeoffs
No single solution is better than the other to a coding problem.
They all have their tradeoffs.
There is no way of measuring it objectively either - no numerical metrics can tell us which solution is more readable or more appropriate.
They are all always subjective.
Comments
Post a Comment