'2. Design'에 해당되는 글 20건

  1. 2017.02.18 Segment tree
  2. 2017.01.31 Counting sort
  3. 2014.12.04 Inversion Of Control (= Hollywood Principle)
  4. 2014.07.15 Free wireframing set for powerpoint
  5. 2014.01.06 Create MySQL ERD using ERWin
  6. 2012.05.04 Dropbox 웹 사이트
  7. 2012.05.04 변수와 가독성
  8. 2012.02.19 아이디와 패스워드
  9. 2011.11.21 사용자의 정신 모델에 따라...
  10. 2011.10.22 임상 실험
  11. 2011.10.18 애플 수석 디자이너 - 조나단 아이브
  12. 2011.10.18 SOLID (Object-oriented design)
  13. 2009.10.13 두 개의 모자
  14. 2009.10.13 Refactoring 의 목적 1
  15. 2009.10.13 Switch 문
  16. 2009.07.07 Scriptable COM Object 설계 시 고려해야 할 점
  17. 2009.02.17 The Open-Closed Principle
  18. 2008.10.06 GOF 디자인 패턴 (생성 패턴)
  19. 2008.08.19 정보 은닉의 가치
  20. 2008.06.15 Strategy 패턴 소스 (셀 정렬 알고리즘 포함) 1
2017. 2. 18. 11:07

Segment tree

2017. 1. 31. 22:51

Counting sort

2014. 12. 4. 12:14

Inversion Of Control (= Hollywood Principle)

Simply it means,



"Don't call us, we'll call you."



In case of the library, you would call its API but, A framework would call your implementation. In addition, a framework would control to create and destroy an object instead of you.


Template method which is one of the GOF patterns is very related to this.


  • Helpful sites:


http://martinfowler.com/bliki/InversionOfControl.html

http://vandbt.tistory.com/43

2014. 7. 15. 03:07

Free wireframing set for powerpoint

Source : http://designmodo.com/windows-8-wireframe/


The wireframing set is available as a .pptx file that you can download using the link below:



It is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License


Screen shots:







windows-8-wireframing-set.zip.pptx


2014. 1. 6. 06:09

Create MySQL ERD using ERWin

Visit the following site to get more detail:


http://mkyojung.wordpress.com/2012/09/21/erwin%EC%97%90%EC%84%9C-mysql-erd-%EC%83%9D%EC%84%B1reverse-engineering/

2012. 5. 4. 06:19

Dropbox 웹 사이트

가끔 Dropbox 를 방문할 때마다 웹사이트의 간결함에 무척이나 놀란것 같습니다. 


처음에 방문하면 단지 아래 화면만 보여주고, 





"Download Dropbox" 라는 버튼을 누르면 아래처럼 정말 필요한 설명만 가지고 해당 서비스를 이용할 수 있게끔 해 줍니다. 




아우, 정말 훌륭합니다!

2012. 5. 4. 06:00

변수와 가독성

출처: The Art of Readable Code (번역서: 읽기 좋은 코드가 좋은 코드다)

☞ 개발자 강추 서적입니다.


변수와 관련된 3가지 문제점들이 있으며,


1. The more variables there are, the harder it is to keep track of them all.

2. The bigger a variable’s scope, the longer you have to keep track of it.

3. The more often a variable changes, the harder it is to keep track of its current value.


이러한 이슈를 처리하는 방법은 다음과 같습니다.


Eliminate Variables

  • Useless Temporary Variables
  • Eliminating Intermediate Results
  • Eliminating Control Flow Variables


Shrink(Reduce) the Scope of Variables

  • Creating "Private" Variables
  • Moving Definitions Down

Prefer Write-Once Variables
  • const or final
  • immutable or permanent

예제입니다.  아래와 같은 텍스트 입력 필드를 가지는 웹페이지가 하나 있습니다.

<input type="text" id="input1" value="Dustin">
<input type="text" id="input2" value="Trevor">
<input type="text" id="input3" value="">
<input type="text" id="input4" value="Melissa">
...
id 는 input 으로 시작하며 1에서 부터 하나씩 증가합니다. 작성해야할 함수는 value 값이 비어 있는 input 을 찾아서 값을 입력하는 것입니다. 앞에서 소개했던 변수와 관련된 원칙들을 고려하지 않고 작성한 코드는 다음과 같습니다.
var setFirstEmptyInput = function (new_value) {
	var found = false;
	var i = 1;
	var elem = document.getElementById('input' + i);
	while (elem !== null) {
		if (elem.value === '') {
			found = true;
			break;
		}
		i++;
		elem = document.getElementById('input' + i);
	}
	if (found) elem.value = new_value;
	return elem;
};

기능을 제대로 수행하지만 이쁘지 않습니다. found, i, elem 변수가 함수 전체에 걸쳐서 여러번 사용되고 있습니다. 우선 found 와 같은 중간 결과값을 저장하는 변수를 제거해 보겠습니다.

var setFirstEmptyInput = function (new_value) {
	var i = 1;
	var elem = document.getElementById('input' + i);
	while (elem !== null) {
		if (elem.value === '') {
			elem.value = new_value;
			return elem;
		}
		i++;
		elem = document.getElementById('input' + i);
	}
	return null;
};

다음은 elem 변수를 살펴보겠습니다. 이 변수는 저장하는 값이 무엇인지 기억하기 쉽지 않게끔 매우 반복적으로 사용되었습니다. 이를 좀 더 개선해 보겠습니다.

