블로그 이미지
따뜻한 코드 만들기 리본매냐

카테고리

분류 전체보기 (34)
.NET (6)
Database (5)
Daily life (11)
세미나 후기 (0)
마음의 지식 (7)
코드 (1)
Python (1)
외출 (3)
Total
Today
Yesterday

달력

« » 2024.4
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

공지사항

태그목록

최근에 올라온 글

'마음의 지식'에 해당되는 글 7건

  1. 2011.07.15 const 보다는 readonly가 좋다 - Effective C#
  2. 2010.09.16 의미 있는 이름
  3. 2010.07.22 Adapter - 구조패턴
  4. 2010.04.29 5. 형식 맞추기
  5. 2010.04.01 Composing Method 1
  6. 2010.03.25 대체 뭐가 문제야(Are your lights on?)
  7. 2010.02.02 개념적 무결성
// 컴파일 타임 상수
public const int _Millennium = 2000;
// 런타임 상수
public static readonly int _ThisYear = 2011;

컴파일타임 상수를 이용하면 컴파일 시 상수형 변수가 사용되는 위치가 실질적인 값으로 치환된다.
if (myDatatime.Year == 2000)

반면 런타임 상수는 수행시 평가된다. 상수에 대한 참조자가 위치한다.
이러한 특성으로 컴파일타임 상수는 단지 내장자료형(정수형, 실수형 등) 이나 enum, string에 대해서만 사용된다.

readonly는 어떤 자료형으로도 선언이 가능하며, readonly 상수를 포함하는 타입의 생성자나 선언시 초기화 방법을 이용하여 값을 초기화 할 수 있다.
DateTime 구조체형의 readonly 상수는 정의할 수 있으나, const 상수는 정의 할 수 없다.

또한, readonly는 타입의 인스턴스 별로 서로 다른 값을 가질 수 있으나 const 상수는 기본적으로 항상 static이므로 항상 동일한 값만을 가질 수 있다.

예)
public class UsefulValues
{
       public static readonly int StartValue = 5;
       public const int EndValue = 10;
}

다른 어셈블리에서 아래와 같이 참조한다.
for (int i = UsefulValues.StartValue; i < UsefulValues.EndValue; i++)
{
          Console.WriteLine("Value is {0}", i);
 }

결과)
Value is 5
Value is 6
...
Value is 9


시간이 지나 새로운 버전을 다음과 같이 수정하였다.

public class UsefulValues
{
       public static readonly int StartValue = 101;
       public const int EndValue = 120;
}
다음과 같은 결과를 바랄 것이다
Value is 101
Value is 102
...
Value is 120
하지만 아무것도 나오지 않는다.

C# 컴파일러는 const필드에 대해 reference 대신에 값 그 자체를 대체한다. EndValue의 값은 여전히 9!!
반면, readonly는 수행시까지 참조자를 유지하며, 참조시점에 값으로 평가된다.

const 값이 바뀌는 경우에는 모든 어셈블리에 대해서 재컴파일을 수행해야 한다. 하지만 reaonly 형으로 정의된 상수의 값이 바뀌는 경우는 단순히 변경된 어셈블리만을 컴파일하여 배포하여도 이진 호환성은 유지된다.
const는 컴파일 시에 값으로 평가되어야 하는 곳에서만 사용되어야 한다. 
Posted by 리본매냐
, |

 아이가 태어났습니다. 아니 태어나기도 전에 부모들은 배속의 소중한 아기에게 이름을 지어줍니다. 그렇게 지어진 이름은 부모의 소망과 사랑이 가득 담기게 되는거죠..
 이름을 짓는 일은 중요한 일입니다. 다른 것과 구별되는 특징이기도 하구요. 의미가 주어지기도 하죠. 우리는 소중한 물건이나 애완동물에게도 예쁜 이름을 지어줍니다.


내가 그의 이름을 불러 주기 전에는
그는 다만
하나의 몸짓에 지나지 않았다.
 
