코컴2 585p를 보던중 복잡한 if 문 대신 데이터 테이블을 활용하는 기법을 보던중..

 

 

이벤트 = 헤더 + 구체적 데이터

이벤트 헤더 테이블 = 이벤트 헤더 타입(key)에 따른 동작될 리스너들(value)의 집합

 

이벤트 처리

 1.이벤트가 있다면 가져온다.

 2.이벤트의 헤더를 읽는다.

 3.헤더로부터 이벤트의 종류를 해석한다.(열거형 decode)

 4.이벤트 헤더 테이블에서 동작할 연산(리스너)을 찾는다.

 5.해당 리스너를 수행한다.

 

awt 이벤트 멀티 캐스터의 동작과 유사하지 않은가..  위의 이벤트 헤더 테이블이 이벤트 소스 풀인가 머가 하는 개념일테고..

(실제 이벤트 핸들링은.. 옵저버패턴을 통한 콜백, 상속트리를 이용한 템플릿 메소드 패턴, 또 머있엇드라..아.. 리스너 생성자

 에 내가 정의한 리스너 넣어서 재정의 해주는게.. 아.. 그게 뭐였더라.. 데코레이터였나? 글고 내 리스너 재정의할때 편하게

 끔 어댑트 윈도우 리스너 머시기도 있었고 )

 

c에서 콜백용 함수 테이블을 만들어 사용했던걸 본 기억도 있다.(일반적인 메세지 처리에서 콜백형식 = awt.component(윈도

우,다이얼로그등)이 이벤트를 정의하고 클라이언트가 구독하는 방식으로, delegate를 통해 event에 내 메서드를 등록하는

방식이다)

 

 

****************************************************************

아래는 대박 설계?

****************************************************************

class AbstractField

{

   public abstract void readAndPrint(FieldData, FileStatus);
}

 

class FloatingPointField implements AbstractField

{

   protected final void readAndPrint(FieldData, FileStatus)

   {

       sysout(xxx);
    }
}

 

class IntergerField implements AbstractField

{...}

class StringField implements AbstractField

{...}

...

***************

 

 

 

enum FieldType

{

FieldType_FloatingPoint,

FieldType_Integer,

FieldType_String,

...
}

struct FieldData

{

String xxx

xxx xxx

...
}

 

struct FieldDescription

{

   FieldData fieldData;

   FieldType fieldType;
}

 

 

FieldDescription[] fieldDescription = FieldDescription.load(); //임의로

 

AbstractField[] fields = new AbstractField[5]; //매직 넘버는 안되지만 이해의 편의상

 

fields[FIELD_FLOATINGPOINT] = new FloatingPointField();

fields[FIELD_INTEGER] = new IntergerField();

fields[FIELD_STRING] = new StringField();

...

*******************

 

int fieldIndex = 1;

while( (fieldIndex <= numFieldIInMessage) && (fileStatus == OK) )

{

   fieldType = fieldDescription[fieldIndex].fieldType;

   fieldData = fieldDescription[fieldIndex].fieldData;
  

   fields[fieldType].readAndPrint(fieldData , fileStatus);
}

********************

 

반복적으로 볼것!

 

테이블을 이용해 비지니스 로직을 단순화 시키자!!

 

(2013/12/2추가) 아래의 RUBY의 스크립팅 처리 방식이 위와 같이 테이블을 만드는 방식 같다.

*************************************

(ex)

?

1
2
3
4
5
6
7
#ruby
  puts 'What is your name?'
  name = gets
  process_name(name)
  puts 'What is your quest?'
  quest = gets
  process_quest(quest)

 

******************************************

 

********************************************

추가로 0~17 =공통, 18,19,20... 65=개별적  66~?? =공통일때

0~17, 66~?를 하나의 키값으로 사상하는 방법

max( min( 66 , num) , 17)   <--- 아름다운 방법이다.

추가로 18,19,20,..65를 5단위로 쪼개서 사상하고 싶을때

num을 5로 나누고(왜냐하면 몫이 같을테니까) 적절하게 max() , min()을 조합해주면.. 이건 hash의 ?

 

그리고 595p의 인덱스 접근 방식에선 인덱스 테이블및 기타 참조 테이블을 활용해 주 데이터 테이블에 접근하는 효율성을

고찰하는데.. 이건db 테이블및 키값 설계 & select 할때 참조 키 선택에 따른 효율성과 같은 개념 아닌가? ㅎㄷㄷ

*************************

 

데코레이터 vs 스트레티지 패턴의 차이가 명확치 않다. 데코레이터가 생성자를 통해 특정 객체를 받아들이고 그 객체의 메서드를

자신의 메서드 이름으로 사용하는 거였나?  스트레티지도 다른 객체를 받아들여 자신의 행동을 변환시키는 거였고.. (Word , Format)  데코레이터는 메서드 동작을 동적으로 확장시키는 것이었다. 자신의 동작 a에 추가로 자신과 같은 타입의 다른 객체 b의 동작b'을 동적으로 받아서 추가로 사용하는 것 (한마디로 또다시 파생 시킬 필요없이 동작을 확장한다)

 

 

 

체크리스트:테이블을 활용한 기법들

1.복잡한 논리 코드에 대한 대안으로 테이블을 활용한 기법들을 고려해 보았는가

2.복잡한 상속 구조에 대한 대안으로 테이블을 활용한 기법들을 고려해 보았는가

