사용자 인터페이스에서 클래스 분리


27

사용자 인터페이스에 대해 알아야 할 클래스를 작성할 때 가장 좋은 방법은 무엇입니까? 사용자 인터페이스가 무엇인지 (콘솔, GUI 등) 의존하기 때문에 모범 사례를 어기는 방법을 아는 클래스가 아닌가?

많은 프로그래밍 서적에서 상속을 보여주는 "Shape"예제를 보았습니다. 기본 클래스 모양에는 원 및 사각형과 같은 각 모양이 재정의하는 draw () 메서드가 있습니다. 이것은 다형성을 허용합니다. 그러나 draw () 메소드가 사용자 인터페이스가 무엇인지에 크게 의존하지 않습니까? 이 클래스를 Win Forms라고 쓰면 콘솔 앱이나 웹 앱에 재사용 할 수 없습니다. 이 올바른지?

질문의 이유는 내가 항상 붙어 있고 클래스를 일반화하는 방법에 매달리기 때문에 가장 유용하기 때문입니다. 이것은 실제로 나를 상대로 일하고 있으며 "너무 열심히 노력하고 있는지"궁금합니다.


왜 분리 하시겠습니까? 그것이 옳은 일이라고 들었거나 다른 이유가 있습니까?
SoylentGray

2
"그 자체를 그리는 법을 아는"전체 클래스는 내가 바라는 끔찍하고 고대의 예일뿐입니다. 특히 게임 프로그래머의 스택에서 =)
Patrick Hughes

2
@ 나는 학교 밖에서 많이 경험하지 못했습니다. 저는 책을 읽었으며 디자인 패턴과 모범 사례에 관한 새로운 것을 배우고 읽는 것을 정말로 좋아합니다. 예, 디커플링이 좋지만 또한 의미가 있다고 들었습니다. 예를 들어 데스크톱 WinForms 앱에 사용할 수있는 코드를 작성하고 해당 코드를 가져 와서 웹 사이트 나 silverlight 앱에 최대한 재사용하고 싶습니다.
Pete

@Pete-좋은 답변입니다.
SoylentGray

2
@Patrick : 공평하게 말하면, Shape클래스를 작성하는 경우 그래픽 스택에 클라이언트를 작성하지 않고 그래픽 스택 자체를 작성하고있을 것입니다.
Ken Bloom

답변:


13

사용자 인터페이스에 대해 알아야 할 클래스를 작성할 때 가장 좋은 방법은 무엇입니까? 사용자 인터페이스가 무엇인지 (콘솔, GUI 등) 의존하기 때문에 모범 사례를 어기는 방법을 아는 클래스가 아닌가?

클래스와 유스 케이스에 따라 다릅니다. 스스로를 그리는 방법을 아는 시각적 요소가 반드시 단일 책임 원칙을 위반하는 것은 아닙니다.

많은 프로그래밍 서적에서 상속을 보여주는 "Shape"예제를 보았습니다. 기본 클래스 모양에는 원 및 사각형과 같은 각 모양이 재정의하는 draw () 메서드가 있습니다. 이것은 다형성을 허용합니다. 그러나 draw () 메소드가 사용자 인터페이스가 무엇인지에 크게 의존하지 않습니까?

다시, 반드시 그런 것은 아닙니다. 인터페이스 (drawPoint, drawLine, Set Color 등)를 만들 수 있다면 모양에 무언가를 그리는 데 필요한 컨텍스트 (예 : 모양의 생성자 내)를 거의 전달할 수 있습니다. 이렇게하면 콘솔이나 주어진 캔버스에 도형을 그릴 수 있습니다.

이 클래스를 Win Forms라고 쓰면 콘솔 앱이나 웹 앱에 재사용 할 수 없습니다. 이 올바른지?

사실입니다. Windows Forms 용 UserControl (일반 클래스는 아님)을 작성하면 콘솔에서 사용할 수 없습니다. 그러나 그것은 문제가되지 않습니다. Windows Forms 용 UserControl이 모든 종류의 프레젠테이션에서 작동하는 이유는 무엇입니까? UserControl은 한 가지 작업을 수행하고 잘 수행해야합니다. 그것은 정의에 의해 특정 형태의 표현에 묶여 있습니다. 결국, 사용자에게는 추상화가 아닌 구체적이 필요합니다. 이는 프레임 워크의 경우에만 일부 해당 될 수 있지만 최종 사용자 응용 프로그램의 경우에는 해당됩니다.