내가 그의 이름을 불러 주었을 때
그는 나에게로 와서
꽃이 되었다.
 
내가 그의 이름을 불러 준 것처럼
나의 이 빛깔과 향기에 알맞은
누가 나의 이름을 불러 다오.
 
그에게로 가서 나도
그의 꽃이 되고 싶다.
 
우리들은 모두
무엇이 되고 싶다.
너는 나에게 나는 너에게
잊혀지지 않는 하나의 눈짓이 되고 싶다.
     
                                  - 김춘수 '꽃'



개발자가 코드를 짜면서 가장 많이 하는 생각은 뭘까요??
비즈니스 로직을 생각하는 일? 객체지향?? 음.. 여러가지가 있겠지만 가장 많이라고는 할 수 없지만 그 중 많은 비중을 차지하는 것은 변수나 클래스, 함수명을 짓는 일이 아닌가 합니다.
 팀내에 네이밍 규칙이 있더라도 말이죠.. 항상 고민되는 이름들...
  하루에 코드에 지어주는 이름이 몇개나 될까요??
 

 그럼 본론으로 들어가서 ...
 '클린코드'에서 나오는 이름을 잘 짓는 간단한 몇가지 규칙에 대해 이야기합니다.

 
  • 의도를 분명히 밝혀라
     좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많다. 
    주의 깊게 살펴 지어진 이름이 (자신을 포함해) 코드를 읽는 사람을 행복하게 한다.
    의도가 드러나는 이름을 사용하면 이해와 변경이 쉬워진다.
  • Ex)
    public List<int[]> getThem(){
       List<int[]> list1 = new ArrayList<int[]>();
       for (int[] x : theList)
         if (x[0] == 4)
           list1.add(x);
      return list1;
    }
    이름 개선
    public List<int[]> getFlaggedCells(){
       List<int[]> flaggedCells = new ArrayList<int[]>();
       for (int[] cell : gameBoard)
         if (cell[STATUS_VALUE] == FLAGGED)
             flaggedCells.add(cell);
      return flaggedCells;
    }
    코드 개선
    public List<Cell> getFlaggedCells(){
       List<Cell> flaggedCells = new ArrayList<Cell>();
       for (Cell cell : gameBoard)
         if (cell.isFlagged())
             flaggedCells.add(cell);
      return flaggedCells;
    }


  • 그릇된 정보를 피하라
    그릇된 단서는 코드의 의미를 흐린다.
    여러 계정을 그룹으로 묶을 때 타입이 List가 아니라면 accountList라고 명명하지 않는다.
    프로그래머에게 List라는 단어는 특수한 의미다. accountGroup, bunchOfAccounts, 아니면 단순히 Accounts 라고 명명한다.
    서로 흡사한 이름을 사용하지 않도록 주의한다. XYZContoroolerForEfficientHandlinfOfStrings, XYZContoroolerForEfficientStorageOfStrings 이 둘의 차이점을 알겠는가 ㅡㅡ;;;;
    그릇된 정보를 제공하는 다른 예로 소문자 L, 대문자 O 는 대문자 I, 숫자 0과 구분이 힘들다. 글꼴을 바꾸는 해결책이 있다. 나는 Bitstream을 좋아한다. ^^ 이름을 바꾸는 것도 좋은 방법이긴하다.
  • 의미있게 구분하라
    컴파일러나 인터프리터만 통과하는 코드는 개발자 스스로 문제를 일으킨다.
    피해야할 이름
    저자의 의도가 전혀들어나지 않는 이름 : a1, a2, a3... aN
    불용어(Noise Word) : variable(변수이름이 ㅡㅡ; ), CustomerObject와 Customer class를 찾았다. 차이가 멀까??)
    class 라는 이름이 있다는 이유만으로 klass 라고 만듦
  • 발음하기 쉬운 이름을 사용하라
    발음하기 어려운 이름은 토론하기도 어렵니다.
    "흠, 여기 비 씨 알 3 씨 엔 티에 피에스 지 큐 int가 있군요...." 어떻게 들리는가?
  • 검색하기 쉬운 이름을 사용하라
    문자 하나를 사용하는 이름과 상수는 텍스트 코드에서 쉽게 눈에 띄지 않는다.
    변수나 상수를 코드 여러곳에서 사용한다면 검색하기 쉬운 이름이 바람직하다.
  • 인코딩을 피하라
    이름에 인코딩할 정보는 아주 많다. 유형이나 범위 정보까지 인코딩에 넣으면 그만큼 이름을 해독하기 어려워진다.
    • 헝가리식 표기법
      과거 윈도우 C API는 헝가리식 표기법을 매우 중요하게 여겼다. 당시에는 컴파일러가 타입을 점검하지 않았으므로 프로그래머는 타입을 기억할 단서가 필요했다.
      객체는 강한 타입이며, 현태적인 IDE는 코드를 컴파일하지 않고도 타입 오류를 감지할 정도로 발전
    • 멤버 변수 접두어
      클래스와 함수는 접두어가 필요없을 정도로 작아야 한다.
      멤버 변수를 다른 색상으로 표시하거나 눈에 띄게 보여주는 IDE를 사용하는 것이 좋다.
    • 인터페이스 클래스와 구현 클래스
      인터페이스 클래스 이름과 구현 클래스 이름 중 하나를 인코딩해야 한다면 구현 클래스 이름을 택하자(작자의 생각)
  • 자신의 기억력을 자랑하지 마라
    • 문자 하나를 사용하는 변수 이름은 문제가 있다. 루프에서 반복 횟수를 세는 변수 i,j,k는 괜찮다. 단, 루프 범위가 아주 작고 다른 이름과 충돌하지 않을때!!
    • 일반적으로 프로그래머들은 아주 똑똑하다. 하지만...
    • 똑똑한 프로그래머와 전문가 프로그래머 사이에서 다른 점
      • 전문가 프로그래머는 명료함이 최고라는 사실을 이해한다. 전문가 프로그래머는 자신의 능력을 좋은 방향으로 사용해 남들이 이해하는 코드를 작성한다.
  • 클래스 이름
    • 클래스 이름과 객체 이름은 명사나 명사구가 적합니다.
      ex) Customer, WikiPage, Account, AddressParser (좋은예)
    • Manager, Processor, Data, Info  와 같은 단어는 피하고, 동사는 사용하지 않는다.
  • 메소드 이름
    • 동사나 동사구가 적합
      ex) postPayment, deletePage, save (좋은예)
    • 접근자Accessor, 변경자 Mutator, 조건자 Predicate 는 자바빈 표준에 따라 값앞에 get, set, is를 붙인다.
    • 생산자를 중복해 정의할 때는 정적 팩토리 메소드를 사용한다.
      Complex fulcrumPoint = Complex.FromRealNumber(23.0);
       
  • 기발한 이름은 피하라
    • 재미는 의미를 파악하기 힘들다.
  • 개념 하나에 단어 하나를 사용하라
    • 동일한 코드 기반에서 동의어를 섞어 쓰면 혼란스럽다.
    • 일관성 있는 어휘는 코드를 사용할 프로그래머가 반갑게 여길 선물이다.
  • 말장난을 하지 마라
    • ex) add
      같은 맥락이 아닌데도 '일관성'을 고려해 add라는 다너를 선택한다. 지금까지 구현한 add 메소드는 두 개를 더하거나 이어서 새로운 값을 만든다고 가정하자. 새롭게 작성하는 메소드는 집합에 값 하나를 추가한다. 이 메소드를 add라 불러도 괜찮을까?
    • 집중적인 탐구가 필요한 코드가 아니라 대충 훑어봐도 이해할 코드가 목표
  • 해법 영역에서 사용하는 이름을 사용하라
    • 코드를 읽을 사람도 개발자라는 사실을 명심한다. 기술적인 개념에는 기술적인 이름이 가장 적합하다.
  • 문제 영역과 관련있는 이름을 사용하라
    • 적절한 '프로그래머 용어'가 없다면 문제 영역에서 이름을 가져온다. 유지보수시 전문가에게 의미를 물어 파악할 수 있다.
  • 의미있는 맥락을 추가하라
    • 변수에 좀더 의미있는 맥락이 필요할까?
      firstName, lastName, street, houseNumber, city, state, zipcode -> 어떤 변수인가?
      위의 변수없이 state만 있다면 어떤 변수인지 알아챌까?
    • 접두어나 클래스 명으로 맥락은 분명해진다.
      addrFirstName, addrLastName, addrStreet, addrState…. (접두어 이용)
      Address.FirstName, Address.LastName, Address.Street….(
      클래스 이용)

  • 불필요한 맥락을 없애라
    • 일반적으로 긴이름보다 짧은 이름이 낫다.단, 의미가 분명한 경우에 한해서
    • ex) accountAddress, customerAddress는 Address 클래스 인스턴스로 좋은 이름이나 클래스 이름으로 적합하지 못하다.

