제 경운 어제 소스코드 버전 관리를 위해 '서브버전'이라는 툴을 사용해보기로 했습니다.

처음엔 제 컴퓨터(로컬)에 관리툴 서버역할(저장소)를 설치하겠다는 목표였고

각 블로그를 참고하며 빠르게 성공할 수 있었습니다.(visual svn server)

 

 

두번째 목표가 바로 생겼는데 '휴대성및 원격 작업을 편하게 하기위해' 웹상에

저장소를 만들어보면 어떨까?란 발상을 하게 되었고 이런 저런 정보를 찾던중

아영이를 통해 네이버 개발자 센터라는 것을 알게되었고 그곳에서 svn도 지원을

 

해주더군요, 순조롭게 작업 진행중 계속 commit이 실패하는 문제가 생겼고,

저는 이 문제에 대해 약 12시간 가량 매달렸던것 같습니다.

 

 

(수업에 집중도 못하고, 제가 공부하고 있는  jsp진도도 못나가고.. 자괴감에

오늘 아침엔 악몽까지 꿨습니다.)

 

 

만약, 애초에 제가 계획한 제 로컬에 저장소 설치를 완료했으니, 네이버 저장소

이용이 계속적으로 실패했다면..

 

"적당히 끊을줄 아는 지혜가 필요했던것 같습니다."

 

 

 

예전 로또 프로젝트에서 로또번호란 vo데이터를 문자열로 처리하겟다는 마음을

먹고 엄청나게 고생을 했던 경험이 있엇는데도요..(덕분에 문자열 처리 관련해

이런 저런 경험을 쌓을수 있었지만요)

참고: http://cafe.naver.com/javachobostudy/96627

 

<추가> 로또 번호를 문자열로 만든 의미를 알게 되었음. 선생님께서 웹상의 유저 입력

데이터를 자바 단(서블릿)으로 가져올때 문자열로 밖에 가져올수 없다고 말씀하심.

결국 파싱 작업이 필요하다. 내가 String lottoNumber를 처리를 위해 int[] makeIntArray

(String lottoNumbers) 이걸 만들었었다. (etx)이름은 convertXXX가 더 나을듯 하다.

 

웹의 모든 데이터는 자바에서 문자열로 읽게되나? <-- 이 문제는 아마 나름 api들이

getInt()식으로 구현을 해놓지 않았을까 한다..

 

저는 생각보다 고집이 강한가 봅니다. 제가 발상을 떠올렸으면.. 그것을 무조건

성공시켜야 하고, 그것이 잘 풀리지 않을땐 엄청난 스트레스를 받아서 자포자기의

감정까지 발생을 시키고.. (자포자기 전까진 고집 때문에 다른 방법, 적당한 타협을

받아들이려 하지 않는것 같습니다.)

 

이전에 오라클 12c설치 작업을 할때에도, 기타 이런 저런 공부를 할때에도 비슷한

느낌을 받았습니다. 지훈이 형님께선 반드시 필요한 정보만 찾아 쉽게쉽게 접근을

하시는 것을 보고 느낀점이 많았는데.. (공부는 수단일뿐 목적이 아니다는 명언)

 

저는 어제 또한번 헤매고 좌절감을 경험했네요..

 

 

신은 개개인에게 다양한 재능을 주신듯 합니다. 제가 문제를 푸는 것을 좋아하고,

적당히를 모르고 몰입하는 성향이 있는 반면, 다른 분야를 좋아하고 그것을 행함

에 있어 다른 성향을 보이는 분들도 계실테고..  "누가 좋다,옳다,뛰어나다"는 아닌

것 같습니다.(저의 고집있는 성향도 어딘가에 쓸모가 있을 수 있겠지요 ^^;)

 

서로 다른 개체간에 영향을 받아가며 조화를 이루는 과정.. 저도 여러분들께 많이많이

배우고 싶습니다. (저와 다른 다양한 생각들,문제 처리 방법들을 수용하고 싶습니다.

자칫 저만의 잘못된 아집으로 이번 처럼 삽질할 수 있으니까요)

 

 

ps.제가 이것 저것 욕심이 많아서 바빠 보이지만, 사실 저도 별로 실속은 없습니다.

저의 도움이 필요한데, 혹시 제가 부담스러워 할까봐 도움 청함을 망설이시는 분들

부담 내려놓고 요청하세요. 가능한 범위에서 , 확실하게 아는 범위에서 도와드릴께요.

(무엇보다 선생님께 질문하고 정답을 얻는것이 가장 현명한 방법입니다. 기억에도

오래남을테고요)

 

(추가로 제게 도움을 청하실때 문제풀이,개발 관련 질문이라면 조건을 하나 달겠습니다.

묻기 전에 수첩에 로직or자신의 문제 풀이 접근 아이디어or 모르는 상황을 서술해 올것.

문제를 저와 함께 풀어 냈을땐 최소 2명에게 공유할것! 입니다.)

 

 

이전에 저는 제일만 책임지고 싶다고 강조한 적이 있었는데.. 그 선언은 민망하지만,