3.코드를 변경하지 않고 데이터를 수정할 수 있도록 테이블의 데이터를 외부에 저장하여 실행시

  읽는 방법을 고려해 보았는가?(스크립트 처리)

4.직관적인 배열 인덱스를 통해서 직접적으로 테이블에 접근할 수 없다면(나이예제), 인덱스

  계산 코드를 코드에 중복하여 작성하는 대신 접근 키 계산 코드를 루틴으로 작성하였는가?

 

 

요점 정리

1.테이블은 복잡한 논리 코드와 상속 구조에 대한 대안을 제공한다. 만약 프로그램의 논리나 상속

  트리가 혼란스럽다고 생각한다면, 참조 테이블을 사용하여 단순화시킬 수 있는지 확인해 본다.

2.테이블을 사용할 때 고려해야 하는 한가지 핵심 사랑은 테이블 접근 방법을 결정하는 것이다.

  여러분은 직접 접근 방식이나 인덱스 접근 방식, 또는 단계적 접근 방식을 사용하여 테이블에 접근할 수 있다.

3.테이블을 사용할 때 고려해야 하는 또 다른 핵심 사항은 테이블에 입력할 내용을 결정하는 것이다.

by givingsheart 2014. 1. 1. 15:31

1.일반적인 숫자

- 사용시 매직넘버(아무런 설명없는 리터럴 숫자)를 피할것  (cf)0,1은 배열의 시작 인덱스, 반복문의 제어식에 사용됨으로 예외

- divide by zero 방지

- 형 변환을 명확히 수행

- 비교연산은 동일한 형간에 (정수vs정수,실수vs실수) 예전 로또 번호의 문자열 "25"의 범위 체크를 위해 정수 1~45 간 대소

  비교를 리마인드, 추가로 문자열의 대소비교 compareto 의 사전식 비교 특징을 기억

 

2.정수

-정수 나눗셈을 검사 (ex) 7/10 = 0.7이 아닌 0  =>젯수 > 피젯수 였나.. 하여간 조심

-오버 플로를 조심 (ex) int형의 표현 범위는? 자바에선 unsigned는 없다. 앞으로 최대 숫자가 증가할 것인지, 변화가 없을것인지

  예측해야한다.

 

3.부동 소수점

-float은 7자리였나 , double 은 15자리 였나

-서로 크기가 매우 다른 수간에 더하기 빼기 조심  float형 1,000,000.00 + 0.1 = 1,000,000.0 임

-동치 비교 조심 0.1 * 10 의 결과는 10이 아닌, 0.9999999

  (sol) equal를 재정의 if(절대값 a-b < 0.0001) 이면 true 식으로

-회계 프로그램등을 만들때 확실한 계산을 위해선 그제 배운 BigDecimal 인가를 사용

 

4.문자와 문자열

-코드에 때려박는 매직 문자열 조심

  (sol) 당연하지만 이러한 리소스는 외부 파일로 별개 관리후 read/write 해야함. 코드에서 데이터(외부파일)와 프로세스

  부분의 분리가 필요 (게임 스크립터라면 로직및 연산도 외부로 빠질수 있음)  <-- 상용 툴들 확인하기.

  현지화 문제에 항상 걸리는 것이.. 문자열, 인코딩 방식,해당 국가별 관련 정책,현지 법인의 특별 요청 등

 

 -현재 내경우엔 이클립스 내부 세팅을 모든 문자 인코딩을 UTF-8로 했는데 이건 옳은 결정인가? (기존 작업물을 제대로 읽지

  못하는 문제가 있고, 앞으로 작업할 것들에 문제는 없을까?)

 

 -프로그램내 여러 서브시스템에서 서로 다른 인코딩을 쓰고 있다면, 입/출력 처리 부분에서 동일한 타입으로 변환해서 처리

 

 -예전에 윈도우 property를 파일로 모두 출력했을때.. /t만 먹고, /n or /r 은 통하지 않았었다. 그 이유는?

 

5.불린

-복잡한 불린 표현식을 조건식에 여러개 배치하지 말것, 불린 변수의 이름을 명확하게 할것

  (ex) if(표현식1 && 표현식2 || 표현식3)   -->  b1 =  표현식1; b2 = 표현식2; b3 = 표현식3;  b4 = b1&&b2; if(b4 || b3) 요렇게

  풀어 쓰는 식으로 (물론 내가 조금 오버하긴 했음.. 불린 변수의 이름을 명확히 줘야하기도 하고..)

  (etc) 반복문의 초기화 식을 반복문 시작 바로 위 라인에 배치해볼것? for(int index=XX.curIndex; i<XX.length; i++)  ->

         int index=XX.curIndex;  .. 이유나 의미를 까먹었음

 

6.열거형

-컴파일러에게 입력값 평가를 세밀하게 시킬수 있음. (ex) int = -327xx ~ 327xx 라면 ok, 그러나 열거형의 경우 Day day =

  Day.Monday ~ Day.Sunday 1~7에 해당하는 범위가 아니면, 컴파일러가 잡아줄수 있음. 물론 엉뚱한 타입을 집어 넣는

  것도 방지해줄테고.

 

-타당하지 않은 값 검사할것: if나 switch문에서 else , default 부분에서 처리

 

 

7.명명된 상수의 유용성: Max를 앞에 붙일지, 뒤에 붙일지에 대해 저자는 형식의 통일성및 중요한 의미 Max가 도드라져 보인

  다고 뒤에 붙일것을 권유함.. 근데 내 생각은 max를 앞에 붙이는게 이클립스 자동완성 기능 ctril space를 통해 사용하기

  쉬웠음. 내부의 많은 변수간에 역할별 카테고리를 나누는 유용성도 있을테고.. static final int lottoNumMax = 45; VS

  maxlottoNum = 45; 

 

