소프트웨어에 추상화가 너무 많고 디자인 패턴이 너무 많거나 더 많은 패턴이 있는지 어떻게 알 수 있습니까?
내가 일하는 개발자는 이러한 점에 대해 다르게 프로그래밍하고 있습니다.
일부는 모든 작은 기능을 추상화하고 가능하면 디자인 패턴을 사용하며 어떠한 비용으로도 중복성을 피합니다.
저를 포함한 다른 사람들은 더 실용적으로 노력하고 모든 디자인 패턴에 완벽하게 맞지 않는 코드를 작성하지만 추상화가 적기 때문에 이해하기가 더 빠릅니다.
나는 이것이 절충안이라는 것을 안다. 프로젝트에 추상화가 충분한 시점을 어떻게 알 수 있습니까? 더 많은 프로젝트가 필요한지 어떻게 알 수 있습니까?
예를 들어, 일반 캐싱 계층이 Memcache를 사용하여 작성된 경우. 우리가 정말 필요합니까 Memcache
, MemcacheAdapter
, MemcacheInterface
, AbstractCache
, CacheFactory
, CacheConnector
, … 또는이 쉽게 유지하기 위해 여전히 좋은 코드는 해당 클래스의 절반 만 사용하는 경우입니까?
트위터에서 찾았습니다.
답변
식사에 필요한 재료는 몇 개입니까? 차량을 만들려면 몇 개의 부품이 필요합니까?
약간의 구현 변경으로 인해 코드 전체에서 일련의 변경 사항이 발생할 때 추상화가 너무 적다는 것을 알고 있습니다. 적절한 추상화는 변경해야 할 코드 부분을 분리하는 데 도움이됩니다.
약간의 인터페이스 변경으로 인해 코드 전체에서 여러 수준으로 일련의 변경 사항이 발생할 때 추상화가 너무 많다는 것을 알고 있습니다. 두 클래스 사이의 인터페이스를 변경하는 대신 속성을 추가하거나 메소드 인수의 유형을 변경하기 위해 수십 개의 클래스와 인터페이스를 수정하는 것을 알게됩니다.
그 외에도, 숫자를 제공하여 질문에 대답 할 수있는 방법은 없습니다. 추상화의 수는 프로젝트마다, 언어에서 다른 언어로, 심지어 한 개발자에서 다른 개발자로 동일하지 않습니다.
답변
디자인 패턴의 문제점은 속담으로 요약 할 수 있습니다. “망치를 잡고 있으면 모든 것이 못처럼 보입니다.” 디자인 패턴 을 적용 해도 프로그램이 개선되지는 않습니다. 실제로 디자인 패턴을 추가하면 더 복잡한 프로그램을 만들고 있다고 주장합니다. 디자인 패턴을 잘 활용하고 있는지 아닌지에 대한 의문이 남아 있으며, 이것이 “언제 추상화가 너무 많습니까?”라는 질문의 핵심입니다.
하나의 단일 구현을위한 인터페이스와 추상 수퍼 클래스를 작성하는 경우 불필요한 불필요한 불필요한 두 개의 컴포넌트를 프로젝트에 추가했습니다. 인터페이스를 제공하는 요점은 작동 방식을 몰라도 프로그램 전체에서 인터페이스를 동일하게 처리 할 수 있다는 것입니다. 추상 슈퍼 클래스의 요점은 구현을위한 기본 동작을 제공하는 것입니다. 만있는 경우 하나의 구현, 모든 합병증 인터페이스와 달마 티아 클래스를 제공하지 얻을 것도 장점.
마찬가지로 팩토리 패턴을 사용하는 경우 수퍼 클래스에서만 사용할 수있는 기능을 사용하기 위해 클래스를 캐스트하는 경우 팩토리 패턴은 코드에 이점을 추가하지 않습니다. 피할 수있는 추가 클래스 만 프로젝트에 추가했습니다.
TL; DR 나의 요점은 추상화의 목표 자체가 추상적이지 않다는 것이다. 그것은 프로그램에서 매우 실용적인 목적을 제공하며 , 디자인 패턴을 사용하거나 인터페이스를 만들기로 결정하기 전에 추가 복잡성에도 불구하고 프로그램이 더 이해하기 쉬운 지 또는 프로그램이 더 강력한 지 스스로에게 묻어 야합니다. 추가적인 복잡성에도 불구하고 (바람직하게는 둘 다). 답이 없거나 어쩌면 몇 분 동안 왜 그렇게하고 싶었는지 고려하고 아마도 코드에 추상화를 추가하지 않고도 더 나은 방법으로 수행 할 수 있습니다.
답변
TL : DR;
나는“필요한”수의 수준의 절제가 아래에 너무 적거나 너무 많다고 생각하지 않습니다. 그래픽 디자인과 마찬가지로, 좋은 OOP 디자인은 보이지 않아야하며 당연한 것으로 여겨 져야합니다. 나쁜 디자인은 항상 아픈 엄지 손가락처럼 튀어 나옵니다.
긴 대답
아마도 당신은 당신이 추상화하고있는 추상화 수준이 얼마나 많은지 모를 것입니다.
대부분의 추상화 수준은 우리에게 보이지 않으며 당연한 것으로 간주합니다.
그 추론은 나를 다음과 같은 결론으로 이끌어줍니다.
추상화의 주요 목적 중 하나는 프로그래머가 시스템의 모든 작업을 항상 염두에 두어야 할 필요성을 줄이는 것입니다. 디자인으로 인해 무언가를 추가하기 위해 시스템에 대해 너무 많이 알면 추상화가 거의 없을 것입니다. 잘못된 추상화 (빈약 한 디자인, 빈약 한 디자인 또는 과도한 엔지니어링)로 인해 무언가를 추가하기에는 너무 많은 지식이 필요하다고 생각합니다. 하나의 극단적 인 경우에는 신 클래스 또는 많은 DTO를 기반으로하는 디자인이 있고, 다른 극단적 인 경우에는 헤아릴 수없는 후프를 뛰어 넘어 안녕하세요 세계를 달성 할 수있는 OR / 지속 프레임 워크가 있습니다. 두 경우 모두 너무 많이 알고 있습니다.
나쁜 추상화는 일단 달콤한 지점을 지나면 방해가되기 시작한다는 사실에서 가우스 벨을 고수합니다. 반면에, 좋은 추상화는 보이지 않으며, 거기에있는 것을 눈치 채지 못하므로 너무 많을 수 없습니다. API, 네트워크 프로토콜, 라이브러리, OS 라이브러리, 파일 시스템, 하웨어 계층 등의 계층에 애플리케이션이 구축되고 당연한 계층 수를 생각하십시오.
추상화의 다른 주요 목적은 구획화 (compartmentation)입니다. 따라서 이중 선체 및 별도의 탱크와 달리 선체의 일부에 구멍이있을 때 배가 완전히 범람하는 것을 방지하지 않고 특정 영역을 넘어서 오류가 침투하지 않습니다. 코드 수정으로 인해 관련이없는 것처럼 보이는 버그 가 발생하는 경우 추상화가 거의 없을 가능성이 있습니다.
답변
디자인 패턴은 문제에 대한 일반적인 해결책입니다. 디자인 패턴을 아는 것이 중요하지만, 잘 설계된 코드의 증상 일뿐입니다 (좋은 코드는 원인이 아니라 4 가지 디자인 패턴 집합에 속하지 않을 수 있습니다).
추상화는 울타리와 같습니다. 프로그램 영역을 테스트 가능하고 교환 가능한 청크로 구분합니다 (깨지기 어려운 비 강성 코드를 만들기위한 요구 사항). 그리고 울타리처럼 :
-
크기를 최소화하기 위해 자연스러운 인터페이스 지점에서 추상화를 원합니다.
-
당신은 그것들을 바꾸고 싶지 않습니다.
-
당신은 그들이 독립적 일 수있는 것들을 분리하기를 원합니다.
-
잘못된 장소에있는 것이없는 것보다 더 나쁩니다.
-
큰 누출 이 없어야합니다 .
답변
리팩토링
지금까지 “리팩토링”이라는 단어가 언급되지 않았습니다. 그래서 여기에 간다 :
새로운 기능을 최대한 직접 구현하십시오. 하나의 단순한 클래스 만있는 경우 인터페이스, 수퍼 클래스, 팩토리 등이 필요하지 않을 수 있습니다.
너무 뚱뚱하게 성장하는 방식으로 수업을 확장하는 것을 눈치 채 셨을 때, 그것을 찢을 때입니다. 당시에는 실제로 어떻게해야하는지 생각하는 것이 좋습니다 .
패턴은 마인드 도구입니다
패턴, 특히 4 명으로 구성된 “디자인 패턴”이라는 책은 개발자가 생각하고 대화 할 수있는 언어를 구축하기 때문에 그 이유가 훌륭합니다. “관찰자”, “공장”또는 “외관”과 모든 사람이 바로 그것이 의미 하는 바를 정확히 알고 있습니다.
따라서 모든 개발자는 최소한 기본 책을 설명하지 않고도 OO 개념에 대해 이야기 할 수 있도록 최소한 원본 책의 패턴에 대한 지식을 전달해야한다고 생각합니다. 실제로 가능성이 나타날 때마다 패턴을 사용해야 합니까? 아마 아닐 것입니다.
도서관
라이브러리는 너무 적은 패턴이 아닌 너무 많은 패턴 기반 선택의 측면에서 오류를 일으킬 수있는 영역 일 수 있습니다. “뚱뚱한”클래스에서 더 많은 패턴 파생 (일반적으로 점점 더 작은 클래스를 의미하는)으로 변경하면 인터페이스가 근본적으로 변경됩니다. 라이브러리에서 변경하고 싶지 않은 것은 라이브러리 사용자에게 유일하게 관심이있는 것이기 때문입니다. 내부적으로 기능을 처리하는 방법에 대해서는 신경 쓰지 않지만 새로운 API로 새 릴리스를 수행 할 때 프로그램을 지속적으로 변경 해야하는 경우 매우 중요합니다.
답변
추상화의 요점은 추상화의 소비자, 즉 추상화의 클라이언트, 다른 프로그래머 및 종종 자신에게 제공되는 가치에 우선해야합니다.
추상화를 소비하는 클라이언트로서 프로그래밍 작업을 수행하기 위해 여러 가지 추상화를 혼합하고 일치시켜야하는 경우 추상화가 너무 많을 수 있습니다.
이상적으로는 계층화가 여러 가지 낮은 추상화를 가져와 소비자가 기본 추상화를 처리하지 않고도 사용할 수있는 단순하고 높은 추상화로 대체해야합니다. 이들이 기본 추상화를 처리해야하는 경우 레이어가 누출됩니다 (불완전한 방식으로). 소비자가 너무 많은 다른 추상화를 처리해야하는 경우 계층화가 누락되었을 수 있습니다.
소비 프로그래머를위한 추상화의 가치를 고려한 후, DRY-ness와 같은 구현을 평가하고 고려할 수 있습니다.
그렇습니다. 유지 보수를 줄이는 것이 중요하지만 우선 품질 추상화와 계층을 제공하여 소비자 유지 보수의 어려움을 고려해야합니다. 그런 다음 중복 방지와 같은 구현 측면에서 자체 유지 보수를 완화하는 것이 좋습니다.
예를 들어, 일반 캐싱 계층이 Memcache를 사용하여 작성된 경우. Memcache, MemcacheAdapter, MemcacheInterface, AbstractCache, CacheFactory, CacheConnector 등이 정말로 필요합니까? 아니면 클래스의 절반 만 사용할 때 유지 관리하기 쉽고 좋은 코드입니까?
우리는 고객의 관점을 살펴 봐야하며, 그들의 삶이 편 해지면 좋습니다. 그들의 삶이 더 복잡하다면 그것은 나쁘다. 그러나 이러한 것들을 사용하기 쉬운 것으로 묶는 누락 된 레이어가있을 수 있습니다. 내부적으로 이것들은 구현의 유지 보수를 훨씬 잘 만들 수 있습니다. 그러나 의심되는 바에 따라 단순히 과도하게 엔지니어링 된 것일 수도 있습니다.
답변
추상화는 코드를 이해하기 쉽게 만들어줍니다. 추상화 계층이 상황을 더 혼란스럽게 만들려면하지 마십시오.
목표는 올바른 수의 추상화 및 인터페이스를 사용하여 다음을 수행하는 것입니다.
- 개발 시간을 최소화
- 코드 유지 보수 극대화
필요할 때만 초록
- 당신이 슈퍼 클래스를 작성하고 있음을 발견했을 때
- 중요한 코드 재사용이 가능한 시점
- 추상화하면 코드가 훨씬 명확하고 읽기 쉬워집니다
때 추상화하지 마십시오
- 그렇게하면 코드 재사용이나 명확성에 이점이 없습니다.
- 그렇게하면 코드가 훨씬 더 길고 복잡 해져서 아무런 이점이 없습니다
몇 가지 예
- 전체 프로그램에서 하나의 캐시 만 가질 예정이라면 수퍼 클래스로 끝날 것이라고 생각하지 않는 한 추상화하지 마십시오.
- 세 가지 유형의 버퍼가있는 경우 공통 인터페이스 추상화를 사용하십시오.