swing, xml, ejb 패턴.. db책.. jsp책.. 스트럿츠책..  이걸 최소 1~2독씩은 해야.. 스프링으로 넘어갈텐데...

아하하핳하하하하하하하하하하하하하핳하하하핳

스트럿츠 관련 유쾌한 분의 블로그 ㅎㅎ


(추가)
스트러츠1을 책을 구매해서 공부를 했다. 스프링도 함께 공부했다. 서버단 MVC가 구분이 되었으며,
각종 전략(바인딩,DI,템플릿)을 알게 되었다.


'프로그래밍 > struts' 카테고리의 다른 글

스트럿츠 교재 저자 웹사이트  (0) 2014.01.08
by givingsheart 2014. 1. 2. 09:38


중 아래 댓글들 참고

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

이부분은 책의 내용을 그대로 발췌


ejb2.0로컬 참조와 cmr(container managed ralation)이 나타나기 전에, 엔티티 빈들은
큰단위의 도메인 객체들을 모델화 하기 위해 주로 사용되었다.

이것은 주로 원격 통신과 관련된 오버헤드 때문에, 클라이언트 티어의 객체가 엔터프라이
즈 티어에 작은 단위로 접근하는 것을 막기 위해서였다. 큰단위(coarse grained)로 된 설계의 
성능은 클라이언트 티어와 엔터프라이즈 티어 사이에 전송되는 모든 데이터를 캡슐화한
data transer object의 구현으로 한층 더 개선되었다. 비록 이것이 높은 퍼포먼스의 설계를
제공해주기는 했지만, 많은 도메인 객체를 가진 복잡한 시스템에서는 시스템 내에
dto의 과잉을 초래하였다.

또한, 이전의 ejb에서는 빈 공급자가 도메인 객체들 사이의 연관을 유지하기 위한 로직을 명시
적으로 제공해야 했다. 도메인 객체들 사이에 복잡한 관계가 있는 상황 안에서는 dto의 설계가
매우 복잡하게 되었다.

로컬 참조와 cmr의 출현은 ejb를 이용한 엔터프라지으 app 개발에 흥미진진한 새로운 길을 열었다.
여기에서 우리는 프리젠테이션 티어와 엔터프라이즈 티어 사이에서 전송될 수 있는 XML 기반의
동적인 데이터 구조를 생성하기 위한.. JAXP와 빈 인트로스펙션(refelct활용한거)을 연계하여
ejb2.0을 사용하는 강력한 길을 얻을 수 있을 것이다.

엔터프라이즈 티어에서 클라이언트 티어로 데이터를 전송하기 위한 XML의 사용은 app내에 들어
있는 다양한 티어들 사이의 느슨한 결합 구조를 가진 구현을 도와준다. 

하지만, 새로운 도메인 객체들을 엔티티 모델에 추가하려고 할때는 , 이것들을 위한 새로운 DOM
구조(예전에 한번 살펴봄..dom,sax등)를 생성할 책임이 있는 클래스를 추가할 필요가 있다.

우리는 주어진 로컬 ejb의 cmp와 cmr 필드들을 동적으로 네비게이션 할 수 있는 프레임워크를 개발
하고 ,app 내의 다양한 티어들 사이에서 전송될 수 있는 xml문서를 생성할 것이다. 이러한 방법에는
다음과 같은 이점들이 있다.

1.엔터프라이즈와 클라이언트 티어 사이에 결합을 느슨하게 한다.(스크립팅 형식이니..)
2.도메인 객체들 사이의 관계들을 관리하기가 훨씬 더 쉽다.(굿!)
3.시스템에서 복잡한 데이터 전송 객체들을 제거한다. (굿!)
4.xml이 cmp 그리고 cmr 필드들을 동적으로 네비게이션 할 수 있게 만들어졌기 때문에, 빈공급자는
새로운 객체들을 도메인 모델에 추가하려고 할대, 이들의 새로운 dom 구조를 생성할 책임이 있는
클래스를 만들 필요가 없다.

ejb2.0로컬 참조는 빈 컴포넌트들의 작은 단위 접근을 권장한다. 로컬참조를 가진 빈들은 컨테이너에
의해 관리되는 다른 빈들과의 관계에 포함될 수 있다. 예를 들면, 헬프 데스크 시스템에서, UserEJB는
ServiceRequestEJB와 일대 다의 양방향 관계를 가질수 있고, ServiceRequestEJB는 ProductEJB와
일대일의 단방향 관계를 가지고, ServiceRequestHistoryEJB와 일대 다의 양방향 관계를 가질수 있다.