8.배열 다룰때 조심할 점인데.. 컨테이너를 사용할 것이니 생략함

 

 

etc)자바에서 참조형이라는 개념을 어떻게 구현했는지 어렴풋이 감을 잡았다.(포인터 사용의 특수한 기법중.. 코컴 464p

그림 참고 )

 

(ex) Object의 인스턴스 크기를 100byte 라고 가정하고 Object를 힙에 할당한다고 사용자가 요청시 new Object(); 

컴파일러는 실제론 104byte를 할당하고 앞의 4byte를 참조 카운트를 기록하기 위해 사용한다. 일반적으로 메모리 접근시엔

앞의 4btyte 다음의 번지부터 리턴해주지만, 삭제시엔 앞의 4byte에 저장된 해당 메모리에 대한 참조수를 확인해 삭제 시킨다.

 

*********************************************************************************************************

(중요)문득 지난주에 이런 저런 플러그인을 설치한답시고(현업 수준의 적응력을 키우려고) 선생님께 이것저것 물어보다

        듣게된 조언이 떠올랐다. "내가 어떤 프로젝트를 하고 필요하기 때문에 특정 플러그인을 설치하는 것이지 플러그인이

        존재하기 때문에 이런 저런 프로젝트를 플러그인에 맞추어 하는것이 아니라는 점."

 

        목적과 수단을 혼동하지 말것! 지훈 형님의 가르침과 일맥상통하는 부분이다. 주변인들의 좋은 영향을 받아 조금이라

        도 성장해야만 한다!

 

        (sol)다음주부터 1.JSP를 실전 수준으로 프로젝트에 적용(내가 사용자에게 무엇을 웹을 통해 서비스 할것인가,어떻게

        할것인가), 2.오라클 DB 12버전 삭제후 재 설치(9~11버전)->계정 생성-> 이클립스 연동-> 프로젝트에 사용   start!

        프로젝트는 로또로 할지, 지난번 떠올린 아이디어를 실제 구체화 시켜서 진행할지.. 깊은 고민이 필요하다.

 

         maven에서 배웠듯 단지 목표(마감일)를 수립하고, goal = 결과물을 만들어낸다. 이것을 반복해 결과물을 키워간다.

         하루 일별 시간표+결과를 포함하는 단기목표를 세울 필요성이 느껴짐.(divide 퀀커 다!.. 스펠링이 머였드라.. )

        

         또 다른 대안으론, 웹 커뮤니티에 참여해 공동 프로젝트 개발에 참여해 보는 방법이 있을 것이다. (조금 더 정보

         탐색이 필요)

***********************************************************************************************************

 

 

by givingsheart 2014. 1. 1. 15:25

1.일반적인 사항

 

a.루틴이 잘못된 입력 데이터로부터 스스로를 보호하는가?

b.선행 조건과 후행 조건을 포함한 가정들을 문서화 하기 위해서 어설션을 사용하였는가?

c.어셜션이 절대로 발생해서는 안 되는 조건들을 문서화 하기 위해서만 사용되었는가?

d.아키텍쳐나 고수준 설계에서 구체적인 오류 처리 기법들을 명시하고 있는가?

e.아키텍쳐나 고수준 설계에서 오류 처리가 견고성이나 정홧성 중 어느것을 중점적으로 여기는가?

f.오류 손상 효과를 포함하고 오류를 처리하기 위해서 필요한 코드를 줄이기 위한 방책을 만들었는가?

g.디버깅 보조 도구들이 코드에서 사용되었는가?

h.디버깅 보조 도구들이 간편하게 활성화 하거나 비활성화 할 수 잇는 방법으로 설치 되었나?

i.방어적인 프로그래밍 코드의 양이 적절한가? 너무 많거나 적지 않은가?

j.개발 시 오류를 간과할 수 있도록 공격적인 프로그래밍 기법들을 사용하였는가?

 

2.예외

a.프로젝트가 예외를 처리하기 위해서 규격화된 접근 방법을 정의하였는가?

b.예외 사용의 대안들을 고려해 보았는가?

c.가능하다면 비-지역적인 예외를 던지는 대신 오류가 지역적으로 처리되고 있는가?

d.코드가 생성자와 소멸자에서 예외를 던지지 않는가?

e.모든 예외들이 예외를 던지는 루틴과 맞는 수준에 있는가?

g.각 예외가 예외와 관련된 모든 배경 정보를 포함하고 있는가?

h.빈 catch블록은 없는가? 비어 있다면 타당한 이유를 표시했는가?

 

3.보안문제

 

a.버퍼 오버프롤우,SQL 명령문 주입, HTML 코드 주입, 정수 오버플로우, 그 밖의 악의적인 입력과 같은

  나쁜 입력 데이터를 검사하는가?

b.모든 오류 리턴 코드를 검사하였는가?

c.모든 예외가 잡히는가?

d.오류 메시지가 시스템을 부수려는 공격자에게 도움을 줄 수 있는 정보를 제공하지 않는가?

by givingsheart 2014. 1. 1. 15:24

