Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

좋은코드작성하기

23 960 vues

Publié le

  • Soyez le premier à commenter

좋은코드작성하기

  1. 1. 좋은 코드 작성하기   JDLab  교육자료     •  작성자 s@jdlab.org   S대 석사   JDLab  엔지니어  
  2. 2. Part  1.  Code  Complete  
  3. 3. 정보 은닉  
  4. 4. 비밀을 숨겨라   •  내부 작동을 가능한 한 숨겨라   •  정보은닉  :     –  Private  Method  사용하기   –  literal을 상수로   –  Custom  데이터 타입 사용   –  루틴 설계   bad  code   good  code   int  employeeID;   EmployeeID    myID;   프로그래머가 >,  <,  = 과 같 은 연산을 수행할 수 있는 분위기를 조성  
  5. 5. 멤버 함수와 데이터   •  클래스에 가능한 적은 수의 루틴을 유지하라   •  클래스에서 호출되는 루틴의 수를 최소화하라   – 클래스가 참조한 클래스가 많을 수록 오류률도 높아 진다.   – 다른 클래스에 대한 간접 루틴 호출을 최소화하라   (o) otherClass.function() (x) otherClass.function().anotherFunction()
  6. 6. 함수  
  7. 7. 나쁜 함수의 예   Find  Answers  Before  Click  Next  Page  
  8. 8. 함수 –  Answer  (1/10)     문서가 없다!  
  9. 9. 함수 –  Answer  (2/10)   함수의 이름   - 함수 역할이 불분명하다  
  10. 10. 함수 –  Answer  (3/10)   •  inputRec가 입력 변수라면, 이 변 수의 값은 변경되지 않아야 한다.   •  변수의 값이 변경되기로 되어 있다 면, 변수의 이름이 inputRec여서 는 안된다.  
  11. 11. 함수 –  Answer  (4/10)   함수의 목적이 하나 가 아니다.       함수는 반드시 분명 하게 정의된 하나의 목적만을 가져야 한 다.  
  12. 12. 함수 –  Answer  (5/10)   •  함수가 잘못된 데이터로부터 자 신을 방어하지 않는다.     •  나누기 0 오류는 항상 주의!  
  13. 13. 함수  –  Answer  (6/10)   •  함수가 전역 변수를 읽고 쓴다.    
  14. 14. 함수 –  Answer  (7/10)   •  함수의 배치가 나 쁘다.   •  구조에 대해서 힌 트를 제공하지 않 고있다.  
  15. 15. 함수 –  Answer  (8/10)   함수가 여러가지 매직넘 버를 사용하고 있다.  
  16. 16. 함수 –  Answer  (9/10)   사용되지 않는 parameter   prevColor는 루틴 내에서 값을 할당받지 않음 에도 불구하고 &로 표시되었다.  
  17. 17. 함수 –  Answer  (10/10)   •  사람들이 이해할 수 있는 parameter의 최대 한 계는 7개이다.     •  함수의 parameter가 잘못정렬되어 있으며 문 서화도 되어 있지 않다.  
  18. 18. 함수   함수을 작성하는 이유   •  복잡성을 줄인다.   •  이해하기 쉬운 중간 단계의 추 상화를 도입한다.   •  코드의 중복을 피한다.   •  서브클래싱을 지원한다.   •  순서를 숨긴다.   •  복잡한 boolean  테스트를 단 순화한다.   •  이식성을 향상시킨다.   •  성능을 개선한다.   효율적인 함수를 방해하는 장애물   •  간단한 함수도 작성하라   –  가독성   –  유지 보수  
  19. 19. 간단한 함수 사용의 예  
  20. 20. 함수가 하는 모든 것을 표현하라   •  (x)  ComputeReportTotals()       •  (o)ComputeReportTotalsAndOpenOutputFile()    
  21. 21. 뚜렷한 특징이 없는 동사들을 피하라   •  (x)  HandleCalculacon(),  PerformServices(),   HandleOutput()   •  (o)  FormatAndPrintOutput()  
  22. 22. 좋은 함수 이름   •  함수 이름을 숫자만으로 구분하지 말라   – (x)  OutputUser,  OutputUser1,  OutputUser2   •  필요한 길이만큼 이름을 만들어라   – 최적화된 함수 이름의 평균적인 길이는 9~15자  
  23. 23. 좋은 함수 이름   •  리턴 값에 대한 설명을 사용하라   – printer.IsRead()   •  동사 다음에 목적어를 사용하라   – PrintDocument()   •  반의어를 정확하게 사용하라   – (x)  FileOpen/_lclose()   •  공통적인 연산을 위한 규약을 만 들어라   – (x)  employee.id.Get()            dependent.GetId()   반의어 목록   add  /  remove   increment  /  decrement   open  /  close   begin  /  end   insert  /  delete   show  /  hide   create  /  destroy   lock  /  unlock   source  /  target   first  /  last   min  /  max   start  /  stop   get  /  put   next  /  previous   up  /  down   get  /  set   old  /  new  
  24. 24. 변수  
  25. 25. 변수의 초기화에 대한 지침   •  각 변수가 처음 사용되는 지점의 근처에서 변수를 초기화하고 정의   •  final이나 const를 사용   •  counter,  accumulator를 주의   – 일반적인 오류 :  다음 번 재사용 전에 초기화하는 것 을 잊는다.   •  입력 parameter의 타당성을 검사   •  컴파일러의 경고 메시지(WARNING)를 활용  
  26. 26. 변수 이름의 효과   •  변수 이름은 10~16자로 유지   •  defini4on  name  +  modifica4on  name 으로 되 도록 사용   – 예)  TotalStudent,  AveragePoint,  MaxHeight   •  Num 의 관습적인 위치   – numCustomer  :  전체 고객의 수   – customerNum  : 현재 고객의 인덱스   è 되도록 Num을 사용하지 말것!  Count,  Total,  Index 등을 사용  
  27. 27. 변수 사용 시 폭과 수명을 줄여라   •  변수의 폭을 줄인다는 것은?   –  한 변수의 사용은 한군데에서   •  변수의 수명을 줄인다는 것은?  (마지막 줄 – 첫번째줄 – 사용된횟수)  
  28. 28. 변수 사용 시 범위를 최소화   •  루프에서 사용되는 변수는 루프 바로 앞에서 초기화 한다.   •  변수를 사용하기 전까지 변수에 값을 할당하지 않는다.   •  필요한 경우에만 변수의 범위를 늘린다.   – 범위 선택 :  private  >  protected  >  package  >  global  
  29. 29. 변수를 한 목적으로만 사용   •  각 변수를 한가지 목적만을 위해서 사용하라   – 임시 변수의 사용을 명확히 하자.     •  숨겨진 의미를 갖는 변수를 피하라   •  E.g.)  pageCount  :  출력된 페이지 수 +    -1이면 오류   vs  
  30. 30. 변수 이름의 효과   •  Flag   –  (X)  Bool  flag;        (O)  Bool  dataReady   •  결과값 기록   –  참/거짓을 함축하는 이름을 사용한다   (X)  Bool  status;        (O)  Bool  StatusOK   –  긍정적인 변수 이름을 사용한다   (X)  Bool  notFound;    (O)  Bool  isFound;  
  31. 31. if-­‐then-­‐else  사용방법   Bad  Example  
  32. 32. if-­‐then-­‐else  사용방법   1.  복잡한 테스트를 boolean  테스트 호출로 단순화 시킨다.   2.  가장 흔한 경우를 앞에 놓는다.   3.  모든 경우를 다루었는지 확인한다.   3   2   1  
  33. 33. 기타 :  Switch-­‐Case  의 사용   •  case 순서 정하기   – 가장 정상적인 경우를 앞으로 한다   – 알파벳 순으로 또는 숫자 순으로 case를 나열한 다 è 가독성 향상   •  case문 사용 팁   – case  문이 하는 일을 간단하게 유지한다 •  복잡하면, 루틴을 작성하고 해당 루틴을 호출한다.   – 오류를 검출하기 위해서 default절을 사용한다.  
  34. 34. Part  2.  Refactoring   좋은 프로그래머는 그들의 코드를 정리하는데 약간의 시간을 할애한다.     깔끔한 코드가 복잡하고 지저분한 코드보다 변경하기 쉽다는 것을 알고 있고,     처음부터 코드를 깔끔하게 작성하는 경우는 거의 없다는 것을 알고 있기 때문이다.  
  35. 35. 프로그램 작업을 어렵게 하는것들   •  읽기 어려운 프로그램   •  중복된 로직   •  특별한 동작을 요구하는 프로그램   •  복잡한 조건문  
  36. 36. 우리가 원하는 프로그램   •  읽기 쉽고,     •  모든 로직은 중복되지 않도록 한곳에서만 존재하고,   •  기존동작을 위험에 빠뜨릴 변경을 허용하지 않으며,     •  조건로직은 가능한 단순하게 표현된 프로그램  
  37. 37. 리팩토링!!!   •  외부 동작을 바꾸지 않으면서 내부 구조를 개선   •  버그가 끼어 들 가능성을 최소화하면서 코드를 정리   •  코드가 작성된 후에 코드의 디자인을 개선하는 것  
  38. 38. 언제 리팩토링을 해야 하는가?   •  삼진 규칙   1. 어떤 것을 처음 할 때는 그냥한다.   2. 두번째로 비슷한 것을 하게 되면, 중복 때 문에 주춤하지만 그냥 중복되도록 한다.   3. 세번째로 비슷한 것을 하게 되면, 그 때 리 팩토링을 한다.   •  기능을 추가할 때 리팩토링을 하라   •  버그를 수정할 때 리팩토링을 하라   •  code  review를 할때 리팩토링을 하라  
  39. 39. 코드속의 나쁜냄새의 예   •  Message  Chains   – 어떤 객체를 얻기 위해 다른 객체에 물어보고, 다른 객체는 다시 또 다른 객체에 물어보고...   •  Data  Class   – 데이터만 저장하고 다른 클래스에 의해 조작됨   •  Middle  Man   – method  대부분이 다른 클래스로 위임하고 있을 때    
  40. 40. Refactoring  List   Extract  Methods   Move  Method   Move  Field   Extract  Class   Subsctute  Algorithm   Replace  Type  with  Subclasses   Replace  Type  Code  with  State/Strategy   Introduce  Parameter  Object   Introduce  Null  Object   Separate  Query  from  Modifier   Encapsulate  Downcast  
  41. 41. Extract  Methods   비슷한 일을 하므로 함수로 묶는다  
  42. 42. Move  Method  : 다른 클래스로 옮긴다   overdraqCharge(){    _type.overdraqCharge(_daysOverdrawn);   }   Account   isPremium();   overdraqCharge(int  _daysOverdrawn);   AccountType   AccountType  _type;   int  _daysOverdrawn;     overdraqCharge(){    if(  _type.isPremium()  ){    …    }   ….   }   Account   isPremium()     AccountType   accountType에 있는   메소드를 더 많이 호출함   Account의 overChange함수가 AccountType의 함수를 이용하므로,   AccountType으로 함수를 이동  
  43. 43. Extract  Class   name     getPhoneNumber     Person   name   officeAreaCode   officeNumber     getPhoneNumber   Person   areaCode   number     getPhoneNumber     Telephone   Number   Extract   Class   officeTelephone   Person클래스에서 TelephoneNumber과 관련된 일이 많음 èTelephoneNumber  클래스를 만들어서 Person  클래스의 부담을 줄여 준다  
  44. 44. Subsctute  Algorithm   읽기 쉬운 알고리즘으로 교체  
  45. 45. Replace  Type  with  Subclasses   ENGINEER  :  int   SALESMAN  :  int   type  :  int   Employee   Employee   Engineer   Salesman   Enum등으로 Sales/Engineer  구분 하지 말것 è 서브클래싱  
  46. 46. Replace  Type  Code  with  State/Strategy    subclass를 할 수 없을때   ENGINEER  :  int   SALESMAN  :  int   type  :  int   Employee   Employee   Type   Engineer   Salesman   Employee   1   SubClassing  이 불가능하다면?  EmployeeType  Class를 만들어라  
  47. 47. Introduce  Parameter  Object   amountInvoicedln(start:  Date,  end:Date)   amountReceivedIn(start:  Date,  end:Date)   amountOverdueIn(start:  Date,  end:Date)     Customer   amountInvoicedln(DataRange)   amountReceivedIn(DataRange)   amountOverdueIn(DataRange)     Customer   Date  _start   Date  _end   DataRange   •  같이 사용되는 Parameter 는 Object로 넘겨라   •  start  +  end  =  range     •  x+y  =  point    
  48. 48. Introduce  Null  Object   Null  Object를 사용  
  49. 49. Separate  Query  from  Modifier   getTotalOutStandingAndSetReadyForSummaries   Customer     getTotalOutStanding   getReadyForSummaries   Customer   Query하나에 함수 하나!  
  50. 50. Encapsulate  Downcast   X   Cascng  은 함수 안으로 숨겨라  
  51. 51. FIN.   last  modified.  2014.03.19  
  52. 52. APPENDIX.  
  53. 53. 코드 속의 나쁜 냄새 (1/4)      -­‐  리팩토링을 언제 해야 하는가?   Bad  Smells   특징   Duplicated  Code   Long  Method   Large  Class   Long  Parameter  List   Divergent  Change   한 클래스가 다른 이유로 인해 여러가지 방법으로 자주 변경되는 경우에 발생.   Shotgun  Surgery   변경을 할때마다 다양한 클래스를 조금씩 수정함.   Feature  Envy   method가 자신이 속한 클래스보다 다른 클래스에 속해 있는 데이터를 더 많이 수정할 때   Data  Clump   항상 함께 사용하는 데이터들이 있으면, 그 데이터를 새로운 객체로 만든 다.  
  54. 54. 코드 속의 나쁜 냄새 (2/4)      -­‐  리팩토링을 언제 해야 하는가?   Bad  Smells   특징   Primicve  Obsession   methods가 적은 작은 객체를 사용하는 것을 꺼림.   e.g.)Range  class,  전화번호, 우편번호 등의 특별한 문자열을 위한 class   Switch  Statements   switch 문을 볼때면 항상 polymorphism을 생각해야 함.   (하나의 메소드에만 영향을 끼치는 몇 개의 경우에는 굳이 바꿀 필요는 없다.)   Parallel  Inheritance   Hierarchies   한 클래스의 서브클래스를 만들면, 다른 곳에도 모두 서브 클래스를 만들 어 주어야 함.   Lazy  Class   클래스를 생성할 때마다 그것을 유지하고, 이해하기 위한 비용이 발생함.   Speculacve  Generality   “언젠가 이런 종류의 일을 처리하기 위한 기능이 필요할텐데….”  사용하 고 있지 않는 것이 유지되고 있을 때.   Temporary  Field   인스턴스 변수가 평소에는 값이 없다가 특정 상황에서만 세팅되는 경우.     보통은 객체의 모든 변수가 값을 가지고 있을거라고 기대함.  
  55. 55. 코드 속의 나쁜 냄새 (3/4)      -­‐  리팩토링을 언제 해야 하는가?   Bad  Smells   특징   Message  Chains   어떤 객체를 얻기 위해 다른 객체에 물어보고, 다른 객체는 다시 또 다른 객체에 물어보고...   Middle  Man   method  대부분이 다른 클래스로 위임하고 있을 때   (delegacon  사용이 너무 많을 때)   Inappropriate  Incmacy   클래스가 지나치게 연결되어 있을 때   e.g.)상속은 종종 과도한 연결을 유도할 수 있다.     Alternacve  Classes  with   Different  Interface   같은 작업을 하지만 다른 signature를 가지는 메소드   Incomplete  Library  Class   라이브러리 클래스에 원해는 메소드가 없을 때   Data  Class   데이터만 저장하고 다른 클래스에 의해 조작됨  
  56. 56. 코드 속의 나쁜 냄새 (4/4)      -­‐  리팩토링을 언제 해야 하는가?   Bad  Smells   특징   Refused  Bequest   서브클래스가 상속받은 것 중에서 원치 않거나 필요하지 않는 것이 존재할 때.   comments   코드가 서투르기 때문에 주석이 있는 경우.   •  주석을 써야 할 것 같은 생각이 들면, 먼저 코드를 리팩토링 하여 먼저 코드 를 리팩토링 하여 주석이 불필요하도록 하라.   Do  refactoring,  NOW!  

×