10 ms·
Learning that some folks can produce so much value with crappy code. I've seen entire teams burn so much money by overcomplicating projects. Bikesheding about
by hu3 2y ago
Learning that some folks can produce so much value with crappy code.
I've seen entire teams burn so much money by overcomplicating projects. Bikesheding about how to implement DDD, Hexagonal Architecture, design patterns, complex queues that would maybe one day be required if the company scaled 1000x, unnecessary eventual consistency that required so much machinery and man hours to keep data integrity under control. Some of these projects were so late in their deadlines that had to be cancelled.
And then I've seen one man projects copy pasting spaghetti code around like there's no tomorrow that had a working system within 1/10th of the budget.
Now I admire those who can just produce value without worrying too much about what's under the hood. Very important mindset for most startups. And a very humbling realization.
- bicx 2y agoMy way of planning and writing software shifted a good bit after I went from working at a mid-size tech company to working for myself. Suddenly I cared very much about how long it took to reach a functional product and very little about developing sophisticated architectures.
- sbayeta 2y agoSame here. This is what happens when business/developer interests align.
- emseetech 2y agoSimple UX too. Early adopters are so much more forgiving of a boring but functional user interface than we want to admit. It doesn't have to look amazing out of the gate. It just needs to do something cool. Plus a lot of our overcomplicated architectures on the frontend are because we shoot for a UI that competes with products that have been iterated on for 15 years now by teams of dozens or even hundreds.
- spoiler 2y agoLike with all things in life, one need to find balance within the two extremes you posted. There's overcomplicated, there's too basic, and then there's simple. I think it's fine adding just enough complexity and abstraction to make something malleable and manageable in the future
- mablopoule 2y agoI don't remember where I saw this quote, but... "It's okay to half-ass something, when all you need is half an ass". EDIT: Totally agree about the 'important mindest for startup', I had a similar eye-opening experience, working in a startup with 'cowboy' code that was actually quite good, but I had to unlearn a bit of stuff I read as a junior/mid-level developper. It was code that was well-architected, had well-concieved data structure, and had business value, but every "professional" coder would deem bad-quality, since it had no unit test, did some stuff unconventionally, and probably would have many linter warning.
- bee_rider 2y agoMost scenarios only warrant fractional assing. Also this philosophy provides the opportunity to say “ok guys, this time… we have to whole ass this one,” which is always fun.
- eru 2y agoSome times you might even have to bring two whole donkeys to bear on a project.
- chrisbrauns 2y agoIt was Gary Bernhardt in this talk: https://m.youtube.com/watch?v=sCZJblyT_XM https://m.youtube.com/watch?v=sCZJblyT_XM
- jwilk 2y agoMore Gary's talks: https://www.destroyallsoftware.com/talks https://www.destroyallsoftware.com/talks
- a_t48 2y agoWell-architected + well designed means you can go back later and fix the code if the project survives. I'm hitting this personally right now - the amount of code I can write is dwarfed by the amount of features needed to get something like a working demo out the door - I can spend time and make every thing perfect, or I can squint and imagine how I will implement fixes later and focus on making sure that I don't have to rearchitect.
- bch 2y agoSo hard to resolve this in my head - unless it’s understood there’s a “detonate” button attached to the code, that it might escape, or worse, that it gets passed on or sold(!!) is a chilling thought.
- 4star3star 2y agoJust leave comments for the most embarrassing pieces. // really not the way to do this, but it works // ideally, we'd do xyz, but this is good enough
- lr4444lr 2y agoI think the other replies miss an important part of your comment: Some of these projects were so late in their deadlines that had to be canceled Speed is really important a lot more often than devs like to acknowledge when a company is small and fighting for its life to get revenue, let alone become profitable, and the code debt is often worth it. Fixing the code debt itself doesn't need to be any more thorough than necessary either.
- mablopoule 2y ago> and the code debt is often worth it. This is something that I like about the metaphor of 'code debt', and which tends to go over peoples head: debt can be a perfectly fine instrument, and just like a real debt, it can be a good thing when leveraged wisely. The issue is more when debt is treated as 'free money', and is used carelessly.
- kaba0 2y agoAt the same time, companies often fail to invest into long-term goals, like maintainability, increasing test coverage, or even bettering the internal UI, even when it’s their core, business-critical product.
- izacus 2y agoAnd the other part is just the sheer amount of projects that can't deliver that "speed" after a year or two because shoddy, quick and poor decisions were made around code quality. Once you find out that your startup chose the wrong architecture because "we need to do it fast" and it needs to stop pivoting for 6 months to unfsck themselves, it's mostly too late. Unfortunately people who create those monstrosities hide behind the same "keep it simple and quick" excuse than people who know how to prioritize. It's interesting how many people here ignore that scenario - it's surprisingly common. Is it because most of developers jump ship at that point?
- deadbabe 2y agoI wonder if you’ll still admire them when they leave and the burden of maintaining the mess they left behind falls on you.
- motoxpro 2y agoNothing to maintain because all the overengineered projects got canceled.
- hnthrow289570 2y agoI'm numb to it. It's just a fact of life because tenures are so short, quality is often very opinionated, and jobs are readily available, and you usually get a raise from the next job too. You do what you can to stay employed until you can get the next job lined up. It has become overwhelmingly obvious that the industry is never going to reach a state where technical debt and bad code is exceptional and high quality is the norm. If there is a maximum amount of pessimism I could have, it would be for this.
- porksoda 2y agoI had only one job so far where code quality was a primary objective it was fantastic, but it was also extremely slow and expensive. Slower and more expensive even than what you're probably thinking right now. I was shocked.
- projectileboy 2y agoAs a good friend of mine often says: We work in a field of people who envision themselves as artists, when all that is wanted are painters.
- deanrtaylor 2y agoThis articulates something I've been thinking about quite a lot recently; quite nicely.
- refulgentis 2y agoTell us more! :)
- gradschoolfail 2y agoSome of the best are in fact also painters. https://paulgraham.com/hackpaint.html https://paulgraham.com/hackpaint.html
- tempie2024 2y agoSo we should put a bug in the room and if the painter whistles a tune while working, sanction them for slacking off?
- deleted 2y ago[deleted]
- icelancer 2y agoNo one wants to be a "programmer." They'd rather be called "engineers." With none of the licensure, mandatory education, and so forth. But the world needs programmers and technicians for most of the work we have to do. I do comparably little "engineering" and the little I have done that qualifies for such a statement I recall. Majority of the work is programming and technician work. Nothing wrong with that.
- just-tom 2y agoActually I call myself a developer. I'm not that good of a programmer, but quite resourceful as a developer.
- mynameishere 2y agoThat's not bikeshedding, but the product of these types: https://en.wikipedia.org/wiki/Architecture_astronaut https://en.wikipedia.org/wiki/Architecture_astronaut ...bikeshedding is when you have that all-day, all-teams meeting where marketing and design and management argue about whether to put X content in the header or footer.
- jjmarr 2y agoThere's a discrepancy that the top comments here say that "some people can produce a ton of value by not caring about code quality" and "I didn't care about code quality and got bit later on". And people discuss that incurring technical debt with bad code can sometimes be worth it and sometimes not be worth it. The logical implication of technical debt having an interest rate (i.e. It costs more to fix something later than now) is that like money, features have time value. This is what makes it worth it to incur technical debt. Thinking about the implied interest rate of technical debt makes it easier to rank what should be prioritized for a fix. High interest debt should be paid off first. But you might also focus on refactors that reduce the interest rate, such as by modularizing your code so it's easier to replace down the line.
- JohnMakin 2y agoI learned this lesson when working on very fast paced projects with way fewer developer resources than needed. to ship a feature on time, shortcuts in quality have to be made, but you learn to make the shortcuts in a way that are easier to go back and clean up later. I became very fond of #TODO ‘s.
- erhaetherth 2y agoMy manager gave me gruff the other day for adding a TODO that I had no intention of ever doing. TODOs are like a get out of jail free card. Don't want to do something the reviewer is likely going to call out? Just add a TODO.
- eru 2y agoThat's why some people insists on having a name with each TODO, and some even want a name and a date.
- datadrivenangel 2y agosome TODOs are actually WOULDDOs
- 2y ago
- buffalobuffalo 2y agoI think one of the most valuable lessons I have learned in software engineering is that you can write entire projects with the express plan of rewriting them if they actually gain traction. If I want to prototype something these days, I will often write code that, while not quite spaghetti, would definitely not pass a proper code review. It's actually kind of fun. Almost like a cheat day on a diet or something.
- satvikpendem 2y agoUnfortunately, that rewrite step often doesn't happen. I can't count the number of times a prototype that was meant to be thrown away was actually put into production because "it's cheaper and faster than rewriting."
- buffalobuffalo 2y agoYeah, there is that. I guess this comes with the caveat that you have to have enough say in the project that you can mandate a rewrite.
- doctor_eval 2y agoI’m working on a prototype now but I deliberately made it run entirely in the browser (indexeddb) to avoid the problem that I might be asked to put it in production!
- mobiuscog 2y ago"Phase 2 never happens"
- Sander_Marechal 2y ago"There is nothing more permanent than a temporary solution that works" I have no idea who said that, but I use it a lot at work when people want to cut corners with the intent to fix it later.
- djeastm 2y ago>I can't count the number of times a prototype that was meant to be thrown away was actually put into production because "it's cheaper and faster than rewriting." Did the business make money, though? I think that's the law of the jungle
- stavros 2y agoThis is a false dichotomy. On one end, you have "overarchitects everything so much that the code is soon unmaintainable" and on the other end you have "architects the code so little that the code is soon unmaintainable". Always write the simplest thing you can, but no simpler. Finding that line is where all the art is.
- keepamovin 2y agoThat's not a "false" dichotomy, that's an actual dichotomy: it's a real thing. Reading your comment, even tho you don't say it, I get the feeling you'd be with the rallying cry, "Bikeshedders Assemble!" hahaha! :)
- mkl 2y agoIt's a false dichotomy because it falsely implies there are only two options. Better than either are the other options which lie in between.
- keepamovin 2y agoOh, I see. That's a good point. But I don't think hu3's comment was suggesting there's only two options, just illustrating some possible margins to describe the landscape. Maybe stavros' was hallucinating that strawman reduction in there, is what I think. Like you don't have to say it's a false dichotomy unless that's the only way you read it. The existence of something between the margins, should be obvious. Anyway, haha! :)
- Paul-Craft 2y agoWell, it almost always becomes an actual dichotomy soon, for sufficiently large values of "soon."
- keepamovin 2y agoYes, the compounding effects of previous architectural decisions, but not if you take a balanced path, guided by awareness of the two extremes. So it needn't. Hahaha! :)
- typ 2y agoThe lack of these design elements in a solo project does not define crappy code. More often, it's due to a codebase being modified by multiple contributors, each wanting to get their work done quickly without paying attention to the overall context or considering others' work.
- dev-jayson 2y agoI can totally understand the move fast and break things mentality, but I'd like to stress it's equally important to pay back the occurring tech debts. I am working on a massive spring monolith that's somewhat of a huge pile of spaghetti, and when the higher management decided to enforce code quality in the pipeline, it became a living hell to work on. I can't even add a logger without having to refactor the whole 2000 line class while writing a whole-ass unit test for it. It's been a full year and I still have to deal with this sort of crap on a weekly basis. The most ironic part is that most of the devs that cooked the spaghetti are now either in upper management or in the same devOps team that's demanding us to clean the mess up.
- cess11 2y agoI've come to the conclusion that you can't architect yourself out of this. What you might do is write tests early, so at least you have integrated a test rig to build on if the system actually gets any use. Most of the work on mature systems is like this, rewriting and refactoring stuff. If it is very concrete, non-abstract, it's generally easier to work with in this phase than if it was cleverly and abstractly architected. Even if it's a big spaghett.
- skepticATX 2y agoI’d argue that by definition, code producing value is good code. It may not be the best, but it has to be at least good. Almost everything else about code is subjective, but value is objective.
- jasfi 2y agoSimilarly, some entrepreneurs (non-tech)e who can produce a basic MVP that generates money from the start, sometimes to an insane MRR. They use something like Google Sheets, Bubble or pay a dev shop a fraction of a corporate project to get it done. As a struggling solo tech founder, I'm in awe.
- khazhoux 2y agoThe team that prides themselves on "we'll take a bit longer to get things right" usually winds up takes much, much longer... and still gets it wrong. By that point, the fast team would be on their third iteration.
- Simon_ORourke 2y agoExactly this - I've a colleague who just fell into "solution mode" and started whiteboarding a LLM framework he could fine-tune with RAG and some 3rd party vector database. It's six months later and there's still nothing working or even a deliverable schedule. Compare this to another colleague, with an almost exactly similar use case, who just downloaded an open-source LLM, wrote some glue code and set it loose in production. It's not pretty but it (mostly) gets the job done. As the old addage goes "Perfect is the enemy of good".
- jaydeegee 2y agoI had a colleague who was old school and loved optimising, everything he reviewed come back with tiny changes that would save fractions of a ms. His nemesis was a guy who was arguably the best coder I have ever worked with. Things come to a head in one meeting and old school said if we did things his way our code would run quicker and the response was legendary 'If we coded like you it'd run quicker because most of the functionality would be still in the backlog.' I still think about that when it comes to optimisation.
- eru 2y ago'Optimising' for simplicity would often be a good idea, though. Optimising for speed of execution only matters some times.
- VBprogrammer 2y agoOptimising for simplicity first is almost always the right thing to do. Even if it turns out to be too slow you then have a reference implementation to confirm correctness against. In my experience it's rare to correctly identify the bottleneck in code while writing it.
- eru 2y agoOh, I had situations in mind where I can quickly write a simple version. But sometimes when I really torture my brain I can spend a few days of doing mathematical proofs etc to come up with a even simpler solution. That extra effort is only sometimes necessary. (But can be lots of fun to develop.)
- Jensson 2y ago> In my experience it's rare to correctly identify the bottleneck in code while writing it. Why? It is so easy, just think of the work being done and pick the big parts, those are the bottlenecks. Only reason I can see anyone fail at that is that they don't know how long things take in their programming language, but that takes very little time to learn, and once learned you will know the bottlenecks before writing. In so many cases the bottleneck is using bad data structures everywhere, that often gets you 100x runtime and doesn't show up in a profiler because it is spread out all over the codebase, that is the real bottleneck that never gets fixed and is why programs are slow today. To fix that you have to learn to know the bottlenecks as you write the program and not rely on a profiler. Profilers helps you find how long things take, they are really bad at helping you understand how to make the program fast.
- surfingdino 2y agoI can relate. I am now on a small team of half a dozen (2 front, two back, 2 devops). We've been smashing it for the last year, replaced a hodgepodge of systems with a configurable framework and a modular integration layer with third-party systems. As a reward our work the management are bringing in a consultancy we are supposed to train to replace us. That will be a very expensive and inefficient exercise. How do I know? Our small team was created to deliver what the previous consultancy could not do in 5+ years. That experience taught me once again that management in large organisations have no idea what they want to build, how to build it, how to maintain it, and that's where large consultancies come in, milk the client for all they can and leave a massive mess behind them.
- throwaway2037 2y agoThe solution sounds simple: Refuse to train the incoming consultants. You can do this indirectly by quitting before the consultants arrive, or, directly, by telling mgmt that you refuse to train your replacements. Your experience sounds great to sell yourself into a new role with better managers.
- sevnin 2y agoI have to kind of ask, maybe it's the design comitee that instead produces the sphagetti in that case? They are trying to commit themselves into decisions without much knowledge about the problem they are solving. I understand this is the reality of business and so on but let's not imply that this is good software design. The basic operation of abstraction (as this vague magical thing which creates concepts) is something that has to have something to abstract from. When we do abstraction in a bubble, not informed by the problem - like the design comitee does. What we get is abstractions made from abstractions: foundation less non-sense. Maybe it's this spagetti monster, the rogue coder, the guy that actually tries to solve the problem - the real designer.
- damethos 2y agoThis comment deserves more upvotes.
- axegon_ 2y agoSo much this. But there is a fine line somewhere in there. I have seen and admittedly worked on such projects where time constraints simply do not allow you to polish all bits and pieces. That's perfectly reasonable during POC/early development stages and if anything, I encourage it: Writing hundreds of tests when all requirements change three times a day is incredibly counter-productive, slow you down and eventually burn you out. It may happen that crappy is much better than shiny, polished and over complicated if the project itself is not going to scale any further than it already has. And once you get a more complete picture of what the end goals are, then you can go back and gradually start doing things "the right way". But I've also been in another extreme. Take my old job for instance, which despite my at the time cognitive dissonance, I hated to a large degree because of this: relatively early stage with ever-changing requirements, endless dependencies, brutally unstable setup for development where deploying a single pod in minikube was a terrifying prospect because everything was hanging by a thread and rebuilding the cluster took hours. That was made even worse by dozens of forked open source projects that were patched left and right to fit the needs, lagging years behind the original projects, wild dependencies between repos, no real observability over what was going on, the version control was catastrophically packed with auto-generated code(like 80% or more) which was made worse by the fact that everything was git push --force so they don't have to deal with conflicts. Imagine having to explain that this practice should be avoided in nearly all cases. In a nutshell imagine crappy code and infrastructure which pretends to be and is sold as an enterprise grade software. I guess cognitive dissonance was a common theme in the company since everyone was under the impression that everything is perfect. Which couldn't have been further from the truth.
- brazzy 2y agoOhh yeah. A few years ago I worked on a system that had replaced a previous system that was like that: a bunch of microservices with multiple instances, communicating via message queues, all in the name of scalability and high availability. The actual nonfunctional requirements? Handle between 0 and a few hundred requests per day, and it would be just fine of they get delayed a few days as well. The best part was that the overengineered previous system actually had far more outages and delays caused by its complex deployment and data model than the simple single-instance monolith that replaced it.
- tcarnell 2y ago100% agree. JUST_DO_IT (add value, fast) <-----------------------------------> WHAT_THE_BOOK_SAYS (enterprise arch etc etc) The BIG problem is the total misconception that: > JUST_DO_IT = bad engineering > WHAT_THE_BOOK_SAYS = good engineering In reality, the quality of execution is independent of the development approach - you can make a complete mess of either approach, however, the WHAT_THE_BOOK_SAYS approach WILL cost you a LOT more time and money to discover your team has messed up it and WILL cost a lot more time and money to fix. My experience is that, just as your product evolves & grows, your engineering strategy should evolve and grow. There's a good reason why fortune 500 companies will have enormous IT teams, using enterprise cloud technology... and there's a good reason why successful tech start-ups do the exact opposite.... but hopefully, the startup will become a fortune 500 company.
- tictacttoe 2y agoHaving heard a variation of this comment many times, I keep waiting for an “aha” moment, where I see the light and abandon my obsession with minimalism and clean code. But at least in science roles it hasn’t happened yet. Rather, I keep seeing instances of bogus scientific conclusions which waste money for years before they are corrected. Being systematic, reproducible, and thorough is difficult, but it’s the only way to do science.
- earnesti 2y agoThere's so much waste in the world, that it is unbelievable. However counterintuitively, I have stopped caring about waste, and have been more focused on the value. Waste you can always optimize later if you want to, value creation is the difficult part.
- underdeserver 2y agoBut that's just the point, for most problems most people have, you don't have to be scientific. If your invariants vary and it breaks 5% of the time that's fine and nothing bad happens.
- tracker1 2y agoLiterally the only thing I tend to worry about up front is deployment automation. I've worked in so many environments that don't have it, or have some byzantine manual deployment strategy that just gets irksome and difficult. I'm a big fan of containers, even for single-system deployments. If only because it always bites you when you are under the greatest time pressure otherwise. Beyond that, my focus is on a solution to the problem/need at hand, and less about optimizations. You can avoid silly stuff, and keep things very simple from the start. Make stuff that's easy to replace, and you often won't ever need to do so. Most software isn't about science, and isn't engineering... it's about solving real world problems, or creating digital/virtual solutions to what would otherwise be manual and labor-costly processes. You can shape a classic rdbms into many uses, it's less than ideal, but easy enough to understand. Very few jobs are concentrated on maximizing performance, or minimizing memory or compute overhead. Most development is line of business dev that gets deployed to massively overpowered machines or VMs.
- datavirtue 2y agoYou refactor and abstract later. A key principle absolutely no one observes. You have to let people turn out slop and then let them clean it up. Instead it's combative code reviews where everything has to enter the code base perfect. Makes me sick.
- mvkel 2y agoThis is how all modern software should be made. Optimizing for 1M concurrent users, paying down tech debt, refactoring, and testing are all things that engineers love to cite that will somehow make everything better. The customer won't feel a single one. Spotify uses 42 different versions of jquery (among a dozen other libraries) and it's working just fine (with >1M concurrent users). Even electron! That crap is so heavy, its (lack of) performance is notable. But! Many billion-dollar companies built on its back. I laughed when an exec at Evernote told me that every year they go to MIT to try to recruit the top 1% of cs grads. What a waste of talent.
- nogridbag 2y agoI always find these discussions interesting. I've been working for the same company 10 years. When we built project A, I was surrounded by people who had built the same product for the past 20 years together. As a younger dev, I deferred to them as they were much older and had done this before. You would probably admire them. They pumped out code and delivered immense value. We had no over-engineering because there was no upfront design discussions. When we needed to use some service, we just wrote that directly in our normal framework code instead of using some over engineered abstraction. That's usually highly praised here on HN. Years later, that project became an extreme maintenance burden. There is no separation of business code from framework code, so the first major framework migration took... years. When they completed the framework migration it was already 2 versions out of date. Subsequent upgrades were faster and given more priority, but still took multiple months. Onboarding new clients took whole teams. The code is fragile, lacks test, etc. The app is classic "spaghetti code". But they sure got to production quick! Around 2.5 years ago, I was tasked with building project B. There was no development team. I worked with two domain experts, but ultimately the development of the product was in my hands. This is a product that will live on for at least another 10 years and will likely overtake our core product in revenue. There is no one to blame, but myself, if in 5-10 years this app becomes another unmaintainable mess. If you're in this position, what do you do? For me, all I could do is draw on my experience to try to avoid the mistakes I've seen made in the past. We made a lot of mistakes in project A, but I knew a big one was tying our business code, the core of our business, to the particular flavor of web framework that happened to be popular at the time the project started. How do you avoid that? Well, "Hexagonal architecture" sounds like a big scary buzzword, but it's a damn simple pattern that solves that elegantly. When we started, I basically received an indirect mandate that we use the same framework as project A. After we had written ~25k LOC, I had enough and we dropped that legacy framework and migrated to something much better. And we didn't have to change a single line of our business code. Our new framework allows us to iterate much faster than legacy framework. 2.5 years in and our code looks as clean as that initial POC I built. Hexagonal was a small bit of the initial architecture I did. I only point it out here as a counter example. But all the little things I've done which are considered "architecture" have paid off years down the road.
- hu3 2y ago
- boznz 2y agoI am one of those people who wrote a production system controlling a million-dollar business fifteen years ago that is now controlling almost a billion-dollar production system today. The auditors are the main reason it is being changed, "single man risk" and "Obsolete software" (Delphi/MySQL) being the two highlights from the Deloits IT team. The code is not brilliant, it is full of technical debt (as thats what happens when companies grow and change) but is still perfectly maintainable. I have been watching the herculean effort of three different teams to replace this system, carving off the low hanging fruit to NetSuite and React/Java applications while repeatedly delaying the core system while they agree on standards to use. I stick around as I am quite close to retirement now and the employees and the company are good to work with and don't deserve me to abandon them. At this point I genuinely want the projects to succeed so I can move on as there are many small companies still out there that I can make a difference in even with my age, single man risk and obsolete software.