1.추상 데이터 형(우리 실세계에 존재하는 실재적(생물&사물등의 개체,데이터),개념적인 것(비지니스등)들을 내가 목적하는

  프로그램에 맞도록 추출해 개념화 한 것으로, 각각의 추상 데이터는 서로간 독립적으로 식별될 수 있는 개념이며 서로간

  관계성을 가지고 있다.)

 

 

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

 

 

=>추상:공통된 데이터&행동을 추출한 독립적인 개념. a.설계도(상위클래스,인터페이스클래스) or b.틀(클래스vs 객체) or

   c.사용자의 시각에서 표현되어진 서비스용 인터페이스의 형태를 정의하는 것or c2.타 패키지,클래스,메서드에 대해 자신과의

   소통 방법을 정의하는 것 

 

   (나는 c2를 내부용 인터페이스, 외부용 인터페이스로 구분을 지었는데, 인터페이스란 개념을 "상대에 대한 자신의 사용법"을

   정의한다로 생각해보면, 조금 더 세밀한 분류가 가능할듯하다. 예전에 인터페이스란 용어를 나는 a,c 두개의 개념으로 구분을

   했는데.. 내가 개념을 잘못 잡는 것일까? 상수화(final) vs 리터럴의 경운 구분을 시켰는데.. 인터페이스란 용어를 구분을 안한

   이유는 뭘까?)

 

   중요한것은 외부에 제공하는 인터페이스적 의미에서 볼때 클래스 단의 추상화 과정, 메서드(루틴)단의 추상화 과정이란

   외부에 복잡성(각종 조건들인 논리적, 순서적 의존등)을 줄여야만 한다.

 

=>클래스:추상 데이터를 틀에 담은것? 음.. 하나의 클래스 안엔 1~n개의 추상 데이터가 들어갈 수 있을 것이다.

   (클래스=붕어빵 틀 , 인스턴스=붕어빵은 클래스와 인스턴스에 대한 비유적 표현이지, 추상에 대한 비유적 표현은 아니라는점.)

 

   객체지향 언어에선 '추상'중에 설계적 개념인 a를 지원하기 위해 "abstract class, interface class"란 정의법(키워드)을

   제공.

 

   또한 설계에 따른 구체적인 구현들, 개념의 확장들(상속및 다형성)을 정의 할수 있도록  "implements, extends" 키워드를

   제공.

 

   설계에 따른 구현(implements), 개념의 확장(extends)은  결국 설계에 대한, base 클래스에 대한 타입에 따른 계층 트리로

   표현될 것이다.(다형성)

 

=>추상 데이터 형(특정 개념을 표현하는 관련 데이터 + 관련 메서드의 집합 = 객체 스스로가 자신을 표현하고(데이터) 책임을

    지고 역할을 할수 있는(인터페이스 메서드 = 서비스) 능동적 개념 vs 구조체(연관 데이터의 집합체인데 스스로는 외부에

    서비스를 제공하지 못하며, 단지 외부에서 연산을 받아야 함으로 피동적 개념이라 생각한다.)

 

=>클래스라면 우선 연관성있는 데이터(agreegation,composition을 포함)및 연산의 묶음이 선행되어야 하고(=개념의 정의및

    역할, 책임의 명확화가 중요하다) , 외부 클래스간의 관계(association)에 대한 정의가 필요할 것이다.

   

   계층트리(상속&다형성)라면 Object 클래스,파생 클래스들의 정의와 그것이 포함하는 멤버필드, 메서드가 클래스의 정의에

   맞는지 확인을 통해 각각의 역할과 책임이 분명한지를 알아야 할것이다. 

 

   부가적으로 제너릭한 컨테이너 클래스들의 공통점과 각각의 자료구조 타입에 따라 구현한 데이터및 메서드들에 대한 이해를

   통해 제너릭 컨테이너 클래스가 무엇을 추상화 시켰는지를 알아야 할것이다. (데이터 타입을 추상화 시켜 데이터 집합에 대한

   각종 연산들을 일반화 시킴) 간단하게 c++의 템플릿 개념으로 Class<T or ?> Class<? extends BaseClassType>

 

 =>자신이 추상화 시킨 개념이 계층트리에서 적절한 데이터와 연산으로 구성되어 있는지 확인할 것이며, 추가적으로 public

    (association = 외부에 노출하는 인터페이스 = 외부가 필요로 하는 구체적 서비스에 대한 범위 설정)

     VS private(외부의 요청에 대한 자신의 업무를 수행하기 위해 필요한 서브 루틴들)을 감출만큼 감추었는가?의 확인이 필요

     할 것이다.)

 

   그리고.. 객체는 조건및 상태에 따라 수행하는 연산이 달라질텐데.. 그러한 조건및 상태가 내부적인 문제인지, 혹은 외부

   다른 객체의 명령(caller)이나 수행에 의존적인 것인지 구분을 해야한다. (caller vs worker의 구분및 그에 따른 역할과

   책임 규명 또한 중요하다. -> throw&catch를 통한 예외처리 정책과도 연결됨)

 

 =>primitive를 제외한 거의 모든 데이터 타입(enum,"has a" 데이터를 표현하기 위한 내부 클래스등 제외)은 객체 지향적이라

    생각한다. 단순히 class를 사용한다고 객체지향적인 설계와 구현이 아니다. (예전 format word 프로젝트에서 format의 역할

    을, word의 역할을  항상 유념할것. 내 경운 format에 대해 객체지향적인 사고를 못하고 struct처럼 사고 했었다.)

 

 =>캡슐화 (외부에 대해 자신의 복잡성을 감춘다) private 메서드와 public 메서드의 구분이 될테고, 자신의 데이터에 대한 접

    근 권한(scope)의 설정일 것이다.

 

    물론 windowListener중 adaptWindowListener 클래스 처럼 상위 클래스의 복잡성을 줄여주는 인터페이스적 의미도 될것

    이다. 엔드유저(사용자)에게 필요한 서비스를 사용자의 시각에서 필요한 만큼만 제공하는 것.

 

