복잡성 관리
효과적이고 효율적인 시스템을 만들기 위해서는 반드시 소프트웨어 복잡성을 관리해야 한다.
소프트웨어 복잡성 관리
본질적 복잡성
을 식별하고,불필요한 복잡성
을 제거하는 능력이 엔지니어에게 가장 중요한 스킬
가능한 모든 부분에서 복잡성의 생성을 최소화
소프트웨어 개발자로서 우리는 높은 품질의 코드, 즉 깨끗하고 신뢰할 수 있는 코드를 만들어야 한다.
복잡성의 영향을 최소화하도록 시도하기 위해서는
우리가 풀고자하는 문제를 완전히 이해
우리가 작성한 코드를 테스트하고 정제해야함
우리는 절대로 복잡성을 완전히 제거할 수 없다.
불필요한 복잡성을 줄이고, 시스템을 단순화할 수 있는 방법을 찾는데 집중하자.
불필요한 복잡성이 자라나지 않게 리뷰하고 확인하자.
복잡성은 아주 작은 영역에서 그 복잡성을 제거하기 위한 충분한 노력을 기울이지 않는한 계속해서 증가한다.
문제의 핵심적인 복잡성을 다루고(제거, 완화, 문제 제기) 난 뒤에 이를 모델링하는 것이 가장 좋은 방법일 때가 많다.
절대 완료할 수 없는 것을 잘하려는 시도를 피하라.
복잡성은 코드, 아키텍처, 도구, 인프라스트럭처, 조직적인 관점에서 전체적으로 고려해야 한다.
탄력적인 추상화를 만들라, 프레임워크, 라이브러리, 패턴으로 복잡성을 구분할 수 있다.
유연성이 요구되는 부분(ex: 기본값을 제공하되, 필요하면 덮어쓰기 기능) 에서 내가 필요를 만족하는지 확인하기
복잡성을 갖는 경향이 있는 조직에서 작업하게 된다면 필연적으로 조직적인 문제를 해결해야하는 업무를 맡게 될것
시지프스 태스크
를 해결하기 위한 영향력을 발휘애햐 한다.시지프스 테스크: 매번 수동 배포, 동일한 버그 계속 수정, 자동화할 수 있는데 안하는 작업, 궁극적으로 가치가 없는 작업
조직적인 복잡성을 정리하고 내재적 복잡성과 우발적 복잡성을 구분했다면 대부분의 작업은 거의 완료했을 것
계속해서 보던 것을 검토, 복잡성은 지속적으로 관리하지 않으면 이내 자라남
복잡성으로 발생하는 문제들
팀 커뮤니케이션 어려움
제품 오류, 비용 초과, 일정 지연
인력 이동
열거되지 않은 상태
확장성 결여(구조의 복잡성)
예기치 못한 상태(보안 구멍)
프로젝트 파악의 어려
복잡성 설명
복잡성은 적어도 두 가지 이상의 유형을 고려해야 함
문제가 가진 복잡성(내재적 복잡성)
해결책이 가진 복잡성(우발적 복잡성)
문제가 가진 복잡성(내재적 복잡성)
문제 자체의 근복적인 속성
특별한 문제를 해결하는데 존재하는 복잡성
우리가 가진 실제 문제의 성격에 따라 결정됨
통제할 수 없는 요소들이 포함될 수 있음
내재적 복잡성 에시
주로 레거시 코드와 관련있음
끊임없는 변경과 진화의 결과, 레거시 코드는 매우 복잡해지는 경우가 많다.
수많은 여러 레이어와 의존성으로 인해 코드는 이해하고 수정하기 어렵게 된다.
새로운 기능을 추가하거나, 에러 유입이나 기존 기능의 손상 없이 시스템을 변경하는 것을 어렵게 만듦
해결책이 가진 복잡성(우발적 복잡성)
문제를 해결하기 위해 취한 특정 접근법으로 인한 결과
문제에 관한 해결책을 구현하는 과정에서 만들어지는 복잡성
팀이 해결책을 얼마나 잘 만들 수 있는가에 따라 결정됨
통제할 수 있는 복잡성
문제를 더 잘 이해할수록 해결책을 찾아낼 가능성이 높다.
우발적 복잡성 예시
언제나 다양한 이유에서 기존 문제에 관한 새로운 해결책을 만듬
팀이 기존 해결책에 관해 인지하지 못함
기존 해결책이 유스 케이스를 충분히 다루지 못함
속한 조직의 통제 밖에 있거나 다른 팀의 작업에 의존성을 유발함
바퀴를 다시 발명하거나, 외부 의존성을 채택하는 것을 선택하는 결정은 어려움
두 가지 모두 복잡성을 증가시키지만, 그 정도가 다를뿐
복잡성의 근본 원인 파악
시스템 복잡성은 여러 내재적/우발적 요소들에 의해 발생 가능
우리가 고려해야 하는 것의 양
시스템의 상이한 요소들 사이의 상호 의존성
제품과 해당 제품을 구축하기 위해 사용한 코드 간 불일치
명확한(단순한) 도메인
시스템 요소들 사이 관계가 분명하고 잘 정의됨
상대적으로 취한 행동의 결과를 예측하기 쉬움
모범 사례들과 전문가 지식을 활용해 의사 결정 내릴 수 있음
난해한 도메인
시스템 요소들 사이의 관계가 보다 복잡
여전히 알 수 있고 예측 가능은함
상황에 따라 구체적인 문맥도 고려해야함
복잡한 도메인
시스템 요소들 사이의 관계들이 완전히 알려져 있지 않거나 완전히 이해되지 않음
행동 결과를 예측하기 어려움
이 도메인에서는 탐색적이고 반복저인 접근법을 활용해 의사결정 해야함
그 과정에서 경험을 통해 학습하고, 적응할 준비
혼란한 도메인
시스템 관계를 예측하기 매우 어려움
이상적으로 가져야하는 모든 정보를 획득하지 않은 상태에서 의사결정 내릴 준비를 해야함
무질서한 도메인
이 시스템이 어떤 시스템에 해당하는지 불분명
먼저 질서와 명확함을 마늗ㄹ기 위한 단계를 밟은 뒤에야 효과적인 의사결정을 내릴 수 있음
소프트웨어 설계 철학
의존성과 모호성을 소프트웨어 설계에서 복잡성을 일으키는 주요 요인으로 본다.
의존성
코드의 어떤 부분을 격리한 상태에서 이해하거나 수정할 수 없을 때 발생
코드를 다른 시스템의 다른 부분들과 관련지어 고려해야함
모호성
중요한 정보가 명확하지 않을 때 발생
개발 당시 명확함이나, 문서가 부족했던 것에서 기인
설계가 너무 크고 복잡해서 모든것을 추적하기 어려운것에서 기인
복잡성 최소화
이해하기 쉽고, 개선하기 쉬운 방식으로 소프트웨어를 작성해야 한다.
복잡성 캡슐화하기
모듈성은 시스템을 관리 가능한 컴포넌트로 분해하는데 도움을 준다.
모듈성을 통해 점진적이고 확장적인 접근법을 설계에 사용할 수 있음
글로벌 복잡성을 로컬 복잡성으로 대체 가능
모듈 사이의 인터페이스를 통한 의존성을 만들어내며, 이는 또 다시 복잡성을 추가한다.
새로운 모듈은 추가되는 복잡성을 뛰어넘는 이익이 있을때만 도입해야 한다.
단순함이 쉬움을 만듬
단순성은 프로그램이 얼마나 상호 연결되었는가로 측정
소프트웨어가 엉켜 있는지 아닌지는 누구나 볼 수 있다.(객관적)
정확성이나 완전성을 희생하지 않고 원하는 지점까지 신속하게 가는 것
복잡성을 만드는 구조보다 단순한 구조를 선택하라
단순성을 기본으로하여 추상화를 만들어라
문제 공간을 단순화한 뒤 시작해라
단순성은 때때로 더 적게가 아닌 더 많이 만드는것을 의미한다.
단순한 해결책은 이해하기 쉽지만 반드시 구현하기 쉽지만은 않다.
불필요한 혹은 혼동을 일으키는 모든 것을 제거하는 것이 목표
단순성은 여러 해결책 중 하나를 선택할 때 항상 가장 중요한 요소는 아니다.
오컴의 면도날
엔티티들은 반드시 필요하지 않다면 늘려서는 안된다.
즉, 한 문제에 대해 여러 해결책이 있다면, 가정과 움직이는 부분이 가장 적은, 가장 단순한 옵션을 선택하라
오컴의 면도날은 모든 사실이 알려지기 이전에 초기 결정을 내리는데 도움을 주는 최고의 멘탈 모델
단순한 구조를 사용하고, 올바른 수준의 추상화를 적용해 컴포넌트를 설계하고, 함수형의 합성을 사용해서 시스템을 만들어 복잡성을 줄일 것을 제안한다.
팀은 어떻게 복잡성을 관리할까?
대규모 시스템을 작은 모듈화된 컴포넌트로 나누는 것이 복잡성을 관리하는데 효율적인 방법
잘 정의된 인터페이스, 계층형 아키텍처를 사용해 보다 작은 저수준 컴포넌트들로 구성된 고수준 모듈을 만들 수 있다.
높은 수준의 창의적인 자율성과 유연성을 주는 동시에 여전히 필요한 제약사항을 부여함으로써 시스템의 다양한 컴포넌트들이 서로 효과적으로 작동함을 보장한다.
모듈성, 잘 정의된 인터페이스, 계층형 아키텍처는 보다 크고 복잡한 시스템을 만들면서도 개별 개발자들의 자율성과 창의성을 희생하지 않게 한다.
복잡성 통제(필수적인 복잡성)
모든 의미 있는 소프트웨어에는 필수적인 복잡성이 존재
그 복잡성은 절대로 제거할 수 없다. 단지 통제할 수 있을 뿐이다.
우리가 해결하고자 하는 문제에 내제된 복잡성은 때때로 단순히 제거하거나 단순화할 수 없다.
우발적 복잡성과는 반대 (우발적 복잡성은 존재해서는 안됨)
Last updated