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