커플 링. 모범 사례


11

이 실에서 나는 시작했다

싱글 톤 패턴

수업이 얼마나 결합되어 있고 느슨한 결합을 달성하는 가장 좋은 방법에 대해 생각하게되었습니다. 나는 새로운 프로그래머 (제 첫 직업에 4 개월)라는 것을 명심하십시오. 이것이 제가 처음으로 고려한 것이므로 개념을 이해하기를 매우 열심입니다.

그렇다면 느슨한 결합과 무거운 결합은 정확히 무엇입니까? 현재 (그리고 첫 번째 프로젝트), ac # winforms 프로젝트에서 작업하고 있습니다. GUI 섹션은 이벤트에 대한 객체와 서브 크리 브를 생성하고 트리거 될 때 GUI가 다른 객체 (이 예에서는 datagridview (클래스)를 만듭니다. 내가 만든 것은 표준 데이터 그리드 뷰를 감싸고 추가 기능을 추가하고 GUI에 첨부하는 것입니다.

나는 나쁜 습관에 빠져 코딩을 제대로 시작하고 싶지 않기 때문에 귀하의 답변에 감사드립니다.

답변:


11

여기에 코드를 느슨하게 결합시키기 위해 기억해야 할 몇 가지 간단한 사항이 있습니다.

1 부:

기술적으로 "문제의 분리"라고합니다. 각 클래스에는 특정 역할이 있으며 비즈니스 논리 또는 응용 프로그램 논리를 처리해야합니다. 두 가지 책임을 모두 갖춘 수업에서 벗어나도록 노력하십시오. 즉, 데이터를 관리하는 클래스는 애플리케이션 로직이고 데이터를 사용하는 클래스는 비즈니스 로직입니다.

개인적으로 나는 이것을 (내 자신의 작은 세계에서)로 언급합니다 create it or use it. 클래스는 객체를 생성하거나 절대 사용하지 않아야하는 객체를 사용해야합니다.

2 부:

우려 분리를 구현하는 방법.
시작점으로 두 가지 간단한 기술이 있습니다.

참고 : 디자인 패턴은 절대적이지 않습니다.
상황에 맞게 사용자 정의해야하지만 모든 응용 프로그램과 유사한 기본 테마를 갖습니다. 따라서 아래의 예를 보지 말고 이것을 엄격하게 따라야한다고 말하십시오. 이것들은 단지 예일뿐입니다.

의존성 주입 :

여기에서 클래스가 사용하는 객체를 전달합니다. 인터페이스를 기반으로 전달하는 객체는 클래스와 함께 무엇을해야하지만 실제 구현을 알 필요는 없습니다.

class Tokenizer
{
    public:
        Tokenizer(std::istream& s)
            : stream(s)
        {}
        std::string nextToken() { std::string token; stream >> token;return token;}
    private:
        std::istream& stream;
};

여기서 스트림을 토큰 화기에 주입합니다. 토크 나이 저는 std :: istream의 인터페이스를 구현하는 한 스트림이 어떤 유형인지 알지 못합니다.

서비스 로케이터 패턴 :

서비스 로케이터 패턴은 종속성 주입에서 약간의 변형입니다. 사용할 수있는 객체를 제공하는 대신 사용하려는 객체를 찾는 방법을 알고있는 객체를 전달합니다.

class Application
{
     public:
         Application(Persister& p)
             : persistor(p)
         {}

         void save()
         {
             std::auto_ptr<SaveDialog> saveDialog = persistor.getSaveDialog();
             saveDialog.DoSaveAction();
         }

         void load()
         {
             std::auto_ptr<LoadDialog> loadDialog = persistor.getLoadDialog();
             loadDialog.DoLoadAction();
         }
    private:
        Persister& persistor;
};

여기서 우리는 애플리케이션 객체를 영속 객체로 전달합니다. 저장 /로드 조치를 수행 할 때 지속자를 사용하여 실제로 조치 수행 방법을 알고있는 오브젝트를 작성합니다. 참고 : 다시 지속자는 인터페이스이며 상황에 따라 다른 구현을 제공 할 수 있습니다.

potentially작업을 인스턴스화 할 때마다 고유 한 개체가 필요할 때 유용 합니다.

개인적으로 이것은 단위 테스트 작성에 특히 유용합니다.

패턴 노트 :