코드를 개선하려는 노력을 중당해서는 안 된다. 다른 사람이 짠 코드를 손본다면 리팩토링 도구를 사용해 문제 해결 목적으로 이름을 개선하라. 단기적인 효과는 물론 장기적인 이익도 보장한다.

Posted by 리본매냐
, |


의도 
클래스의 인터페이스를 사용자가 기대하는 인터페이스 형태로 적응(변환)시킵니다.
서로 일치하지 않는 인터페이스를 갖는 클래스들을 함께 동작시킵니다.

다른 이름 
래퍼(Wrapper)

동기
이미 존재하기는 하지만 현재 이를 사용하고자 하는 클래스와는 아무런 연관 없이 개발될 클래스이거나, 서로 일치하지 않는 인터페이스를 갖는 클래스들을 잘 통합하여 하나의 응용프로그램을 개발해야할 때. 
활용성
기존 클래스를 사용하고 싶은데 인터페이스가 맞지 않을 때
아직 예측하지 못한 클래스나 실제 관련되지 않은 클래스들이 기존 클래스를 재사용하고자 하지만, 이미 정의된 재사용 가능한 클래스가 지금 요청하는 인터페이스를 꼭 정의하고 있지 않을 때. 다시 말해, 이미 만든 것을 재사용하고자 하나 이 재사용 가능한 라이브러리를 수정할 수 없을 때
[객체 적응자(object adapter)만 해당됨] 이미 존재하는 여러 개의 서브클래스를 사용해야 하는데, 이 서브클래스들의 상속을 통해서 이들의 인터페이스를 다 개조한다는 것이 현실성이 없을 때. 객체 적응자를 써서 부모 클래스의 인터페이스를 변형하는 것이 더 바람직함
Posted by 리본매냐
, |
1. 목적 : 오늘 구현한 코드의 가독성은 아픙로 바뀔 코드의 품질에 지대한 영향을 미친다.
             원활한 소통을 장려하는 코드 형식은?