그러나 그 뒤에있는 논리는 분리되어야하므로 다른 프리젠 테이션 기술과 함께 다시 사용할 수 있습니다. 필요한 경우 인터페이스를 도입하여 응용 프로그램의 직교성을 유지하십시오. 일반적인 규칙은 다음과 같습니다. 구체적인 것은 다른 구체적인 것과 교환 할 수 있어야합니다.

질문의 이유는 내가 항상 붙어 있고 클래스를 일반화하는 방법에 매달리기 때문에 가장 유용하기 때문입니다. 이것은 실제로 나를 상대로 일하고 있으며 "너무 열심히 노력하고 있는지"궁금합니다.

익스트림 프로그래머는 야 그니의 태도를 좋아 합니다. 모든 것을 일반적으로 쓰려고 노력하지 말고 모든 것을 일반적인 목적으로 만들려고 노력하지 마십시오. 이를 오버 엔지니어링이라고하며 결국 완전히 복잡한 코드로 이어질 것입니다. 각 구성 요소에 정확히 하나의 작업을 제공하고 올바르게 수행하십시오. 필요한 곳에서 변경 될 것으로 예상되는 곳에 추상화를 넣습니다 (예 : 위에서 언급 한 상황을 그리기위한 인터페이스).

일반적으로 비즈니스 응용 프로그램을 작성할 때는 항상 분리해야합니다. MVC와 MVVM은 프리젠 테이션에서 로직을 분리하는 데 유용하므로 웹 프리젠 테이션 또는 콘솔 애플리케이션에 로직을 재사용 할 수 있습니다. 결국에는 어떤 것이 구체적이어야한다는 것을 명심하십시오. 사용자는 추상화로 작업 할 수 없으며 구체적이어야합니다. 추상화는 프로그래머가 코드를 확장 가능하고 유지 관리 할 수 ​​있도록 돕는 도우미 일뿐입니다. 융통성있게 코드가 필요한 위치를 고려해야합니다. 결국 모든 추상화는 구체적인 무언가를 낳아야합니다.

편집 : 모범 사례를 제공 할 수있는 아키텍처 및 설계 기술에 대한 자세한 내용을 보려면 @Catchops 답변을 읽고 Wikipedia의 SOLID 사례에 대해 읽어보십시오 .

또한 초보자를 위해 항상 다음과 같은 책을 추천합니다. Head First Design Patterns . GoF 서적 (초보자에게는 적합하지 않음)보다 추상화 기술 / OOP 디자인 실습을 이해하는 데 도움이됩니다.


1
좋은 대답이지만 극단적 인 프로그래머는 ' 변화 가 예상 되는 곳에 추상화를 넣지 않습니다 '. 우리 는 코드를 건조시키기 위해 상황 바뀌는 추상화를 넣었 습니다.
케빈 클라인

1
@kevin cline은 이전 동작 및 인터페이스를 준수해야하는 API를 사용하여 공개적으로 사용 가능한 라이브러리를 디자인하지 않는 한 훌륭합니다.
Magnus Wolffelt

@ Magnus-예, 일부 언어로 라이브러리를 디자인하고 이전 바이너리 호환성을 계획하는 것은 까다 롭습니다. 하나는 미래의 확장을 위해 현재 불필요한 모든 종류의 코드를 작성해야합니다. 이것은 금속으로 컴파일되는 언어에 적합 할 수 있습니다. 가상 머신으로 컴파일되는 언어는 어리 석습니다.
케빈 클라인

19

당신은 확실히 맞습니다. 그리고 아니, 당신은 "그냥 잘하고 있습니다":)

단일 책임 원칙 에 대해 읽으십시오

수업의 내부 작업과이 정보를 사용자에게 제공하는 방법은 두 가지 책임입니다.

