6 ms·
The longer I've worked in software development, the less I'm convinced that any of this matters, at all. What has mattered more to me is choosing the right arc
by risaacs99 7y ago
The longer I've worked in software development, the less I'm convinced that any of this matters, at all.
What has mattered more to me is choosing the right architecture, technologies and dependencies. Understanding the fundamentals, especially at least a vague understanding of what the computer is doing with the code I am writing. Basic understanding of algorithms and techniques like state machines.
I've grown almost disdainful of things like SOLID principles, after taking them more seriously in the past.
- ctvo 7y agoI agree, mostly. The more experience I gain, the less I’m concerned about refactorable, local issues. Distributed systems is hard. Scaling is hard. Data consistency is hard. Security is hard. API design is hard. Refactoring a local code base to extract out methods and implement interfaces, much less so. These days if the biggest problem we have is a monolithic service is badly coded (but is correct and works), it’s something I’ll take.
- Swizec 7y agoSeconding this. I used to really care about code maintainability, cleanliness, and other topics super important to us engineers. 4 years in The Valley have quickly dissuaded me of such foolish naive notions. Your code (outside some common sense basics) is completely irrelevant. Whatever you can stick together with duct tape and chewing gum is almost always the best solution. All the business wants is speed. By the time "bugs" is the highest reason for churn ... well you're likely going to be on your 5th employer by the time your first employer reaches that point. Absolutely nobody in the real world cares about the quality of your code. They just want to do their job with as little interaction with your software as possible and move on. It's kinda sad really how much time we waste talking about the best way to hold a hammer, the best hammer you can use, the best nails etc. when all our customers want is the picture to be up on the wall already. Edit: One important addition -> If you're senior and you see juniors writing "bad code" on your team, your job isn't to teach them why it's bad. Your job is to create systems that make good code easier and more obvious to write than bad code. Be the force multiplier.
- Silhouette 7y agoThe customer does generally prefer it if the picture doesn't fall off the wall the moment you leave, though.
- Swizec 7y agoThis where the "some common sense" basics part comes into play.
- cgrealy 7y agoNot everyone works in "The Valley". The vast majority of software is not written with that amount of churn. The end user doesn't care about the quality of the code, but you can be damn sure they care about the quality of your software. Also, talking about hammers is overly reductive. Software is far more complex than hitting something with a hammer. Builders might not talk about the best way to hold a hammer, but they constantly talk about the best way to build a house.
- mooreds 7y ago> The vast majority of software is not written with that amount of churn. My current employer has code that is 6 years old. I had coffee with a former colleague and they are still running code from when I was there, and I left 5 years ago. Code lives longer than you think.
- sanderjd 7y agoSome code lives longer than you think it will, and some dies really quickly. The problem is that you never know which is which.
- cgrealy 7y ago6 years is still young for code. My current employer has code that's 13 years old. My last had code that was nearing 20. And there's nothing wrong with that. Old code isn't "bad". In fact, it's almost certainly better than new code, because it's been battle hardened. It's got that fix in it for that weird edge case.
- dudul 7y agoEven using the "right" architecture or tech stack doesn't matter that much. All business problems can be solved with any language, with a monolith or a fleet of microservices, it doesn't matter. What matters is to ship code that brings a solution to the client's problem.
- ljm 7y agoI think I agree too. Maybe not disdainful, but certainly skeptical. I put things like SOLID and design patterns in the same bucket as scalable agile, and similar prescriptive practices. To me, they seem more concerned with organisation as opposed to exposing real business problems so that you can solve them, and as a result you're wrestling with the abstraction and the glue code more than the business logic. A finite state machine is my favourite example, as I've seen all kinds of 'well-organised' setups that could have been massively simplified as an FSM. Whatever the right architecture and tech is, I've become more convinced over time that the easier it is to delete bits of your code, the better. And that doesn't always mean you go full-on OOP. More to the point, 'maintainable' is massively subjective. Many of the metrics we use to measure that are utterly shallow.
- kibibu 7y agoI wonder if this is because you used them, learnt from them, internalized whatever design intuitions you could from them, and have moved onto higher levels of understanding. Expert bike riders disdain using training wheels, but only after they've learned how to ride using them. --- (please hn don't derail with "well actually"s about training wheels)
- keithnz 7y agoI was active in the XP mailing group when things like SOLID got popularized, mainly by consultants. Of course the principles had been around for much longer in various forms. To me, there seemed to be a distinct difference between what some of the consultants focused on, and the books they ended up writing compared to what people who were using XP techniques and trying to leverage (determine) the best software design approaches to write actual production software. Some of the book writers / consultants were much better at actually observing (or having direct experience of) real issues and how to deal with them. But actual software design did not center around things like SOLID, those things sort of just fell out of approaching design in a particular way. I find the language too strong ( laws / principle ). Instead as you find ways to construct modular and composable software, you'll notice that things tend to have a single responsibility, you'll notice that "modules" tend to become stable and extendable through other "modules" of software. They are like side effects of good design, not things to focus on other than if a design is not really working well, it might provide an insight into why its suffering. Which is all a polite way of saying it is mostly crap and the insight of people with real problems and who dealt with those problems is mostly ignored.
- projectileboy 7y agoI find myself somewhat reluctantly agreeing. While I think the SOLID principles and similar things are helpful tools for thinking, I think they should in general take a back seat to the simple principle of Less Code. I’ve seen so many over-complicated code nightmares that were created in the name of “separation of concerns”, or some such, that my spine tingles anytime someone starts talking about some abstract design principles.
- lowercased 7y ago> were created in the name of “separation of concerns” when I hear "separation of concerns", I now immediately ask (internally or externally) "do we need to be concerned about this at all? right now or even years in the future?" Recent project: untangling something that was written 2 years ago as "best enterprise engineering practices". That dude is gone, no one else on the team understands it because it's insanely over-engineered. This is literally "send a notification email", and there's about 38 core files, another 25 'helper' files, ~20 templates and a custom template parser/nested template thing, and a few dozen node/npm dependencies. This is a 'microservice' running on lambda. literally, someone needs to be able to send a notification that "X is ready", and it's this behemoth that no one understands. They do understand that all the templates and logic were taken away from each caller's context - so all the various teams that used to be in control of their own notification messaging now have to wait for someone to dig in to this other codebase which is basically unmaintained now. It's got its own custom date parser, because... why not? And there have been random "wrong dates" being sent out for months because... no one can quite trace down the root problem. I finally did, and I'm not saying "no one ever can", but it's under no one's direct ownership, and the people that have tried to take it over have just been overwhelmed with trying to trace through it, make it testable, etc. And last week I heard rumblings that another team is "rebuilding notifications". It's as much a failure of management/oversight as it is "overengineering" in general, but at each review step (so I was told), things "looked good", in isolation. No one quite pieced together that this was an unwieldy behemoth until after this guy was gone. :/ (no doubt an extremely typical story, but one which, by now, I would have hoped would be 'less typical').
- 7y ago
- barbs 7y agoI agree to some extent. I think in general they're good principles, but I think people tend to take them as gospel and forget about code readability and complexity in order to adhere to them. It's important to understand the trade-offs involved, and to understand that different problems will require different solutions.
- foxylad 7y agoAfter thirty years of software development, the one principle that keeps recurring is Donald Knuth's "Premature optimization is the root of all evil". It applies on so many levels, including whether to go all in on any software engineering methodology. For instance, applying SOLID principles to your personal side project is counter-productive; but if it grows into a multi-developer project you might well gain efficiencies by rationalising your code structure.
- paulgrant999 7y agoI just got rejected from a job, because they wanted me to write tests, without even supplying ANY input with which to presume what types of tests would be applicable (i.e. how was the data gathered)... when I pointed out I wrote the spec-based generation hookable so that you could override it in seconds to generate any set of errors you'ld care to model, and that it was a deliberate choice to avoid premature optimization, they were not amused. I told them the toy spec they sent, would never work for testing an experienced engineer who is aware of the many specific modes of failure depending on how the system was architected. I don't get it anymore. I send beautiful, well-thought out code. And get spit in my face for the effort. Not even a first-round interview. Its like they're specifically avoiding hiring experienced engineers. It is positively, frustrating. My last two projects were so well-architected you could significantly enhance the scope of the project with a few lines of code, that literally write themselves (you know have a good code-base when it suggests an immediate, maintainable solution for feature creep, with zero uncertainty)... And yet, apparently, I'm not fit to get a coding monkey job... So I read these articles, and think? Why the fuck even bother? You don't have coders anymore. Just mediocre software engineers who think coding is 'writing tests'.
- zmmmmm 7y agoYep. As another old-timer, pretty much the only principles I have seen that consistently pay off are KISS and YAGNI. And the problem is nearly all of this SOLID type stuff is directly contrary to that.
- 13rac1 7y agoI've found it important to include the context of that quote: > We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. That 3% can be significant.
- deleted 7y ago[deleted]
- Jupe 7y agoSo glad to see this stated publicly, and actually getting some positive responses. 25+ years of software development and the best "pattern" I can identify after dozens of projects is just one: simplicity. If you can't follow the logic by just reading the code, then maintenance will be slow and cumbersome. New development will eventually taper off as more and more time is spent fixing issues. I've written production systems, still in operation today decades later, that hold true to the simplicity principle. I wouldn't do it any other way. But, the battle I frequently face is with upstart devs who want to use some new pattern or principle because they read that it was "better" than straight-up code. And yes, they can implement some new feature quick, but 2 years down the road all hell breaks loose. Some of my pet-peeve anti-patterns: * "Plugin" systems only used by the primary development team. There's power in being able to follow the logic for any call stack by just reading the code; plugins make the flow much more challenging, and provide little value. * Large (and complicated) run-time configuration IOC systems which make any debug session a dreadful process. * Rules Engines. 'nuff said. * Piles of abstractions, one atop the other, because teams had no time to find commonalities and/or sensible use-cases. * 25+ new source code files to respond to a /heartbeat endpoint. * Fixing a problem in 3 lines of code is not fixing anything if it complicates the debug process, forces a re-write of the unit test drivers, enables mysterious build failures or taxes the DevOps team. And some of my favorite simplifying patterns: * AOP for logging; but NOT (dear god) for business logic. * 3 levels of abstraction, and no more. If you can't figure out a way to do it in 3 levels of abstraction, then something else is wrong. * 3 systems of state: config (global), current request and persistence (database). If you need more than that, then something is wrong with the architecture. (Ok, compilers may not be able to get away with this, but most applications can, in my experience.) * If you use a pattern (MVC, for example) apply it to the whole system. E.g. doing IOC only in the upstream API system when the rest of the code doesn't, just makes a mess.
- jlj 7y agoRules engines come up frequently in my domain area. What are some good resources for managing either high volume or high complexity business rules? Usually these start out as hard-coding, then evolve into a rules engine or framework. Sometimes after the original devs leave, the rules engine turns into a shiny black box that remaining devs are afraid to touch. What are some anti-anti-patterns?
- JamesBarney 7y agoYeah >write code that's easily understood >write code where things are where they're expected to be >write code that can be adjusted and extended quickly >write code that can be adjusted and extended quickly without producing bugs >write code that allows for implementations to be swapped out (think swapping out Email APIs, ORMs or web server frameworks) The problem is to further these goals they introduce abstraction and complexity which make the code harder to change, harder to reason about, harder to test. And a lot of times you end up taking one step forward but two steps back.
- namelosw 7y agoI too disdainful SOLID. I appreciate this finally has been pointed out. Principles are in fact moral high grounds, without telling you what to do. For example, you need to resolve the expression problem[0] in Java, with Open-Closed principle compliant. Then the answer could be Java code like in this article[1] (the technique is Object Algebra). However the moral for me is, if I'm using Haskell or Ruby, when expressing Open-Closed idea is simple, I would use it. If I'm using Java, just forget the principle. I would just express the business, and change the code if I need to add new types or operations. Because the principle is written the code is not understandable to other people, just like design pattern abused codebases. Another thing is Liskov Substitution Principle. I found most of the books cover this idea don't even mention how to judge if an object is LSP compliant. Every people I know talk about the principle haven't heard of covariant and contravariant, and didn't realize almost all of the mutable data type inheritance are in fact not LSP compliant. [0] https://en.wikipedia.org/wiki/Expression_problem https://en.wikipedia.org/wiki/Expression_problem [1] https://koerbitz.me/posts/Solving-the-Expression-Problem-in-Haskell-and-Java.html https://koerbitz.me/posts/Solving-the-Expression-Problem-in-...
- goto11 7y agoThe most important rule is understanding the context of any design guideline, rule-of-thumb, "pattern" or "best practice". Something like the Open/Closed-principle is a really great principle for the kinds of projects if was created for. It is just that for 90% of software development it is not appropriate and therefore leads to needless complexity. Discussing whether SOLID is good or bad in itself does not make any sense IMHO.
- chungleong 7y agoProgramming paradigms are like diet plans from weight-loss companies: most of the time they're just the original problem repackaged as a solution--with a snazzy name and aspirational slogans. The difficulty of the endeavor basically get hidden in the contrapositive. "Eating meals that we provide" sounds easy. Not eating what you want to eat--that's the hard part. Writing code that meet certain standards is easy. Not writing code that does not is incredibly hard when have hard requirements and delivery dates.
- maximus1983 7y agoTotally disagree and I am rather dismayed by people conflating their bad experiences with people over-engineering with these principles. They are like anything else a good they are good rules of thumb when scaffolding your projects. Understanding IoC with DI has cleaned up my code soo much and I know it works as I can Unit Test easily.
- dirkg 7y agoAgreed. Adherence to dogma like this is cancer. i was rejected rom a pretty big company after clearing other stages because I wasn't able to recite SOLID. Its like asking people if they know 'design patterns' and expecting them to come up with the textbook answer from the GoF book. Telling people that you need to use OOP or DI or any fixed software methodology is just stupid. None of this crap is used in real companies, the good ones anyway. You should be flexible, open, and strive for maintainable, consistent, and simple design.