←back to thread

1455 points nromiun | 3 comments | | HN request time: 0.677s | source
Show context
Buttons840 ◴[] No.45074873[source]
I'm probably one of the "smart developers" with quirks. I try to build abstractions.

I'm both bothered and intrigued by the industry returning to, what I call, "pile-of-if-statements architecture". It's really easy to think it's simple, and it's really easy to think you understand, and it's really easy to close your assigned Jira tickets; so I understand why people like it.

People get assigned a task, they look around and find a few places they think are related, then add some if-statements to the pile. Then they test; if the tests fail they add a few more if-statements. Eventually they send it to QA; if QA finds a problem, another quick if-statement will solve the problem. It's released to production, and it works for a high enough percentage of cases that the failure cases don't come to your attention. There's approximately 0% chance the code is actually correct. You just add if-statements until you asymptotically approach correctness. If you accidentally leak the personal data of millions of people, you wont be held responsible, and the cognitive load is always low.

But the thing is... I'm not sure there's a better alternative.

You can create a fancy abstraction and use a fancy architecture, but I'm not sure this actually increases the odds of the code being correct.

Especially in corporate environments--you cannot build a beautiful abstraction in most corporate environments because the owners of the business logic do not treat the business logic with enough care.

"A single order ships to a single address, keep it simple, build it, oh actually, a salesman promised a big customer, so now we need to make it so a single order can ship to multiple addresses"--you've heard something like this before, haven't you?

You can't build careful bug-free abstractions in corporate environments.

So, is pile-of-if-statements the best we can do for business software?

replies(23): >>45074916 #>>45074936 #>>45074945 #>>45075059 #>>45075089 #>>45075095 #>>45075106 #>>45075135 #>>45075188 #>>45075195 #>>45075392 #>>45075443 #>>45075463 #>>45075515 #>>45075547 #>>45075846 #>>45076426 #>>45077189 #>>45077500 #>>45077548 #>>45078893 #>>45079553 #>>45080494 #
1. ajuc ◴[] No.45078893[source]
I like to make truth tables for understanding piles of ifs. Like there's 5 ifs with 5 different conditions - so I make 5 columns and 32 rows, and enumerate all the possible combinations of these 5 ifs and write what happens for each. And then what should happen.

Of course, the disadvantage is the exponential growth. 20 ifs means a million cases (usually less because the conditions aren't independent, but still).

Then I have a flat list of all possible cases, and I can reconstruct a minimal if tree if I really want to (or just keep it as a list of cases - much easier to understand that way, even if less efficient).

replies(1): >>45084630 #
2. cma ◴[] No.45084630[source]
Often you can check validity one time before everything else. 5 bools might only actually be valid in 7 possible combinations instead of 32. Convert in one place to a 7 element enum and handle with exhaustive switch statements everywhere else can sometimes be a lot cleaner.

Making invalid data unrepresentable simplifies so much code. It's not always possible but it is way underused. You can do some of it with object encapsulation too, but simple enums with exhaustive switch statements enforced by the compiler (so if it changes you have to go handle the new case everywhere) is often the better option.

replies(1): >>45086436 #
3. ajuc ◴[] No.45086436[source]
> Making invalid data unrepresentable simplifies so much code

That's the dream. Error handling is what crushes it :)