Clean Code that Works.

출처. CODE COMPLETE 5장

클래스를 작성 하는 이유

실세계의 객체를 모델링하라
 - 실세계의 객체를 모델링하는 것이 클래스를 생성하는 유일한 이유는 아니겠지만, 그래도 여전히 정당한 이유이다! 여러분의 프로그램이 모델링하는 실세계의 모든 객체 형에 대한 클래스를 생성하라. 객체에 필요한 데이터를 클래스에 입력하고, 객체의 행위를 모델링하는 서비스 루틴들을 구축한다.

추상 객체들을 모델링하라
 - 클래스를 생성하기 위한 또 다른 정당한 이유는 추상 객체, 즉 실체가 없는 실세계의 객체지만 다른 실질적인 객체의 추상화를 제공하는 객체를 모델링하기 위한 것이다. Shape 객체가 좋은 예이다. Circle과 Square는 실제로 존재하지만, Shape는 다른 구체적인 도형들에 대한 추상화이다.
   프로그래밍 프로젝트를 진행할 때, 추상화는 Shape에서처럼 미리 만들어져 있지 않기 때문에 분명한 추상화를 이끌어내기 위해서 더욱 열심히 일해야 한다. 실세계의 엔티티로부터 추상적인 개념을 만들어내는 과정은 결정저이지 않으며, 서로 다른 설계자들이 서로 다른 일반 법칙들을 추상화할 것이다. 예를 들어, 여러분이 원이나 정사각형, 삼각형과 같은 기하학적인 모양을 모른다면, 찌그러진 모양, 줄기 모양, 폰티악 아즈텍 모양과 같이 특이한 모양을 생각해낼 것이다. 적절한 추상화 객체를 생각해내는 것은 객체 지향 설계에서 가장 어려운 난제 중 하나이다.

복잡성을 줄여라
 - 정보를 감추기 위해서 클래스를 생성하면 그러한 정보에 대해 생각할 필요가 없을 것이다. 물론, 클래스를 작성할 때에는 정보에 대해서 생각해야 할 것이다. 하지만 클래스를 작성하고 난 후에는, 세부사항들을 잊고 내부 작동 방식에 대해서 몰라도 클래스를 사용할 수 있어야 한다. 클래스를 생성하는 또 다른 이유들에는 코드의 크기를 최소화하거나, 유지 보수성을 향상시키거나, 정확성을 향상시키기 위한 것들이 있다. 하지만 클래스의 추상적인 능력이 없다면, 복잡한 프로그램을 지적으로 관리하는 것이 불가능할 것이다.

복잡성을 고립시켜라
 - 복잡한 알고리즘이나 큰 데이터 집합, 뒤얽힌 통신 프로토콜 등 어떤 형태든지 간에 복잡성은 오류를 유발할 가능성이 있다. 오류가 발생했을 때, 오류가 코드 전체에 퍼져 있지 않고 클래스 내에 지역화되어 있다면 훨씬 찾기 쉬울 것이다. 오류를 수정하기위한 변경 사항들은 다른 코드에 영향을 미치지 않을 것이다. 왜냐하면 한 클래스만 변경되고 다른 코드는 건드리지 않을 것이기 때문이다. 만약 더 좋고, 간단하며, 신뢰할 수 있는 알고리즘을 발견했을 때, 해당 알고리즘이 클래스에 고립되어 있다면 오래된 알고리즘을 보다 쉽게 대체할 수 있을 것이다. 개발을 하는 도중에도 다양한 설계를 쉽게 시도해 볼 수 있고 가장 잘 작동하는 설계를 유지하기가 쉬울 것이다.

세부적인 정보를 숨겨라
 - 세부적인 정보를 감추고자 하는 바람은, 세부 사항이 복잡한 데이터베이스에 대한 접근처럼 복잡하거나 특정한 데이터 멤버에 숫자나 문자가 저장되는 것처럼 평범한지에 상관없이 클래스를 생성하기 위한 훌륭한 이유이다.

변경의 영향을 제한하라
 - 변경할 가능성이 있는 부분을 고립시켜서 변경의 영향을 단일 클래스나 적은 수의 클래스로 제한한다. 변경될 가능성이 제일 높은 부분을 가장 쉽게 변경할 수 있도록 설계하라. 변경할 가능성이 있는 부분에는 하드웨어에 의존적인 부분, 입력/출력, 복잡한 데이터 형, 비즈니스 규칙들이 있다.

