Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

소프트웨어 설계 악취: 기술 부채 관리 방법

8,668 views

Published on

"소프트웨어 악취를 제거하는 리팩토링: 구조적 설계 문제를 풀어내는 최선의 실천법" 책을 토대로 만든 세미나 자료

Published in: Software
  • People used to laugh at me behind my back before I was in shape or successful. Once I lost a lot of weight, I was so excited that I opened my own gym, and began helping others. I began to get quite a large following of students, and finally, I didn't catch someone laughing at me behind my back any longer. CLICK HERE NOW ♥♥♥ https://tinyurl.com/1minweight4u
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

소프트웨어 설계 악취: 기술 부채 관리 방법

  1. 1. + 소프트웨어 설계 악취: 기술 부채 관리 방법 엑셈 CTO I 박재호(jaypark@ex-em.com)
  2. 2. + 목차 n  기술 부채 n  설계 악취 n  설계 원칙 n  악취에 대한 사례 연구: 추상화, 캡슐화, 모듈화, 계층화 n  깨끗한 코드
  3. 3. + 프로그램이 진화함에 따라 유지보수 작업을 행하거나 복잡도를 줄이지 않는 이상 프로그램의 복잡도는 증가한다. - 늘어나는 복잡도에 대한 레만의 법칙
  4. 4. + 부채 n  부채 n  미래의 부를 현재로 할인해서 당겨오는 행위로 인해 발생 n  부의 확장, 편의성 추구, 생존을 위한 지렛대로 사용할 수 있지만 기본적 으로는 최대한 작게 유지(risk!) n  이자 발생 n  상환 기간 n  복리 n  변동 금리 n  인플레이션
  5. 5. + 설계 악취와 기술 부채 n  설계 악취의 정의 n  설계 품질에 부정적인 영향을 미치고 기본 설계 원칙을 위반하는 설계상 의 특정 구조 n  설계 구조에서 잠재적인 문제 n  기술 부채의 정의 n  잘못되거나 최적화되지 않은 설계 결정을 의식적이거나 무의식적으로 내 릴 경우 축적되는 부채다 n  워드 커닝햄(1992)이 처음으로 사용 n  누적된 이자를 갚지 못하면 파산 à 기술 부채를 해소하지 못하면 제품 파산 n  코드 부채, 설계 부채, 테스트 부채, 문서 부채
  6. 6. + 기술 부채가 등장하는 이유? n  빨라진 제품 주기 n  경쟁사에 비해 더 빨리 더 저렴하게 시장에 신제품 출시 요구 n  설계 결정의 영향력을 적절히 평가할 기회나 시간적 여유 부족 n  지역적인 설계 결정의 집합이 구조적인 품질을 떨어뜨림 à 설계 부채 축 적 n  문제는 유지보수! n  기술 부채가 눈에 보이지 않는 이유? n  결함은 최종 사용자에게 직접 보임 n  기술 부채는 소프트웨어 시스템의 내부 품질에 영향을 미침 à 보이지 않 으므로 무시됨
  7. 7. + 기술 부채가 미치는 영향 n  기술 부채의 구성 요소 n  원금(꼼수나 지름길)과 이자(상환하지 않을 경우 치뤄야 할 대가) n  기술 부채에서 복리로 붙는 이자 문제 n  소프트웨어에 가해지는 새로운 변경이 부채에 허덕이는 설계 구조와 결 합해 부채를 더 늘이기 때문 à 더 많은 꼼수 à 더 많은 부채 n  변경 비용이 기술 부채에 따라 기하급수적으로 증가함 à 기술 파산 n  개발팀의 사기 저하 n  부채를 짊어진 3류 제품을 개발하고픈 개발자는 아무도 없다! n  단기간에 부채를 갚기란 쉽지 않기 때문 n  소프트웨어 변경을 시도할 경우 발생하는 불확실성과 위험에 직접 노출
  8. 8. +
  9. 9. + 기술 부채를 초래하는 원인 n  관리자, 아키텍트, 개발자들이 내린 엉뚱한 결정의 원인 n  일정 압력: 복사해붙이기 n  좋은/숙달된 설계자 부족: 악화(나쁜 관례)가 양화를 구축 n  설계 원칙의 응용 부족: 경험/인식 부족 n  설계 악취와 리펙터링에 대한 인식 부족 Programming == Googling stackoverflow?
  10. 10. + 기술 부채를 관리하는 방법 n  기술 부채에 대한 점진적인 자각 n  기술 부채의 감지와 상환 n  기술 부채의 누적 방지
  11. 11. + 설계 악취란? n  설계가 잘못되었음을 알려주는 징표 n  악취에 신경을 써야 하는 이유? n  소프트웨어 이해 가능성에 치명적인 문제를 일으킴 n  결함 수정과 개선을 위한 변경이 끊이지 않고 유지 보수 시간이 늘어남 n  논리적인 재사용이 불가함 n  안정성과 테스트 가능성이 점점 나빠짐 n  소프트웨어 설계가 소프트웨어 품질에 영향을 미침 n  설계가 잘못되면 악취가 발생!
  12. 12. + 악취가 영향을 미치는 품질 속성 n  소프트웨어 비기능 측면 n  이해 가능성 n  변경 가능성 n  확장 가능성 n  재사용 가능성 n  테스트 가능성 n  안정성 n  주의: 비기능은 소프트웨어의 내재된 속성이므로 개발자가 보증해 야 한다!
  13. 13. + 설계 악취를 일으키는 요인 n  설계 원칙 위반 n  부적절한 패턴 사용 n  언어 제약 n  객체지향에서 절차적인 사고 방식 n  점성 n  우수 관계와 우수 프로세스의 미준수
  14. 14. + 설계 악취를 일으키는 요인 n  java.util 패키지 일부인 Calendar 클래스 n  실세계의 달력 기능을 추상화 n  날짜와 관련된 기능을 제공 n  하지만 시간 관련 기능도 제공 n  여기서 위반된 설계 원칙 n  추상화는 유일한 책임만 맡아야 함 à 추상화 원칙 위반 n  다면적인 추상화 악취 발생 사례(설계 원칙 위반)
  15. 15. + 설계 악취를 일으키는 요인 n  JDK의 AbstractQueuedSynchronizer와 AbstractQueuedLongSynchronizer 클래스 n  두 클래스는 AbstractOwnableSynchronizer 에서 파생 n  원시 타입의 차이뿐! n  여기서 위반된 설계 원칙 n  펙터링이 안 된 설계 계층 악취 n  문제) 자바에서는 제네릭에서 원시 타입을 지원하지 않음! à 필연적인 코드 중첩 발생 사례(언어 제약)
  16. 16. + 설계 악취를 일으키는 요인 n  소프트웨어 점성이란? n  올바른 해법을 문제에 적용하는 과정에서 반드시 직면하는 저항(늘어나 는 노력과 시간) n  꼼수는 시간과 노력을 적게 요구(낮은 저항) n  환경 점성이란? n  우수 관례를 따르기 위해 반드시 극복해야 할 소프트웨어 개발 환경으로 인한 ‘저항’ n  우수 관계를 따를 때 시간이 더 많이 걸리면 나쁜 관례를 선택! n  개발 프로세스, 재사용 프로세스, 조직 요구 사항, 법적인 제약 사례(점성)
  17. 17. + 악취 분류에 기반한 설계 원칙 n  악취 맥락에서 위반이 일어난 설계 원칙을 인식할 필요가 있음 n  추상화 n  단순화와 일반화 기법을 사용해 엔티티의 단순화를 옹호함 n  단순화는 불필요한 세부 사항을 제거하며, 일반화는 공통적이며 중요한 특성을 파악 하고 명세함 n  캡슐화 n  추상화의 세부 구현과 변형을 숨기는 기법을 사용해 관심사 분리와 정보 은닉을 옹호 n  모듈화 n  지역화와 분해 기법을 사용해 응집력은 높고 결합력은 낮은 추상화 생성을 옹호 n  계층 구조 n  분류, 일반화, 대체, 배치와 같은 기법을 사용해 계층적인 추상화 구조 생성을 옹호
  18. 18. + 몇 가지 추가적인 설계 원칙(1) n  OCP(Open/Close Principle) n  모듈은 확장에 대해 열려야 하지만 변경에 대해 닫혀야 마땅하다 n  모듈은 코드 변경 없이 새로운 요구 사항을 지원할 수 있어야 마땅하다 n  단일 책임 원칙(SRP, Single Responsibility Principle) n  클래스가 변경되어야 하는 이유가 결코 둘 이상 있어서는 안 된다 n  각 책임은 변경 축이되므로, 각 변경은 단일 책임에만 영향을 미쳐야 마 땅하다 n  LSP(LISKOV’S SUBSTITUTION PRINCIPLE) n  상속 받은 클래스는 사용자가 차이점을 알 필요 없이 기초 클래스 인터페 이스를 통해 사용 가능해야만 한다
  19. 19. + 몇 가지 추가적인 설계 원칙(2) n  KISS(KEEP IT SIMPLE SILLY) 원칙 n  소프트웨어 설계 구성에는 두 가지 방법이 있다. 하나는 아주 단순하게 만들 어 명백하게 의존성이 하나도 없게 만드는 방법이며, 다른 하나는 아주 복잡 하게 만들어 명백한 의존성이 하나도 없게 만드는 방법이다 n  정보 은닉(Information Hiding) 원칙 n  어렵거나 변경되기 쉬운 설계 결정을 파악하고 적절한 모듈이나 타입을 생성 해 다른 모듈이나 타입으로부터 이런 결정을 감추는 방식 n  DRY(Don’t Repeat Yourself) 원칙 n  모든 지식은 시스템 내부에서 단일하고 모호하지 않고 권위 있는 표현이 되어 야만 한다 n  비순환 의존성 원칙(ADP, Acyclic Dependencies Principle) n  패키지 사이의 의존성은 순환을 형성해서는 안 된다
  20. 20. +
  21. 21. + 사례 연구 n  중복된 추상화 악취란? n  이름이 같거나 구현이 동일하거나 이름도 같고 구현도 동일할 때 발생하 는 악취 n  동일한 이름: 추상화 이름이 동일(우연히 이름이 동일할 가능성에 주 의!) n  동일한 구현: 의미상으로 동일한 멤버 정의가 있는 경우 n  문제의 원인: DRY, 중복 방지 원칙을 어김(예: 복붙) n  여파: 코드 중복으로 인한 유지보수가 어려워짐 추상화 악취 중 중복된 추상화
  22. 22. + 사례 연구 n  예제: JDK에 존재하는 이름이 동일한 클래스 n  자바 7에서 4005개 타입 중 135개 타입이 중복(3.3%)! n  예: java.util.Date와 여기서 파생된 java.sql.Date 클래스 n  컴파일러가 문제 삼지 않는 이유 n  패키지가 다르다 n  사용자 입장에서 문제가 되는 이유 n  두 클래스를 동시에 import할 경우 명시적으로 한정해야 한다 à 모호성 문제를 수동으로 해소 추상화 악취 중 중복된 추상화
  23. 23. + 사례 연구 n  리펙터링 제안 n  java.sql.Date JavaDoc 문서: “SQL DATE 정의에 순응하기 위해, java.sql.Date 인스턴스가 감싼 밀리 초 값은 관련된 인스턴스가 위치한 특정 시간대에 맞춰 시, 분, 초, 밀리 초를 0으로 설정하는 방식으로 ‘정규화되어야’만 한다.” n  더 나은 설계안 n  java.sql.Date에서 java.util.Date 인스턴스를 감싸기 n  상속을 위임으로 변환 n  또한 java.sql.SQLDate로 이름 변경 추상화 악취 중 중복된 추상화
  24. 24. + 사례 연구 n  누락된 캡슐화 악취란? n  구현 변형을 계층 내부나 추상화 내부에서 캡슐화하지 않을 경우 발생하 는 악취 n  문제의 원인: OCP 위반(타입의 행동 양식은 변경이 아니라 확장에 의해 바꿔야 함) n  여파: 계층에 새로운 변형을 지원하려고 시도할 때마다 불필요한 클래스 ‘폭발’ 발생 캡슐화 악취 중 누락된 캡슐화
  25. 25. + 사례 연구 n  예제(1) n  데이터 암호화를 위한 Encryption 클래스: DES (Data Encryption Standard), AES (Advanced Encryption Standard), TDES (Triple Data Encryption Standard)를 포함해 알고리즘에 대한 다양한 선택이 가능 n  초보 개발자는 Encryption 클래스 내부에 EncryptUsingDES(), EncryptiUsingAES(), …와 같은 수많은 메소드를 추가 n  문제점 n  Encryption 클래스가 알고리즘 추가에 따라 점점 커짐(한번에 알고리즘 을 하나만 사용하더라도 덩치 큰 클래스를 가져와야 함) n  새로운 알고리즘 추가가 어려움 n  특정 알고리즘 하나만 재사용하기가 불가능 캡슐화 악취 중 누락된 캡슐화
  26. 26. + 사례 연구 n  예제(2) n  데이터 암호화를 위한 알고리즘 뿐만 아니라 다양한 유형의 데이터를 암 호화 n  내용 유형과 암호화 알고리즘 유형의 두 가지 변형이 존재 n  DESImageEncryption, AESTextEncryption, … n  문제점 n  구현에서 변형이 서로 뒤섞이며, 독자적으로 캡슐화되지 못함 n  클래스 폭발로 마무리 캡슐화 악취 중 누락된 캡슐화
  27. 27. + 사례 연구 n  리펙터링 제안 n  예제(1) n  EncryptionAlgorithm 인터페이스를 생성 n  DESEncryptionAlgorithm와 AESEncryptionAlgorithm는 EncryptionAlgorithm 인터페이스를 구현하고 각각 DES와 AES 알고 리즘을 정의 n  Encryption 클래스는 EncryptionAlgorithm 인터페이스에 대한 참조 를 유지 n  장점 n  Encryption 객체는 실행 시간에 특정 암호화 알고리즘으로 구성 가능 n  EncryptionAlgorithm 계층에 정의된 알고리즘은 다른 맥락에서 재사 용 가능 n  새로운 알고리즘 추가 용이 캡슐화 악취 중 누락된 캡슐화
  28. 28. + 사례 연구 캡슐화 악취 중 누락된 캡슐화 깨진 계층화 악취 다른 맥락에서 알고리즘 재사용 불가
  29. 29. + 사례 연구 n  리펙터링 제안 n  예제(2) n  두 가지 직교적인 관심사에 대해 독자적으로 변형을 캡슐화 캡슐화 악취 중 누락된 캡슐화
  30. 30. + 사례 연구 n  불충분한 모듈화 악취란? n  완벽하게 분해되지 않은 추상화 à 추가로 분해할 경우 크기/구현 복잡도 해소 가능 n  부풀어로은 인터페이스: 추상화의 공개 인터페이스에 엄청나게 많은 멤버 존재 n  부풀어오른 구현: 구현에 엄청나게 많은 메소드 존재/구현 복잡도가 과 도하게 높은 메소드가 하나 이상 존재 n  문제의 원인: 추상화를 관리 가능한 크기로 유지하지 못함 n  ‘연산과 클래스는 조화로운 크기가 되어야 마땅하다. 다시 말해, 크기 는 양극단을 피해야 마땅하다.” n  주의: SRP와 혼동 à 책임이 하나인 추상화면서도 여전히 크고 복잡할 수 있다. 유사하게, 작은 추상화면서도 여전히 책임이 여럿일 수 있다 모듈화 악취 중 불충분한 모듈화
  31. 31. + 사례 연구 n  불충분한 모듈화 악취란? n  완벽하게 분해되지 않은 추상화 à 추가로 분해할 경우 크기/구현 복잡도 해소 가능 n  부풀어로은 인터페이스: 추상화의 공개 인터페이스에 엄청나게 많은 멤버 존재 n  부풀어오른 구현: 구현에 엄청나게 많은 메소드 존재/구현 복잡도가 과 도하게 높은 메소드가 하나 이상 존재 n  문제의 원인: 추상화를 관리 가능한 크기로 유지하지 못함 n  ‘연산과 클래스는 조화로운 크기가 되어야 마땅하다. 다시 말해, 크기 는 양극단을 피해야 마땅하다.” n  주의: SRP와 혼동 à 책임이 하나인 추상화면서도 여전히 크고 복잡할 수 있다. 유사하게, 작은 추상화면서도 여전히 책임이 여럿일 수 있다. 모듈화 악취 중 불충분한 모듈화
  32. 32. + 사례 연구 n  예제: JDK에 존재하는 java.awt.Component 클래스 n  메소드가 332개(그 중 259개가 public으로 선언!) n  중첩된 내부 클래스가 11개, 필드가 107개(상수 포함) n  원시 코드: 10,102행 n  문제점 n  분석, 유지보수, 기능 추가 과정에서 이 클래스를 이해하기가 너무 복잡 하다! 추상화 악취 중 중복된 추상화
  33. 33. + 사례 연구 n  리펙터링 방안 n  부풀어오른 인터페이스 n  공개 인터페이스의 부분 집합이 밀접히 연관된 (응집력이 높은) 멤버를 포 함하면, 부분 집합을 독자적인 추상화로 추출 n  클래스가 멤버로 구성된 부분 집합을 둘 이상 포함하며 각 부분 집합의 응 집력이 높으면, 이런 부분 집합을 독자적인 클래스로 나눔 n  클래스 인터페이스가 클라이언트에 밀접한 메소드를 사용해 여러 클라이 언트를 서비스하면, 원본 인터페이스를 클라이언트에 밀접한 여러 인터페 이스로 분리하기 위해 ISP(Interface Segregation Principle)를 적용 n  부풀어오른 구현 n  메소드 논리가 복잡하면, 해당 메소드에 있는 코드를 단순하게 만들기 위 해 사적인 도우미 메소드를 도입 n  불충분한 모듈화 악취와 함께 다면적인 추상화 악취까지 포함하는 추상화 라면, 각 책임을 분리된 (새로 만들거나 기존에 존재하는) 추상화에 캡슐화 추상화 악취 중 중복된 추상화
  34. 34. + 사례 연구 n  넓은 계층 악취란? n  중간 타입이 빠졌을지도 모른다는 사실을 암시하는 ‘너무’ 넓은 상속 관계 가 존재하는 악취 n  문제의 원인: ‘의미있는 일반화 적용’이라는 요소 기술을 위반 n  빠진 중간 타입은 계층에 있는 클라이언트가 하위 타입을 직접 참조하 게 강제할지도 모른다. 이런 의존성은 계층의 변경 가능성과 확장 가능 성에 영향을 미친다. n  타입 내부에 불필요한 중복이 있을지도 모른다(중간 타입의 부족으로 인해 공통성을 적절히 추상화할 수 없다) n  영향: 동일 층에 하위 타입 수가 너무 많으면(9개를 넘길 경우), 계층을 이해하거나 사용하기가 더 어려워짐 계층 악취 중 넓은 계층
  35. 35. + 사례 연구 n  예제 n  JDK 7에서 바로 아래 하위 클래스 36개를 거느리는 java.util.EventObject 클래스 n  문제점 n  형제자매 클래스가 엄청나게 많아서 이해가 어려움 계층 악취 중 넓은 계층
  36. 36. + 사례 연구 n  리펙터링 제안 n  중간 타입을 도입 n  예: TreeEvent 계층 악취 중 넓은 계층
  37. 37. + 설계에서 코드로 n  설계 리펙터링은 코드 리펙터링과 밀접한 관련이 있다! n  깨끗한 설계를 유지하는 동시에 깨끗한 코드를 유지해야 한다
  38. 38. + 참고 자료
  39. 39. +

×