2.추상화

 

a.클래스가 핵심적인 목적을 갖고 있는가?

b.클래스의 이름이 잘 지어졌고, 클래스의 이름이 핵심적인 목적을 설명하고 있는가?

c.클래스의 인터페이스가 일관성 있는 추상화를 제공하는가?

d.클래스의 인터페이스가 클래스의 사용 방법을 분명히 하고 있는가?

e.여러분이 클래스의 서비스가 어떻게 구현되었는지에 대해서 생각할 필요가 없을 정도로 클래스의 인터페이스

  가 추상적인가? 클래스를 블랙박스로 취급할 수 있는가?

f.다른 클래스들이 클래스의 내부 데이터를 쓸데없이 참견할 필요가 없을 만큼 클래스 서비스가 완벽한가?

g.관련 없는 정보를 클래스에서 제거하였는가?

h.클래스를 컴포넌트 클래스로 분할하는 것에 대해서 생각해 보았는가? 그리고 최대한 분할 하였는가?

i.클래스를 수정할 때, 클래스 인터페이스의 무결성을 유지하고 있는가?

 

3.캡슐화

 

a.클래스가 멤버에 대한 접근성을 최소화하고 있는가?

b.클래스가 멤버 데이터의 노출을 피하고 있는가?

c.클래스가 프로그래밍 언어가 허용하는 한 다른 클래스들로부터 세부적인 구현 사항들을 감추고 있는가?

d.클래스가 파생 클래스와 사용자들에 대한 가정을 피하고 있는가?

e.클래스가 다른 클래스에 독립적인가? 느슨하게 결합되었는가?

 

4.상속

 

a.상속이 "is a" 관계를 모델링하기 위해서마 사용되었는가? 즉 파생클래스가 LSP("데이터or행위가 is a가 아니면 상속x")

  를 따르고 있는가?

b.클래스의 설명 문서가 상속 전략을 기술하고 있는가?

c.파생 클래스가 오버라이드 불가능한 루틴에 대해서 "오버라이딩"을 피하고 있는가?

d.공통적인 인터페이스, 데이터, 행위가 상속 트리에서 최대한 높은 곳에 있는가?

e.상속 트리가 적절하게 얕은가?

f.기본 클래스에 있는 모든 데이터 멤버들이 protected 대신 private인가?(필요한 경우에만 protected getter 제공)

 

5.구현에 대한 다른 문제들

 

a.클래스가 7개 이하의 데이터 멤버들을 포함하고 있는가?

b.클래스가 다른 클래스에 대한 직접적이고 간접적인 루틴 호출을 줄였는가?

c.클래스가 반드시 필요한 경우에만 다른 클래스와 협력하는가?

d.모든 멤버 데이터가 생성자에서 초기화 되었는가?

e.만약 얕은 복사를 생성해야하는 합당한 이유가 엇다면, 클래스가 얕은 복사 대신 깊은 복사로 사용되도록

  설계 되었는가?

 

etc)예외처리에 관해

 

내경운 일단 자신의 역할과 책임에 따라 오류를 throw하기로 했다, 단지 추가로 고려할 점은 내가 던질 오류의 책임 소재가

콜러1이냐? 워커 1이냐? 워커 2냐? 를 구분해 해당 객체의 클래스의 추상화 수준에 맞게끔 xxxExeption을 포섭해서 던져야

한다는 것이다. 오류를 처리할 수 있는 상위 루틴or클래스에 익셉을 던지며, 그 루틴과 클래스에 어떠한 정보가 필요할지를

고려해야 한다. 또한 오류를 catch하는 입장에선 자신의 책임 소재의 부분은 확실히 처리를 해줘야 한다.

 

일반적으로 내 app에서 처리해야할 오류들은 정상적 사용자의 입력오류, 악의적인 사용자의 입력, 각종 하위수준의 작업(

네트워크,db,웹처리등에서 io관련 오류) 등이 있을 것이다.

 

사용자의 잘못된 입력 오류라고 자바 api에서 지원하는 wrongInputDataException(맞는진 모름)를 바로 사용하지 말고, 선생

님이 말씀해주셧듯, 내가 한번 더 재정의해서 myXXXException extends wrongInputIdDataException 식으로 재 정의해서

로그인 입력 처리 컨트롤러 클래스에게 던져 주는것이 더 나을것이다.

 

그외 ..mvc중 컨트롤러 클래스단에서 사용자의 입력처리외 외부 파일or클래스의 입력을 다루어야 하는데.. 아직 작업은 안해

봤지만 상당한 난이도가 될듯 하다. (awt의 component의 그 수많은 파생 이벤트들, 이벤트에 따른 구체적 리스너들의 분리..

사용자와 interaction 하는 부분이 많을수록 상당히 복잡해 진다. 그렇기에 불안하다.)

 

 

<예외처리 정책2>

외부 입력등은 컨트롤러 단에서 확실히 처리해야한다.(잘못된 값이라면 view단으로 알아서 리턴) -> 컨트롤러가 워커(비지

니스클래스 메서드)에게 작업을 지시할때 넘기는 매개변수는 확실하게 유효성이 검증된 녀석이여야 하고, 그것을 통해 작업

