5 ms·
I am surprised by a number of people here with a lot of relevant experience and opinions like "to hell principles and patterns, just make your software simple".
by SergeAx 7y ago
I am surprised by a number of people here with a lot of relevant experience and opinions like "to hell principles and patterns, just make your software simple". Most of the software just cannot be made simple. I'll go further and say: you cannot make life with simple software, because there are a lot of players around who will take your simple software and make it into more profitable complex software.
SOLID is essentially a way to make complex software simple to understand. Yes, you have to write 5 classes to introduce new type of persisting entity, but they are simple classes, mostly boilerplate. Complexity is not in number of LOC or files, it's in business processes, their interdependencies, "when this then that, except those" and so on.
With SOLID (coupled with DDD) your hiring process becomes quite simple: you check basic knowledge of language, performance tricks and caveats (like n+1 problem), understanding of principles with examples and voila, you have new team member. On the first day you will show him or her your domain dictionary, give access to git and ticket system, and you will get good enough code to fix bugs or introduce features in a matter of days. And it doesn't matter if your code base is 10 years old, if you followed those principles yourself for all that time.
- redact207 7y agoI'm a DDD convert, but boy do I still have trouble selling it. "why do we need a ubiquitous language?" "why can't I jam everything into a single domain?" "why can't everything be an aggregate root?" "It's too complicated, why can't I just PATCH my data directly into the database from API?" Honestly for me it's these abstract principles and practices that outweigh any flavour of the month technology. DDD encourages code to model the business domain, meaning the complexity should equal that of the business. A lot of problems I see with apps are due to reducing complex domains into CRUD ops, then trying to build the complexity on top as an afterthought. Also, a DDD helper package for node - https://github.com/node-ts/ddd https://github.com/node-ts/ddd
- dep_b 7y agoI really can't write code other than a) experimental (when testing a new library that encompasses a totally new concept) or b) absolutely readable and SOLID. a) code never makes it to production before it became b) since when I understand the problem and my solution I can't leave dead or unreadable code. I've seen people that write nice code by day check in horrible entangled vomit because they wanted to make a deadline. So the next time I pull it, "it has just a few issues" and it takes me two days to sort out their mess where just writing it cleanly myself might have cost me only one day. My code just looks the same no matter what pressure. I just don't believe I go faster by making code harder to understand and maintain.
- SamuelAdams 7y ago> I've seen people that write nice code by day check in horrible entangled vomit because they wanted to make a deadline. So the next time I pull it, "it has just a few issues" and it takes me two days to sort out their mess where just writing it cleanly myself might have cost me only one day. I've checked in "bad" code before. Maybe I can shed some light on the other side of this. The business needed a feature a week ago, because all their marketing material had a hard date on the go-live date for this feature. They could not miss that launch date. Unfortunately the dev team was overloaded and they couldn't deliver all the features on time. So I, a consultant, was tasked with a few last-minute things. Fortunately this new feature was very similar to an existing feature. It used a lot of the same code as something already in the system. So I copied that into a new class (C#), made some (very minor) adjustments, and checked it in. We were able to launch the product on time. But now there was quite a lot of code duplication. Yes, I could have just "written it cleanly myself". But this was a tremendously complex product. We had unit tests, integration tests, and more. But we still had to perform hours of manual testing on any code that changed prior to a release. Refactoring the old code would have introduced more testing requirements, which slows down the entire release cycle - the risk was too great for our timeline. It's important to consider the total cost of your work, not just the amount of time a certain task takes you, individually. It's also worth noting, we made a new Jira ticket about the code duplication right away, and we were able to fix the code duplication in the next sprint, after the product release. The next iteration, 1.0.1, had the "correct / ideal" code.
- dep_b 7y agoYeah, duplicating code that by itself isn't quite what I was getting at. I mean one big god class full of flags that is shared by two quite distinctive views that happen to share just a bit of functionality. In fact duplicating code in that particular scenario would perhaps have been a more sane thing to do but that didn't happen. It's just not helping me to ship something faster, slapping together crap. "Create new file" takes 15 seconds, adding a function there and calling it from the original class I was working in another 15. Debugging sessions to figure out where what flag in what condition was misplaced take 10 minutes. Every time. Where am I really winning time?
- benschulz 7y ago> you cannot make life with simple software, because there are a lot of players around who will take your simple software and make it into more profitable complex software. I believe you are conflating simplicity and value. Someone may take one's solution and add value, and with it complexity inherent to that value, thereby increasing revenue. Adding (incidental) complexity, without adding value, will make your solution less profitable. edit: formatting
- SergeAx 7y agoMaybe you are right, but I honestly don't see how one can add value without adding complexity. Take any real life example: pizza vs plain bread, car vs bike, piano vs harp. There are still demand and markets for simple things, but it has much less profit margin vs complex goods.
- danesparza 7y agoI can't tell if you're being sarcastic or not. There is irony in that if you're not being sarcastic.
- SergeAx 7y agoSorry if my text brings mixed message to you; alas, English is not my native language. No, I wasn't being sarcastic at all, I truly believe in what I wrote and I'm practicing it on a daily basis in my code and during code review.
- mannykannot 7y agoThis is how SOLID, or rather its most zealous proponents, go from reasonable but limited capabilities to claims that cannot be sustained. While small classes and methods can be (though are not necessarily) at least superficially easy to understand, this does not guarantee that the system as a whole is understandable. This is because a lot of the complexity is in how the classes interact with one another. There are contracts and constraints that have to be observed, that are inherently about more than one thing, and so cannot be localized in one method. This approach, applied to writing, would be to allow only kernel sentences using common words. This is not going to be enough to make a complex topic simple to understand, and, if applied zealously, is likely to have the opposite effect. Unnecessarily complex code is not a consequence of not following simple rules; it is usually a consequence of trying to write simple code but not understanding all the issues. There is nothing about SOLID that guarantees that unnecessary complexity will be avoided. Your idea of turning programming into something like painting-by-the-numbers will not work.
- SergeAx 7y agoIn SOLID there is S for "single responsibility", which in turn gives us simplicity on a component (class/object/file, depends on language) level but lead to complexity due to number of components. 100 tasks gives us 100 components, then software grows to 1000 and even 10000 tasks. But then comes letter D for dependency inversion. This principle gives us back simplicity due to abstracting away any set of those components as meta-components like repositories, queues, services, factories and so on. This is about integfaces, e.g. contracts, as you call them. My zealotry comes from about 30 years of writing and SUPPORTING code. SOLID code is harder to write, but much more easier to maintain. All those war stories about "business needs that feature week ago" comes from unmaintainable code, when you just cannot add new features by any other means except spaghetti with epoxy glue and nuts and bolts all around. Business wants to move fast and break things. Our mission as software engineers is to create and maintain codebases solid enough (pun intended) to sustain years of development, pivots, M&As and whatnot.
- gdy 7y ago"But then comes letter D for dependency inversion. This principle gives us back simplicity due to abstracting away any set of those components as meta-components" I honestly don't understand how this produces simplicity. Could you possibly elaborate?
- GordonS 7y agoSOLID is... well, "solid" advice. But it absolutely should not be applied dogmatically - the same principle holds true for design patterns, agile processes, and the like. It seems like most devs have some kind of epiphany when they learn about concepts such as SOLID, and apply them with zeal. It's almost like a stepping stone to learning what SOLID is really about - simple, clean, maintainable code. At some point this realisation dawns, and the dev reaches a zen-like state, where the tenants of SOLID are obvious, without the need to consciously think about them - it's at this point that the dev realises the error of their ways.