UserEJB는 또한 PhoneEJB와 일대 다의 양방향 관계를 가질수 있다. 그래서 EJB 2.0 로컬 참조와
cMR을 사용하여, 연관된 엔티티들의 복잡한 집합을 설계할수 있다. cmp와 cmr 필드들은 빈클래스
안에서 추상 접근자 메소드(getter/setter)를 사용하여 정의 된다.

cmr필드들을 위한 접근자 메소드들은 관계의 기수성에 의존하여 일의 관계이면.. 빈의 로컬 인터페이스를
, 다의 관계이면 빈의 로컬 인터페이스의 컬렉션을 돌려보낸다. 이들 접근자 메소소들은 빈 컴포넌트들의 로컬 
인터페이스를 통해서 외부에 드러날 수 있다. ejb2.0의 더 깊은 범위는 이 책의 영역에서 벗어난다. 보다 상세한 
ejb2.0규약에서 제공한다. -_-;;;

효과적인 디자인 패턴은 facade 컴포넌트를 통해서 app의 큰 단위 유스케이스를 드러내며, 클라이언트 
티어로부터 엔티티 컴포넌트로의 직접적인 접근을 막는다.

이것은 비지니스 서비스를 제공하기 위해 로컬 엔티티 빈들이 협력하는 복잡한 계층 구조와
상호작용하는 리모트 세션빈 컴포넌트와 같은 facade 유스케이스의 구현에 의해 성취될 수 있다.

앞에서 언급된 헬프데스크 예제로 돌아가서 , 주어진 user의 자세한 정보를 얻기위한 하나의 유스케이스가
있다. facade 컴포넌트는 요청된 user엔티티 컴포넌트를 찾고, cmp와 cmr 필드들을 통하여 검색을 하여
필요한 데이터를 얻고, 이를 프리젠테이션 티어로 리턴한다.

데이터 전송 객체를 위한 확실한 서택은 일반 자바 빈이다. UserBean은 cmp와 cmr필드를 나타내는
특성들을 가질 수 있다. cmr 필드의 타입은 관계의 기수성에 따라 java.util.Collection 이거나, 다른 빈 컴포
넌트일수 있다. UserBean은 ServiceRequestBean과 PhoneBean 컬렉션을 가질 수 있다. 

ServiceRequestBean은 한개의 ProdctBean과 ServiceRequestHistoryBean의 컬렉션을 가질수 있다.
추가적으로 이들 빈들은 도한 cmp필드들을 표현하는 원시 타입의 어트리뷰트나 간단한 string을 가질수
있다.

이러한 선택의 중요한 단점은 엔티티 모델이 복잡해질수록 데이터 전송객체의 계층구조가 더 복잡해지는
것으로, 이것은 서비스(엔터프라이즈) 티어와 소비자(프리젠테이션)티어 사이의 결합을 단단하게 할 수 
있다는 점이다. 

관계들의 복잡한 계층 구조를 보면, 더 나은 선택은 데이터 전송 객체로서 XML,DOM 객체를 사용하는 것이다.
(세션빈에서 직접 jdbc에 연동해서 데이터를 가져올때 java.sql.resultset -> java.sql.rowset 사용하기도 함)

facade컴포넌트는 org.w3c.dom.Document 타입의 객체를 생산하고 프리젠테이션 컴포넌트는 xml을 인지하는
jsp커스텀 태크나(오옷!!) xslt(이게 xml변환하는 라이브러리였던가? 예전에 정리했었는데;;) 파일을 사용하여
그것들을 소비할 것이다.

다음과 같은 질문이 있다. cmp 로컬빈의 참조로부터 xml문서를 어떻게 생성할 수 있는가? 

우리는 dom컴포넌트의 서로 다른 타입을 생성하기 위해 팩토리(factory) 기반의 접근을 사용할 수 있다.
하지만, 이것은 팩토리 컴포넌트의 과잉을 생성하여.. 엔티티 모델을 확장할 때 새로운 팩토리 컴포넌트의
추가가 필요할 것이다. (아..하긴..) 

우리가 필요한 것은 cmr을 찾아서 동적으로 dom구조를 생성하기 위해 cmr엔티티 로컬 객체들을 인트로스펙트
(리플렉션)할수 있는 기능을 가진 유틸리티이다.

