4 ms·
Most people have never worked on a long term project applying SOLID principles and DDD and therefore cannot fathom how efficient a team can be when it is applie
by xutopia 7y ago
Most people have never worked on a long term project applying SOLID principles and DDD and therefore cannot fathom how efficient a team can be when it is applied.
Have you ever worked at a company where you join and there is a God class (or two or three) and none of the business people and developers talk the same language.
The code does things but you couldn't in a million years guess why or how you came about it without having a huge history lesson on the company and its codebase.
Now imagine how amazing it is to join a team where efforts are constantly made to name meaningfully and that there aren't 8 concerns mixed into a single god class. New devs join and they immediately understand what's happening in the business because the code translates directly to the reality. They don't have to learn two languages (business and dev speak).
Now imagine that dev having to add a grandfather clause to an old account. Where should he put it in the `Account`, `Plan`, `User`, `Subscription` or `Business` class? When the distinction between concepts are clear in the code it's easy to determine where the code should go and where logic of different kinds should reside.
- slavik81 7y agoI worked for several years on a team that championed SOLID and DDD, and while it was better than the multi-process, shared-memory, stringly-typed horror that it replaced, efficient is not the word I'd use to describe it. The single responsibility and open-closed principles created a Cambrian explosion of tiny classes and the ratio of boilerplate to interesting code skyrocketed. Maybe we were just interpreting things wrong, but it was very difficult to agree on what those principles meant in practice. Liskov's substitution principle is also rather complex. I'm not sure I correctly understand it, but I think it is widely violated even by good code. If I have it right, the principle means the result of your program cannot change, no matter what subtype you substitute.
- safety-third 7y agoLSP just says that derived classes should behave similar to their base classes. class Base { virtual int size() { return size_; } ... class Derived : public Base { virtual int size() { return rand(); } ... Here we see an issue. Derived is overriding Base's size method, which has a straightforward implementation, with something wild. If a Derived is sent to a method expecting Base-like behavior, something bad is going to happen. Derived should act like a Base with slightly different implementation details. This is all LSP is. It's a fancy phrase for a very simple concept.
- slavik81 7y agoNot just similar. All provable properties must be the same. As I understand it, Java's Object.toString() is an example of an LSP violation because different subtypes of Object return different strings.
- safety-third 7y agoNo, it is very much LSP compliant. The purpose of toString() is to give a string representation of the object. Most overloads of this do exactly that. An LSP violation of toString() would be something that returns a string that doesn't represent the object. If you were to return the current time as a string for an object that has nothing to do with time, that would be an LSP violation.
- slavik81 7y agoI'm very confused. The definition of LSP is: > Subtype Requirement: Let ϕ(x) be a property provable about objects x of type T. Then ϕ(y) should be true for objects y of type S where S is a subtype of T. Why is the exact value of the string returned not a provable property? And, to your example, if a provable property is that the returned string represents the object, how did you know it was a provable property? And how do you prove it? The rule seems very formal, but your notions seem very informal, and I don't know how to reconcile them.
- hansvm 7y agoWith the caveat that LSP is still violated in the given example, I think it's important to note that when talking about "all" instances of a given class you might not have much information about the exact value of a string. Their notions are informal, but on some level it's just the experimentalist's interpretation of LSP -- much how some physicists (loosely) argue that if you can't make measurements to prove a theory wrong then the theory doesn't matter, it might similarly be reasonable to ignore LSP with respect to properties that you don't care about (where that definition is fuzzy and hard to pin down but should represent a definitive class of things within any given single program). E.g., most people don't rely on toString() doing much more than giving a bit of human intuition into the type and properties of an object, so any implementation which respects that behavior satisfies a realist's LSP.
- mumblemumble 7y agoThink of LSP as being like semver for inheritance: A derived class can add new behavior, but it can't make any breaking changes.
- wirrbel 7y agoCan you recommend an introduction that shows the "grandfather rule" aspect? I have read DDD intros but don't remember exactly something that would help me.