전역 데이터를 숨겨라
 - 만약 전역 데이터를 사용할 필요가 잇다면, 세부적인 구현 사항을 클래스 인터페이스 뒤에 숨길 수 있다. 접근 루틴들을 통해서 전역 데이터를 다루면, 적연 데이터를 직접적으로 다루는 것에 비해서 여러 가지 이점을 제공한다. 여러분은 프로그램을 변경하지 않고 데이터의 구조를 변경할 수 있다. 여러분은 데이터에 대한 접근을 감시할 수 있다. 또한, 접근 루틴을 사용하는 원칙을 지키면 그 데이터가 정말로 전역인지에 대해서 생각하게 된다. 실제로 "전역 데이터"가 단순한 객체 데이터일 뿐이라는 점이 명백해지는 경우가 종종 있다.

매개변수의 전달을 간소화하라
 - 만약 어떤 매개변수를 여러 루틴들 사이에서 전달하고 있다면, 매개변수를 객체 데이터로 공유하는 클래스에 이 루틴을 포함시켜야 할 필요성이 있다는 것을 암시한다. 매개변수 전달을 간소화하는 것 자체가 목표가 아니지만, 수많은 데이터를 전달한다는 것은 다른 클래스 구성이 더 잘 작동할 것임을 말해준다.

중앙 집중 관리하라
 - 한 곳에서 작업을 처리하는 것은 좋은 아이디어이다. 제어에는 많은 형식이 있다. 테이블에 있는 엔트리들의 수에 대한 정보도 한 형식이고, 디바이스들(파일, 데이터베이스 연결, 프린터 등)의 관리도 또 다른 형식이다. 그리고 데이터베이스로부터 읽고 쓰는 클래스를 작성하는 것도 집중화된 관리의 또 다른 형식이다. 만약 데이터베이스가 파일이나 메모리 내의 데이터로 변환되어야 한다면, 그러한 변경 사항이 한 클래스에만 영향을 미칠 것이다.
   집중화된 관리의 기본 개념은 정보 은닉과 유사하지만, 여러분의 프로그래밍 도구 상자에 추가할 가치가 있는 유일한 경험적인 힘을 갖고 있다.

코드의 재사용을 도와라
 - 코드를 잘 분리된 클래스에 입력하면 하나의 큰 클래스에 포함되어 있는 것보다 다른 프로그램에서 쉽게 재사용될 수 있다. 비록 어떤 코드 섹션이 프로그램내의 한 곳에서만 호출되고 큰 클래스의 일부로써 이해하ㅣㄱ 쉽다고 하더라도, 해당 코드 섹션이 다른 프로그램에서 사용될 것 같다면 별도의 클래스에 입력 하는 것이 좋다.

프로그램군(family)을 위한 계획을 작성하라
 - 만약 프로그램이 변경될 것으로 예상하고 있다면, 그러한 부분들을 별도의 클래스로 입력하여 고립시키근 것이 좋다. 그러면 프로그램의 나머지 부분에 영향을 미치지 않고 클래스를 변경할 수 있거나, 대신 완전히 새로운 클래스를 입력할 수 있다. 단순히 한 프로그램의 모습만이 아니라 전체 프로그램군의 모습을 생각하는 것이 전체적인 변경 내용을 예상하는 데 크게 도움이 된다.

연관된 기능을 패키지화하라
 - 만약 여러분이 정보를 숨기거나, 데이터를 공유하거나, 유연한 계획을 세울 수 없는 경우에는, 관련된 기능들을 삼각법 함수들, 통계 함수들, 문자열 처리 루틴들, 비트 처리 루틴들, 그래픽 루틴들과 같이 적당한 그룹으로 패키지화할 수 있다. 클래스는 연관된 기능들을 결합하는 한 가지 수단이다. 여러분은 언어에 따라서 패키지나 네임 스페이스, 또는 헤더 파일을 사용할 수 있다.

특정한 리팩토링을 수행하라
 - 특정한 리팩토링을 수행하면 하나의 클래스를 두 개의 클래스로 변환하고, 델리게이트를 감추고, 미들 맨을 제거 하고, 확장 클래스를 만다는 방법으로 ㅅ로운 클래스들이 만등러진다. 이 섹션을 통해서 소개된 임무를 더 잘 달성하고자 한다면 이러한 새로운 클래스를 만들어 볼 수 있다.

피해야 할 클래스

만능(GOD) 클래스를 생성하지 말라
 - 모든 것을 알고 있고 모든 것을 할 수 있는 전지전능한 클래스를 생성하지 말라. 만약 어떤 클래스가 Get()과 Set() 루틴을 사용하여 다른 클래스로 부터 데이터를 얻는 데 시간을 보내고 있다면(즉, 다른 사람의 일에 끼어들어서, 무엇을 해야 하는지 말하고 있다면), 그 기능은 만능(god) 클래스보다 다른 클래스로 구성하는 것이 더 좋지 않은지 물어 보라