이 유틸리티는 무한 순환을 피하기 위해 양방향 관계에서 원형 참조를 조심해야하고, 또한 관계 엘리먼트
(realation ship element)들의 검색에서 환경설정이 가능한 drill-down depth (????)를 가져야 한다.

다음 섹션에서 이러한 기능을 제공하는 유틸리티 클래스를 보여준다.

package ws.business.service.util;
//jaxp
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
//dom
import org.w3c.com.Document; //오오.. 기억이 새록새록 내경운 jdom2를 썼었지..
import org.w3c.dom.Element;
//ejb
import javax.ejb.EJBLocalObject; //이거..자바ee6 받아서 설치후.. 외부 라이브러리에서 찾아야함;;
//collection
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
//빈 introspection
import java.beans.Introspetor; //오.. 이런 api들이 제공되었었군.. 나는 직접 reflect 쓰는줄..
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor; 
import java.beans.IntrospectionException;
//reflection 에잉.. 추가해주네..
import java.lang.reflect.Method; //예전 생각한대로.. 조회해가며 게터,세터 찾으려는건가? 찾아서 invoke하고
import java.lang.reflect.InvocationTargetException;

public class DOMGenerator
{
  //문서 만든다.
  private Document doc;
  //사용자가 drill-down depth를 정의한다.. .. 이거 element의 계층 구조 의미하는 거였나? xml이 데이터를 트리처럼 관리하니
  private int drillDownDepth;
  //특정 참조를 저장하기 위한 사적 인스턴스 변수
  private ArrayList _circularRef = new ArrayList();
  //현재의 depth of the drilldown으로 저장하기 위한 사적 인스턴스 변수
  private int _currentDepth;
  //getEJBLocalHome, getLocalHandle, getClass and getPrimaryKey 메소드들은 
  //처리하지 말아야 한다. why???
  private static String RESERVED = "EJBLocalHome^localHandle^class^primaryKey";
  //대박이다.. 예약어를 xor로 묶었어.. 헐.. 대박.. 천재다..

  public DOMGenerator(String docElementName, int drillDownDepth)
  {
     try
     {
        DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = fact.newDocumentBuilder(); //익숙해서 좋고~
        doc = builder.newDocument(); //이제 나도 팩토리 패턴에 익숙해진건가?
     }
     catch(ParserConfigurationException ex)
     {
        throw new RuntimeChainedException(ex); //오.. 체크드를 언체크드로 변환후 그래도 콜러에게 알리네? 워커가 착함;;
     }
     //drilldown depth를 저장
     this.drillDownDepth = drillDownDepth;
     //사용ㅈ가 정의한 이름을 사용하여 문서 요소를 만든다.
     doc.appendChild(doc.createElement(docElementName)); //아.. 어렴풋이 기억이 난다.
   }


   //이 메소드는 dom을 만들기 위해 로컬 참조를 넘긴다.
   public Document getDOM(EJBLocalObject local)
   {
      try
      {
         //cmp와 넘겨진 로컬 참조를 위한 관계 필드를 사용하여 요소를 만들기 위해 이메소드를 호출한다.
         populateElement(doc.getDocumentElement(), local); //먼가 심오한데?.. local 인스턴스를 통해 reflection으로 
         //클래스 정보에서 각종 메서드,관계들 파헤쳐서 doc에 넣어주는듯..
         //dom을 리턴
         return doc;
       }
      catch(IntrospectionException ex)
      {
         throw new RuntimeException(ex.getMessage()); //오 이런게 일반적 기법이구나~
      }
      catch(IllegalAccessException ex) //흠..리플렉션 패키지로 접근제한자 다 뚤을수 있는데?
      {
         throw new RuntimeException(ex.getMessage()); 
      } 
      catch(InvocationTargetException ex)
      {
         throw new RuntimeException(ex.getMessage()); 
      } 
   }


