12 ms·
Write code that is easy to delete, not easy to extend (2016)
- tkfu 6y agoI have to confess, I was a solid halfway through before I realized it was satire.
- noir_lord 6y agoYou missed the Sarte quote about programming in C at the top then. It's at least good satire, it's so close to the real kind of article it apes.
- miceeatnicerice 6y agoNot satire so much as an ironic dialectic - a progress through a series of (decreasingly?) daft ideas
- ben0x539 6y agoWhich ones are daft?
- dragonwriter 6y agoIt's not satire; the technique of peppering a work like this with slightly-modified-famous-out-of-domain-quotes is not a tool of satire but of implicit metaphor.
- ajuc 6y agoIs it? I agree with almost all of it.
- imposterr 6y agoIt most definitely isn't. It's written in a bit of an absurdist tone, but beneath all that it's a lot of solid advice about not over engineering things from the beginning and working iteratively.
- simonhamp 6y agoIt’s not satire. These are exceptionally pragmatic suggestions packaged up in well-written prose. Worth digesting
- ahaferburg 6y agoThat sounds dismissive, did you intend that? It's my favorite type of writing. It tickles your brain. Does he mean it like he says? Do I agree? It makes you think, even when it sounds like he's telling you what to do.
- kmorgh 6y agoThis guy has a talk too with the same kind of tone about the whole industry. Had a good laugh when I was starting out. https://youtu.be/AUYPnxv0yss https://youtu.be/AUYPnxv0yss
- earthscienceman 6y agoHere's his github too, if anyone's interested. Fairly prolific to say the least: https://github.com/tef https://github.com/tef
- edelans 6y agomost of the commits are empty https://github.com/tef/0.0/commit/59575ac7d888c60eb043fe3b3c4a7f3057a31165 https://github.com/tef/0.0/commit/59575ac7d888c60eb043fe3b3c...
- slooonz 6y agoI wholeheartedly agree with "don't immediately jump on the modularize and abstract everything right away". I think that "modularization and abstraction is always and uniformly good" is one of the big lies of our profession. It’s easy to see how it’s attractive : programming is intellectual work, and displaying capacity of abstraction is rewarding. I was extremely enthusiastic about that stuff when I was young, too. Then I got to school to get a CS degree, and it only reinforced it. Now that I have some years of experience, let me talk to you about my last job. It’s a web app like most of us (I think) are doing. Backend in node. Frontend in react. The client was extremely unhappy about the delays and cost of their current contractor (weeks and 4-digit invoices for simple features), they wanted us to in charge of the app. As soon as I received the source code, I looked at the backend part. It was incredibly clean for the standards of my younger self and CS teachers. Each class in his own file. You had one routes/_index.ts file that just included routes/users/_index.ts for /users, routes/blog/_index.ts for /blog, and so on (recursively: you would have routes/blog/comments/_index.ts too). routes/*.ts would be just that, declaring routes. Code was cleanly separated and implemented in controllers (controllers/users/_index.ts, and so one). Of course the controller didn't directly used the ORM, there was intermediate DAO classes to do that. Very clean. Also, changing the slightest things required to go through 5-6 files. May god save your soul if you wanted to change more complex stuff. I discarded everything. Most of the code now lies in /app.ts, which contains all routes. Each route is directly implemented in this file (no separate controllers) and directly calls the ORM (no DAO), except one which does complicated stuff and has his own implementation file. Loccount on my "ugly, not modular" backend, which, incidentally, has many more features (that the client wanted for months but the previous contractor couldn’t implement for a reasonable price/time). And ~1/3rd of those lines are just some CSS assets moved from the frontend to the backend because we needed them for the mailing list: all SLOC=2284 (100.00%) LLOC=0 in 13 files Loccount on the "very clean" backend of the previous contractor: all SLOC=12507 (100.00%) LLOC=0 in 262 files Now, don’t get me wrong. Abstraction and modularization are not uniformly and always bad. But they have to make sense. Don’t write and organize a 2k LOC project the same way you would write and organize a 100k LOC project — or you’ll end up with a 500% overhead in LOC that WILL translate to a 500% higher burden of maintenance. I just wish school taught me that, or that my younger self could have been clever enough to see it by himself.
- flohofwoe 6y agoThe unfortunate side effect of this (very good) advice is that all code that's easy to delete will eventually be replaced with code that's hard to delete (and thus will eventually be impossible to delete in order to be replaced with something better).
- nxpnsv 6y agoIt is like the Murphy's law of deletable code "Anything that can be made hard to delete will be made hard to delete".
- tobr 6y agoMore like a variant of the Peter principle: all code tends to be refactored to its level of unrefactorability.
- mumblemumble 6y agoHaving just completed a change that should have been small, but ended up spanning ~75 files, I can attest to this. It would have been small, up until the point where one of the excitable members of the team discovered Uncle Bob and got excited. Which, disclaimer, I generally like what Uncle Bob has to say. But there's this thing, and I don't quite understand how it happens, where it seems to be really easy to implement the cosmetic parts of the programming style he advocates while simultaneously achieving the diametric opposite of the fundamental goals that these techniques are supposed to achieve.
- dionian 6y agoI have seen many a TDD enthusiast create many more problems in terms of test maintenance than they solved in code quality. Doesn't mean TDD is bad, it just means like anything it is not a silver bullet
- mumblemumble 6y agoI certainly don't think TDD is bad; I do it myself. Though I will say that the Classicism vs Mockism debate is alive and well, and it is my (a classicist's) opinion that test-induced design damage is largely a by-product of getting so caught up in the red-green-refactor flow that the tests start to become an end in and of themselves. At which point maintainability has taken a back seat to mockability. I'd rather have a slow test that doesn't unnecessarily concern itself with implementation details, than a test that is fast, but achieves its speed by getting its dirty little fingers all over the implementation details, and throws a tantrum and refuses to let go of them every time you attempt some spring cleaning.
- kqr 6y agoThis was part of the initial idea of extension. David Parnas' 1970's paper that popularised the term was called Designing for the Ease of Extension and Contraction where "ease of contraction" refers to subsettability, i.e. removing parts of the code without having to change other parts. These original papers are well worth a read!
- Jtsummers 6y agoThanks for the reference. I've read some of his writing, but had not seen this one. I've submitted it here [0]. [0] https://news.ycombinator.com/item?id=23917627 https://news.ycombinator.com/item?id=23917627
- Paddy3118 6y agoThe articles structure makes it difficult to comprehend.
- agumonkey 6y agoThis is the essence of a variable. (physical) engineers probably know that more tangibly than coders.
- smileypete 6y agoI think that one possible problem with the 'O' in SOLID (open closed principle) is spending excess time second guessing future modifications to the code. The examples are always clear cut, but in the real world it sometimes doesn't work out that way. OTOH I'd say that the 'L' is worthwhile (Liskov substitution principle) as inheritance can be abused as a kind of 'version control' for functionality, and LSP helps guard against that.
- deleted 6y ago[deleted]
- Uberphallus 6y agoSome time ago I worked exposing an API that, given that it was constantly evolving and different partners adapted to it at different paces, we had to support a wide range of versions of it, which was basically what you say as version control. I'm not gonna say it was pretty, actually from a design perspective it was disgusting, but from the perspective of handling a dozen versions of the same code in the same application, it was certainly very sane. For example, at some point we supported versions 2.0, 3.0, 4.0, 4.1, 4.2, 4.3 and the freshly new 5.0. They inherited this way: 2.0 -> 3.0 -> 4.0 -> 4.1 -> 4.2 -> 4.3 -> 5.0, easy enough. One day decide to deprecate version 2.0. What happens is we consolidate 2.0 code in 3.0: 1. If a method calls super, copy + paste from 2.0 its place. 2. If it's overridden, there's nothing to do. 3. Run unit, regression tests, on the remainder of the versions and fix anything that might have been missed. 4. Delete 2.0 code. The end. If we need to fix a bug introduced in 4.1, you fix it there and it gets fixed automatically for the rest of the higher versions.
- smileypete 6y agoSounds reasonable, I should really have said 'informal version control' where it's used to get stuff out the door and piles on technical debt as well :-o
- jholman 6y agoThe L really doesn't fit in with the others. It's super weird that people even try to compare it with the other "SOLID rules". The Liskov substitution principle isn't advice on architecture, it's a statement of what the mathematical requirements are for inheritance to be compatible with a type system. If you violate it, you are no longer in compliance with the expectations your compiler has of you, and your compiler may fail you. It's like allowing UB into your C code. You might very well get away with it, but if you end up with a run-time type error, even though you have an allegedly static type system, well it's your OWN FAULT. The other principles are all recommendations that have to do with whether or not other future developers will be happy building on your work. It is very easy to imagine a perfect-until-you-maintain-it piece of software that wildly violates every single one of those principles. I'm personally not convinced by most of them, but as someone with only 10-ish years of experience, I'm definitely still learning, and it won't surprise me if I'm absolutely wrong about some or all of S/O/I/D. But either way, they're rules of thumb, not mathematical laws, and they're rules of thumb about future work, not rules of thumb about whether the software will work right this moment.
- underdeserver 6y agoMissing (2016).
- dang 6y agoAdded. Thanks!
- stef-13013 6y agoVery funny :)
- mrep8 6y agosure, because you have your mom cleaning your mess behind
- amai 6y agoThe author has a followup: "Write code that’s easy to delete, and easy to debug too." https://programmingisterrible.com/post/173883533613/code-to-debug https://programmingisterrible.com/post/173883533613/code-to-...
- devchris10 6y agoA Philosophy of Software Design - John Ousterhout
- onnnon 6y agoThis reminds me of a talk Greg Young gave called "The Art of Destroying Software". https://vimeo.com/108441214 https://vimeo.com/108441214
- hew 6y agoOne of my all time favorite talks in software.
- marijn 6y agoApropos, the author is currently looking for work: http://tef.computer/ http://tef.computer/
- staycoolboy 6y agoFun read, but does anyone actually change their coding practices based on high-level essays like this? HN seems to be filled with a highly opinionated bunch, and I question the point of these musings.
- tbugrara 6y agoI'll admit I haven't necessarily changed my coding practices directly based on posts like this, but they do help me formalize the things I've learned in my own experience.
- ben0x539 6y agoI find value in essays like that even if they don't make me write completely different code tomorrow. Having design consideration clearly laid out and discussed is really helpful, imo. (Of course that varies with how effective the essay is at conveying its points and how relevant the points are to me to begin with.) Maybe I've been thinking about similar things myself but never got around to thinking it all the way through or formulating actionable conclusions. Then reading the essay is just like having bits and pieces fall into place in my mind and having disorganized thoughts finally make sense, like a shortcut through the whole mental bureaucracy of forming opinions. Maybe I've been having a disagreement with coworkers about something the essay discusses. Then reading the essay may open up a new perspective on the issue, or introduce terminology that helps us discuss things more clearly, or at least validate that we're discussing something meaningful that other people have also had to think about. Maybe I've already been doing exactly what the hypothetical essay advocates for! But I've always felt kind of bad about it because I couldn't convince myself that I'm doing it for a good reason, and now the essay is making me feel better about myself. Maybe the essay is completely wrong, but it's wrong enough that it provokes an expert into writing an enlightening comment on the details on why and how it's wrong, and how to be less wrong. More people should write more essays, even if they don't end up as seminal blogposts that are cited for decades to come.
- grugagag 6y agoPerhaps you are using your intuition. I do let it guide me without overanalizing every decision but more like feeling it. Programming is also an art and intuition can play a bigger role in it. Engineering is the organized form but built on pre-existent ideas enforcing helpful boundaries. I think when faced with too many slices in decision-making and decision considerations as you put it, it could become overwhelming especially if one is not completely sold on a certain ideology/opinion to fight for. Thats where intuition can be a good guide. However, intuition can do only as much, it needs to feed off at times with some external input such as this type of opinionated articles.
- dkarl 6y agoMicroservices tip for this: Don't put code into a shared library without careful consideration of the consequences. Even if it is used in multiple services, consider duplicating it instead, and compare the risks and trade-offs compared to putting it in a shared library. Common scenario: New developer: "I'm done refactoring the implementation of the BingBong class in the shared library. It was a lot of work to change and test all the frobnicateXxxx methods!" Manager: "Wait, I thought none of our services do any frobnification?" The old hands discuss: "They don't. Not anymore." "Are we sure? Perhaps the Foo service we haven't touched since last year?" "No, the Foo service never did." "Let's search the repos. Maybe we can delete some of these methods." "This is weird. We have seven different frobnicate methods, and we never needed to support that many different kinds of frobnification." "Of course. It's such a pain to roll out a new major version of a library, you don't want to change anything existing." "Do you remember when the rendering service was stuck on version 3 of the auth library? It was because we removed a method from the auth library and rolled out 4.0 without it. Turns out it was being used on a feature branch in the rendering service that got merged right before the release." "I remember. I'm the one who had to roll out version 4.1 the next day with exactly the same code as version 3.7." There's a simple way of understanding how stories like this happen, and a simple conclusion: Once functionality is added to a shared library, changing it requires much more care. Therefore, shared code is much more expensive to maintain than non-shared code. This is why it makes sense to ask a question like, "Which is cheaper in the long run, maintaining three non-shared copies of this code, or maintaining one shared copy?"
- butisaidsudo 6y agoYup, I'm a big believer in applying the rule of three ( https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming) https://en.wikipedia.org/wiki/Rule_of_three_(computer_progra... ) for moving code into a library as well. I find if I create an API with just one or two examples in mind, it often doesn't turn out to be as general as I thought it would be. By the time I've done something three times, I have a much better idea of what the different use cases will be.
- dang 6y agoDiscussed at the time: https://news.ycombinator.com/item?id=11093733 https://news.ycombinator.com/item?id=11093733