관련이 없는 클새스들을 제거하라
 - 만약 클래스가 행위는 없이 데이터로만 구성된다면, 그 클래스가 정말로 클래스인지 확인해 보고, 그 클래스를 강등시켜 클래스의 멤버 데이터가 하나 이상의 다른 클래스들의 특성이 될 수 있는지 골해 본다.

동사가 따라오는 클래스를 피하라
 - 데이터는 없이 행위로만 구성된 클래스는 일반적으로 클래스가 아니다. DatabaseInitialization()이나 StringBuilder()와 같은 클래스를 다른 클래스의 루틴으로 변환할 것을 고려해 본다.


체크 리스트 : 클래스의 품질

추상 데이터 형
 - 프로그램에 있는 클래스들을 추상 데이터 형으로 생각하고, 그러한 관점에서 클래스의 인터페이스들을 평가해 보앗는가?

추상화
 - 클래스가 핵심적인 목적을 갖고 있는가?
 - 클래스의 이름이 잘 지어졌고, 클래스의 이름이 핵심적인 목적을 설명하고 있는가?
 - 클래스의 인터페이스가 일관성 있는 추상화를 제공하는가?
 - 클래스의 인터페이스가 클래스의 사용 방법을 분명히 하고 있는가?
 - 여러분이 클래스의 서비스가 어떻게 구현되었는지에 대해서 생각할 필요가 없을 정도로 클래스의 인터페이스가 추상적인가? 클래스를 블랙박스로 취급할 수 있는가?
 - 다른 클래스들이 클래스의 내부 데이터를 쓸데없이 참견할 필요가 없을 만큼 클래스 서비스가 완벽한가?
 - 관련 없는 정보를 클래스에서 제거 하였는가?
 - 클래스를 컴포넌트 클래스로 분할하는 것에 대해서 생각해 보았는가? 그리고 최대한 분할하였는가?
 - 클래스를 수정할 때, 클래스 인터페이스의 무결성을 유지하고 있는가?

캡슐화
 - 클래스가 멤버에 대한 접근성을 최소화하고 있는가?
 - 클래스가 멤버 데이터의 노출을 피하고 있는가?
 - 클래스가 프로그래밍 언어가 허용하는 한 다른 클래스들로부터 세부적인 구현 사항들을 감추고 있는가?
 - 클래스가 파생 클래스와 사용자들에 대한 가정을 피하고 있는가?
 - 클래스가 다른 클래스에 독립적인가? 느슨하게 결합되어 있는가?
 
상속
 - 상속이 "is a"관계를 모델링 하기 위해서만 사용되었는가?
 - 클래스의 설명 문서가 상속 전략을 기술하고 있는가?
 - 파생 클래스가 오버라이드 불가능한 루틴에 대해서 "오버라이딩"을 피하고 있는가?
 - 공통적인 인터페이스, 데이터, 행위가 상속 트리에서 최대한 높은 곳에 있는가?
 - 상속 트리가 적절하게 얕은가?
 - 기본 클래스에 잇는 모든 데이터 멤버들이 protexted 대신 private 인가?

구현에 대한 다른 문제들
 - 클래스가 7개 이하의 데이터 멤버들을 포함하고 있는가?
 - 클래스가 다른 클래스에 대한 직접적이고 간접적인 루틴 호출을 줄였는가?
 - 클래스가 반드시 필요한 경우에만 다른 클래스와 협력하는가?
 - 모든 멤버 데이터가 생성자에서 초기화 되었는가?
 - 만약 얕은 복사를 생성해야 하는 합당한 이유가 없다면, 클래스가 얕은 복사 대신 깊은 복사로 사용되도록 설계되었는가?

언어에 따른 문제
 - 여러분이 사용하고 있는 프로그래밍 언어에서 클래스에 대한 이슈들을 조사하였는가?


환경 설정 파일을 불러 들일때 사용하는 파일.

다양한 파일 포맷을 지원한다.
  • Properties files
  • XML documents
  • Windows INI files
  • Property list files (plist)
  • JNDI
  • JDBC Datasource
  • System properties
  • Applet parameters
  • Servlet parameters
이정도? ㅋ

http://commons.apache.org/configuration/
저기 가면 다운 로드 받을 수 있다.

간단한 사용 설명은
http://moai.tistory.com/789

요기 블로그에 가서 확인