   //
   private void populateElement(Element parent, EJBLocalObject local) throws IntrospectionException,
   IllegalAccessException, InvocationTargetException
   {
      //현재 로컬 참조를 링크된 참조 목록에 추가한다.
      _circullarRef.add(local); //참조를 기억해둠
      //현재의 drilldown depth를 증가시킨다.
      _currentDepth++;
      //현재 로컬 참조에 대한 빈 정보를 얻는다.
      BeanInfo info = Introspector.getBeanInfo(local.getClass()); //오`~ 이해되고 있음..리플렉션 사용해 각종정보추출
      //속성 descrptors의 목록을 얻고 배열에서 반복시킨다.
      PropertyDescriptor[] properties = info.getPropertyDescriptors(); //굿굿!
      
      for(int i=0; i< properties.length; i++)
     {
         //속성 읽기 메소드를 얻는다. 프로퍼티 디스크립터라는 자료형이 편하긴 한듯.. 
         Method propReadMethod = properties[i].getReadMethod(); //메소드 순회하면서 어트리뷰트.. properties[i] 이름
         //과 일치하는 게터 메서드를 클래스에 선언된 메서드들을 탐색해서 찾고..실행(invoke)해서 값을 얻는듯.
         //속성 이름을 얻는다.
         String propName = properties[i].getName();
         //reflection을 사용하여 속성 값을 얻는다.
         Object prop = propReadMethod.invoke(local, null); 
         //예전되어 있던 속성을 건너뛴다.
         if(RESERVED.indexOf(propName) > = 0) continue; // 천재다..

         try
         {
            //ejb 로컬 참조로 속성을 캐스트 한다. 구현 방법이 아주 다양하기에 instanceof를 사용하지 말자!
            EJBLocalObject locProp = (EJBLocalObject)prop;
           //만일 링크 참조목록에서 로컬 참조를 이미 이용하고 있거나,
           //현재의 drilldown depth가 설정된 driildown depth보다 더 크다면.. 건너뛴다. = 트리 순회 로직
           if(isCircularRef(locProp) || _currentDepth >= drillDownDepth) continue;
           
           //속성으로 요소를 만든다.
           Element child = doc.createElement(propName);
           //자식 로컬 참조의 관계 필드와 연속 필드로 새로 만들어진 요소를 반복해서 만든다.(핵심= 재귀)
           populateElement(child, locProp); //내가 파일 시스템 트리 탐색할때 재귀 시도한거처럼..
         }
         catch(ClassCastException ex1)
         {
             //ClassCastException이 throw되었으면.. 핸들링! 내가 전에 깨달은 익셉션 핸들링
             //속성을 로컬 참조의 컬렉션으로 캐스팅하도록 한다.
             //이때 구현방법이 컨테ㅣ너마다 다른 instanceof는 사용하지 않도록 한다.
             try
             {
                 Collection colProp = (Collection)prop;
                 //현재의 drilldown depth가 설정된 driildown depth보다 크다면 처리과정을 건너띈다. =트리순회에서 제한조건
                 if( _currentDepth >= drillDownDepth) continue;

                 //컬렉션을 캡슐화할 자식 요소를 만든다.
                Element child = doc.createElement(propName);
                Iterator it = colProp.iterator(); 
                //당근 현재 catch된 블럭은 컨테이너 타입(트리에서 마지막 노드x)이니까.. 내부 요소를 접근해야지..
                while(it.hasNext())
                {
                    //컬렉션에서 각각의 로컬 참조를 얻는다.
                    EJBLocalObject locProp = (EJBLocalObject)it.next();
                    //만일 링크 참조 목록에서 로컬 참조를 이미 이용하고 있거나, 현재의 drilldown depth가
                    //설정된 drilldown depth보다 크다면 처리 과정을 건너뛴다. = 위에도 나왓지만 중복처리 방지이자 무한루프
                    //방지
                    if( isCircullarRef(locProp)) continue;
                     
                    //컬렉션에 현재 로컬 참조를 위한 지속 정보와 관계 정보를 포함할 요소를 만들고, 
                    //그것을 컬렉션을 나타내는 요소에 추가하ㅕ 컬렉션을 만든다.
                    Element grandChild = doc.createElement(propName + "-child");
                    child.appendChild(grandChild); //예전에 사용자 정의 익셉션을 스택및 재귀호출을 이용해 처리한 어떤
                    //분의 코드에선.. 트리의 깊이 * '\t' 함으로서 층을 표현햇지만.. dom구조의 xml은 계층구조가 알아서
                    //잘 표시되니.. 그런 구현까진 신경안써도 될듯
                    populateElement(grandChild, locProp); //손주 노드 탐색 ㄱㄱ (진짜 내가 예전에 파일 시스템에서 트리
                    //순회하려던 것과 유사하다...내 삽질도 의미가 있었다 ㅠㅠ)
                 }
                 //위의 while을 통과했다면.. 현재 노드의 하위 계층을 전부 추가했을테니..(재귀를 통해)
                 //자식들을 만든다.
                 parent.appendChild(child);
              }
              catch(ClassCastException ex2)
              {
                 //ClassCastException이 발생했다면.. 속성은 연속필드이고.. 
                 //그값이 애트리뷰트로 연재 노드에 추가된다. 헐.. 진짜 내가 구상했던 트리식 파일 시스템 처리와 거의 똑같네..
                 //isDirectory따라 재귀 순회하고.. isFile이라면.. 현재 노드의 데이터 필드에 추가하고;; 내가 대박친건가.. 아님
                 //사람들 생각이 다 비슷한건가;;
                 parent.setAttribute(propName, prop.toString() );
              }
          }
      }

      //순환 참조를 추적하기 위해 목록에서 현재의 로컬 참조를 삭제한다. <- 이해불가..내가 전에 이걸 몰라서 실패했나?
      _circularRef.remove(local); //하여간 심플한..순회 종료조건들이다.
      //현재의 drilldown depth를 감소시킨다. 
      _currentDrpth--;
   }