수업을 분리하는 것을 두려워하지 마십시오. 드물게 문제는 너무 많은 추상화와 디커플링입니다 :)

웹 애플리케이션을위한 Model-View-Controller 와 Silverlight / WPF를위한 Model View ViewModel의 두 가지 관련 패턴이 있습니다 .


1
+1 웹이 아닌 응용 프로그램에 MVC를 사용할 수도 있습니다. 최소한 책임을 명확하게하는 관점에서 생각하는 데 도움이됩니다.
패트릭 휴즈

MVVM은 MVC에 대한 규범입니다. MVC는 주로 웹 앱과 같은 상태 비 저장 응용 프로그램을위한 것입니다.
보리스 얀 코프

3
-1 내 경험에서 가장 일반적인 문제 중 하나는 일반적으로 조기 일반화 및 과도 엔지니어링입니다.
dietbuddha

3
과도하게 엔지니어링하려면 무언가를 어떻게 엔지니어링해야하는지 알아야합니다. 내 경험상 사람들은 엔지니어가 아닌 소프트웨어를 훨씬 더 자주 사용합니다.
보리스 얀 코프

소프트웨어 디자인을 개선하려는 노력에 감사하지만, 인터페이스에서 호출을 클래스 호출로 대체해도 의미 상 분리되지 않습니다. 동적으로 유형이 지정된 언어를 사용할 때 어떤 일이 발생하는지 고려하십시오. 스택 교환의 프로그래머 섹션에서 제공되는 조언에서 피상적 (구문 적) 디커플링에 대해서는 너무 강조하고 진정한 디커플링에는 거의 강조하지 않습니다.
Frank Hileman

7

나는 MVVM을 많이 사용하며 비즈니스 객체 클래스는 사용자 인터페이스에 대해 전혀 알 필요가 없습니다. 물론 SelectedItem, 또는 IsChecked, 또는 IsVisible등 을 알아야 할 수도 있지만 이러한 값은 특정 UI에 연결될 필요가 없으며 클래스의 일반 속성 일 수 있습니다.

Focus 설정, 애니메이션 실행, 단축키 처리 등과 같은 코드 숨김 인터페이스에서 무언가를 수행해야하는 경우 코드는 비즈니스 로직 클래스가 아닌 UI의 코드 숨김의 일부 여야합니다.

따라서 UI와 클래스를 분리하려고 시도하지 마십시오. 연결이 끊어 질수록 유지 관리 및 테스트가 쉬워집니다.


5

당신이 말하는 것을 정확하게 다루기 위해 수년에 걸쳐 개발 된 많은 시도되고 진정한 디자인 패턴이 있습니다. 귀하의 질문에 대한 다른 답변은 단일 책임 원칙 ( 이것은 절대적으로 유효 함)과 귀하의 질문을 주도하는 것입니다. 그 원칙은 단순히 수업이 한 가지 일을 잘해야한다고 말합니다. 다시 말해, 응집력을 높이고 결합을 낮추는 것은 객체 지향 디자인이 좋은 것입니다. 클래스는 한 가지 일을 잘 수행하고 다른 것에 의존하지 않습니다.

글쎄 ... 당신은 iPhone에 원을 그리려면 Windows를 실행하는 PC에서 원을 그리는 것과 다를 것입니다. 당신은 (이 경우) 하나는 iPhone에서 잘 그리는 것과 다른 하나는 PC에서 잘 그리는 구체적인 클래스를 가져야합니다. 이 모든 형태의 예제가 제공하는 기본 상속 OO 테넌트가 여기에 있습니다. 상속만으로는 단순히 할 수 없습니다.

4 개의 갱 상태 (MUST READ) 와 같이 인터페이스가 들어오는 곳 입니다. 상속보다 항상 구현을 선호합니다. 다시 말해, 인터페이스를 사용하여 하드 코딩 된 종속성에 의존하지 않고 다양한 방식으로 다양한 기능을 수행 할 수있는 아키텍처를 구성 할 수 있습니다.

