복잡성 관리

효과적이고 효율적인 시스템을 만들기 위해서는 반드시 소프트웨어 복잡성을 관리해야 한다.

소프트웨어 복잡성 관리

본질적 복잡성을 식별하고, 불필요한 복잡성을 제거하는 능력이 엔지니어에게 가장 중요한 스킬

  • 가능한 모든 부분에서 복잡성의 생성을 최소화

대규모 소프트웨어 시스템 개발과 유지보수에서 가장 큰 문제는 복잡성이다. 대규모 시스템은 이해하기 어렵다.

  • 복잡성은 아주 작은 영역에서 그 복잡성을 제거하기 위한 충분한 노력을 기울이지 않는한 계속해서 증가한다.

  • 문제의 핵심적인 복잡성을 다루고(제거, 완화, 문제 제기) 난 뒤에 이를 모델링하는 것이 가장 좋은 방법일 때가 많다.

    • 절대 완료할 수 없는 것을 잘하려는 시도를 피하라.

    • 복잡성은 코드, 아키텍처, 도구, 인프라스트럭처, 조직적인 관점에서 전체적으로 고려해야 한다.

  • 탄력적인 추상화를 만들라, 프레임워크, 라이브러리, 패턴으로 복잡성을 구분할 수 있다.

    • 유연성이 요구되는 부분(ex: 기본값을 제공하되, 필요하면 덮어쓰기 기능) 에서 내가 필요를 만족하는지 확인하기

  • 복잡성을 갖는 경향이 있는 조직에서 작업하게 된다면 필연적으로 조직적인 문제를 해결해야하는 업무를 맡게 될것

    • 시지프스 태스크를 해결하기 위한 영향력을 발휘애햐 한다.

      • 시지프스 테스크: 매번 수동 배포, 동일한 버그 계속 수정, 자동화할 수 있는데 안하는 작업, 궁극적으로 가치가 없는 작업

  • 조직적인 복잡성을 정리하고 내재적 복잡성과 우발적 복잡성을 구분했다면 대부분의 작업은 거의 완료했을 것

    • 계속해서 보던 것을 검토, 복잡성은 지속적으로 관리하지 않으면 이내 자라남

은탄환은 없다

  • 소프트웨어 개발에서 단 하나의 기술이나 방법론으로 모든 문제를 해결할 수 있는 만능 해결책은 없다는 것

  • 이 기술만 도입하면 모든 문제가 해결된다"라는 식의 접근은 위험하며, 지속적인 개선과 다양한 접근 방식이 필요하다는 뜻

복잡성으로 발생하는 문제들

  • 팀 커뮤니케이션 어려움

  • 제품 오류, 비용 초과, 일정 지연

  • 인력 이동

  • 열거되지 않은 상태

  • 확장성 결여(구조의 복잡성)

  • 예기치 못한 상태(보안 구멍)

  • 프로젝트 파악의 어려

복잡성 설명

복잡성은 적어도 두 가지 이상의 유형을 고려해야 함

  • 문제가 가진 복잡성(내재적 복잡성)

  • 해결책이 가진 복잡성(우발적 복잡성)

문제가 가진 복잡성(내재적 복잡성)

문제 자체의 근복적인 속성

  • 특별한 문제를 해결하는데 존재하는 복잡성

  • 우리가 가진 실제 문제의 성격에 따라 결정됨

  • 통제할 수 없는 요소들이 포함될 수 있음

내재적 복잡성 에시

주로 레거시 코드와 관련있음

  • 끊임없는 변경과 진화의 결과, 레거시 코드는 매우 복잡해지는 경우가 많다.

  • 수많은 여러 레이어와 의존성으로 인해 코드는 이해하고 수정하기 어렵게 된다.

  • 새로운 기능을 추가하거나, 에러 유입이나 기존 기능의 손상 없이 시스템을 변경하는 것을 어렵게 만듦

해결책이 가진 복잡성(우발적 복잡성)

문제를 해결하기 위해 취한 특정 접근법으로 인한 결과

  • 문제에 관한 해결책을 구현하는 과정에서 만들어지는 복잡성

  • 팀이 해결책을 얼마나 잘 만들 수 있는가에 따라 결정됨

  • 통제할 수 있는 복잡성

  • 문제를 더 잘 이해할수록 해결책을 찾아낼 가능성이 높다.

우발적 복잡성 예시

언제나 다양한 이유에서 기존 문제에 관한 새로운 해결책을 만듬

  • 팀이 기존 해결책에 관해 인지하지 못함

  • 기존 해결책이 유스 케이스를 충분히 다루지 못함

  • 속한 조직의 통제 밖에 있거나 다른 팀의 작업에 의존성을 유발함

  • 바퀴를 다시 발명하거나, 외부 의존성을 채택하는 것을 선택하는 결정은 어려움

    • 두 가지 모두 복잡성을 증가시키지만, 그 정도가 다를뿐

복잡성의 근본 원인 파악

시스템 복잡성은 여러 내재적/우발적 요소들에 의해 발생 가능

  • 우리가 고려해야 하는 것의 양

  • 시스템의 상이한 요소들 사이의 상호 의존성

  • 제품과 해당 제품을 구축하기 위해 사용한 코드 간 불일치

커네빈 프레임워크

  • IBM 연구자들이 개발한 복잡성 유형을 구분하여 접근법을 결정하는 도구

  • 주어진 시스템의 다양성 복잡성 유형을 식별하는 방법으로 고안됨

  • 각각의 복잡성 유형은 고유한 특성을 가지고 의사결정과 문제해결 접근법이 달라진다.