오늘의 깨달음으로 철회하겠습니다. "함께 고민한다"의 중요성을 알아버렸기도 하고,

무엇보다 사실.. 저는 여러분들을 좋아하거든요 ㅎㅎ

 

단지 조급함 (제 처지:나이-실무경험-시간부족) 때문에 선을 그으려 한것이고요. 

반성할께요~ 오늘도 좋은(행복+의미있는) 하루가 되기를!

 

 

ps2.오늘 버스타고 오면서 생각한 잡설

 

1.디폴트 생성자의 역할.

=>저는 여전히 모든 멤버 필드(어트리뷰트)를 받는 생성자만이 필요하다고 생각하지만,

해당 클래스가 상속 트리 계층에 속해 있다면, 상위타입(부모)의 생성자를 호출해주는

연결 과정은 무척 중요합니다. 모든 멤버 필드를 받는 하위 클래스의 생성자에서도

명시적으로 super(); 를 호출해 줘야하듯이..

 

즉 디폴트 생성자는 위험성은 있지만, 상위 타입의 생성자를 호출하는 super()가 암시적으

로 숨어있기에 자칫 깜박하고 super()를 비호출하는 위험을 줄여준다고 생각했습니다.

(정확히 맞는지는 모르겠네요)

 

아 그러고 어제 배운 object클래스의 equal,hashcode,copy란 개념은 확실히 해두시는 것이

좋습니다. 제 예전글에서 한번 집어본 기억이 있는데.. 개체간의 "비교"한다는 연산은

전산에서 중요한 연산중 하나입니다. 서로 같은지 다른지 알아야 식별해서 조회도 할것이며,

식별이 되야 정렬도 할것이며, 식별을 해야 추가및 삭제도 할것이며..

 

레퍼런스 형의 메모리상 주소 비교&대입(치환) 연산   vs    개체가 가지고 있는 멤버필드들(어트리뷰트들)간

의 비교&대입 연산의 구분!   을 강조합니다.  (hash란 개념은 "식별"보단 "효율적인 식별과 배치"

의 개념이니 논외할께요)

 

개인적으로 훌륭한 블로그라 생각합니다. 제게 엄청난 영감과 깨달음을 주는 곳

(불펌)  http://iilii.egloos.com/4427484

 

 

-(추가) equals , hashCode 재정는 아래처럼 한다. (.는 멤버필드의 value이고

hashCode에서 상위 클래스(Object등)에 정의된 hashCode값에 비트연산 xor(서로 비트값이 다를떄만 1을 리턴)

를 하는것에 주목할것!   <--> 비트 마스크를(&연산) 이용해 추출하는 것과 다른 xor의 사용법임!

원본 1100 xor 암호키 1000 => 암호데이터 0100 xor 암호키 1000 => 1100 이거 + 비트간 자리수 이동 반복이 DES?

 RSA는 머였지? 공개키 머시기 였는데;;)

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

     public boolean equals(Object obj) {
         return obj instanceof GregorianCalendar &&
             super.equals(obj) &&
              == ((GregorianCalendar)obj).;
     }

    
Generates the hash code for this GregorianCalendar object.
 
     public int hashCode() {
         return super.hashCode() ^ (int);
     }

 

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

 

 

-(추가2) 매개변수를 잘못 받은 워커측의 대처 방법 ㅋㅋ (콜러야 니잘못이다 나는 처리 못한다. 옛다 받어라~

그러면 콜러측에선 입력값에 대한 재처리등 작업을 할 수 있다. 물론 내가 정의한 익셉션 객체를 던지면

추가 정보도 전달해 줄 수 있을것이고. (ex)선생님이 말씀하신 주문수량 vs 재고수량 tradeOff)

 

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

 

public void add(int fieldint amount) {

         // If amount == 0, do nothing even the given field is out of
         // range. This is tested by JCK.
         if (amount == 0) {
             return;   // Do nothing!
         }
 
         if (field < 0 || field >= ) {
             throw new IllegalArgumentException();
         }

 

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

 

2.저는 인터페이스를 두가지 의미로 구분을 했는데.. 조금 더 구분을 할 필요를 느꼇습니다.

a.해당 클래스 계층 트리에서 설계의 의미.

b.다른 역할 클래스(비지니스 클래스,입력처리 클래스,화면 그리기 클래스,데이터 관리 클래스

기타 등등) 및 패키지및 서스시스템... 과 서로간 association(상대 객체가 제공하는 메서드 호출)

관계에서 public으로 노출해주는 메서드명.

 

이중 b를 한번 더 쪼개야 할듯 싶단 생각을 했습니다.

b.클래스 외부에 노출하는 public 메서드 = 외부 인터페이스

c.클래스 내부의 각종 작업을 위해 쪼개진 private 메서드들 간에도 서로간 소통 관계(associ...)

있기 때문에 그것을 = 내부 인터페이스

 

정확한 지식이 아닌, 착상 수준의 느낌입니다. 주의해주세요!




<2013.11.27 코드컴플리트중 상속과 오버라이딩 관련 추가>


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패턴을 의미






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()





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. 15:15