var setFirstEmptyInput = function (new_value) {
	for (var i = 1; true; i++) {
		var elem = document.getElementById('input' + i);
		if (elem === null)
			return null; // Search Failed. No empty input found.
		if (elem.value === '') {
			elem.value = new_value;
			return elem;
		}
	}
};

이 코드에서 elem 의 범위가 루프의 안쪽에 국한되었으며 값이 한 번만 할당되는 변수임에 주목하세요. for 루프의 조건으로 true 를 사용하는 게 흔한 일이 아니지만, 그렇게 함으로써 i 의 정의와 i의 값을 변경하는 구문을 한 줄에 담을수 있습니다. 

☞ 전 이 예제에서 for 루프를 이용하여 임시 변수 i 를 사용하면서도 while(true) 효과를 주는 방식이 아주 맘에 듭니다.







2012. 2. 19. 09:32

아이디와 패스워드

'소프트웨어, 누가 이렇게 개떡같이 만든 거야' 중에서...

개발자는 사용자가 아이디와 패스워드를 자유롭게 선택할 수 있도록 해야 합니다. 이는 사용자가 원할 경우 이메일 주소를 아이디로 사용할 수 있어야 함을 뜻하며, 이를 거부할 경우는 채찍으로 다스려야 합니다. 개발자는 사용자의 삶을 복잡하게 하기 위해 존재하는 것이 아닙니다. 그리고 은행과 같이 큰 돈을 지키고 있는 것이 아니라면, 사용자가 원하는 패스워드가 어떤 것이든 허용해야 합니다. 문자의 선택에 제한을 두면 안되고, 강력한 패스워드를 요구해서도 안됩니다. 그럼 사용자는 패스워드를 적어둘 것이고, 그러면 패스워드의 안전성은 포스트잇 수준으로 떨어지겠죠.

- 가끔 회원가입을 하려고 하면 이메일 주소에 '.' 과 같은 잘못된 문자가 있다고 하는 사이트가 더러 있습니다. 이런 경우 그냥 사이트에서 나가버리는 데 가끔 아주 유명한 사이트마저도 그렇게 하는 경우가 있습니다. ㅡㅡ;
2011. 11. 21. 21:51

사용자의 정신 모델에 따라...

사용자의 정신 모델에 따라 인터페이스를 설계하지 않고 사용자에게 프로그램의 내부 구현에 맞추도록 요구하는 것은 매우 거만한 행동이지만 우리 업계에서는 매우 흔하게 볼 수 있습니다.

- 소프트웨어, 누가 이렇게 개떡같이 만든 거야 - 中에서
2011. 10. 22. 14:14

임상 실험