2. 적절한 행 길이를 유지하라
   일반적으로 큰 파일보다 작은 파일이 이해하기 쉽다.
  
   신문 기사처럼 작성하라
   위 -> 아래
   이름은 간단하면서도 설명적으로 짓는다.
   파일 첫 부분은 고차원 개념과 알고리즘 설명 -> 의도를 세세하게 묘사 -> 마지막 : 가장 저차원 함수와 세부 내역

   개념은 빈 행으로 분리하라
   왼쪽 -> 오른쪽, 위 -> 아래
   각 행은 수식이나 절을 나타내고, 일련의 행 묶음은 완결된 생각 하나를 표현
   생각 사이는 빈 행을 넣어서 분리
   빈행은 새로운 개념을 시작한다는 시각적 단서

   세로 밀집도
   세로 여백이 개념을 분리한다면 세로 밀지보는 연과성

   수직 거리
   서로 밀접한 개념은 세로로 가까이 두어야한다. 두 개념이 서로 다른 파일에 속하다면 규칙은  통하지 않는다. 하지만 타당한 근거가 없다면 서로 밀접한 개념은 한 파일에 속해야한다.
   protected 변수를 피해야 하는 이유 중 하나

   변수 선언 : 변수는 사용하는 위치에 최대한 가까이 선언
   인스턴스 변수 : 클래스 맨 처음, 변수간 세로로 거리를 두지 않는다. (논쟁이 분분)

   변수 선언을 어디서 찾을지 모두가 알고 있어야한다.

   종속 함수 : 한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치
                    호출하는 함수를 호출되는 함수보다 먼저 배치

   개념적 유사성 : 어떤 코드는 서로를 끌어당긴다. 친화도가 높을수록 코드를 가까이 배치

   세로 순서 : 함수 호출 종속성을 아래 방향으로 유지
                    호출되는 함수를 호출하는 함수보다 나중에 배치
                    신문 기사와 마찬가지로 가장 중요한 개념을 가장 먼저 표현 
                    가장 중요한 개념을 표현할 때는 세세한 사항을 최대한 배제