하는 워커가 자신의 클래스에 속한 서브 워커에게 값을 전달하고 서브워커는 내부적으로 assert를 사용해야 할것이다.

왜냐하면 내부적으로 전달 받은 데이터는 유효성을 거쳤기 때문에 만약 이상한 값이 들어 있다면, 내부 처리 로직상의 오류

일 가능성이 높기 때문이다.

 

(코드 컴플리트 302p "방책과 어설션"  좀더 이해가 필요하다.)

 

아 글고.. 개발용 오류처리 vs 배포용 오류처리를 구분해야 할테고.. (예외처리 너무 복잡함;;)

 

 

 

ps.너무 학문적으로 접근한 감이 없지 않아 있는데.. 이런 과정을 통해 객체 지향에 대한 내 이해가 깊어지길.. 그리고 이런

    고민들이 헛되질 않길..

 

by givingsheart 2014. 1. 1. 15:23

1. 상속 계층 트리에서 메서드 오버라이딩 할때 구분할 개념들


a.오버라이드 가능한 "추상" 루틴(=메서드)은 파생 클래스가 루틴의 인터페이스를 상속받지만 구현부는 상속받지

않는다는 것을 의미한다.=>설계(interface)와 구현의 분리

 

b.오버라이드 가능한 루틴은 파생 클래스가 루틴의 인터페이스의 기본 구현을 상속받으며 기본 구현을 오버라이드할

수 있다는 것을 의미한다. =>Object 클래스의 equal() , hashcode(), copy() 등을 내 클래스의 사용 목적에 맞게 재정의

하는것

 

c.오버라이드 불가능한 루틴은 파생 클래스가 루틴의 인터페이스와 기본 구현을 상속 받지만 루틴의 구현을 오버라이드

할수 없다는 것을 의미한다. =>즉 해당 인터페이스 클래스가 외부에 노출시키는 public 인터페이스(메서드)를 의미

 

(ex)

 public abstract class Base

{

a. public abstract void method;

 

b. public void method()

{

   doSomething~ 
}

 

c. public final void method()

{

   doSomething~
}


}


 

=> 인터페이스를 상속(a)받고 싶을땐 구현 상속(b)을 주의하고, 구현을 상속받고 싶을땐 인터페이스 상속을 주의하고

만약 인터페이스는 필요없고 구현만 사용하고 싶다면 상속 대신 포함(agreegacion)을 사용하라! => stratergy패턴을 의미

 

(2013/11/29 추가)

=> 메서드를 구현한다(abstract) , 메서드를 확장한다(overide). 라는 심플한 개념으로 구분이 가능할 것이다.

 

 

2.오버라이드 불가능한 멤버 루틴을 오버라이드 하지 말것 (ex) Base의 private void method()를 Child가 private void method()

=> 별개의 루틴이지만, 이름이 똑같이에 다형성인듯 착각되기 쉽기 때문

 

3.공통적으로 사용되는 인터페이스,데이터,행위를 상속트리에서 가능한 한 가자 높은 곳으로 이동시킨다

=>높이는 정도는 해당 루틴이 해당 객체의 추상화를 깰때. 음.. Dog 에 있는 eat() Tiger 에 있는 eat()는 

   Animal의 eat()으로 이동이 가능하지만, eat()을 Object클래스에 올리면 Object 클래스의 '일반적'개념이 부셔지지..

 

4.인스턴스가 하나뿐인 클래스를 의심하자

=>파생시킨 클래스가 별개의 클래스로서가 아니라 데이터로 표현될수 있나?를 고려해야 한다. is a가 아닌, has a 인지,

   이도 저도 아니라면 서로 다른 계층 트리에서 xxAble이라고 interface class를 통해 특정한 속성의 집합으로 묶을수 있다.

   단, 싱글턴은 예외이다. 동물들에 싸움 기능을 추가하고 싶다고 dog -> fightAbleDog , nonFighterAble로 파생시켜 확장

   하는 것은 미친짓. 차라리 Animal에 FighteAble 필드를 추가하거나, FighteAlbe을 인터페이스 클래스로 구현해 implements

   하거나..

 

5.파생클래스가 하나뿐인 기본 클래스를 의심하자

=>너무 앞서서 설계했다. 가능한한 현재의 작업을 분명하고 직관적이며 단순하게 만드는게 중요하다.

 

6.루틴을 오버라이드하고 파생된 루틴 내부에서는 아무것도 하지 않는 클래스들을 의심하자.

=>기본 클래스 설계의 오류를 암시한다. "is a   vs    has a "

 

7.깊은 상속 트리를 피하자

=>내 경우에 awt를 분석하고 java api의 클래스들간 관계성을 분석할때 해당 클래스가 깊은 계층 트리에 있어서 복잡성

이 심했다.

 

8.간결및 직관성 vs 디자인 패턴

=> 무조건 패턴(추상적인 설계)을 적용시켜야만 할까?


(ex)

switch( ui.Command() )

{

 case Command_OpenFile:

         OpenFile();

          break;

 

  case Command_Print:

          Print();

          break;

 

  case Command_Save:

          Save();

          break;

 

  case Command_Exit:

           Exit();

          break;

   ...

}

 

=> 이 경우에 기본 클래스를 생성하여 각 명령에 대한 다형성 DoCommand()메서드를 만들수 있다