text/html
application/pdf
video/quicktime
applicaton/java
image/jpeg
application/jar
application/octet-stream
application/x-zip

등등..

지금은 아키텍트 보다는 구현이 더 좋기 때문에...
생각을 해보지는 않았지만 나중에는 아마 해보고 싶을꺼 같다.

책 읽으면서 느끼는게 우왕.. 역시 아키텍쳐는 어렵군화.. -ㅂ-..

대규모 프로젝트를 진행해야 할때는 챙겨야 하는 선행 조건이 장난 아니게 많다 -ㅂ-...

code2 complete
chaptor 3 준비는 철저하게 : 선행조건 에 나온 요점 정리를 보면

- 구현을 준비함에 있어서 가장 중요한 목표는 위험 감소이다. 준비 작업이 위험을 증가시키지 않고 감소시킬 수 있도록 한다.
- 만약 품질이 뛰어난 소프트웨어를 개발하고 싶다면, 처음부터 끝까지 소프트웨어 개발 ㅗ가정 내내 품질에 대한 관심을 유지해야 한다. 초기의 품질에 대한 관심은 나중에 관심을 갖는 것보다 제품의 품질에 훨씬 큰 영향을 미친다.
- 프로그래밍을 시작하기 전에, 적절한 준비의 중요성과 함께 소프트웨어 개발 과정에 대해서 상사와 동료를 교육하는 일도 프로그래머의 몫이다.
- 프로젝트의 종류가 구현의 선생 조건에 중대한 영향을 미친다. 반복적으로 진행해야 하는 프로젝트가 있는 반면, 순차적으로 진행해야 하는 프로젝트도 있다.
- 만약 요구 사항 개발이 제대로 이루어지지 않았다면, 문제의 중요한 사항들을 놓칠 수 있다. 요구 사항 변경은 구현 다음 단계부터는 처음보다 20~100배 정도로 비용이 들기 때문에, 프로그래밍을 시작하기 전에 요구 사항이 맞는지 확인 해야 한다.
- 만약 구조적인 설계가 제대로 이루어지지 않았다면, 구현 시에 올바른 문제를 잘못된 방법으로 해결할 수 잇다. 잘못된 구조로 작성된 코드가 증가할수록 구조적인 변경 비용이 증가하므로, 아키텍처가 맞는지 확인해야 한다.
- 구현 선행 조건에 어떤 접근 방법을 적용햇는지 이해해야 하며, 그에 따라서 적절한 구현 방법을 선택한다.


프로젝트를 진행하면서 구현시에 항상 구현에만 급급하지 않고 프로젝트의 전체적인 모습을 볼 수 있도록 항상 생각하는 프로그래머가 되자. !!

CODE COMPLETE


와.. 두껍다 -ㅅ-;;;
이번달은 개념서를 좀 읽어야 겠다.
이거랑.. 생각하는 프로그래밍.

이번엔 집중해서 재빨리 읽어 버리자!!!

음..
자바의 정석에서 발췌.

1. 제네릭스(Generics)
- 제네릭스는 컬력신 프레임웍과 관련된 기능으로 컬렉션에 저장하는 객체의 타입을 컴파일시에 체크하기 때문에 객체의 타입 안정성을 높이고 꺼낼 때는 자동으로 형변환해주기 때문에 편리하다.

2. 향상된 for문
- 배열
    for (배열의 타입 변수명 : 배명) {
          // 반복할 문장
    }
- 컬렉션
    for (컬렉션에 저장된 요소의 타입 변수명 : 컬렉션) {
          // 반복할 문장
    }

3. 오토박싱
- 컬렉션에는 객체로 저장해야하기 때문에 기본형 값을 저장하기 위해서는 Integer나 Long과 같은 Wrapper클래스를 사용해야했다.
  그러나 이제부터는 기본현 값을 직접 컬렉션에 저장할 수 있다. 컴파일러에 의해서 자동적으로 Wrapper클래스로 변환되어 저장되는 데 이것을 오토박싱 이라고 한다.
  뿐만아니라 저장되 값을 꺼낼 때도 변환과정을 거치지 않고도 기본형 형태의 값을 바로 얻을 수 있는데 이것을 언박싱 이라고 한다.

4. 타입에 안전한 열거형
- 이전 방식으로는 타입이 달라고 값이 같으면 조건식결과가 true였으나, 새로 도입된 타입에 안전한 영거형에서는 실제 값이 같아도 타입이 다르면 조건식의 결과가 false가 된다.