   //이것은 참조가 링크된 참조 목록에 있는지 여부를 검사하기 위한 유틸리티 메소드이다.
   private boolean isCircularRef(EJBLocalObject local)
   {
      Iterator it = _circularRef.iterator(); //전체 로직을 완벽히 이해는 못했지만.. 대박..
      while(it.hasNext())
      {
         if(local.isIdentical( (EJBLocalObject)it.next() ) ) return true;
         
         return false;
       }
   }
}

아래의 코드는 이 클래스를 사용하기 위한 방법을 보여준다.
User local = userHome.findByPrimaryKey("1");
return new DOMGenerator("user", 4).getDOM(local); //아름답다...

엔티티 모델에 의존하여 생성된 dom이 아래에 나와있다.


<?xml version="1.0" encoding="UTF-8" ?>
  <user firstName="Meeraj" id="1" lastName="Kunnu">
   <requests>
      <requests-child description="Outlook not working" id="2" status="p">
          <product description="Install Laptop" id="1" name="SVC01"/>
       </requests-child>
       <requests-child description="PC not booting" id="1" status="O".
           <histories>
              <histories-child description="Information requested" id="2" loggedAt="2000-12-12 12:!2:12.0" />
              <histories-child description="Request logged" id="1" loggedAt="2000-12-12 00:00:00.0" />
            </histories>
            <product description="Install Laptop" id="1" name="SVC01" />
         </requests-child>
     </requests>
     <phones>
         <phones-child id="2" number="0771 8210586" type="M" />
         <phones-child id="1" number="0231 2973536" type="W" />   
     </phones>
   </user>
                


우리는 j2ee app의 엔터프라이즈와 프리젠테이션 티어 사이에서 복잡한 데이터를 전송하기
위한 멋지고 유연한 모델을 보았다. 프리젠테이션 티어는 엔터프라이즈 티어에 의해 생성된
xml데이터를 xml을 인지하는 jsp 커스컴 태그와 xslt를 사용하여 클라이언트 디바이스(이를테면
file)상에 표현할 수 있다.

도메인 모델에 새로운 정의를 추가할때, 당신이 해야할 필요가 있는 유일한 일은 .. 작은 단위 로컬
엔티티 빈들을 사용하기 위한 그런 정의들을 정의하는 것과 cmr을 사용하기 위한 연관을 정의하는 것이다.

dom생성기(generator)는 동적인 xml문서들을 생성하기 위하여 그런 관계들을 검색하는 일반적인
방법을 제공한다.

하지만, 임의의 다른 설계 솔루션처럼... 이러한 접근은 또한 약점과 결정들을 가지고 있다. 

첫번째 명백한 측면은 xml기반의 data transfer object에 대해 개발자들이 자주 걱정하는 퍼포먼스
이다. app서버 (wls 6.1)와 데이터 서버(adaprive sql anywhere)가 동시에 돌아가는 1ghz,256mb의
windows mf 컴퓨터 상에서 복잡한 관계들을 가진 천개의 레코드 집합을 처리하는데 0.5초 이하 정도의
시간이 걸렸다.