디자인 패턴은 그 자체로 큰 주제입니다. 이것은 느슨한 결합을 돕기 위해 사용할 수있는 독점적 인 패턴 목록이 아닙니다. 이것은 일반적인 출발점입니다.

경험을 통해 이미 이러한 패턴을 사용하고 있다는 것을 알게 될 것입니다. 우리는 그들의 이름을 표준화하고 모든 사람들이 그것들을 배우게함으로써 아이디어를 쉽고 빠르게 전달할 수 있다는 것을 알게되었습니다.


3
@Darren Young : 받아 주셔서 감사합니다. 그러나 당신의 질문은 3 시간 밖에되지 않았습니다. 나는 하루 안에 돌아와 다른 사람들이 더 나은 답변을 제공하지 않았 음을 확인합니다.
Martin York

훌륭한 답변 감사합니다. 우려 분리에 대해 .... 사용하기 위해 데이터가 필요한 클래스가 있으며 해당 데이터로 무언가를 수행합니다. 이것은 과거에 수업을 디자인 한 방법입니다. 따라서 데이터를 가져 와서 올바른 형식으로 조정 한 다음 다른 클래스에서 실제로 데이터를 사용하는 클래스를 만드는 것이 더 좋을까요?
대런 영

@Darren Young : 모든 프로그래밍과 마찬가지로 선이 회색이며 흐릿하게 정의되지 않습니다. 코드를 읽지 않고 정확한 응답을하기는 어렵습니다. 그러나 내가 이야기 할 때 managing the data변수 (실제 데이터가 아닌)를 참조하고 있습니다. 따라서 포인터가 누출되지 않도록 포인터와 같은 것을 관리해야합니다. 그러나 데이터를 주입하거나 데이터를 검색하는 방법을 추상화 할 수 있으므로 클래스를 다른 데이터 검색 방법으로 재사용 할 수 있습니다. 더 정확하지 못해 죄송합니다.
Martin York

1
@Darren Young : @StuperUser가 그의 답변에서 언급 한대로. 배 밖으로 나가지 마십시오 (AKA minutae of loose coupling(minutae라는 단어를 좋아합니다)). 프로그래밍의 비밀은 기술을 사용할 때 배우는 것입니다. 과도하게 사용하면 코드가 복잡해질 수 있습니다.
Martin York

@Martin-조언 주셔서 감사합니다. 나는 그것이 현재 어려움을 겪고있는 곳이라고 생각합니다 ..... 코드의 아키텍처에 대해 끊임없이 걱정하고 C #을 사용하는 특정 언어를 배우려고합니다. 나는이 물건을 배우고 싶은 경험과 욕구가 올 것이라고 생각합니다. 당신의 의견에 감사드립니다.
대런 영

6

저는 ASP.NET 개발자이므로 WinForms 커플 링에 대해 잘 모르지만 UI, 도메인, DAL (Domain, Data Access Layer)의 3 계층 응용 프로그램 아키텍처를 가정하면 N-Tier 웹 응용 프로그램에서는 조금 알고 있습니다.

느슨한 결합은 추상화에 관한 것입니다.

@MKO에 따르면 어셈블리를 다른 어셈블리 (예 : 도메인 프로젝트를 사용하는 새 UI 프로젝트, 데이터베이스가 아닌 스프레드 시트에 저장하는 새 DAL)로 교체 할 수 있으면 연결이 느슨합니다. 도메인과 DAL이 체인 아래로 떨어진 프로젝트에 의존하는 경우 커플 링이 느슨해 질 수 있습니다.

느슨하게 결합 된 것의 한 측면은 객체를 동일한 인터페이스를 구현하는 다른 것으로 교체 할 수 있는지 여부입니다. 실제 객체에 의존하지 않지만 그 기능에 대한 추상적 인 설명 (인터페이스).
느슨한 커플 링, 인터페이스 및 종속성 인젝터 (DI) 및 IoC (Inversion of Control)는 테스트 가능성을위한 디자인의 격리 측면에 유용합니다.

예를 들어 UI 프로젝트의 객체는 도메인 프로젝트의 리포지토리 객체를 호출합니다.
당신은 만들 수 있습니다 가짜의 구현은 테스트 용도에 따라 코드가 다음 시험 (특별 행동 작성하는 것이 저장소와 같은 인터페이스하는 개체를 스텁 저장 프로덕션 코드 / 삭제를 방지하기위한이 / 전화를하고 도착 모의 객체 의 스텁으로 행동한다는 추적 테스트 목적으로 위조 객체의 상태).
즉, 호출되는 유일한 프로덕션 코드는 이제 UI 객체에만 있으며 테스트는 해당 메소드에만 적용되며 테스트 실패는 해당 메소드에 대한 결함을 분리합니다.