( Command패턴 ) 하지만 위처럼 switch case간단하고 명확한 경우엔 굳이 Command패턴을

사용해 비 직관적이게 만들 필요가 없다.


9.상속 계층 트리에서 기본 클래스의 모든 데이터(멤버필드)를 protected가 아닌 private로 만들자?

=>상속은 캡슐화를 부순다(joshua bloch) 그럼으로 파생 클래스에서 기본 클래스의 특성을 접근해야

한다면 protected 접근 메서드를 대신 제공하라.  <- 개념엔 동의를 하지만, 실제 구현시 너무 귀찮아짐으로

패스


10.다중 상속은 미친짓

=>다이아몬드 상속구조와 그에 따른 메서드명 중복, 생성&소멸자의 호출순서등 너무 복잡해짐으로 무조건 동의. 

더이상 노코멘트 



1~10 정리

a.만약 다중 클래스가 데이터는 공유하지만 행위를 공유하지 않는다면, 클래스가 포함할수 있는 객체를 만든다.

=>연산은 공유하지 않고 특성만 공유할 경우(has a)


b.만약 다중 클래스가 행위는 공유하지만 데이터를 공유하지 않는다면, 공통적인 루틴들을 정의한 기본 클래스를 

상속받는다.

=>인터페이스(외부 노출 public 메서드에 대한 계약or통제) 즉, 인터페이스 클래스의 존재 의의와 개념


c.만약 다중 클래스가 데이터와 행위를 공유한다면, 공통적인 데이터와 루틴들을 정의해 기본 클래스를 상속받는다.

=>일반 베이스 클래스 or 추상 클래스의 존재 의의와 개념


d.인터페이스를 제어하기 위한 기본 클래스가 필요할 때에는 상속을 하고(인터페이스 클래스를 의미), 인터페이스를

제어하고 싶다면 포함시킨다.(stratergy패턴 = 메서드의 확장)




<멤버 함수와 데이터를 효율적으로 구현하기 위한 몇가지 지침들>


1.클래스에 가능한 한 적은 수의 루틴을 유지


2.원하지 않는 멤버 함수와 연산자들이 암시적으로 생성되지 않도록 주의

=>자바의 경우 컴파일러가 추가해주는 암시적 default 생성자및 Object클래스에서 상속 받게 되는 

copy() 참조주소 복사 , equal() 참조주소 비교 , hashCode() 참조주소를 통한 해쉬코드 등을 의미한다.

즉 내 클래스의 목적과 특성에 맞도록 재정의해야만 하고, 또한 주의해야만 한다.


3.클래스에서 호출되는 루틴의 수를 최소화

=>클래스가 타 클래스와 assciation이 많아지면 오류가 증가할 가능성이 많아지고 이것을 "팬아웃" 이란 용어로 사용


4.다른 클래스에 대한 간접 루틴 호출을 최소화("데미테르의 법칙")

=> 객체 A가 객체 B를 인스턴스화했다면, B가 제공하는 루틴은 어느 것이던 호출이 가능하지만 , B에 의해 제공되는

객체들(C,D)의 루틴은 호출하지 말아야 한다.

(ex) account.contactPerson()   vs   account.contactPerson().dayTimeContactInfo()

 

 

-(추가) 이행적으로 종속되다?  ... 고민해볼 안건..

maven(메이븐) manage 문서를 보던중,.. 메이븐 저장소는 의존 관계가 있는 아티팩트를 다운로드 하기 위하여

POM? 을 해석하여 프로젝트에 어떤 "이행 종속관계"이 있는지 판단하여 처리한다.

(ex) A->B->C   :   A->C    

5.일반적으로 클래스가 다른 클래스와 협력하는 정도를 최소화(4번을 다시 설명)

a.인스턴스화되는 객체의 수

b.인스턴스화된 객체에 대한 서로 다른 직접적인 루틴 호출의 수

c.인스턴스화된 다른 객체에 의해서 리턴되는 객체에 대한 루틴 호출의 수 



<생성자에 필요한 지침>


1.가능하다면 모든 멤버 데이터를 모든 생성자에서 초기화

=>내 경우에도 이것을 동의함. 매개변수 없는 생성자는 너무 위험하다고 느낌.(reflect를 이용해 생성할때

  클래스에 정의된 매개변수있는 생성자 타입 객체를 만드는게 가능한데.. 왜 프레임워크 들에서 단순하게 

  디폴트 생성자 타입 객체를 인스턴스화하고 거기에 invoke를 이용해 setter로 멤버 데이터를 초기화 하는진 의문임..)


2.private 생성자를 사용하여 싱글턴 속성을 구현

