Then a year or two later you quit/get fired/move to a new team and that code is underpinning a business critical task. Everyone responsible for the code is scared to do any major refactoring because of how important it is but it seems to be working ok. Hopefully they’ll have time for a big refactor next quarter when they can afford to take some time and manage the associated risk.
The newly responsible team decides to rewrite it because “it’ll be easier than adding the new feature”, hopping on for another ride on the rollercoaster of sadness.
One way or another, the interest on the technical debt always comes due. When you hear phrases like “we can’t do that without a major refactor” with increasing frequency, you’ll know that day is not far off.
…And I just realized that it might be time for me to start looking for a new job cause the credit line on my current project is about maxed out.
I’ve given up at this point because in the tech industry, there are zero wins. Even if you knock something out in 2 weeks, you’re “too slow” and need to “iterate faster”.
Okay fine.
iterates faster
“Why is this missing X, Y, and Z? Why is this button blue?”
Did you want good or fast? You get one.
weird how every temporary fix becomes legacy code as soon as it hits production
I feel attacked.
marketing can either let me do it right or keep bugging me with more changes and forcing it to be done in two weeks without hiring anyone else for my team
deleted by creator
Honestly, this is probably not too bad if we’re talking about Haskell or Purescript. They say, “if it compiles, ship it” because these languages are rigorous about types at compilation time.
Because if the types are correct, it’s mostly bug free already, right?
Yeah. and since it is so strict, it’s pretty satisfying when it actually does compile.
That’s pure nonsense. Types don’t tell you that your code is correct, they just tell you that your types align. Here’s a perfect example of where the mentality that if it compiles, ship it leads you in practice.
Haskell bro wrote a benchmark comparing Haskell with C implementation of websockets. The initial results looked extremely favorable for Haskell. However, it turned out that the Haskell implementation failed to deliver messages reliably, dropping 98% of the messages it received.
Furthermore, static typing is that it’s inherently more limiting in terms of expressiveness because you’re limited to a set of statements that can be verified by the type checker effectively. This is a subset of all valid statements that you’re allowed to make in a dynamic language.
So, a static language will often force you to write code for the benefit of the type checker as opposed to the human reader because you have to write code in a way that the type checker can understand. This can lead to code that’s more difficult to reason about, and you end up with logic errors that are much harder to debug than simple type mismatches. People can also get a false sense of confidence from their type system as seen here where the author assumed the code was correct because it compiled, but in fact it wasn’t doing anything useful.
At the same time, there is no automated way to check the type definitions themselves and as you encode more constraints via types you end up with a meta program describing your program, and there is nothing to help you know whether that program itself is correct. Consider a fully typed insertion sort in Idris. It’s nearly 300 lines long! I could understand a 10 line Python version in its entirety and be able to guarantee that it works as intended much easier than the Idris one.
In one of my old jobs we had a couple thousand line shell script called something like prod_corrections_adhoc.ksh. It was used to jam through emergency fixes between code releases.
It still has ‘adhoc corrections’ from 2006
“After I leave, this is going to be someone else’s problem.”