나는 SOLID 원칙 에 대한 참조를 보았다 . 그것들은 훌륭합니다. 'S'는 단일 책임 원칙입니다. 그러나 'D'는 종속성 반전을 나타냅니다. 제어 패턴 반전 (종속 주입)을 여기에서 사용할 수 있습니다. 그것은 매우 강력하며 PC뿐만 아니라 iPhone의 원을 그릴 수있는 시스템을 설계하는 방법에 대한 질문에 답할 수 있습니다.

일반적인 비즈니스 규칙과 데이터 액세스가 포함 된 아키텍처를 만들 수 있지만 이러한 구성을 사용하여 다양한 사용자 인터페이스 구현이 있습니다. 그러나 실제로 그것을 구현 한 팀에 참여하고 실제로 이해하는 것이 실제로 도움이되는 것이 도움이됩니다.

보다 자세한 답변이 필요한 질문에 대한 빠른 답변입니다. 이러한 패턴에 대해 자세히 살펴 보시기 바랍니다. 이러한 패턴의보다 구체적인 구현은 MVC 및 MVVM의 잘 알려진 이름으로 볼 수 있습니다.

행운을 빕니다!


나는 누군가 (물론 풍자)에 대해 언급하지 않고 무언가를 공감 할 때 그것을 좋아합니다. 내가 말한 원칙은 사실입니다. downvoter가 일어 서서 왜 그런지 말하십시오.
Catchops

2

사용자 인터페이스에 대해 알아야 할 클래스를 작성할 때 가장 좋은 방법은 무엇입니까?

사용자 인터페이스가 무엇인지 (콘솔, GUI 등) 의존하기 때문에 모범 사례를 어기는 방법을 아는 클래스가 아닌가?

이 경우에도 여전히 MVC / MVVM을 사용하고 공통 인터페이스를 사용하여 다른 UI 구현을 삽입 할 수 있습니다.

public interface IAgnosticChartDrawing
{
   public void Draw(ChartProperties chartProperties);
   event EventHandler ChartPanned;
}

public class GuiChartDrawer : UserControl, IAgnosticChartDrawing
{
    public void Draw(ChartProperties chartProperties)
    {
        //GDI, GTK or something else...
    }

    //Implement event based on mouse actions
}

public class ConsoleChartDrawer : IAgnosticChartDrawing
{
    public void Draw(ChartProperties chartProperties)
    {
        //'Draw' using characters and symbols...
    }

    //Implement event based on keyboard actions
}

IAgnosticChartDrawing guiView = new GuiChartDrawer();
IAgnosticChartDrawing conView = new ConsoleChartDrawer();

Model model = new FinancialModel();

SampleController controllerGUI = new SampleController(model, guiView);
SampleController controllerConsole = new SampleController(model, conView);

이렇게하면 새로운 유형의 GUI를 추가 할 수있을 때 컨트롤러 및 모델 논리를 재사용 할 수 있습니다.


2

MVP, MVC, MVVM 등 다양한 패턴이 있습니다.

Martin Fowler (큰 이름)가 읽은 좋은 기사는 GUI 아키텍처입니다. http://www.martinfowler.com/eaaDev/uiArchs.html

MVP는 아직 언급되지 않았지만 인용 할 가치가 있습니다. 살펴보십시오.

Google Web Toolkit 개발자가 사용하도록 제안한 패턴입니다. 정말 깔끔합니다.

이 방법이 왜 유용한 지에 대한 실제 코드, 실제 예제 및 이론적 근거를 찾을 수 있습니다.

http://code.google.com/webtoolkit/articles/mvp-architecture.html

http://code.google.com/webtoolkit/articles/mvp-architecture-2.html

여기에 충분히 강조되지 않은 이러한 또는 유사한 접근법을 따르는 장점 중 하나는 테스트 가능성입니다! 많은 경우에 나는 그것이 주요 이점이라고 말할 것입니다!


1
링크는 +1입니다. MVVM에 대해 MSDN에서 비슷한 기사를 읽었으며 Google 기사는 약간 다른 패턴으로 훨씬 나아졌습니다.
Pete

1

이것은 OOP 추상화에서 잘하지 못하는 곳 중 하나입니다 . OOP 다형성은 단일 변수 ( 'this')에 대해 동적 디스패치를 ​​사용합니다. 다형성이 Shape에 기반한 경우 렌더러 (콘솔, GUI 등)에서 다형성으로 디스패치 할 수 없습니다.

