SOLID AND LAMBS

One of the most common arguments I hear without adhering to SOLID principles in object-oriented design is YAGNI (although the argument often doesn't call it):

"It's okay that I put both functions of X and included Y in the same class. It's so simple because you need to add a new class (i.e. complexity)."

"Yes, I can put all of my business logic right into the GUI code, it's much simpler and faster. It will always be the only GUI, and it is unlikely that new important requirements will appear."

"If in the unlikely event of new requirements my code is too confused, I can still reorganize the new requirement. Therefore, your argument" What if you need ... "does not count."

What would be your most convincing argument against such a practice? How can I really show that this is an expensive practice, especially for those who do not have too much experience in software development.

+57
design oop solid-principles yagni
Oct 13 '10 at 8:27
source share
10 answers

Design is about managing and balancing compromises. YAGNI and SOLID do not conflict: the first tells when to add functions, the latter tells how, but they both guide the design process. My answers below each of your specific quotes use principles from both YAGNI and SOLID.

  • Three times more difficult to create reusable components as disposable components.
  • The repeatable component must be tried out by three different applications before it is general enough to be accepted for reuse.

& EPRS; - Robert Glass' Rules of Three , Facts and Errors in Software Development

Refactoring for reusable components has a key element for first finding the same target in multiple places and then moving. In this context, YAGNI is applied by inserting this goal where necessary, without worrying about possible duplication, instead of adding common or reusable functions (classes and functions).

The best way in the initial design to show when YAGNI is not applied is to define specific requirements. In other words, do some refactoring before writing the code to show that duplication is not just possible, but already exists: it justifies the extra effort.




Yes, I can put all my business logic into GUI code, it is much simpler and faster. This will always be the only graphical interface, and it is unlikely that new requirements will appear.

Is this the only user interface? Is there an initial batch mode planned? Will there ever be a web interface?

What is your test plan and will you test functionality without a graphical interface? This will make it easier for you to work with the graphical interface, since you usually do not want to test external code (for example, platform GUI controls), but instead focus on your project.

It's good that I put both functions of X and included Y in one class. It is so simple why you need to add a new class (i.e. Complexity).

Can you point out a common mistake that should be avoided? Some things are simple enough, like squaring a number ( x * x vs squared(x) ) for an overly simple example, but if you can point out a specific mistake someone made, especially in your project or team, you can show how a common class or function will avoid this in the future.

If in the unlikely event of new requirements my code gets too dry, I can still reorganize the new requirement. So, your argument "What if you need ..." does not count.

The problem here is the "improbability" assumption. Do you agree with this unlikely? If so, you agree with this person. If not, your design idea is not consistent with this person - letting the discrepancy solve the problem, or at least show you where to go next. :)

+37
Oct 13 2018-10-10
source share

It looks like you are arguing with a brick wall. I am a big fan of YAGNI, but at the same time I also expect my code to always be used in at least two places: application and tests. This is why things like business logic in user interface code do not work; you cannot test business logic separately from user interface code in this case.

However, from the answers you describe, it seems that the person is simply not interested in a better job. At this moment, no principle will help them; they just want to make the minimum possible. I went so far as to say that this is not YAGNI, but rather laziness, and you are not going to beat laziness alone (almost nothing can but a threatening manager or job loss).

+5
Oct 13 2018-10-10
source share

I like to think of YAGNI in terms of “half, not half” to borrow a phrase from 37 signals ( https://gettingreal.37signals.com/ch05_Half_Not_Half_Assed.php ). This is about volume limits, so you can focus on doing the most important things. This is not a reason to get sloppy.

The business logic in the GUI feels half like me. If your system is trivial, I would be surprised if your business logic and GUI have not changed independently, several times. Therefore, you should follow the SRP ("S" in SOLID) and the refactor - YAGNI is not used because you already need it.

The argument about YAGNI and unnecessary complexity is absolutely applicable if you do extra work today to meet hypothetical future needs. When these “what if we need to ... later” scenarios are not implemented, you are stuck with higher maintenance costs from abstractions that now interfere with the changes you actually have. In this case, we are talking about simplifying the design by limiting the scope - making it half, not half.

+4
Sep 15 '14 at 1:58
source share

The correct application of these principles is often not very obvious and largely depends on experience. It is hard to get if you did not do it yourself. Each programmer should have had experience with the consequences of improper action, but, of course, it should always be a "not mine" project.

Explain to them what the problem is, if they do not listen, and you cannot make them listen, let them make mistakes. If you solve the problem too often, you should polish your resume.

+2
Oct. 13 2018-10-10T00:
source share

In my experience, this is always a solution. Yes, you don’t have to worry about every little detail of your implementation, and sometimes sticking to a method in an existing class is an acceptable, albeit ugly, solution.

It is true that you can reorganize later. An important point is the actual execution of refactoring. Therefore, I believe that the real problem is not an accidental compromise in design, but the elimination of refactoring when it becomes clear that the problem is. In fact, this is the hard part (like so many things in life ...).

As for your individual points:

OK, I put both functions of X and include Y in the same class. It is so simple that you need to add a new class (i.e. complexity).

I would like to point out that everything in one class is more complex (because the relationships between the methods are more intimate and more difficult to understand). Having many small classes is not difficult. If you feel the list is getting to the end, just organize them into packages and everything will be fine :-). Personally, I have found that simply dividing a class into two or three classes can help with readability without any further changes.