명확한(단순한) 도메인

  • 시스템 요소들 사이 관계가 분명하고 잘 정의됨

  • 상대적으로 취한 행동의 결과를 예측하기 쉬움

  • 모범 사례들과 전문가 지식을 활용해 의사 결정 내릴 수 있음

난해한 도메인

  • 시스템 요소들 사이의 관계가 보다 복잡

  • 여전히 알 수 있고 예측 가능은함

  • 상황에 따라 구체적인 문맥도 고려해야함

복잡한 도메인

  • 시스템 요소들 사이의 관계들이 완전히 알려져 있지 않거나 완전히 이해되지 않음

  • 행동 결과를 예측하기 어려움

  • 이 도메인에서는 탐색적이고 반복저인 접근법을 활용해 의사결정 해야함

    • 그 과정에서 경험을 통해 학습하고, 적응할 준비

혼란한 도메인

  • 시스템 관계를 예측하기 매우 어려움

  • 이상적으로 가져야하는 모든 정보를 획득하지 않은 상태에서 의사결정 내릴 준비를 해야함

무질서한 도메인

  • 이 시스템이 어떤 시스템에 해당하는지 불분명

  • 먼저 질서와 명확함을 마늗ㄹ기 위한 단계를 밟은 뒤에야 효과적인 의사결정을 내릴 수 있음

소프트웨어 설계 철학

의존성모호성을 소프트웨어 설계에서 복잡성을 일으키는 주요 요인으로 본다.

복잡성은 시간이 지남에 따라, 설계의 규모가 커짐에 따라 증가하며 설계 프로세스의 반복적이고 확장적인 특에 의해 더욱 악화된다.

의존성

  • 코드의 어떤 부분을 격리한 상태에서 이해하거나 수정할 수 없을 때 발생

  • 코드를 다른 시스템의 다른 부분들과 관련지어 고려해야함

모호성

  • 중요한 정보가 명확하지 않을 때 발생

  • 개발 당시 명확함이나, 문서가 부족했던 것에서 기인

  • 설계가 너무 크고 복잡해서 모든것을 추적하기 어려운것에서 기인

복잡성 최소화

이해하기 쉽고, 개선하기 쉬운 방식으로 소프트웨어를 작성해야 한다.

복잡성 캡슐화하기

  • 모듈성은 시스템을 관리 가능한 컴포넌트로 분해하는데 도움을 준다.

  • 모듈성을 통해 점진적이고 확장적인 접근법을 설계에 사용할 수 있음

  • 글로벌 복잡성을 로컬 복잡성으로 대체 가능

  • 모듈 사이의 인터페이스를 통한 의존성을 만들어내며, 이는 또 다시 복잡성을 추가한다.

  • 새로운 모듈은 추가되는 복잡성을 뛰어넘는 이익이 있을때만 도입해야 한다.

단순함이 쉬움을 만듬

단순성은 프로그램이 얼마나 상호 연결되었는가로 측정

소프트웨어가 엉켜 있는지 아닌지는 누구나 볼 수 있다.(객관적)

정확성이나 완전성을 희생하지 않고 원하는 지점까지 신속하게 가는 것

  • 복잡성을 만드는 구조보다 단순한 구조를 선택하라

  • 단순성을 기본으로하여 추상화를 만들어라

  • 문제 공간을 단순화한 뒤 시작해라

  • 단순성은 때때로 더 적게가 아닌 더 많이 만드는것을 의미한다.

  • 단순한 해결책은 이해하기 쉽지만 반드시 구현하기 쉽지만은 않다.

  • 불필요한 혹은 혼동을 일으키는 모든 것을 제거하는 것이 목표

"오늘 느리게 가는 것은 내일 더 빠르게 갈 수 있음을 의미한다."

  • 아키텍처 의사 결정에서 장기적인 의미를 심사숙고하는 것의 중요성 강조

  • 속도를 늦추고 품질에 집중함으로써 보다 유지보수성 높고 확장 가능한 시스템을 만들 수 있음

  • 보다 빠르고 효율적인 개발 사이클을 만들어 냄

팀은 어떻게 복잡성을 관리할까?

대규모 시스템을 작은 모듈화된 컴포넌트로 나누는 것이 복잡성을 관리하는데 효율적인 방법

  • 잘 정의된 인터페이스, 계층형 아키텍처를 사용해 보다 작은 저수준 컴포넌트들로 구성된 고수준 모듈을 만들 수 있다.

  • 높은 수준의 창의적인 자율성과 유연성을 주는 동시에 여전히 필요한 제약사항을 부여함으로써 시스템의 다양한 컴포넌트들이 서로 효과적으로 작동함을 보장한다.

복잡성 통제(필수적인 복잡성)

모든 의미 있는 소프트웨어에는 필수적인 복잡성이 존재

그 복잡성은 절대로 제거할 수 없다. 단지 통제할 수 있을 뿐이다.

  • 우리가 해결하고자 하는 문제에 내제된 복잡성은 때때로 단순히 제거하거나 단순화할 수 없다.

    • 우발적 복잡성과는 반대 (우발적 복잡성은 존재해서는 안됨)

복잡성은 어딘가에는 살아남아야 한다.

복잡성을 포용한다면 적절한 장소를 마련하라.

여러분의 시스템과 조직이 복잡성이 존재함을 알 수 있도록 설계하라.

적응에 집중하라.

여러분의 강점이 될 것이다. - 프레드 해버트

Last updated