두 개 이상의 변수를 전달할 수있는 프로그래밍 시스템을 고려하십시오.

poly_draw(Shape s, Renderer r)

또한 시스템이 Shape 유형과 Renderer 유형의 다양한 조합에 대해 poly_draw를 표현할 수있는 방법을 제공한다고 가정합니다. 그러면 셰이프와 렌더러를 분류하는 것이 쉬울까요? 타입 체커는 당신이 구현을 놓친 모양과 렌더러 조합이 있는지 알아내는 데 도움이 될 것입니다.

대부분의 OOP 언어는 위와 같은 것을 지원하지 않습니다 (일부 언어는 주류가 아닙니다). 해결 방법 에 대한 방문자 패턴 을 살펴 보는 것이 좋습니다 .


1

... draw () 메소드가 사용자 인터페이스가 무엇인지에 크게 의존하지 않습니까? 이 클래스를 Win Forms라고 쓰면 콘솔 앱이나 웹 앱에 재사용 할 수 없습니다. 이 올바른지?

위의 소리가 맞습니다. 내 이해에 따르면 MVC 디자인 패턴 측면에서 ControllerView 사이의 상대적으로 긴밀한 결합을 의미한다고 말할 수 있습니다 . 이것은 또한 desktop-console-webapp 사이를 전환하기 위해서는 Controller와 View 를 쌍으로 전환해야한다는 것을 의미합니다 . 모델 만 변경되지 않습니다.

... 항상 클래스를 일반화하는 방법에 항상 얽매여서 가장 유용합니다.

현재 제가 생각하고있는이 View-Controller 커플 링 은 정상이며, 더 현대적인 디자인에서는 다소 트렌디 합니다.

1 년 또는 2 년 전에 나는 그것에 대해 불안감을 느꼈습니다. Sun 포럼에서 패턴 및 OO 디자인에 대한 토론을 공부 한 후에 마음이 바뀌 었습니다.

관심이 있으시면이 포럼을 직접 사용해보십시오.이 포럼은 지금 Oracle로 마이그레이션되었습니다 ( link ). 거기에 가면 Saish 핑 핑을 시도하십시오. 당시에는 까다로운 문제에 대한 그의 설명이 가장 도움이되었습니다. 그가 여전히 참여하고 있는지 알 수는 없습니다-나 자신은 꽤 오랫동안 거기에 없었습니다.


1

그러나 draw () 메소드가 사용자 인터페이스가 무엇인지에 크게 의존하지 않습니까?

실용적인 관점에서 시스템의 일부 코드 Rectangle는 사용자 엔드 요구 사항 인 경우 와 같은 것을 그리는 방법을 알아야합니다 . 그리고 픽셀을 래스터 화하거나 콘솔에 무언가를 표시하는 것과 같은 저수준 작업을 수행하기 위해 어느 시점에서 정리 될 것입니다.

커플 링 관점에서 나에게 질문은 누가 / 무엇이 이런 유형의 정보에 의존해야하며, 어느 정도의 세부 사항 (예를 들어, 추상적인가)에 달려 있는가?

드로잉 / 렌더링 기능 추상화

더 높은 수준의 드로잉 코드가 매우 추상적 인 것에 의존한다면, 추상화는 대상으로 삼고 자하는 모든 플랫폼에서 (구체적인 구현의 대체를 통해) 작동 할 수 있습니다. 고안된 예로서, 매우 추상적 인 일부 IDrawer인터페이스는 플롯 모양과 같은 작업을 수행하기 위해 콘솔과 GUI API 모두에서 구현 될 수 있습니다 (콘솔 구현은 콘솔을 ASCII 아트의 80xN "이미지"처럼 처리 할 수 ​​있습니다). 물론 그것은 당신이 원하는 것은 아니지만 이미지 / 프레임 버퍼처럼 콘솔 출력을 다루는 것이기 때문에 고안된 예입니다. 일반적으로 대부분의 사용자 엔드는 콘솔에서 더 많은 텍스트 기반 상호 작용을 요구합니다.