Do not be afraid of small classes, they do not bite; -).

Yes, I can put all my business logic directly into the GUI code, which is much simpler and faster. It will always be the only graphical interface, and it is very unlikely that meaningful new requirements will ever appear.

If someone can say: "it is unlikely that important new requirements will ever appear." with a straight face, I believe that a person really, really needs a reality check. Be stupid but gentle ...

If in the unlikely event of a new requirement my code, too, I can still reorganize the new requirement. So, your “What if you later need ...” argument is not count

This has some advantages, but only if they do reorganize later. Therefore, accept this and accept them to their promise :-).

+2
Oct 13 '10 at 10:22
source share

SOLID principles allow software to adapt to changes - both in requirements and in technical changes (new components, etc.), two of your arguments are for constant requirements:

  • "it is unlikely that new requirements will appear."
  • “If in the unlikely event of new requirements”

Is that really true?

It is impossible to replace experience when it comes to various development costs. For many practitioners, I think that doing something in a lousy, difficult way to maintain a path never led to problems for them (hey! Work safety). Over time, the product, I think these costs become clear, but to do something ahead of time is someone else.

There are some more great answers here.

+2
Oct 13 2018-10-10
source share

Clear, flexible and capable of fixes and improvements, you always need the things you need. . In fact, YAGNI assumes that you can come back and add new features when they prove the need with relative ease, because no one is going to do something crazy, for example, hammer in irrelevant functionality in a class (YAGNI in this class!) Or push business logic to user interface logic.

There may be times when lunatics were now reasonable in the past - sometimes the UI boundary lines against the business or between different sets of responsibilities that should be in a different class are not so clear or even moving. There may be times when 3 hours of work are absolutely necessary after 2 hours. There are times when people just don't make the right call. For these reasons, occasional interruptions in this regard will occur, but they will interfere with the use of the YAGNI principle, and not be the reason for this.

+2
Oct 14 '10 at 9:21
source share

Quality unit tests, and I mean unit tests, not integration tests, I need code that adheres to SOLID. Not necessarily 100%, actually rarely, but in your example, adding two functions to one class will complicate unit testing even more, violate the principle of uniform responsibility and greatly simplify the maintenance of the code with the newbies command (since it is much more difficult to understand)

With unit tests (provided that the code is well covered) you can use refactoring function 1 safely and safely, you do not violate function 2, but without unit tests and with functions of the same class (just be lazy in your example), refactoring is risky at best, disastrous at best.

Bottom line: follow the KIS principle (keep it simple) or the intelligent KISS principle (stupid). Take every case you deserve it, there is no global answer, but always consider whether other encoders should read or maintain code in the future and the benefits of unit tests in each scenario.

+2
Jul 29 '16 at 22:59
source share

There is no answer, or rather, there is an answer that neither your interlocutor will like you: both YAGNI and SOLID may be the wrong approaches.

Trying to go for SOLID with an inexperienced team or a team with tight delivery tasks pretty much ensures that you end up with an expensive, reworked bunch of code ... that WILL NOT be SOLID, just reworked (also welcome to the real world).

Trying to go YAGNI for a long-term project and hope that you can reorganize later works only to a certain extent (also welcome in the real world). YAGNI succeeds in proving concepts and demonstrators by acquiring a market / contract, and then can invest in something more than SOLID.

You need both at different points in time.

+2
Mar 30 '17 at 14:19
source share

TL; DR;

SOLID assumes, you understand (somewhat at least), future code changes, by SRP. I will say that I am optimistic about the ability to predict. On the other hand, YAGNI involves most of the time when you don’t know the future direction of change, which pessimistic about the ability to predict.

It follows that SOLID / SRP asks you to create classes for the code so that it has one reason for the change. For example. minor GUI changes or ServiceCall changes.

YAGNI says (if you want to enforce it in this scenario), since you don’t know what will change, and if changing the GUI will change the GUI + ServiceCall (similarly, changing the database calling GUI + SeviceCall), just put the whole this code into one class.

Long answer:

Read the book, Agile Software Development, Principles, Patterns, and Practice.

I am posting a short excerpt from it about SOLID / SRP: “If the application [...] does not change in ways that cause the two responsibilities to change at different times, there is no need to separate them. Indeed, separating them will smell like unnecessary complexity.

There is a steamer here. The axis of change is the axis of change only if changes occur. "It is not practical to apply SRP or any other principle if it is not, if there are no symptoms."

+1
Sep 04 '14 at 6:28
source share



All Articles