Programing

SOLID 대 YAGNI

crosscheck 2020. 11. 21. 15:40
반응형

SOLID 대 YAGNI


객체 지향 디자인에서 SOLID 원칙을 고수하지 않는 것에 대해 내가 듣는 가장 빈번한 주장 중 하나 YAGNI입니다 (이론자는 종종 그것을 그렇게 부르지 않습니다).

"특징 X와 기능 Y를 같은 클래스에 넣는 것은 괜찮습니다. 새로운 클래스를 추가해야하는 이유가 너무 간단합니다 (예 : 복잡성)."

"네, 모든 비즈니스 로직을 GUI 코드에 직접 넣을 수 있습니다. 훨씬 쉽고 빠릅니다. 이것은 항상 유일한 GUI이며 중요한 새로운 요구 사항이 들어올 가능성은 거의 없습니다."

"새로운 요구 사항의 드문 경우에 내 코드가 너무 복잡해지면 새 요구 사항에 대해 리팩토링 할 수 있습니다. 따라서 '나중에 필요한 경우…'인수는 중요하지 않습니다."

그러한 관행에 대해 가장 설득력있는 주장은 무엇입니까? 특히 소프트웨어 개발 경험이 많지 않은 사람에게 이것이 비용이 많이 드는 관행임을 어떻게 보여줄 수 있습니까 ?


디자인은 트레이드 오프의 관리 및 균형입니다. YAGNI와 SOLID는 상충되지 않습니다. 전자는 기능 추가 시기말하고 후자는 방법을 말하지만 둘 다 디자인 프로세스를 안내합니다. 아래의 각 인용문에 대한 나의 답변은 YAGNI와 SOLID의 원칙을 사용합니다.

  1. 재사용 가능한 구성 요소를 만드는 것은 일회용 구성 요소보다 3 배 더 어렵습니다.
  2. 재사용 가능한 구성 요소는 재사용 라이브러리에 수용하기에 충분히 일반적이되기 전에 세 가지 다른 응용 프로그램에서 시도해야합니다.

  — Robert Glass 의 3 가지 규칙 , 소프트웨어 엔지니어링의 사실과 오류

재사용 가능한 구성 요소로 리팩토링하는 것은 먼저 여러 위치에서 동일한 목적을 찾은 다음 이동 하는 핵심 요소입니다 . 이러한 맥락에서 YAGNI는 일반 또는 재사용 가능한 기능 (클래스 및 함수)을 추가하는 대신 중복 가능성에 대해 걱정하지 않고 필요한 곳에 해당 목적을 인라인하여 적용합니다.

초기 설계에서 YAGNI가 적용되지 않는시기를 표시하는 가장 좋은 방법은 구체적인 요구 사항을 식별하는 것입니다. 즉, 코드작성하기 전에 일부 리팩토링을 수행 하여 복제가 가능할뿐만 아니라 이미 존재 함을 보여줍니다. 이는 추가 노력을 정당화합니다.


예, 모든 비즈니스 로직을 GUI 코드에 직접 넣을 수 있습니다. 훨씬 쉽고 빠릅니다. 이것은 항상 유일한 GUI이며 중요한 새로운 요구 사항이 들어올 가능성은 거의 없습니다.

정말 유일한 사용자 인터페이스입니까? 계획된 백그라운드 배치 모드가 있습니까? 웹 인터페이스가 있습니까?

테스트 계획은 무엇이며 GUI없이 백엔드 기능을 테스트 할 예정입니까? 일반적으로 외부 코드 (예 : 플랫폼 일반 GUI 컨트롤)를 테스트하지 않고 대신 프로젝트에 집중하기 때문에 GUI를 쉽게 테스트 할 수 있습니다.

기능 X와 기능 Y를 같은 클래스에 넣는 것은 괜찮습니다. 새로운 클래스를 추가해야하는 이유는 매우 간단합니다 (예 : 복잡성).

피해야 할 일반적인 실수를 지적 할 수 있습니까? 지나치게 간단한 예를 들어 숫자 ( x * xvs squared(x))를 제곱하는 것과 같은 일부는 충분히 간단하지만, 특히 프로젝트에서 또는 팀원이 범한 구체적인 실수를 지적 할 수있는 경우 클래스 나 함수는 미래에 그것을 피할 것입니다.

새로운 요구 사항이있을 가능성이없는 경우 코드가 너무 복잡해지면 새로운 요구 사항에 대해 리팩토링 할 수 있습니다. 따라서 "나중에 필요한 경우 ..."라는 주장은 중요하지 않습니다.