또 다른 고려 사항은 안정적인 추상화를 설계하는 것이 얼마나 쉬운가 입니다. 타겟팅하는 모든 것이 현대적인 GUI API라면 선, 사각형, 경로, 텍스트, 이런 종류의 것들을 그리는 것과 같은 기본 모양 그리기 기능을 추상화하는 것이 쉬울 수 있기 때문에 (제한된 프리미티브 세트의 간단한 2D 래스터 화) 적은 비용으로 다양한 하위 유형을 통해 쉽게 구현할 수있는 하나의 추상 인터페이스가 있습니다. 그러한 추상화를 효과적으로 설계하고 모든 대상 플랫폼에서 구현할 수 있다면, 모양이나 GUI 제어 또는 그러한 추출.

그러나 Playstation Portable, iPhone, XBox One 및 강력한 게임 PC 사이에서 다양하고 까다로운 세부 사항을 추상화하려고하지만 각 요구 사항에 대해 최첨단 실시간 3D 렌더링 / 음영 처리 기술을 사용해야합니다 . 이 경우 기본 하드웨어 기능과 API가 너무 다양 할 때 렌더링 세부 사항을 추상화하기 위해 하나의 추상 인터페이스를 만들려고 시도하면 엄청난 시간의 설계 및 재 설계가 발생할 것으로 예상됩니다. 디스커버리와 마찬가지로 기본 하드웨어의 전체 고유성과 성능을 활용하지 못하는 최저 공통 분모 솔루션입니다.

안정적인 "쉬운"디자인으로 종속성을 전달

내 분야에서 나는 마지막 시나리오에 있습니다. 우리는 근본적으로 다른 기본 기능과 API를 가진 많은 다른 하드웨어를 목표로 삼고, 하나의 렌더링 / 그리기 추상화를 시도하여 그것들을 모두 결정하는 것은 경계가없는 것입니다 (우리는 게임처럼 효과적으로하는 것이 세계적으로 유명해질 수 있습니다) 업계의 체인저). 그래서 필자의 경우 마지막으로 원하는 것은 유추와 ShapeModel거나 Particle Emitter그 그림을 최고 수준의 가장 추상적 인 방법으로 표현하더라도 그 자체를 그리는 방법을 알고 있습니다 ...

... 추상화는 제대로 설계하기가 너무 어렵고 설계가 정확하지 않고 모든 것이 그에 의존하기 때문에 가장 비용이 많이 드는 중앙 설계 변경에 따라 모든 것이 파열되고 끊어집니다. 따라서 마지막으로 원하는 것은 시스템의 종속성이 추상 디자인으로 흘러 들어가기에는 너무 어렵습니다.

어려움은 쉽지 않다, 쉽지 않다 쉽지 않다

따라서 우리가하는 일은 의존성이 디자인하기 쉬운 것들을 향해 흐르게하는 것입니다. 다각형 및 재질과 같은 것을 저장하는 데 중점을두고 추상적 인 "모델"을 설계하는 것이 훨씬 쉬우 며 서비스 도면에 효과적으로 대체 할 수있는 추상 "렌더러"를 설계하는 것보다 정확한 설계를 얻는 것 PC에서 PSP와 다른 하드웨어에 대해 균일하게 요청합니다.

여기에 이미지 설명을 입력하십시오

따라서 우리는 의존성을 설계하기 어려운 것들과 반대 방향으로 뒤집습니다. 추상 모델이 모두 자신이 의존하는 추상 렌더러 디자인으로 자신을 그리는 방법을 알도록하는 대신 (디자인이 변경되면 구현이 중단되는 대신) 장면에서 모든 추상 객체를 그리는 방법을 알고있는 추상 렌더러가 있습니다 ( 모델, 파티클 이미 터 등), PC와 같은 PC RendererGl, PSP RendererPsp, 휴대 전화 등 의 OpenGL 렌더러 하위 유형을 구현할 수 있습니다 .이 경우 종속성은 안정적인 디자인으로 흘러 가기 쉬우 며, 렌더러에서 장면의 다양한 유형의 엔티티 (모델, 파티클, 텍스처 등)에 이르기까지, 다른 방식은 아닙니다.