3. 가로 형식 맞추기
    한 행은 가로로 얼마나 길어야 적당할까?
   
   가로 공백과 밀집도
   가로로는 공백을 사용해 밀접한 개념과 느슨한 개념을 표현

   가로 정렬
   필자는 유용하지 못하다고 생각함. 오히려 정렬하지 않으면 중대한 결함을 찾기 쉽다.

   들여쓰기
   계층 표현, 구조가 한눈에 들어온다.

4. 팀 규칙 : 팀은 한 가지 규칙에 합의해야한다. 좋은 소프트웨어 시스템은 읽기 쉬운 문서로 이뤄진다. 일관적이고 매끄러워야 한다. 
   





  
Posted by 리본매냐
, |

1) 이름 : Extract Method(136) 
    요약 : 그룹으로 함께 묶을 수 있는 코드 조각이 잇으면, 코드의 목적이  잘 들어나도록 메소드의 이름을 지어 별도의 메소드로 뽑아낸다. 
    동기 : 지나치게 긴메소드를 보거나, 목적을 이해하기 위해서 주석이 필요한 코드를 보면 그 부분을 하나의 메소드로 뽑아낸다.

 짧은 메소드의 이점
1) 다른 메소드에서 사용될 확률이 높아진다. 
2) 고수준의 메소드를 볼 때 일련의 주석을 읽는 것 같은 느낌이 들도록 할 수 있다.
3) 오버라이드 하는 것이 쉽다.
이름을 잘 지었을 때만 그 진가가 드러나므로, 이름을 지을 때 주의

               

Posted by 리본매냐
, |

문제를 접했을 때 생각해봐야할 6가지 질문

1. 무엇이 문제인가?
2. 그것은 어떤 문제인가?
3. 정말로 무엇이 문제인가?
4. 누구의 문제인가?
5. 문제는 어디에서 비롯되는가?
6. 정말로 그것을 해결하고 싶은가?
Posted by 리본매냐
, |
개념적 무결성

좋은 기능들이긴 하지만 서로 독립적이고 조화되지 못한 아이디어들을 담고 있는 시스템보다는 여러가지 다양한 기능이나 갱신된 내용은 비록 빠졌더라도 하나로 통합된 일련의 설계 아이디어를 반영하는 시스템이 훨신 좋다.


개념적 무결성을 이루는 방법
: 사용의 쉬움
: 단순성과 직설성

한 사람 또는 마음이 잘 맞는 극소수의 사람들의 합의에 의하여 설계된 결과



Posted by 리본매냐
, |

최근에 달린 댓글

최근에 받은 트랙백

글 보관함