4 ms·
The problem with a careful but non-methodical approach is that it requires the programmer to correctly determine the stability value of their design. We often o
by sempron64 3y ago
The problem with a careful but non-methodical approach is that it requires the programmer to correctly determine the stability value of their design. We often overestimate the importance of architecture on stability, or worse, architect something that is harder to maintain than the naive solution.
With buggy ship-it-now software you have a known bounded risk - bugs will occur in some cases but the software will ship and the bugs can be fixed because it’s simple.
With prematurely architected software the risk is unbounded - the project may get bogged down indefinitely in its own complexity without shipping.
The inverse extreme can also be a problem, of course A project that is maintained for a long time on the naive implementation will also become unmaintainable. However, this will be due to _known_ architecture problems encountered during maintenance. These problems can be addressed in a relatively bounded amount of time. They are also quantifiable and thus explainable to management.
- im_down_w_otp 3y agoThe specific case of building a proper parser doesn't take that much longer if you know what you're doing, and it also enables lots of wonderful quality of life features for end users through additional opportunities for automation and contextualization that can be surfaced. Though, given the constant incentive to never learn how to write a proper parser does mean that practically nobody knows how to do it, and so it will always look & feel like an unbounded science project, and thus rarely done. Infinitely recursive MVP'ing is a race to the bottom.
- sempron64 3y agoParticularly regarding parsing: Here's an excerpt from an interview with Anders Hjelsberg I heard recently. He's the creator of the Turbo Pascal compiler and later on of the creators of C#. https://www.aarthiandsriram.com/p/our-dream-conversation-anders-hejlsberg https://www.aarthiandsriram.com/p/our-dream-conversation-and... ``` Turbo Pascal 2 and Hash Tables Sriram: I think there is some, we're going to talk later about things like GitHub co-pilot, we're dealing with different kinds of code reuse, but I do think there's a little bit of romance in the, for example, I idol you and folks like John Carmack. John Carmack noodling away and trying to make sure every instruction and memory access is aligned on some cash line. The amazing thing is, even today, if you look at AI at the heart of it, you have matrix multiplication and doing things with floating point numbers. Some of these things really tend to matter, which on the theme of optimization, tell us a story of Turbo Pascal 2 and you discovering hash tables because it's legendary. Anders: [laughs] It is a funny story. You have to remember here that I am self-taught in the art of writing compilers. Now, I have since discovered and read a lot of the literature, but at the time, I was just coding away and doing it the best way I knew how. When you create a compiler, one of the things you have to create is simple tables, or they're not necessarily tables. They could be linked list, they could be whatever, but you have to look up names. When you're trying to compile a code that tries to assign one to X, well, you have to figure out where is X? What memory address have I associated with X? You have to look it up the declaration of X. In Turbo Pascal 1.0, the first version of Turbo Pascal, all of the variable declarations were just kept on a linked list because that much I knew, but of course, searching linked lists is not particularly efficient when they get large. For really large functions, that would just take an awfully long time. Then, well, maybe you could try first go by first letter, and then have 26 linked lists or whatever, and that could help a little bit. Then I remember reading the literature about these things called hash tables actually in this book by Niklaus Wirth, Algorithms +, what is it? Yes, Algorithms + Data Structures = Programs. A great book. He explains hash tables and I go, "Oh my God, that's amazing. I got to go try this." I went and implemented it and boom, the compiler went twice as fast. There's Turbo Pascal version 2.0. [laughter] Aarthi: Awesome. Anders: There's a good reason to sell upgrades. ``` Do you really need a proper parser to sell 1.0? A literal compiler project did not fail due to the lack of a "proper" parser (though it can be argued that the lookup table is after the parsing stage; obviously there was not a strong distinction in the Turbo Pascal implementation between tokenization and compilation).
- krisoft 3y ago> With buggy ship-it-now software you have a known bounded risk How would be the cost of bugs be known and bounded? A race condition in the code might not bother anyone ever in practice, or it might break down the whole system right as the most important investor decides to dogfood the product. In one case the bug can cause zero harm, and in the other might ruin the whole company. How much was the "known and bounded risk" of shipping a buggy transactional model to the British Post Office? [1] It is "just" a buggy database, yet it cost many lives and sent many people to prison wrongfully. > the bugs can be fixed because it’s simple. Maybe? Have you tried in practice? Sometimes a buggy implementation forces you into a pathway where you need to spend inordinate amount of effort to get to a non-buggy solution. (This is the idea behind the term "technical debt".) Very often this effort is more than what you would need to do to just do it correctly the first time. 1: https://en.wikipedia.org/wiki/British_Post_Office_scandal https://en.wikipedia.org/wiki/British_Post_Office_scandal
- twh270 3y agoThere are more choices than "ship-it-quickly and fix bugs later" and "over-engineer something complicated that ships later". There are _lots_ of good practices which reduce the (potential) bug count without making things more complicated -- indeed, good practices serve to reduce complexity in design and architecture. Selecting the right data structures and algorithms, server-side validation, making proper use of your language's type system, choosing the correct type of database, writing some unit/integration/system tests, use caching judiciously, I could go on.
- fknorangesite 3y ago> There are more choices than "ship-it-quickly and fix bugs later" and "over-engineer something complicated that ships later". It is abundantly clear that GP is roughly describing two ends of a spectrum, not enumerating every possible option.
- IshKebab 3y agoThat was to make the point very clear. Twh270 is correct. There's a whole spectrum of robustness. It's a constant fight to push towards the robust end no matter where you are on the spectrum. The other big one I constantly fight have to fight for is using type annotations in Python. It's a total no brainer and definitely not an extreme end of the spectrum. I'm not advocating formal software verification.
- 8n4vidtmkvmk 3y agoThe bugs can be fixed later but won't and also the person who has the most context to fix them will likely have quit by then.
- ilyt 3y ago>The problem with a careful but non-methodical approach is that it requires the programmer to correctly determine the stability value of their design. We often overestimate the importance of architecture on stability, or worse, architect something that is harder to maintain than the naive solution There is EXACT SAME PROBLEM with choosing to cut engineering tho. And the cost of getting it wrong is far higher. If you catch a problem early, well you just wasted the amount of time you tried to save. If QA catches the problem before you get it to the client, that's 2-3x the cost right there. 5-10x when it gets caught on production. 20 to near unbound when it causes some long standing issue that's noticed too late >With buggy ship-it-now software you have a known bounded risk - bugs will occur in some cases but the software will ship and the bugs can be fixed because it’s simple. >With prematurely architected software the risk is unbounded - the project may get bogged down indefinitely in its own complexity without shipping. Not every software is a startup. If you have a requirements, first verify that they make sense in wider scope, then implement carefully while caring about potential edge cases. Not even handling them just making sure that they error out instead of propagate potentially invalid data further. That doesn't cost you even 2x the productivity. > The inverse extreme can also be a problem, of course A project that is maintained for a long time on the naive implementation will also become unmaintainable. However, this will be due to _known_ architecture problems encountered during maintenance. These problems can be addressed in a relatively bounded amount of time. They are also quantifiable and thus explainable to management. In vast majority of cases those end up as pieces of spaghetti legacy code that are worked around by the rest of the org, not fixed. "Fixing it later" is more and more and more expensive the longer it is in production and the more code grows around it.