여기에 이미지 설명을 입력하십시오

  • 나는 '안정성 / 불안정성'을 밥 아저씨의 구 심성 / 친 화성 결합 측정법과 약간 다른 의미로 사용하고 있는데, 이것은 내가 이해할 수있는 한 변화의 어려움을 더 측정하고 있습니다. 그의 안정성 지표는 유용하지만 "변화가 필요할 확률"에 대해 더 이야기하고 있습니다. "변경 가능성"이 "변경 용이성"에 비례 할 때 (예 : 변경이 필요할 가능성이 가장 높은 것이 불안정하고, Uncle Bob의 메트릭에서 구 심성있는 커플 링을 갖는 경우), 그러한 가능한 변경은 저렴하고 방해가되지 않습니다. 중앙 디자인을 건드리지 않고 구현 만 교체하면됩니다.

코드베이스의 중앙 레벨에서 무언가를 추상화하려고 시도하고 디자인하기가 너무 어렵다면, 벽에 고집스럽게 머리를 두드리고 매월 / 년마다 지속적으로 변경하여 8,000 개의 소스 파일을 업데이트해야하므로 소스 파일을 업데이트해야합니다. 그것에 의존하는 모든 것을 깨뜨리는 나의 가장 큰 제안은 의존성을 뒤집는 것을 고려하는 것입니다. 디자인하기 어려운 것이 디자인하기 쉬운 것에 의존하지 않고 디자인하기 어려운 것에 의존하지 않고 디자인하기 쉬운 모든 것에 의존하는 방식으로 코드를 작성할 수 있는지 확인하십시오. 구현에 대한 것이 아니라 디자인 (특히 인터페이스 디자인)에 대해 이야기하고 있습니다. 때로는 디자인하기 쉽고 구현하기가 어렵습니다. 때로는 디자인하기가 어렵지만 구현하기도 쉽습니다. 의존성은 디자인을 향하여 흐르므로 의존성이 흐르는 방향을 결정하기 위해 무언가를 디자인하는 것이 얼마나 어려운지에만 초점을 두어야합니다.

단일 책임 원칙

나에게 SRP는 일반적으로 (컨텍스트에 따라 다르지만) 그렇게 흥미롭지 않습니다. 의도적으로 명확하고 유지 관리가 가능한 것을 디자인하는 줄타기 균형 조정법이 있지만 Shape객체가 예를 들어 자신을 그리는 방법을 모르면 더 자세한 정보를 노출해야 할 수도 있습니다. 특정 사용 컨텍스트에서 구성하고 구성하는 것보다 모양을 사용하십시오. 거의 모든 것과의 상충 관계가 있으며 특정 상황에서 내 경험에서 그러한 유지 보수의 악몽이 될 수있는 방법을 알 수있는 SRP와 관련이 없습니다.

커플 링 및 시스템에서 종속성이 흐르는 방향과 더 관련이 있습니다. 모든 것이 의존하는 추상 렌더링 인터페이스를 새로운 타겟 API / 하드웨어에 이식하려고 시도하고 효과적으로 작동하도록 디자인을 변경해야한다는 것을 알고 있다면 그것은 시스템을 만드는 방법을 알고있는 시스템의 모든 구현을 교체해야하는 비용이 많이 드는 변경입니다. 그리고 그것은 내가 올바르게 설계하기가 너무 어려운 추상화로 흘러가는 의존성의 보트로드로 변환된다면 스스로를 그리는 방법을 알고있는 것들과 관련하여 가장 실질적인 유지 보수 문제입니다.

개발자 자부심