여기서 문제는 "불가능"이라는 가정입니다. 그럴 가능성이 없다는 데 동의하십니까? 그렇다면이 사람과 동의하는 것입니다. 그렇지 않은 경우 디자인에 대한 아이디어가이 사람의 아이디어와 일치하지 않습니다. 이러한 불일치를 해결하면 문제가 해결되거나 적어도 다음에 어디로 가야할지 보여줄 것입니다. :)


벽돌 벽으로 다투는 것 같습니다. 나는 YAGNI의 열렬한 팬이지만 동시에 내 코드가 항상 애플리케이션과 테스트라는 두 곳 이상에서 사용될 것으로 기대합니다 . 이것이 UI 코드의 비즈니스 로직과 같은 것이 작동하지 않는 이유입니다. 이러한 상황에서는 UI 코드와 별도로 비즈니스 로직을 테스트 할 수 없습니다.

그러나 당신이 설명하는 답변을 보면 그 사람은 단순히 더 나은 일을하는 데 관심이없는 것처럼 들립니다. 그 시점에서 어떤 원칙도 그들을 도울 수 없습니다. 그들은 가능한 최소한의 일만을 원합니다. 나는 YAGNI가 그들의 행동을 주도하는 것이 아니라 오히려 게으름이라고 말하고 싶습니다. 당신 혼자 게으름을 이길 수는 없습니다 (위협적인 관리자 또는 실직을 제외하고는 거의 아무것도 할 수 없습니다).


나는 37signals ( https://gettingreal.37signals.com/ch05_Half_Not_Half_Assed.php ) 에서 문구를 빌리기 위해 "반이 아닌 절반"이라는 관점에서 YAGNI에 대해 생각하고 싶습니다 . 가장 중요한 일을 잘하는 데 집중할 수 있도록 범위를 제한하는 것입니다. 조잡 해지는 것은 변명의 여지가 없습니다.

GUI의 비즈니스 로직은 나에게 반쯤 어리석은 느낌이 듭니다. 시스템이 사소한 것이 아니라면 비즈니스 로직과 GUI가 이미 여러 번 독립적으로 변경되지 않았다면 놀랄 것입니다. 따라서 SRP (SOLID의 "S")를 따르고 리팩터링해야합니다. YAGNI는 이미 필요하기 때문에 적용되지 않습니다.

YAGNI와 불필요한 복잡성에 대한 주장은 가상의 미래 요구 사항을 수용하기 위해 오늘 추가 작업을 수행하는 경우 절대적으로 적용됩니다. "나중에 우리가해야 할 일 ..."시나리오가 구체화되지 않을 때, 당신은 이제 당신이 실제로 가지고있는 변화를 방해하는 추상화로 인한 더 높은 유지 비용에 갇히게됩니다. 이 경우 우리는 범위를 제한하여 설계를 단순화하는 것에 대해 이야기하고 있습니다.


대답이 없거나 오히려 당신이나 대담자가 좋아하지 않는 대답이 있습니다. YAGNI와 SOLID는 모두 잘못된 접근 방식 일 수 있습니다.

경험이 부족한 팀이나 빡빡한 제공 목표를 가진 팀과 함께 SOLID를 시도하면 비용이 많이 들고 과도하게 엔지니어링 된 코드 묶음으로 끝날 것입니다. 현실 세계에).

장기 프로젝트를 위해 YAGNI를 시도하고 나중에 리팩토링 할 수 있기를 바라는 것은 어느 정도 효과가 있기를 바랍니다 (실제 세계에 오신 것을 환영합니다). YAGNI는 개념 증명 및 시연자에게 탁월하여 시장 / 계약을 체결 한 다음보다 확실한 것에 투자 할 수 있습니다.

서로 다른 시점에서 둘 다 필요합니다.


이러한 원칙의 올바른 적용은 종종 그다지 분명하지 않으며 경험에 크게 의존합니다. 당신이 직접하지 않으면 얻기가 어렵습니다. 모든 프로그래머는 그것을 잘못한 결과에 대한 경험을 가지고 있어야하지만, 물론 그것은 항상 "내가 아닌"프로젝트 여야합니다.

문제가 무엇인지 설명하십시오. 그들이 듣지 않고 당신이 그들을들을 수있는 위치에 있지 않다면, 그들이 실수를하도록 내버려 두십시오. 문제를 너무 자주 고쳐야하는 사람이라면 이력서를 다듬어야합니다.


내 경험상, 그것은 항상 판단이다. 예, 구현의 모든 세부 사항에 대해 걱정할 필요가 없으며 때로는 추악한 솔루션이지만 기존 클래스에 메서드를 고정하는 것이 허용되는 경우도 있습니다.

나중에 리팩토링 할 수 있다는 것은 사실입니다. 중요한 점은 실제로 리팩토링을 수행하는 것 입니다. 그래서 진짜 문제는 가끔 디자인 타협이 아니라 문제가 있다는 것이 분명 해지면 리팩토링을 미루는 것이라고 생각합니다. 실제로 그것을 겪는 것은 어려운 부분입니다 (삶의 많은 것들과 마찬가지로 ...).