=>잘 알기에 패스 (단, 멀티스레드 환경을 고려할때 getInstance()의 if(instance == null) syncronized(instance) if(instance

  == null) {instance = new ClassType();} <- 이 패턴을 기억해둘것 (첫번째 if조건은 비 인스턴스화시 불필요한 연산을 

  방지하기 위한 성능 향상 목적이고, 두번째 if조건은 멀티스레드 환경을 고려한 구문임)


3.다른 사항이 증명될 때까지 얕은 복사보다 깊은 복사를 하자

=>동의함. value비교,복사는 시간은 오래 걸리지만, 객체의 독립성을 보장해줌. reference(주소)비교 복사는 시간은 빠르지만

객체의 독립성을 보장해주지 않고, 객체의 메모리상 존재만 보장해줌. 그럼으로 copy, equal, hashCode 는 기계적으로 해주자. 나중에 참조 형태로 풀어주더라도..



<클래스를 작성하는 이유>


1.실세계의 객체를 모델링


2.추상 객체들을 모델링


3.복잡성을 줄인다 

=>캡슐화&정보은닉&무엇을 public으로 노출시킬것인가 = 무엇을 private로 감출 것인가에 대한 고찰


4.복잡성을 고립시킨다.

=>클래스의 역할및 개념정의 책임의 영역 설정, 타 클래스와의 불필요한 관계 단절


5.세부적인 정보를 숨기자(3번과 동일. Interface적 의미)


6.변경의 영향을 제한할것(3,5의 정보 은닉과 동일)

=>(ex)하드웨어에 의존적인 부분(display,io등), 비지니스 규칙, 복잡한 데이터형


7.전역 데이터를 숨길것

=>클래스에서 public 으로 멤버 필드를 노출해주면 전역 데이터 처럼 사용이 가능한데.. 이것은 멀티스레드에

   안전하지 않을 뿐더러 관계되는 여러 클래스들이 전역 데이터에 의존적이게 됨


8.association에서 매개변수의 전달을 간소화

=>만약 어떤 매개변수를 여러 루틴들 사이에서 전달하고 있다면, 매개변수를 객체 데이터로 공유하는 클래스에 

이 루틴들을 포함시켜야 할 필요성이 있다는 것을 암시


9.중앙 집중 관리할것 

=>Format, Word(비지니스로직)의 설계를 reminding , 즉 Word는 여러개의 부분들을 통합해 의미 있는 업무

 를 창출하는 중앙 통제자의 역할임


=> 이해가 부족함. 코드 컴플릿2 236p.. 매우 중요한 개념 같은데.. 프레임 워크의 개념을 의미하는 것일까?


10.코드의 재사용을 도울것

=>재사용 가능성이 높은 일반적인 연산이라면 별도의 클래스로 추출하는 것이 효과적(중복 코드 방지)

   내 경운 이것을 클래스or 멤버 메서드로 뽑아내는 것만 생각했지 클래스로 추출한다는 것은 생각을 못했음.

   왜냐하면 객체지향이란, 연산의 집합이 아닌, 데이터 + 연산의 집합이기 때문.


11.프로그램군(family)를 위한 계획을 작성 (10을 다시 설명)


(ex) 수년전에 나는 보험을 파는 고객이 사용할 일련의 프로그램들을 작성하는 팀을 관리했얶다. 우리는 각 프로그

램을 작성하는 팀을 관리했었다. 우리는 각 프로그램을 고객의 보험률과 보고서 양식등에 맞추어야 했다. 하지만 프로그램의

많은 부분들이 유사했었다. 잠재적인 고객에 대한 정보를 입력하고 고객 데이터베이스에 정보를 저장하고, 보험률을 검색하고

,특정 그룹의 전체 보험료를 계산하는 클래스들이 비슷했다. 처음 프로그래밍했을 때는 석 달 정도 결렸던 것 같은데, 새로운

고객이 생겼을 때에는 새로운 고객을 위해서 새로운 클래스를 몇 개만 작성하여 나머지 코드 부분에 추가하였다.

몇일 동안 작업을 한 다음 , 소프트웨어 완성!  


=>내 이해가 부족해서 책의 내용을 그대로 옮겼음. 하지만 다수의 인스턴스를 관리하는 매니저 클래스의 연산인

   생성,삽입,조회,정렬,수정,제거,소멸은 알고 있다.


12.연관된 기능을 패키지화하자

=>정보를 숨기거나, 데이터를 공유하거나, 유연한 계획을 세울 수 없는 경우엔 관련된 기능들을 도메인 그룹으로 패키지

화 해서 묶자. 문제 발생시 전체 시스템에 파장이 적어진다. (즉 위에서 집어본 독립성과 동일한 개념)


13.특정한 리팩토링을 수행 (아직 개념이 정립이 안돼서 패스)


(ex)하나의 클래스를 두 개의 클래스로 변환하고(역할,개념적 분리?) 델리게이트(delegate=대표)를 감추고,

미들 맨 (middle man)을 제거하고, 확장 클래스를 만드는 방법으로 새로운 클래스들이 만들어진다. 


=>책의 내용 그대로 옮김(추후에 이해될듯.. 현재로선 내가 아는 범위 밖의 내용임)



<피해야할 클래스>

1.만능 클래스를 생성하지 말것

=>당연.. 코드가 더럽게 꼬이고 추후 수정도 거의 불가능


2.관련이 없는 클래스들을 제거할것

=>클래스의 위상이 아니다, 끽해봐야 내부 클래스 위상


3.동사가 따라오는 클래스를 피할것

=>다른 클래스의 루틴의 일부로



<전체 요약>

1.실세계의 객체를 모델링

2.추상객체를 모델링

3.복잡성을 줄일것

4.복잡성을 고립시킬것

5.세부적인 정보를 숨길것

6.변경의 영향을 제한할것

7.전역 데이터를 숨길것

8.매개변수의 전달을 최소화 할것

9.중앙 집중 관리할것

10.코드의 재사용을 도울것

11.프로그램군을 위한 계획을 작성할것 (이해 상당히x)

12.연관된 기능을 패키지화 할것(아주 살짝 이해)

13.특정한 리팩토링을 수행할것 (이해 전혀x)

by givingsheart 2014. 1. 1. 14:57
| 1 |