두번째 명백한 측면은 타입 안정성이다. xml이 가장 높은 레벨의 데이터 추상화를 제공하기 때문에 
어트리뷰트나 텍스트노드들의 값은 항상 string 문자처럼 다루어진다. 

만약 당신이 엔터프라이즈 티어로부터 조회된 dto상에서 비지니스 연산을 수행하고자 한다면,
자바빈  컴포넌트(일반 자바클래스)를 사용하는 dto패턴을 채택하는 것이 더 좋다.

하지만, xml스키마는 xml문서상의 타입 안정성을 위한 강력한 메커니즘을 제공한다. 또한 이문서에서
설명된 접근 방법에서, 엔티티와 그것의 종속적인 엔티티에 연관된 대부분의 비지니스 로직은
엔티티 그 자체 내에 구현될 것이고, 독립적인 엔티티들과 연관된 비지니스 로직은
session facade에서 구현될 것이다. 두 경우 모두 모데인 객체로서 로컬 엔티티의 객체를 사용한다.

이러한 접근방법의 가장 큰 단점중 하나는 xml기반의 데이터 모델링을 위해 잘 정의된 기술이 없다
는 것이다. xml을 사용하여 도메인 객체의 관계를 모델링하기 위한 어떤 uml표기법이나 대중적인
스테레오 타입을 찾아내지 못했다.


'프로그래밍 > ejb' 카테고리의 다른 글

해쉬맵의 활용 전략(map dto, dto factory)  (0) 2014.01.02
ejb관련 - EJB.. 그만 공부하자..  (0) 2014.01.02
by givingsheart 2014. 1. 2. 09:37
정확치 않은 이해를 스케치 하는것임을 주의!

목적:

서버,클라간 요청/응답 횟수를 줄이고, do들과 dto들 사이의 의존성 줄임

전제:
클라의 ui에 표시되는 데이터들은 서버측 데이터를 이용해 초기화된다.

서버측에 여러 do들의 모임..(게임이라면.. 캐릭터정보do, 맵정보do, 아이템정보do, 몬스터정보do등등)
을 관리하는 객체가 있다면 (facade 세션빈.. 메디에이터)

요놈에 대해 정보를 요청할때.. 전체 정보를 요청할 것인가? 아니면 개별 do정보를 요청할 것인가?
개별 do중 각각의 어트리뷰트를 요청할 것인가에 대해..


컨셉:
1.클라측에서 해당 유스케이스A에 해당하는 dto를 요청(캐릭정보중 a,b 맵정보중 a,b 몬스터정보중 a,b)

2.서버에선 유스케이스별로 dto를 해쉬맵에 구성해둔후 맵을 통채로 클라에 전달

물론 이작업 역시.. 팩토리 클래스가 담당
글고 여기서 제네릭 엑세스 패턴이 활용.. 컨셉은 전체 집합에서 찾아낼 집할을 의미하는 키값의 집합을 매개
변수로 get메서드를 호출하면.. 내부에서 전체 조회를 통해 일치하는 키에 해당하는 집합을 새로이 해쉬
맵으로 구성해 리턴하는 전략.. 컨테이너의 생성자등 메서드의 매개변수로 다른 컨테이너를 받는 의미가
이러한 의미임!

아참.. 타입을 제너릭하게 사용시..Object 타입들이 왔다 갔다 하니..  형변환이란 노가다 작업이 필요해지긴하
다.. 큰 목적을 이루기 위해 이정도 수고쯤음 -_-a

제네릭 엑세스 인터페이스 형태

public interface AttributeAccess
{
  public Map getAttributes(Collection attributeKeys);
  public Map getAllArrtibutes();
  public void setAttributes(Map attributes); //셋과 비교해 맵의 장점 = 덮어쓰기 가능!(예전에 맵의 put을 잘못 이해했었지..)
}

글고.. dto에 맵적용 패턴활용시 타입점검의 기능이 약해짐.. 단순하게 구성하면.. key도 object형이기 
때문에.. 해당 맵엔 모든 타입(do)들이 들어갈수 있음.. 이걸 방지하려고.. 상위 타입을 만들고 key값에
<? extends BaseA>가 가능하긴 하지만.. 이렇게 되면.. 너무 복잡해질듯.. 직접 구현할 레벨이 안되기 
땜에.. 막연한 느낌이랄까..?