귀하의 개별 포인트에 관하여 :

기능 X와 기능 Y를 같은 클래스에 넣는 것은 괜찮습니다. 새로운 클래스를 추가해야하는 이유는 매우 간단합니다 (예 : 복잡성).

나는 모든 것을 하나의 클래스에 포함하는 것이 더 복잡 하다는 것을 지적 할 것입니다 (방법 간의 관계가 더 친밀하고 이해하기 어렵 기 때문입니다). 소규모 수업을 많이 갖는 것은 복잡하지 않습니다. 목록이 길어지고 있다고 생각되면 패키지로 정리하면 괜찮습니다 :-). 개인적으로 저는 클래스를 두 개 또는 세 개의 클래스로 나누는 것만으로도 더 이상 변경하지 않고도 가독성에 많은 도움이 될 수 있음을 발견했습니다.

소규모 수업을 두려워하지 마십시오. 그들은 물지 않습니다 ;-).

예, 모든 비즈니스 로직을 GUI 코드에 직접 넣을 수 있습니다. 훨씬 쉽고 빠릅니다. 이것은 항상 유일한 GUI이며 중요한 새로운 요구 사항이 들어올 가능성은 거의 없습니다.

If someone can say "it is highly unlikely that signifcant new requirements will ever come in." with a straight face, I believe that person really, really needs a reality check. Be blunt, but gentle...

If in the unlikely case of new requirements my code gets too cluttered I still can refactor for the new requirement. So your 'What if you later need to ...' argument doesn't count

That has some merit, but only if they actually do refactor later. So accept it, and hold them to their promise :-).


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

  • "it is highly unlikely that signifcant new requirements will ever come in."
  • "If in the unlikely case of new requirements"

Could this really be true?

There is no substitute for experience when it comes to the various expenses of development. For many practitioners I think doing things in the lousy, difficult to maintain way has never resulted in problems for them (hey! job security). Over the long term of a product I think these expenses become clear, but doing something about them ahead of time is someone else's job.

There are some other great answers here.


Understandable, flexible and capable of fixes and improvements are always things that you are going to need. Indeed, YAGNI assumes that you can come back and add new features when they prove necessary with relative ease, because nobody is going to do something crazy like bunging irrelevant functionality in a class (YAGNI in that class!) or pushing business logic to UI logic.

There can be times when what seems crazy now was reasonable in the past - sometimes the boundary lines of UI vs business or between different sets of responsibilities that should be in a different class aren't that clear, or even move. There can be times when 3hours of work is absolutely necessary in 2hours time. There are times when people just don't make the right call. For those reasons occasional breaks in this regard will happen, but they are going to get in the way of using the YAGNI principle, not be a cause of it.


Quality unit tests, and I mean unit tests not integration tests, need code that adheres to SOLID. Not necessarily 100%, in fact rarely so, but in your example stuffing two features into one class will make unit testing harder, breaks the single responsibility principle, and makes code maintenance by team newbies much harder (as it is much harder to comprehend).

With the unit tests (assuming good code coverage) you'll be able to refactor feature 1 safe and secure you won't break feature 2, but without unit tests and with the features in same class (simply to be lazy in your example) refactoring is risky at best, disastrous at best.

Bottom line: follow the KIS principle (keep it simple), or for the intellectual the KISS principle (kis stupid). Take each case on merit, there's no global answer but always consider if other coders need to read / maintain the code in the future and the benefit of unit tests in each scenario.


tldr;

SOLID assumes, you understand (somewhat atleast), the future changes to the code, wrt SRP. I will say that is being optimistic about capability to predict. YAGNI on the other hand, assumes most of the times you don't know future direction of change, which is pessimistic about capability to predict.

Hence it follows that SOLID/SRP asks you to form classes for the code such that it will have single reason for change. E.g. a small GUI change or ServiceCall change.

YAGNI says (if you want to force apply it in this scenario), since you don't know WHAT is going to change, and if a GUI change will cause a GUI+ServiceCall change (similarly A backend change causing GUI+SeviceCall change), just put all that code in single class.

Long answer :

Read the book 'Agile Software Development, Principles, Patterns, and Practices'

I am putting short excerpt from it about SOLID/SRP : "If,[...]the application is not changing in ways that cause the two responsibilities to change at different times, there is no need to separate them. Indeed, separating them would smell of needless complexity.

There is a corrolary here. An axis of change is an axis of change only if the changes occur. It is not wise to apply SRP—or any other principle, for that matter—if there is no symptom."

참고URL : https://stackoverflow.com/questions/3921904/solid-vs-yagni

반응형