필자가 경험 한 바에 따르면, 이는 의존성 방향을 설계하기 쉬운 것들로 옮기는 데 가장 큰 장애물이되기 때문에 종종 언급한다. 개발자들이 여기에서 약간의 야심을 갖고 말하기를 매우 쉽습니다. "저는 플랫폼 간 렌더링 추상화를 설계하여 모든 것을 지배 할 것입니다. 다른 개발자들이 몇 달 동안 포팅에 소비 한 것을 해결할 것입니다. "우리가 지원하는 모든 단일 플랫폼에서 마술처럼 작동 할 것입니다. 모든 플랫폼에서 최첨단 렌더링 기술을 사용하고 있습니다. 이미 머리 속에 상상했습니다."어떤 경우에 그들은 그것을 피하고 의존성의 방향을 뒤집어 놓고 막대한 비용과 반복적 인 중앙 설계 변경을 구현에 대한 저렴하고 로컬 반복 변경으로 변환하는 실제 솔루션에 저항합니다. 개발자가 추상적 인 수준으로 디자인하기가 너무 어려울 때 포기하고 전체 전략을 재고해야 할 경우에는 일종의 "백기"본능이 있어야합니다. 그렇지 않으면 많은 슬픔과 고통에 빠지게됩니다. 이러한 야심과 투쟁을 세계를 정복하려는 야심을 인터페이스 디자인 수준으로 가져가는 것보다 설계하기 쉬운 최신 구현 방식으로 전환하는 것이 좋습니다.


1
나는 "디자인하기 어려운 것들로부터 의존성을 뒤집는 것"이라는 생각을 이해하지 못하는 것 같습니다. 상속에 대해서만 이야기하고 있습니까? PSP / OpenGL을의 예를 사용하여, 당신은 대신이 만드는 말은 OpenGLBillboard, 당신은 할 줄 OpenGLRenderer알고 그 방법의 모든 유형을 그릴 IBillBoard? 그러나 논리를 위임하여 그렇게합니까 IBillBoard, 아니면 IBillBoard조건부 가있는 거대한 스위치 또는 유형이 있습니까? 그것이 내가 유지하기 어려운 것처럼 보이기 때문에 내가 이해하기가 어렵습니다!
Steve Chamaillard

@SteveChamaillard 차이점은 PSP (제한된 하드웨어)가 구식 스크린 도어 투명성과 다른 렌더링 평가 순서 ( digitalrune.github.io/DigitalRune-Documentation/media/…)를 사용하여 볼륨 프리미티브를 처리해야한다는 것 입니다. RendererPsp게임 장면의 높은 수준의 추상화를 알고 있는 하나의 중심 이 있으면 PSP에 설득력있는 방식으로 그러한 일을 렌더링하는 데 필요한 모든 마술과 역전을 할 수 있습니다 ....
Dragon Energy

이러한 볼륨 프리미티브가 자신을 렌더링하도록 요청하는 경우, 해당 작업은 기본적으로 렌더링하도록 자신을 지정하는 것 (왕복 중복 및 추가 커플 링을 제외하고는 차이가 없음)이거나 렌더러 추상화가 실제로 불가능합니다. PSP에서 가능한 가장 효과적인 방법을 수행합니다 (적어도 백 플립을 수행하지 않고 종속성이 반전 된 경우 필요하지 않음).
드래곤 에너지

1
알았어. 이제 알았어. 기본적으로 당신은 그러한 우려 (즉, 하드웨어)가 너무 높아서 BillBoard그것들에 의존하는 것과 같은 저수준 물체를 만드는 것이 실제로 어렵다는 것을 말하고 있습니까? 반면에 a IRenderer는 이미 높은 수준이며 훨씬 적은 문제로 이러한 문제에 의존 할 수 있습니까?
Steve Chamaillard

1
이종 플랫폼, 이종 하드웨어 기능에 대한 최첨단 렌더링 문제로 인해 내가 사장 인 무언가를 디자인하고 무엇을해야하는지 말하기가 너무 어렵습니다. "이봐, 나는 이처럼 회색의 물이 많은 입자로 흐리고 안개가 자욱 해 보이고, 내가 최근에 면도하지 않은 목을 사로 잡지 말고 기분 좋게 보이도록 노력하십시오.", 렌더러가 작업하는 제한 사항을 고려하여 가능한 한 아름답고 실시간으로 나를 렌더링하는 방법을 알아 보겠습니다. 무엇을해야하는지에 대한 모든 시도는 거의 확실하게 비생산적인 경로를 초래할 것입니다.
드래곤 에너지
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.