또한 VS의 분석 메뉴 (사용하는 버전에 따라 다름)에는 프로젝트에 대한 코드 메트릭을 계산하는 도구가 있으며 그 중 하나는 클래스 커플 링이며 MSDN 설명서에 이에 대한 자세한 정보가 있습니다.

하지 마세요 TOO은 NO의 기회 일을 (하나 이상의 UI를 예를 들어 도메인 프로젝트)를 다시 얻을 수 있습니다 및 제품의 수명이 작다는 사실이 있다면, 비록 느슨한 결합의 minutae에서 수렁에 빠져, 다음 느슨한 결합은 이하가 우선 순위 (여전히 고려 될 것임)이지만 코드를 검토 할 건축가 / 기술 책임자의 책임입니다.


3

커플 링은 한 클래스가 다른 클래스에 대한 직접적인 지식의 정도를 나타냅니다 . 이것은 캡슐화 대 비 캡슐화로 해석되지 않습니다. 다른 클래스의 속성이나 구현에 대한 한 클래스의 지식에 대한 참조가 아니라 다른 클래스 자체에 대한 지식입니다. 종속 클래스에 필요한 동작을 제공하는 구체적 클래스에 대한 포인터가 포함 된 경우 강력한 결합이 발생합니다. 종속 클래스를 변경할 필요없이 종속성을 대체하거나 "서명"을 변경할 수 없습니다. 종속 클래스에 인터페이스에 대한 포인터 만 포함 된 경우 느슨한 결합이 발생하며 이는 하나 이상의 콘크리트 클래스로 구현 될 수 있습니다.종속 클래스의 종속성은 인터페이스에 의해 지정된 "계약"에 대한 것입니다. 클래스를 구현하는 메소드 및 / 또는 프로퍼티의 정의 된리스트 따라서 인터페이스를 구현하는 모든 클래스는 클래스를 변경하지 않고도 종속 클래스의 종속성을 충족시킬 수 있습니다. 이것은 소프트웨어 디자인의 확장 성을 허용합니다. 종속 클래스를 변경하지 않고도 일부 또는 모든 상황에서 현재 종속성을 대체하기 위해 인터페이스를 구현하는 새로운 클래스를 작성할 수 있습니다. 새로운 클래스와 기존 클래스를 자유롭게 교환 할 수 있습니다. 강한 결합은 이것을 허용하지 않습니다. 참조 링크.


3

5 가지 SOLID 원리를 살펴보십시오 . SRP를 준수하면 ISP와 DIP는 커플 링을 현저히 낮추어 DIP가 가장 강력합니다. 이미 언급 된 DI 아래의 기본 원칙 입니다.

또한 GRASP 는 살펴볼 가치가 있습니다. 추상 개념 (처음에는 구현하기 어려울 것임)과 구체적인 패턴 (실제로는 도움이 될 수 있음) 사이의 이상한 혼합이지만, 아름다움은 아마도 지금 가장 걱정거리가 아닐 것입니다.

마지막으로, IoC에서이 섹션은 일반적인 기술의 진입 점으로 매우 유용합니다.

사실 저는 stackoverflow에 관한 질문을 발견했습니다 . 여기서 구체적인 문제에 대한 SOLID의 적용을 보여줍니다. 흥미로운 읽을 거리가 될 수 있습니다.


1

Wikipedia에 따르면 :

컴퓨팅 및 시스템 설계에서 느슨하게 결합 된 시스템은 각 구성 요소가 다른 개별 구성 요소의 정의에 대해 거의 또는 전혀 모르는 시스템입니다.

타이트한 커플 링 문제로 인해 변경하기가 어렵습니다. (많은 필자들은 이것이 유지 보수 과정에서 문제를 일으킨다는 것을 시사하는 것처럼 보이지만 내 경험상 초기 개발 과정에서도 관련이 있습니다.) 밀접하게 결합 된 시스템에서 발생하는 경향은 시스템의 한 모듈을 변경하려면 추가 변경이 필요하다는 것입니다 연결된 모듈에서. 종종 다른 모듈에서 더 많은 변경이 필요합니다.