"소프트웨어, 누가 이렇게 개떡같이 만든거야" - 인사이트
(http://book.daum.net/detail/book.do?bookid=KOR9788991268395)

중에서 발췌한 내용입니다. (강추)

사이트 디자이너는 테스트 사용자에게 어떤 작업을 주어야 할지 모를 때도 종종 있습니다. 예를 들면 "7월에 탈라하시(Tallahassee)로 가는 항공편 중 가장 싼 티켓을 구매하시오."와 같이 실제 사용자가 사이트에 와서 하려는 일을 시키는 대신, "사이트에서 좋은 점과 나쁜 점을 알려주세요."와 같이 말하는 것을 본 적이 있습니다. 재어드 스풀은 Ikea.com 에서 수행했던 테스트에 대해 다음과 같이 설명합니다.

이케아의 디자이너들은 테스트 사용자들에게 "책장을 찾으시오."와 같은 작업을 시켰습니다. 거의 모든 테스트 사용자가 사이트의 검색창에 '책장'을 입력해 원하는 결과를 얻었습니다. 그러나 스풀이 "여러분은 200권 이상의 소설책을 소장하고 있으며 현재 상자에 담겨 거실 여기저기에 널브러져 있습니다. 어떻게 정리하는 게 좋을까요?"라고 테스트 사용자들에게 말했을 때, 그들은 매우 다르게 행동했습니다. 그들은 검색창을 사용하는 대신 상품 목록을 살펴보고, 가끔 검색 기능을 사용하기도 했지만 검색어는 '책장'이 아니라 '선반'이었습니다. 사용자들은 훨씬 더 어려워했는데, 그들의 정신 모델(mental model)이 사이트 디자이너와 매우 달랐기 때문입니다. 디자이너들이 이런 테스트를 하고 제3자에게 익숙하지 않은 질문을 던지게 할 정도로 똑똑하지 못했다면 이런 사실을 절대 깨닫지 못했을 것입니다.
 

뭉뜽그려서 "일단 
사용해 보시구 장점과 단점을 알려주세요" 보단 구체적인 기능, 사용성과 관련된 질문을 스스로에게, 테스터에게, 그리고 고객에게 할 수 있어야겠습니다. 
 
2011. 10. 18. 22:48

애플 수석 디자이너 - 조나단 아이브

애플 수석 디자이너 

조나단 아이브 (Jonathan ive)

- 이러한 제품에 관해서 가장 많이 노력했던 것은 바로 디자인을 멀리하는 것이었습니다. 저는 이러한 방법으로 만들어낸 형태야 말로 좀 더 객관적인 형태가 될 수 있다고 생각합니다. 느끼기에 이것이 필연적인 결과이고 디자인되지 않은 것처럼 보이고, 이것이 원래부터 이런 모습일 것이고, 어떻게 다른 모습일 수 있겠냐고 생각하겠지만 말이죠.

(어찌 이리도 멋진말을... 스마트폰 하면 아이폰 스타일... 이것 말고 어떻게 다른 모습일 수 있을까... 제가 느꼇던 바가 당신의 디자인이군요...ㅎㅎ)




 
2011. 10. 18. 22:16

SOLID (Object-oriented design)

출처: http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

 
InitialStands for
(acronym)
Concept
SSRP
Single responsibility principle
the notion that an object should have only a single responsibility.
OOCP
Open/closed principle
the notion that “software entities … should be open for extension, but closed for modification”.
LLSP
Liskov substitution principle
the notion that “objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program”. See also design by contract.
IISP
Interface segregation principle
the notion that “many client specific interfaces are better than one general purpose interface.”[5]
DDIP
Dependency inversion principle
the notion that one should “Depend upon Abstractions. Do not depend upon concretions.”[5]
Dependency injection is one method of following this principle.
2009. 10. 13. 05:51

두 개의 모자

소프트웨어를 개발하기 위해 리팩토링을 사용할 때, 두 가지 구별된 작업(기능 추가와 리팩토링)을 위해 시간을 나누어야 한다. 기능을 추가할 때는 기존 코드를 건드려서는 안되고 단지 새로운 기능만 추가해야 한다. 테스트를 추가하고, 테스트가 잘 작동하는지를 확인함으로써 진행상황을 알 수 있다. 리팩토링을 할 때는 기능을 추가해서는 안되고, 단지 코드의 구조에만 신경써야 한다. 그리고 어떤 테스트도 추가하지 않는다 (이전에 빼먹은 테스트가 없는 한). 단지 인터페이스가 변하여 작업을 계속하기 위해서 어쩔 수 없는 경우에는 테스트를 수정한다.

소프트웨어를 개발할 때, 아마 모자를 바꿔 쓰는 자신을 발견할 것이다. 새로운 기능을 추가하기 위해 시작했는데, 코드 구조가 바뀌면 작업이 더 쉬워진다는 것을 깨닫는다. 그래서 모자를 바꿔 쓰고, 한동안 리팩토링을 한다. 코드의 구조가 더 좋게 바뀌었으면, 다시 모자를 바꿔 쓰고 새로운 기능을 추가한다. 새로운 기능이 제대로 작동할 때, 새로운 기능에 대한 코드가 이해하기 힘들게 작성되었다는 것을 깨닫고는, 다시 모자를 바꿔 쓴 다음 리팩토링을 한다. 이 모든 작업을 하는데 단지 10분 정도 걸릴 뿐이지만, 그 시간 동안은 항상 자신이 어떤 모자를 쓰고 있는지 알고 있어야 한다.

출처 : Refactoring - 마틴 파울러
2009. 10. 13. 05:42

Refactoring 의 목적

첫째, 리팩토링의 목적은 소프트웨어를 보다 이해하기 쉽고, 수정하기 쉽도록 만드는 것이다.

이것과 대조되는 좋은 예가 퍼포먼스 최적화이다. 리팩토링과 마찬가지로 퍼포먼스 최적화도 보통 동작을 바꾸지는 않는다 (속도는 빼고). 단지 내부 구조를 바꿀 뿐이다. 그러나 그 목적이 다르다. 퍼포먼스 최적화는 종종 코드를 이해하기 더 어렵게 만들지만, 필요한 퍼포먼스를 얻기 위해서는 그렇게 해야 한다.

둘째, 리팩토링은 겉으로 보이는 소프트웨어의 기능을 변경하지 않는다는 것이다. 리팩토링 후에도 소프트웨어는 여전히 동일한 기능만을 가지고 있다.

만일 리팩토링을 하다 while 루프의 실행이 늘어 났다고 하자. 시간이 오래걸리는 while 루프는 퍼포먼스를 나쁘게 한다. 많은 프로그래머는 이와 같은 단순한 이유로 이런 리팩토링을 하지 않으려 할지도 모른다. 그러나 단지 그럴지도 모른다는 말에 주목하라. 프로파일(profile)을 보기 전에는 계산을 위해 루프가 얼마나 많은 시간을 소모할 지, 또는 그 루프가 시스템의 전체 퍼포먼스에 영향을 줄 만큼 자주 호출될 지에 대해 알 수 없다. 이 while 리팩토링에 대해 걱정할 필요 없다. 만약 최적화를 하고 있다면 이 부분에 대해 걱정을 해야겠지만, 그렇지 않으면 이와 같이 리팩토링을 함으로써 최적화를 하기가 더 유리해 질 것이고, 최적화를 효과적으로 하기 위한 더 많은 옵션을 가지게 될 것이다.

출처 : Refactoring - 마틴 파울러
2009. 10. 13. 05:18

Switch 문

다른 객체의 속성에 기반 한 switch문을 사용하는 것은 별로 좋은 생각이 아니다. 만약 switch 문을 사용해야 한다면 자기 자신의 데이터를 사용해야지, 다른 객체의 데이터를 사용하면 안된다.

 class Rental...
    double getCharge() {
        double result = 0;
        switch(getMovie().getPriceCode()) {
            case Movie.REGULAR:
                ...
            case Movie.NEW_RELEASE
                ...
                break;
            case Movie.CHILDREN:
                ...
                break;
        }
        return result;
    }

위 코드를 보면 getCharge 메소드를 Movie 클래스로 옮겨야 함을 의미한다.

 class Rental...
    double getCharge() {
        return _movie.getCharge(_daysRented);
    }

그리고 _movie 에 추상 메소드와 상속을 이용한 다형성을 주어 구현하면 깔끔하게 switch 문을 제거할 수 있다.

출처 : Refactoring - 마틴 파울러
2009. 7. 7. 11:26

Scriptable COM Object 설계 시 고려해야 할 점

Eric's Complete Guide To Type Signatures Of Scriptable Object Models

 

: 이 글은 마지막에 링크된 주소의 글을 번역한 것이다. 번역이 미숙하더라도 이해바람.

 

내가 수년 동안 받은 많은 질문들에 대해서 소개한다.

 

"VBScript JScript 둘 다에서 쉽게 호출될 수 있도록 하기 위해서는 어떻게 객체를 디자인 하는가?"

 

COM 은 매우 복잡한 타입 시스템을 정의하고 스크립트 엔진은 그 타입 시스템의 하위 집합만을 지원한다. C++ 에서 쉽게 호출될 수 있는 객체를 생성하는 것은 가능하지만 VB6, VBScript,  그리고 특별히 JScript 와 같은 다른 언어에서 쉽게 호출되지 않을 수 있다.

 

나는 여러번 개인적인 이슈에 대하여 블로그에 글을 올렸다; 지난달에 그에 관해 설명하는 문서를 요청 받았다. 뒤에 좀더 자세한 설명을 위한 메인 기사에 관한 링크를 제공할 것이다.

 

이것은 기본적으로 "해야할 것 들"에 대해서가 아니라 "하지 말아야 하는 것"에 대한 목록이다. 또한 직관적이고, 발견될 수 있는, 테스트 가능한, 문서화할 수 있는, 확장할 수 있는, 등등의 객체 모델을 디자인 하는 것에 관해 언급해야 할 것들이 굉장히 많이 더 존재한 다는 것을 기억하라. 언젠가 그것에 관해 이야기 할지도 모르지만, 오늘은 메소드 타입 원형의 구현자(the implementor of method type signatures) 가 반드시 피해야 하는 매우 기초적인 질문에 관해서만 언급할 것이다.

 

Numeric types

 

VBScript VT_I2(short signed integer), VT_I4(long signed integer), VT_R4(single float), VT_R8(double float), VT_CY(currency), 그리고 VT_UI1(unsigned bye) 데이터에 대한 산술연산을 할 수 있다. 8-바이트 정수, unsigned integers, signed bytes 그리고 fixed-point decimals 는 지원되지 않는다.

 

대조적으로, Jscript bytes, shorts, singles, currencies 그리고 unsigned integers 를 즉시 VT_I4 또는 VT_R8 중 하나로 (알맞은 것으로) 즉시 변환한다, 그리고 그것들을 가지고 연산을 수행한다.

 

일반적으로, 스크립트 엔진이 비록 특정 타입에 대한 연산을 지원하지 않더라고, 여전히 그 값을 저장하고 그것을 파라미터로 전달할 수 있다. (?: you can still store the value and pass it around.) 한 객체에서 VT_DECIMAL 값을 얻기 위한 접착제(glue)”로서 스크립트를 사용할 수 있고 그것을 다른 객체에 전달한다.

 

만약 당신의 객체 모델이 fixed-point decimals(VT_DECIMAL)을 사용한다면, 스크립트에서 객체를 사용하는 것은 어려울 것이다. 거의 모든 floating point 산술 연산은 에러가 생긴다는 것을 기억하라. 당신의 객체 모델이 currencies 의 의존적이라면 Jscript 는 원하는 목적을 실패하게끔 할 수 있다. 원칙적으로는, double long 만 지원한다.

 

좀더 많은 정보를 위해서는 아래 링크를 보라.

http://blogs.msdn.com/ericlippert/archive/2003/09/15/53000.aspx

 

Dates

 

VBScript Jscript 는 날짜를 다룸에 있어 완전히 다른 코드를 사용한다. 두 시스템은 좋았어(gotchas)”로 가득하다. 코드가 COM 에서 사용되는 표준 VT_DATE를 사용하여 date를 조작한다면, Jscript 는 그것들을 자동적으로 내부 date 포맷으로 변환할 것이다. 일반적으로 그것을 다루는 방법이 있긴 하지만, 그 코드는 약간 트릭키 할 수 있다.

 

자세한 정보는 아래를 보라.

http://blogs.msdn.com/ericlippert/archive/2003/09/16/53013.aspx
http://blogs.msdn.com/ericlippert/archive/2003/10/06/53150.aspx

 

Object Types

 

IDispatch 가 아닌 인터페이스를 노출하는 객체는 VBScript Jscript 에서 사용될 수 없다. VT_UNKNOWN 을 넘긴다면, 즉시 그것을 VT_DISPATCH 로 변환하려고 시도한다. Scriptable 객체 모델은 전적으로 dispatchable 해야 한다.

 

-디폴트(non-default) 디스패치 인터페이스는 나쁘다. Jscript 는 비-디폴트 디스패치를 지원하지 않는다. VBScript 는 하나가 주어진다면 비-디폴트 디스패치를 사용하긴 하지만, 디폴트 디스패치로부터 디스패치를 얻기 위한 어떠한 방법도 제공하지 않는다. 다중으로 분리된 디스패치 인터페이스를 지원하는 객체를 작성하지 말라.

 

자세한 정보는 아래를 보라.

http://blogs.msdn.com/ericlippert/archive/2003/10/10/53188.aspx

 

 빠뜨린 인자, 빠뜨린 정보

 

VBScript 는 빠뜨린 인자를 지원한다. 메소드를 아래와 같이 호출 할 수 있다.

 

x = foo.bar(123,  , 456)

 

그러면 VBScript PARAMNOTFOUND 가 설정된 에러 필드를 가진 파라미터 VT_ERROR 를 넘길것이다. 그러고 나서는 Callee 가 그 문제를 다루는 책임이 있고, 그 인자를 알맞은 디폴트 값으로 채운다.

 

Jscript 는 빠뜨린 인자를 지원하지 않는다. 12개의 인자를 가지고 그들 중 일부는 빠뜨릴 수 있다고 예상하는 객체 모델은 Jscript 에서는 사용하기가 어렵다. (그리고 그들은 아마도 매우 나쁘게 설계된 메소드이다.)

 

Jscript VBScript 모두 이름지어진 인수(named arguments)를 지원하지 않는다.

 

빠뜨린 인자를 전달하는 일반적인 대안은 VBScript 에서는 Nothing, Null, 또는 Empty 를 넘기는 것이고, Jscript 에서는 null 또는 undefined 를 넘기는 것이다. Null null VT_NULL 을 전달하고, Empty undefined VT_EMPTY 를 전달한다, 그리고 Nothing 은 디스패치 객체 포인터 값이 없는 VT_DISPATCH 를 전달한다. Jscript 에서 “null” 객체를 전달하는 쉬운 방법은 없다. 이것은 Jscript 의 디자인 결함이라고 생각한다, 하지만 우리는 현재 그것에서 벗어날 수 없다. 좋은 Scriptable 객체 모델의 설계자는 Jscript 에서 사용하는 것을 쉽게 하기 위해 Null Nothing 을 동일하게 다루는 것을 고려할 수도 있다.

 

또 다른 관련 이슈는 “empty/null  문자열문제이다. C에서, 빈 문자열과 널 문자열은 다르게 처리된다. VB6, VBScript, 그리고 Jscript 는 그렇지 않다. 널 문자열과 빈 문자열은 동일하다는 규약을 사용한다. 하지만 VB는 이 규약을 사용하지 않는 Win32 API 를 호춣랄 수 있다, 그래서 VB6 VBScript 는 실행시에 빈 문자열 또는 널 문자열을 넘기는 것을 허용한다. Jscript 는 이 기능을 가지고 있지 않다.

 

널과 빈 문자열을 구분하는 Dispatchable COM 객체 모델은 거의 확실히 버그가 있다. 그렇게 하지 마라.

 

자세한 정보는 아래를 보라.

 

http://blogs.msdn.com/ericlippert/archive/2003/09/12/52976.aspx
http://blogs.msdn.com/ericlippert/archive/2003/09/30/53120.aspx
http://blogs.msdn.com/ericlippert/archive/2003/10/01/53128.aspx

 

More On Parameter Passing

 

“Out” 파라미터는 나쁘다. 스크립트가능한 객체 모델에서는 out 파라미터를 가지는 메소드는 작성하지 마라. Jscript out 파라미터를 전혀 지원하지 않는다. VBScript 경우에도 메모리 릭이 일어나는 시나리오가 있을 수 있다.

 

“In-out” 파라미터 역시 나쁘다.” – Jscript in-out 파라미터를 전혀 지원하지 않는다. VBScript 는 항상 VT_VARIANT | VT_BYREF 를 넘긴다, 그리고 IDispatch::Invok 의 디폴트 구현은 만일 메소드가 hard-typed byref 파라미터를 예상하고 있다면 타입 불일치(type mismatch)를 일으킬 것이다. 고유한 강제적인 로직을 작성하거나 인자를 variant 로 만들수 있지만, 둘 다 트릭키 하다. 전적츠로 그것을 피하는 가장 좋은 방법은 – out 또는 in-out 파라미터를 사용하지 않는 것이다.

 

“Out-retval” 값은 사실상 파라미터가 아니다 그것은 반환값이다 그래서 out-retval 은 괜찮다.

 

자세한 정보는 아래를 보라.

 

http://blogs.msdn.com/ericlippert/archive/2003/09/15/52996.aspx
http://blogs.msdn.com/ericlippert/archive/2003/09/15/53005.aspx
http://blogs.msdn.com/ericlippert/archive/2003/09/15/53006.aspx
http://blogs.msdn.com/ericlippert/archive/2003/09/29/53117.aspx

 

Arrays

 

배열은 나쁘다. Jscript VB-스타일의 배열에 대해 매우 빈약하게 지원한다. 다차원 vb스타일 배열은 Jscript 에서 처리하기가 특히 어렵다. 파라미터로 배열을 가지는 객체 모델을 작성하지 않으려고 노력하거나 배열을 반환하기만 하는 객체 모델을 작성하라. (이것은 큰 배열을 복사하는데 드는 성능 비용을 피할 수 잇기 때문에 역시 좋은 생각이다.)

 

VB6 foo(10 to 20, 4 to 6) 과 같은 임의의 인덱스 범위를 가진 배열을 생성할 수 있다. VBScript 는 그러한 배열을 사용할 수는 있지만 그것들을 생성할 수는 없다 모든 VBScript 0 에서 시작하는 배열을 생성한다.

 

스크립트 엔진은 variant 배열만 지원한다. 바이트의 배열은 underlying OS 에 의해 문자열로 변환될 수 있지만, 그것은 아주 엉망으로 만드는 것이다.

 

좀더 자세한 정보는 아래를 보라.

 

http://blogs.msdn.com/ericlippert/archive/2003/09/22/53061.aspx
http://blogs.msdn.com/ericlippert/archive/2003/09/22/53069.aspx
http://blogs.msdn.com/ericlippert/archive/2004/05/25/141525.aspx

 

Collections

 

VBScript Jscript 모두 IEumVARIANT 를 구현한 컬렉션을 지원한다. 다른 열거자는 지원하지 않는다.

 

자세한 정보는 아래를 보라.

http://blogs.msdn.com/ericlippert/archive/2003/09/22/53063.aspx

 

Method names

 

객체 모델 이름에 A~Z 0~9 문자만 사용하라. Unerbar 를 가진 이름은 나쁘다. VB 에서는 라인 결합자(line continuation, _ ) 와 아주 쉽게 혼될 되고, 보기가 흉하다. 피하라.

 

Jscript 또는 VBScript 예약어 또는 내장(built-in) 객체 모델 엘리먼트와 충돌하는 이름은 역시 나쁜 생각이다.

 

자세한 정보는 아래를 보라.

http://weblogs.asp.net/ericlippert/archive/2004/06/10/152831.aspx

 

빠뜨린 점이 분명 있다고 확신한다. 나중에 그 목록에 대해 다시 업데이트할 것을 약속한다.

 

원문 : http://blogs.msdn.com/ericlippert/archive/2004/07/14/183241.aspx

 


2009. 2. 17. 20:33

The Open-Closed Principle

확장에 대해서는 열고, 수정에 대해서는 닫는다.

OCP 원칙은 Bertrand Meyer가 제시한 것으로 Robert C. Martin이 C++ Report (Jan. 1996)에 쓴 Engineering Notebook이라는 컬럼에 정리되어 잇다. (The Open-Closed Principle, http://www.objectmentor.com/publications/ocp.pdf )

이 원칙은 클래스 등이,
-. 확장(extension)에 대해서는 열려(open)있지만
-. 수정(modification)에 대해서는 닫혀(closed)있어야 한다

고 주장하고 있다.

클래스를 설계할 때 특별한 이유가 없는 한 확장을 허용해야 한다. 이유 없이 확장을 금지해서는 안되며, 이것이 '확장에 해서는 열려있다'라는 의미이다.

그러나 확장을 할 때마다 기존의 클래스를 수정해야 하는 것도 곤란한다. 확장을 해도 기존의 클래스는 수정할 필요가 없는 것이 '수정에 대해서는 닫혀있다'라는 의미이다.

확장은 대환영이지만 기존의 클래스를 수정해서는 안된다. 기존의 클래스를 수정하지 않고 확장할 수 있도록 하는 것이 The Open-Closed Principle의 원칙이다.

클래스에 대한 요구는 빈번하게 변화한다. 그리고 그 요구는 대부분 '기능을 확장하고 싶은' 경우이므로 클래스가 기능 확장을 할 수 없다면 곤란하다. 그러나 한편으로는 이미 완성되어 테스트까지 마친 클래스를 수정한다면 소프트웨어 품질을 떨어뜨릴 위험이 있다.

확장에 대해서는 열려있고 수정에 대해서는 닫혀있는 클래스가 부품으로써 재이용 가치가 높은 클래스이다. 그리고 디자인 패턴의 목적, 객체지향의 목적이란 바로 이러한 클래스를 만들 수 있는 구조를 제공하는 것이다.

참고 : Java 언어로 배우는 디자인 패턴 입문 - YUKI HIROSHI 저

2008. 10. 6. 21:45

GOF 디자인 패턴 (생성 패턴)


1.    Singleton 패턴

 

목적

n        어떤 객체가 하나만 생성되어 사용되어야 적용

 

 

public class A {

       private static A instance;

      

       private A() {}      // 생성자 제한

       public static synchronized A getInstance() {

             if(instance == null) {

                    instance = new A();

                    return instance;

             }else

                    return instance;                

       }

      

       public static void main(String [] args) {

             A a1 = A.getInstance();

             A a2 = A.getInstance();

            

             if(a1 == a2) {

                    System.out.println(" 객체는 동일합니다.");

             }

       }

}

 

 

2.    Factory Method 패턴

 

목적

n         객체를 생성하기 위한 인터페이스를 정의

n         서브클래스가 어느 클래스를 인스턴스화 할지를 결정

 

 



public abstract class Connection {

       protected String url;

      

       public Connection(String url) {

             this.url = url;

       }

       abstract public void connect();

}

 

class TCPConnection extends Connection {

       public TCPConnection(String url) {

             super(url);

       }

       public void connect() {

             System.out.println(url + " TCP 연결을 시도합니다.");

       }

}

 

class UDPConnection extends Connection {

       public UDPConnection(String url) {

             super(url);

       }

      

       public void connect() {

             System.out.println(url + " UDP 연결을 시도합니다.");

       }

}

 

class HTTPConnection extends Connection {

       public HTTPConnection(String url) {

             super(url);

       }

      

       public void connect() {

             System.out.println(url + " HTTP 연결을 시도합니다.");

       }

}

 

abstract class ConnectionFactory {

       abstract public Connection getConnection(String str);

}

 

class TCPConnectionFactory extends ConnectionFactory {

       public Connection getConnection(String url) {

             return new TCPConnection(url);

       }

}

 

class UDPConnectionFactory extends ConnectionFactory {

       public Connection getConnection(String url) {

             return new UDPConnection(url);

       }

}

 

class HTTPConnectionFactory extends ConnectionFactory {

       public Connection getConnection(String url) {

             return new HTTPConnection(url);

       }

}

 

public class Client {

       public static void main(String[] args) {

             ConnectionFactory factory = new TCPConnectionFactory();

             Connection socket = factory.getConnection("SOCKET://70.12.113.168:5555");

             socket.connect();

            

             ConnectionFactory factory1 = new UDPConnectionFactory();

             Connection datagram = factory1.getConnection("DATAGRAM://70.12.113.168:5555");

             datagram.connect();

            

             ConnectionFactory factory2 = new HTTPConnectionFactory();

             Connection http = factory1.getConnection("HTTP://70.12.113.168:5555");

             http.connect();

       }

}

 

3.    Abstract Factory 패턴

 

목적

n         구체 클래스를 명시하지 않고 관련된 혹은 의존적인 객체의 집합을 생성하기 위한 인터페이스를 제공

n         단순하게 객체 하나를 생성하는 경우보다는 여러 개의 객체를 생성해야 하는 경우에 유용

 

 





 

abstract class Head {

       abstract public void display();

}

 

class CircleHead extends Head {

       public void display() {

             System.out.println("둥근 타입의 머리를 가졌습니다.");

       }

}

 

abstract class Leg {

       abstract public void display();

}

 

class WheelLeg extends Leg {

       public void display() {

             System.out.println("바퀴 타입의 다리를 가졌습니다.");

       }

}

 

abstract class Body {

       abstract public void display();

}

 

class LCDBody extends Body {

       public void display() {

             System.out.println("몸통에는 LCD 화면을 가지고 있습니다.");

       }

}

 

abstract class Arm {

       abstract public void display();

}

 

class FingerArm extends Arm {

       public void display() {

             System.out.println("손가락 팔을 가지고 있습니다.");

       }

}

 

 

 

class Robot {

       private Head head;

       private Body body;

       private Leg leg;

       private Arm arm;

      

       public void addHead(Head head) {

             this.head = head;

       }

       public void addBody(Body body) {

             this.body = body;

       }

       public void addLeg(Leg leg) {

             this.leg = leg;

       }

       public void addArm(Arm arm) {

             this.arm = arm;

       }

       public void displayRobot() {

             System.out.println("완성된 로봇은 다음과 같은 기능을 가지고 있습니다.");

             head.display();

             body.display();

             leg.display();

             arm.display();

       }

}

 

 

 

abstract class RobotFactory {

       abstract public Head createHead();

       abstract public Body createBody();

       abstract public Leg createLeg();

       abstract public Arm createArm();

}

 

class HomeRobotFactory extends RobotFactory {

       public Head createHead() {

             return new CircleHead();

       }

       public Body createBody() {

             return new LCDBody();

       }

       public Leg createLeg() {

             return new WheelLeg();

       }

       public Arm createArm() {

             return new FingerArm();

       }

}

 

 

 

public class Client {

       public static void main(String[] args) {

             Robot homeRobot = new Robot();

             RobotFactory homeFactory = new HomeRobotFactory();

             homeRobot.addHead(homeFactory.createHead());

             homeRobot.addBody(homeFactory.createBody());

             homeRobot.addLeg(homeFactory.createLeg());

             homeRobot.addArm(homeFactory.createArm());

            

             homeRobot.displayRobot();

       }

}

 

 

 

4.    Builder 패턴

 

목적

n         Product 대한 다양한 추가 작업으로 인한 결과값의 변형에 유용

n         하나의 Product 완성하기 위해서 복잡한 작업을 거쳐야 경우에도 유용

 

 




 

 

import java.io.*;

 

abstract class Builder {

       StringBuffer result = new StringBuffer();

      

       public boolean makeFile(String filename) {

             try {

                    FileOutputStream fout = new FileOutputStream(filename);

                    DataOutputStream dout = new DataOutputStream(fout);

                   

                    dout.writeUTF(result.toString());

                    return true;

             }

             catch (Exception e) {

                    return false;

             }

       }

       public abstract String getResult();

       public abstract void makeTitle(String title);

       public abstract void makeAuthor(String author);

       public abstract void makeDate(String date);

       public abstract void makeSubTitle(String subTitle);

       public abstract void makeContext(String context[]);

}

 

 

 

class HTMLBuilder extends Builder {

       public String getResult() {

             result.append("</body></html>");

             return result.toString();

       }

       public void makeTitle(String title) {

             result.append("<html><<head>");

             result.append("<title>" + title + "</title>");

             result.append("</head>");

             result.append("<body>");

             result.append("TITLE : " + title + "<br>");

       }

       public void makeAuthor(String author) {

             result.append("AUTHOR : " + author + "<br>");

       }

       public void makeDate(String date) {

             result.append("DATE : " + date + "<br><hr>");

       }

       public void makeSubTitle(String subTitle) {

             result.append(subTitle + "<br>");

       }

       public void makeContext(String context[]) {

             result.append("<ul>");

             for(int i=0; i<context.length; i++) {

                    result.append("<li>" + context[i] + "</li>");

             }

             result.append("</ul>");

       }

}

 

 

 

class Director {

       private Builder builder;

       private String filename;

      

       public Director(Builder builder, String filename) {

             this.builder = builder;

             this.filename = filename;

       }

       public String construct() {

             builder.makeTitle("Member List");

             builder.makeAuthor("kkang");

             builder.makeDate("2005.12.25");

             builder.makeSubTitle("A++");

             builder.makeContext(new String[]{"홍길동", "김길동", "강길동"});

             builder.makeSubTitle("B++");

             builder.makeContext(new String[]{"길동", "원길동", "정길동"});

             return builder.getResult();

       }

      

       public boolean makeFile() {

             return builder.makeFile(filename);

       }

}

 

 

 

public class Client {

       public static void main(String[] args) {

             Director director = new Director(new HTMLBuilder(), "member.html");

            

             System.out.println(director.construct());

             director.makeFile();

       }

}

 

 

5.    Prototype 패턴

 

목적

n         새로운 객체를 생성할 new 연산자를 사용하지 않고 기존의 객체를 복사하여 이용하는 패턴


 



 



 

class Product implements Cloneable {

       private String name;

       private int price;

      

       public Product(String name, int price) {

             this.name = name;

             this.price = price;

       }

       public Product cloneMe() throws CloneNotSupportedException {

             return (Product) clone();

       }

      

       public String getName() {

             return name;

       }

       public void setName(String name) {

             this.name = name;

       }

       public int getPrice() {

             return price;

       }

       public void setPrice(int price) {

             this.price = price;

       }

}

 

 

 

class Manager {

       private Product product = null;

      

       public Product getProduct() {

             if(product == null) {

                    product = new Product("design pattern", 10000);

                    return product;

             }

             else {

                    try {

                           product = product.cloneMe();

                           return product;

                    } catch (Exception e) {

                           return null;

                    }

             }

       }

}

 

 

 

public class Client {

       public static void main(String[] args) {

             Manager manager = new Manager();

            

             Product product = manager.getProduct();

             System.out.println("name:" + product.getName());

             System.out.println("price:" + product.getPrice());

             System.out.println();

            

             Product product1 = manager.getProduct();

             System.out.println("name:" + product1.getName());

             System.out.println("price:" + product1.getPrice());

             System.out.println();

            

             product1.setName("java programming");

             product1.setPrice(5000);

            

             Product product2 = manager.getProduct();

             System.out.println("name:" + product2.getName());

             System.out.println("price:" + product2.getPrice());

             System.out.println();

       }

}

 

 

참고

1.      삼성 SDS 멀티캠퍼스 교육 과정 – “자바 개발자를 위한 디자인 패턴” (수강 추천)

      2.   StarUML 패턴 관련 도움말.
2008. 8. 19. 00:57

정보 은닉의 가치

전형적인 객체 지향적인 설계는 세계를 객체로 모델링할 수 있는 발견적인 능력을 제공하지만, 객체 지향적인 사고는 여러분이 ID를 int 대신 IdType으로 선언하는 데 도움을 주지 않을 것이다.

객체 지향적인 설계자는

"ID가 객체로 다루어져야 하는가?"

라고 물을 것이다. 프로젝트의 코드 작성 표준에 따라서 "네"라는 답변은 프로그래머가 생성자와 소멸자, 복사 연산자, 할당 연산자를 작성하고 모든 코드에 주석을 작성한 다음, 코드를 구성 제어에 저장해야 한다는 것을 의미한다. 대부분의 프로그래머들은 "아니요,ID를 위해서 완전한 클래스를 생성할 필요는 없습니다. 그냥 int를 사용하겠습니다"라고 결정할 것이다.

방금 무슨 일이 있어났는지 주의 깊게 관찰해 본다.

ID의 게이터 타입을 간단하게 숨길 수 있는 유용한 설계 대안은 고려되지도 않았다.

만약 설계자가

"ID가 감추어져야 할까?"

라고 물었다면, 그는 int 대신 IdType으로 대체하는 간단한 타입을 선언하여 ID의 타입을 숨기기로 결정할 것이다. 이 예제에서 객체 지향적인 설계와 정보 은닉의 차이점은 확실하게 규칙에 충돌하는 것보다 미묘하다. 객체 지향적인 설계도 정보 은닉처럼 이러한 설계 결정을 받아들일 것이다.

이 경우에 차이점은, 정보 은닉에 대한 발견적인 사고가 객체 지향적인 사고가 하지 않는 설계 결정들을 장려한다는 것이다.

"이 클래스에서 무엇을 숨겨야 하는가?"

라고 묻는 것이 인터페이스 설계 문제를 해결하기 위해서 가장 중요하다. 만약 클래스의 비밀을 손상시키지 않고 함수나 데이터를 public 인터페이스에 놓을 수 있다면, 그렇게 하도록 한다. 하지만, 그렇지 않다면 하지 말라.

=> "내가 무엇을 숨겨야 하지?"라고 질문하도록 버릇을 들인다. 그러면 여러분은 얼마나 많은 어려운 설계 문제들이 사라지는지에 놀랄 것이다.

출처 : CODE COMPLETE 2nd Edition -스티브 맥코넬
2008. 6. 15. 13:49

Strategy 패턴 소스 (셀 정렬 알고리즘 포함)

import java.util.Comparator;


public class Sorters
{
 /** 셀 정렬 구현. */
  public static void shellSort(Object[] base, Comparator compareStrategy)
  {
    int i, j;
    int gap;
    Object p1, p2;

    for(gap=1; gap <= base.length; gap = 3*gap + 1)
      ;

    for( gap /= 3; gap > 0 ; gap /= 3)
      for( i = gap; i < base.length; i++ )
        for( j = i-gap; j >= 0 ; j -= gap )
        {
          if( compareStrategy.compare( base[j], base[j+gap] ) <= 0)
            break;

          Object t = base[j];
          base[j] = base[j+gap];
          base[j+gap] = t;
        }
  }

  // ...

  public static void main( String[] args )
  {
    String array[] = { "b", "d", "e", "a", "e" };
    Sorters.shellSort(
      array,
      new Comparator()
      {
        public int compare( Object o1, Object o2 )
        {
          // 역방향으로 정렬
          return -( ((String)o1).compareTo((String)o2) );
        }
      }
   );

   for ( int i=0; i < array.length; ++i )
     System.out.println( array[i] );
  }
}