계층적 분해

응용 프로그램에 대한 클래스 작성을 즉시 시작해서는 안됩니다. 먼저 설계해야 합니다. 디자인은 사려 깊은 아키텍처로 끝나야 합니다. 그리고 이 아키텍처를 얻으려면 시스템을 지속적으로 분해해야 합니다.

분해는 계층적으로 수행되어야 합니다. 먼저 시스템은 가장 일반적인 형태로 작동을 설명하는 대형 기능 모듈/하위 시스템으로 나뉩니다. 그런 다음 결과 모듈을 더 자세히 분석하고 하위 모듈 또는 개체로 나눕니다.

객체를 선택하기 전에 최소한 정신적으로 시스템을 기본 의미론적 블록으로 나눕니다. 소규모 응용 프로그램에서는 일반적으로 매우 쉽습니다. 시스템이 먼저 하위 시스템 / 패키지로 나뉘고 패키지가 클래스로 나뉘기 때문에 몇 가지 수준의 계층 구조로 충분합니다.

계층적 분해

이 아이디어는 보이는 것처럼 사소하지 않습니다. 예를 들어 MVC(Model-View-Controller)와 같은 일반적인 "아키텍처 패턴"의 본질은 무엇입니까?

비즈니스 로직에서 프리젠테이션을 분리하는 것이 전부입니다 . 첫째, 모든 사용자 애플리케이션은 두 개의 모듈로 나뉩니다. 하나는 비즈니스 로직 자체(모델) 구현을 담당하고 두 번째는 사용자와의 상호 작용(사용자 인터페이스 또는 보기)을 담당합니다.

그런 다음 모듈이 어떻게 든 상호 작용해야한다는 것이 밝혀졌습니다. 이를 위해 모듈의 상호 작용을 관리하는 작업을 담당하는 컨트롤러를 추가합니다. 또한 모바일(클래식) 버전의 MVC에서는 View가 모델에서 이벤트를 수신하고 표시된 데이터를 실시간으로 변경할 수 있도록 Observer 패턴이 추가되었습니다.

시스템을 가장 큰 구성 요소로 처음 분할한 결과 얻은 일반적인 최상위 모듈은 다음과 같습니다.

  • 비즈니스 로직
  • 사용자 인터페이스
  • 데이터 베이스;
  • 메시징 시스템
  • 객체 컨테이너.

첫 번째 분할은 일반적으로 전체 애플리케이션을 2-7개(최대 10개 부분)로 분할합니다. 더 많은 부분으로 나누면 그룹화하려는 욕구가 생기고 다시 2-7개의 최상위 모듈을 얻게 됩니다.

기능 분해

모듈/하위 시스템으로의 분할은 시스템이 해결하는 작업에 따라 가장 잘 수행됩니다 . 주요 작업은 서로 독립적으로 자율적으로 해결/수행할 수 있는 구성 하위 작업으로 나뉩니다.

각 모듈은 일부 하위 작업을 해결하고 해당 기능을 수행해야 합니다 . 기능적 목적 외에도 모듈은 다음과 같이 기능을 수행하는 데 필요한 일련의 데이터로 특징지어집니다.

모듈 = 기능 + 실행에 필요한 데이터.

모듈로의 분해가 올바르게 수행되면 다른 모듈(다른 기능을 담당하는)과의 상호 작용이 최소화됩니다. 그럴 수도 있지만 부재가 모듈에 중요한 것은 아닙니다.

모듈은 임의의 코드 조각이 아니라 특정 작업에 대한 솔루션을 제공하고 이상적으로는 독립적으로 또는 다른 환경에서 작동하고 재사용할 수 있는 별도의 기능적으로 의미 있고 완전한 프로그램 단위(서브 프로그램)입니다. 모듈은 일종의 "행동과 개발에서 상대적인 독립성이 가능한 무결성"이어야 합니다. (크리스토퍼 알렉산더)

따라서 유능한 분해는 우선 시스템 기능 분석 과 이러한 기능을 수행하는 데 필요한 데이터를 기반으로 합니다. 이 경우 함수는 개체가 아니므로 클래스 함수 및 모듈이 아닙니다. 모듈에 몇 개의 클래스만 있는 경우 과도하게 사용한 것입니다.

강하고 약한 연결

모듈화로 무리하지 않는 것이 매우 중요합니다. 초보자에게 모놀리식 Spring 애플리케이션을 제공하고 모듈로 나누라고 요청하면 그는 각 Spring Bean을 별도의 모듈로 꺼내 작업이 완료되었다고 생각할 것입니다. 하지만 그렇지 않습니다.

분해 품질의 주요 기준은 모듈이 작업 해결에 집중하고 독립적인 방식입니다.

이것은 일반적으로 다음과 같이 공식화됩니다. "분해의 결과로 얻은 모듈은 내부적으로 최대로 결합되어야 하고(높은 내부 응집력) 서로 최소한으로 상호 연결되어야 합니다(낮은 외부 결합)."