5. 가변인수
- 기존에는 메서드의 매개변수 개수를 고정적으로 지정해주어야만 했으나 JDK1.5 부터는 동적으로 매개변수의 개수를 지정해 줄 수 있게 되었다.

6. static import문
- import문을 사용하면 크래스의 패키지명을 생략할 수 있는 것과 같이 static import문을 사용하면 static멤버를 호출할 때 클래스명을 생략할 수 있다.

7. StringBuilder
- StringBuilder는 StringBuffer와 완전히 동일한 클래스이다. 다만 동기화 처리를 하지 않기 때문에 멀티쓰레드 프로그래밍에서는 사용하면 안되지만 멀티쓰레드 프로그래밍이 아닌 경우에는 StringBuffer보다 빠른 성능을 보장한다.
  동기화여 부를 제외하고는 두 클래스가 기능상으로 완전히 동일하기 때문에 코드에서 StringBuffer를 StringBuilder로 바꾸기만 하면 된다. 즉, StringBuffer타입의 참조 변수를 선언한 부분과 StringBuffer의 생성자만 바꾸면 된다는 말이다.

properties 는 iso-8859-1 인코딩방식을 쓰기 때문에 한글을 입력해서 나중에 쓸때 깨진다.
이클립스에서 이것을 안깨지고 보게 할려면.. 간단한 플러그인을 추가 하면 된다.

이클립스 find and install 메뉴에 가서
새로운 리모트 사이트를 추가 하는데.
이름은 간단하게 Properties
주소는 http://propedit.sourceforge.jp/eclipse/updates
이렇게 추가를 하고 업데이트를 하면

다운로드 받을수 있는 목록이 3가지 뜬다.
거기서 가운데껏만 빼고(3.1.x 버전용)
나머지 두개를 인스톨한 후 사용하면 된다.

http://cafe.naver.com/snp6th.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=422
참고 사이트

루씬 검색 결과에 검색어 문자열 하일라이팅을 추가 하기 위하여..

http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/SearchStyleText.htm

위의 소스를 참고하여 .. 머 똑같이 -_-;;
하여서 구현.

깔끔하고 이해하기 쉽운 소스를 만들기 위해 구입한 책.
리팩토링 중에서 자주 쓰이는 것들을 간단한 예제와 함께 잘 정리해 두었다.
아주 쉽게 읽을수 있었던 책.

주요 내용은

- 매직넘버를 심볼릭 정수로 치환하기 : 소스에 '100'이라고 쓰여져 있다면.
- 제어 플래그의 삭제 : 제어 플래그 때문에 코드를 읽기 힘들다면.
- assertion의 도입 : '이것이 성립될 것' 이라고 하는 주석이 있으면.
- NULL 오브젝트 도입 : Null 체크가 너무 많다면.
- 메소드의 추출 : 코드가 너무 길어 읽기 힘들다면.
- 클래스의 추출 : 클래스의 책임이 너무 많다면.
- 타입코드를 클래스로 치환하기 : 오브젝트 식별에 int가 사용되고 있다면.
- 타입코드를 서브클래스로 치환하기 : 타입코드마다 동작이 다르다면.
- 타입코드를 State/Strategy로 치환하기 : 타입코드마다 동작이 다르다면.
- 오류 코드를 예외로 치환하기 : 오류 처리가 어지럽게 흩어져 있다면.
- 생성자를 Factory Method로 치환하기 : 클래스명이 new로 하드코딩 되어 있다면.
- 관찰되는 데이터의 복제 : 모델과 뷰가 혼재되어 있다면.
- 상속을 위임으로 치환하기  : IS-A관계가 아님에도 불구하고 상속하고 있다면.
- 위임의 은폐 : 위임 클래스까지 보인다면.
- 상속의 분할 : 상속이 얽혀 있다면.

아.. 보면서 내가 짰던 프로그램을 생각해보니..
리팩토링 해야할 것들이 ... ㄷㄷㄷㄷ
주말엔 소스 리팩토링좀 하자 ;ㅁ ;

이클립스에서 assertion을 도입하기 위해서는 약간의 옵션을 손봐주어야 한다.

메뉴에 Window -> Preferences -> Java -> Compiler -> Compliance and Classfiels and set
에 들어간후.

Compiler Compliance Level : 1.4
use default compliance을 체크를 풀고
Generated .class files compatibility 1.4 로 바꾸고
Source compatibility를 1.4로 바꾸면 된다.
Compiler Compliance level을 1.4로 마지막으로 바꾸어준다.

그리고 실행하기전에 VM 인수를 -ea 를 줘서 사용할 수 있도록 한다.

출처 : http://cafe.naver.com/5758 부관리인(upright00)님