반대로 느슨하게 결합 된 시스템에서는 변경이 상대적으로 분리됩니다. 따라서 비용이 덜 들고 더 큰 확신을 가지고 만들 수 있습니다.

특정 예에서 이벤트 처리 항목은 GUI와 기본 데이터를 약간 분리합니다. 그러나 다른 분리 영역이있는 것처럼 들립니다. 특정 상황에 대한 자세한 내용이 없으면 구체적으로 지정하기가 어렵습니다. 그러나 다음과 같은 3 계층 아키텍처로 시작할 수 있습니다.

  • 데이터 저장 및 검색 로직
  • 비즈니스 로직
  • UI를 실행하는 데 필요한 논리

고려해야 할 사항은 단일 개발자가있는 소규모 일회성 응용 프로그램의 경우 모든 수준에서 느슨한 결합을 적용하면 이점이 없을 수 있다는 것입니다. 반면에 여러 개발자가있는 더 크고 복잡한 응용 프로그램은 필수입니다. 처음에는 추상화를 소개하고 아키텍처 관련 코드에 익숙하지 않은 개발자를 교육하는 데 비용이 발생합니다. 그러나 장기적으로 느슨한 커플 링은 비용보다 훨씬 큰 이점을 제공합니다.

느슨하게 결합 된 시스템 설계에 대해 신중한 경우 SOLID 원리 및 설계 패턴을 읽으십시오.

그러나 실현해야 할 중요한 점은 이러한 패턴과 원칙이 패턴과 원칙이라는 것입니다. 그것들은 규칙 이 아닙니다 . 이것은 그들이 실용적이고 지능적으로 적용되어야 함을 의미합니다.

패턴이 관련된 경우 패턴의 단일 "정확한"구현이 없음을 이해하는 것이 중요합니다. 자체 구현을 디자인하기위한 쿠키 커터 템플릿도 아닙니다. 좋은 솔루션의 형태를 알려주고 다른 개발자와 디자인 결정을 의사 소통하기위한 공용 언어를 제공합니다.

모두 제일 좋다.


1

의존성 주입, 전략 패턴 및 이벤트를 사용하십시오. 일반적으로 디자인 패턴을 읽으면 느슨하게 결합하고 종속성을 줄이는 것에 관한 것입니다. 의존성 주입 및 전략 패턴에 일부 인터페이스가 필요한 동안 이벤트가 느슨하게 결합된다고 말하고 싶습니다.

좋은 트릭은 클래스를 다른 라이브러리 / 어셈블리에 배치하고 가능한 적은 수의 다른 라이브러리에 의존하게하여 더 적은 종속성을 사용하도록 리팩터링하도록하는 것입니다.


4
콘돔은 추상적 인 IT 용어입니까, 아니면 단순히 말장난을하지 않습니까?
대런 영

3
의존성 주입 컨테이너의 또 다른 이름입니다.
Mchl

2
또한 바이러스 확산을 방지하는 좋은 방법입니다. 우리는 같은 것에 대해 이야기하고 있습니까?
sova

1
무거운 연결은 종종 백엔드에서 이루어집니다
Homde

1
제목을 설정하는 것은 형식을 남용하기가
어렵습니다

0

다른 견해를 제공하겠습니다. 각 클래스가 좋은 API라는 관점에서 이것을 생각합니다. 메소드가 호출되는 순서는 분명합니다. 그들이하는 일은 분명하다. 메소드 수를 최소한으로 줄였습니다. 예를 들어,

초기화, 열기, 닫기

setTheFoo, setBar, initX, getConnection, 닫기

첫 번째는 명백하고 멋진 API처럼 보입니다. 잘못된 순서로 호출하면 두 번째 오류가 발생할 수 있습니다.

발신자를 수정하고 다시 컴파일해야하는 것에 대해 너무 걱정하지 않습니다. 나는 새로운 코드와 15 세의 코드를 많이 유지합니다. 나는 보통 변경할 때 컴파일러 오류를 원한다. 때때로 나는 그런 이유로 API를 의도적으로 깨뜨릴 것입니다. 각 발신자에게 미치는 영향을 고려할 수있는 기회를 제공합니다. 블랙 박스없이 코드를 시각적으로 추적 할 수 있기를 원하고 컴파일러가 가능한 한 많은 오류를 포착하기를 원하기 때문에 의존성 주입의 큰 팬이 아닙니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.