컨테이너들이 직렬화를 구현한 이유는 원격 송수신 이란.. 기본 전제가 있기 때문임.. 스윙의 컴포넌트
들.. 역시.. bean 형태로서 직렬화및, 각종 셋/겟지원.. + key/value로서 내부에 해쉬셋을 가지고 있다는
점.. (프로퍼티란 데이터 타입은 해쉬셋의 일종으로 키와 값을 문자열로 다룬다는 점만 특이점임.. 문자열
타입의 집합은 xml과 연동이 쉽고..)
추가로 키값을 개발자가 알지 못할 경우를 위해 해당 컨테이너(빈클래스,스윙컴포넌트) 클래스에선
static final String XXXX = "xxaasasa"; 처럼 키값을 지원함..  예전에 워드 + 포맷 객체 프로젝트 진행시
포맷 객체를 외부에서 생성후 전략 패턴을 사용했지만.. 내가 생각했었던.. 즉..외부에서 type을 지정해
주고.. 내부에서 switch case..  사용시 word객체.(Format.NORMAL, "안녕하세요") 처럼.. 요렇게 사용할
수 있게끔.. 타입(key)를 지원해주는것임.. 

물론 타입 안정성을 더욱 엄격히 해주려면.. 예전에 구상했던.. 채팅 프로그램에서 메세지를 계층
구조화 한것처럼.. enum을 사용해서.. 정확한 구현은 기억안나지만.. enum KeyType{A,B,C}로..
구현하고 위에서 생각한 것처럼.. 매개변수를 받을때 extends 상위 타입 또는 매개변수의 타입을 KeyType
으로 .. 요게 될런지는 모르겠음..


3.클라에선 해당 맵에서 알아서 꺼내씀.. 캐릭정보라면.. dto객체에 get("character")해서 캐릭터 해쉬맵
을 얻고, 캐릭터 정보중 상태정보를 원하면.. 캐릭터 해쉬맵에 대해 get("status")를 해서 상태정보(이걸
do로 구분할지, 어트리뷰트로 구분할진..모르겠음) 해쉬맵을 얻고.. 캐릭터의 hp가 필요하다면.. -_-;; 
int hp = statusMap.get("hp"); 요런식으로 ??  하여튼.. 모든 어트리뷰트에대해 set/get 추가가 불필요하
단.. 장점이 있음.. 

(주의할게.. bean managed  vs container managed 에서 전문가들은 cmp를 권하는 것의 의미를 상기해
야함.. ejb 패턴.. 너무너무 복잡하고.. 개념이 명확히 서질 않고 혼동되고 잇음 ㅠㅠ DTO Factory패턴과
DTO hashmap 패턴이 짬뽕이 된듯.. 이책은 3번쯤 읽어봐야 감좀 잡을듯;; 내수준에 너무 벅참;;)

2번에서 유스케이스별(몬스터와 싸우다 = 캐릭터 정보, 몬스터정보, 아이템정보, 지형정보등) 필요한 데이터를
이뮤터블로서(원본/사본) 묶어준후에.. 클라에 전송하면.. 클라는 필요한 정보를 뽑아내서 사용하면 될테고..
중요한 판정,유효성 검증등은 서버측에 맡기고.. (이것도 애매함.. 서버와 클라간 통신 횟수를 줄이는게 주요
목적인데.. 데이터를 받는게 아닌, 판정및 유효성을 맡기는 것이라.. 게임을 예로 들기엔 이상하단 느낌..OTL)

1.클라측의 ui가 계좌 거래 화면이면.. 일단 서버측에서 계좌정보란 do를 얻어와야 할것이고(로그인등 인증 생략)
.. 이것을 do통채로 전달하냐, dto로 필요정보만 추출하냐, 또는 계좌외 다른 do의 정보도 추가로 필요하냐에 따라 
dto용 데이터를 구성한후..(물론 dao를 통해 얻어온 데이터로) 클라에게 전달하고 클라는 잔고,이체가능액수
기타등등을 뿌려줄것이고

2.클라측에선 해당 계좌 정보를 사용자에게 비쳐주며.. 사용자의 유스케이스(이체,조회,출금...)를 선택받으면..
서버에 이체란 사용자의 커맨드를 전달하고. 서버는 세션빈 + 비지니스를 의미하는 엔티티빈 등을 이용해..
아.. 생각이 막혔다.. 나중에 다시 정리..


by givingsheart 2014. 1. 2. 09:35