모듈 내의 높은 응집력, 높은 응집력 또는 "결합력"은 모듈이 하나의 좁은 문제를 해결하는 데 집중하고 이기종 기능이나 관련되지 않은 책임을 수행하는 데 관여하지 않음을 나타냅니다.

응집력은 모듈이 수행하는 작업이 서로 관련되는 정도를 나타냅니다.

High Cohesion의 결과는 Single Responsibility Principle 입니다 . 이는 5가지 SOLID 원칙 중 첫 번째이며 , 이에 따라 모든 개체/모듈은 하나의 책임만 가져야 하며 변경 이유가 한 가지 이상 있어서는 안 됩니다.

Low Coupling , 느슨한 결합은 시스템을 분할하는 모듈이 가능하면 독립적 이거나 서로 느슨하게 결합되어야 함을 의미합니다. 그들은 상호 작용할 수 있어야 하지만 동시에 서로에 대해 가능한 한 적게 알고 있어야 합니다.

각 모듈은 다른 모듈이 어떻게 작동하는지, 어떤 언어로 작성되었는지, 어떻게 작동하는지 알 필요가 없습니다. 종종 이러한 모듈의 상호 작용을 구성하기 위해 이러한 모듈이 로드되는 특정 컨테이너가 사용됩니다.

적절한 설계를 사용하면 하나의 모듈을 변경하면 다른 모듈을 편집할 필요가 없거나 이러한 변경 사항이 최소화됩니다. 결합이 느슨할수록 프로그램 작성/이해/확장/복구가 더 쉬워집니다.

잘 설계된 모듈은 다음과 같은 속성을 가져야 합니다.

  • 기능적 무결성 및 완전성 - 각 모듈은 하나의 기능을 구현하지만 잘 구현하고 완벽하게 구현하며 모듈은 기능을 구현하기 위해 전체 작업 세트를 독립적으로 수행합니다.
  • 하나의 입력 및 하나의 출력 - 입력에서 프로그램 모듈은 특정 초기 데이터 세트를 수신하고 의미있는 처리를 수행하며 결과 데이터 세트를 반환합니다. 즉, 표준 IPO 원칙이 구현됩니다 - 입력 -\u003e 프로세스 -\u003e 산출.
  • 논리적 독립 - 프로그램 모듈의 작업 결과는 초기 데이터에만 의존하지만 다른 모듈의 작업에는 의존하지 않습니다.
  • 다른 모듈과 약한 정보 링크 - 모듈 간의 정보 교환은 가능한 한 최소화해야 합니다.

초보자가 모듈의 연결성을 더욱 줄이는 방법을 이해하는 것은 매우 어렵습니다. 부분적으로는이 지식은 경험과 함께 제공되며 부분적으로는 똑똑한 책을 읽은 후에 제공됩니다. 그러나 기존 애플리케이션의 아키텍처를 분석하는 것이 가장 좋습니다.

상속 대신 구성

유능한 분해는 일종의 예술이며 대부분의 프로그래머에게 어려운 작업입니다. 여기서 단순함은 기만적이며 실수는 비용이 많이 듭니다.

전용 모듈은 서로 강하게 결합되어 독립적으로 개발할 수 없습니다. 또는 각각이 담당하는 기능이 명확하지 않습니다. 유사한 문제가 발생하면 모듈 분할이 잘못 수행되었을 가능성이 큽니다.

각 모듈이 어떤 역할을 하는지 항상 명확해야 합니다 . 분해가 올바르게 수행되었다는 가장 신뢰할 수 있는 기준은 모듈이 애플리케이션의 나머지 부분과 별도로 사용할 수 있는(따라서 재사용할 수 있는) 독립적이고 가치 있는 서브루틴인지 여부입니다.

시스템을 분해할 때 "각 모듈은 어떤 작업을 수행합니까?", "모듈을 테스트하기가 얼마나 쉬운가요?", "모듈을 자체적으로 사용할 수 있습니까?"와 같은 질문을 통해 품질을 확인하는 것이 바람직합니다. 아니면 다른 환경에서?" 다른 사람에게 영향을 미칩니까?"

모듈을 가능한 한 자율적 으로 유지하려고 노력해야 합니다 . 앞서 언급했듯이 이것은 적절한 분해를 위한 핵심 매개변수입니다 . 따라서 처음에는 모듈이 서로 약하게 종속되도록 수행해야 합니다. 당신이 성공했다면 당신은 훌륭합니다.

그렇지 않다면 여기에서도 모든 것이 손실되지 않습니다. 하위 시스템 간의 링크를 추가로 최소화하고 약화시킬 수 있는 특수 기술과 패턴이 많이 있습니다. 예를 들어 MVC의 경우 이를 위해 Observer 패턴을 사용했지만 다른 솔루션도 가능합니다.

디커플링 기술이 주요 "설계자의 툴킷"을 구성한다고 말할 수 있습니다. 우리는 모든 하위 시스템에 대해 이야기하고 있으며 계층의 모든 수준 , 즉 클래스 간뿐만 아니라 각 계층 수준의 모듈 간 연결을 약화시키는 것이 필요하다는 것을 이해하기만 하면 됩니다.