[Info]Tags categorized posts and contents patterns..

[AJAX] Ajax Code E xamples.. [Book] About the book.. [CSS] CSS Code E xamples.. [DB] Sql Code E xamples.. [DEV] All development stor...

레이블이 객체지향인 게시물을 표시합니다. 모든 게시물 표시
레이블이 객체지향인 게시물을 표시합니다. 모든 게시물 표시

2016년 2월 24일 수요일

[Book] Refactoring - 기존 코드의 디자인을 개선하는 방법..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

Refactoring - 10점
Martin Fowler 지음, 윤성준.조재박 옮김/대청(대청미디어)

마치 TDD처럼 언젠가는 해야지 하면서 맘속에만 있고 현실로는 적용해보지 못하던 리팩토링을 좀 알기 위해서 집어든 책이다. 나는 자바를 사용하고는 있고 최근에는 MVC Model 2니 해서 클래스의 사용을 좀 높이고 있기는 하지만 자바가 객체지향언어임에도 불구하고 나는 여전히 절차식 프로그래밍을 하고 있다.

단순히 재사용성을 위해서 클래스를 사용하고 있을뿐 전혀 객체지향이라고 할 수 없는 개발을 하고 있고 이런 거는 대부분 마찬가지일 것이다. 항상 코드를 더 좋게 만들고자 하는 마음은 있지만 현실적으로는 적용하기가 쉽지 않고 그에 대한 지식을 쌓는 것도 만만치 않다.

이 책의 저자인 마틴 파울러는 리팩토링에 흠뻑 빠져 있는 것을 느낄 수 있으며 초기에 아주 간단한 리팩토링의 예제를 보여주고는 리팩토링이 무엇이며 어떻게 해야 하는 가를 설명하면서 개발자들이 리팩토링을 하려고 할때의 고민들은 하나하나 설명해 주고 있다.

이 책에서 마틴 파울러가 설명하고 있는 리팩토링에 대한 개념중 가장 맘에 드는 것은 리팩토링을 하면 언제든 더 좋은 디자인으로 바꿀 수 있다는 것이다. 항상 초기 설계할때 좋은 설계, 좋은 디자인을 하는 것은 매우 중요하지만 우리 모두 현실적으로 이것이 쉽지 않은 것임을 알고 항상 설계와 디자인은 개발과정에서 수없이 바뀌게 마련이다. 하지만 리팩토링을 잘 할수 있는 사람은 이에 대한 걱정이 없다는 것이다. 일단 코드를 짜고 잘못된 부분이 있거나 의도하지 않은 방향으로 갔으면 언제든지 리펙토링으로 더 좋은 디자인으로 코드를 수정할 수 있다는 것이다.

간단한 개념 설명뒤에는 대부분의 책 내용을 실제 리팩토링을 할 수 있는 예재로 보여주고 있다. 자바를 기준으로 예제를 보여주고 있기 때문에 자바개발자라면 어느정도 이해할 수 있을 것이고 개념은 좀 어렵더라도 해당 리팩토링 예제에만 집중할 수 있도록 간단하게 예제를 작성해 놓았기 때문에 그렇게 다다가기가 어렵지는 않을꺼라고 생각한다. 각 리팩토링을 단위별로 뽑아내어서 설명하고 있다. Extract Method, Move Method등 하나하나 단위화 하여서 처음 배우는 사람이 최대한 접근하는 것이 쉽도록 제공하고 있다.

물론 다 읽고 난 후에도 이런것은 적용하는 것이 쉽지 않다고 생각하고 있다. 리팩토링을 하려면 어떤 부분을 리팩토링해야 되는지 알아야 하고 그 부분을 찾으려면 어떻게 리팩토링해야 하는지 확실히 알고 있어야 하는데 현실에서의 코드는 여기에 나와있는 예제처럼 명확치 않을 것이 확실하기 때문에 쉽지 않다. 여기 나오는 수십개의 예제를 다 외우고 있을 수도 없고 외우고 있다고 하더라도 이걸 현실에서 적용하려면 단순히 외운것 만으로는 할 수 없고 실제 경험적으로 알고 있어야 한다. 책을 옆에 두고 있다고 하더라도 적용하기는 보통의 노력으로는 쉽지 않을 것이다.

하지만 나에겐 이게 크게 가치있어 보인다. 리팩토링은 그만큼 매력적으로 보이고 아직 OOP를 제대로 알지 못하는 나에게도 이 책을 보면서 객체지향이 어떤것인지 약간은 개념을 잡을 수 있었다. (이걸로 객체지향을 알게 되었다면 웃긴 일이겠지만... ㅋ) 마틴 파울러가 얘기하는 것 중에서 메소드를 추출할 때 주석단위로 추출해서 메소드명을 명확히 하여서 주석자체가 필요없게 한다는 것은 꽤나 멋진 아이디어라고 생각했고 내가 추구하는 개발방향하고도 맞아떨어진다고 생각한다.

결국 이런 개념을 현실로 적용하려면 아주 간단한 거부터 적용하기 시작하는게 최고라고 생각한다. 그리고 물론 여기서 리팩토링을 한다는것 더 괜찮은 객체지향코드로 바꾼다는 것이기 때문에 리팩토링을 하기 전에 객체지향부터 확실히 이해해야 될듯하다. 그걸 제대로 이해못하면 객체지향 자체가 어렵기 때문에.... 하나하나 붙잡고 지속적으로 노력해서 경험을 통해서 감을 잡는 수밖에 없을듯 하다. 그래도 마틴파울러가 어떤걸 어떻게 바꾸어야 하는지는 다 적어놨으니....

2016년 2월 11일 목요일

[JS]prototype.js에서 클래스 상속(inheritance)하기..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

아래의 포스팅에서 prototype.js에서 제공하는 클래스 부분에 대한 설명을 했는데 OOP에 중요한 특징인 상속에 대해서 좀 보자. 이번 프로젝트에서 클래스 상속은 우리가 가진 설계의 핵심부분이었기 때문에 많이 중요했는데 처음엔 잘 안되서 좀 힘들었었다.

일단 자바스크립트에서는 상속이라는 개념을 제공하지 않는다. prototype이라는 기능을 제공하고 있기는 하지만 상속이라기 보다는 확장에 훨씬 가까운 느낌이다. 그래서 완젼(?)한 OOP를 위해서 프로토타입 프레임워크는 상속을 위한 extend라는 메서드를 제공하고 있다.

Object.extend(destination, source);

가 기본적인 extend의 사용법이다. source부분에 있는 객체의 모든 프로퍼티를 destination 객체로 복사한다. 어찌보면 완전한 상속이라고 하기엔 좀 다른 부분이 있다.(아직 난 OOP의 개념조차 좀 부족하기 때문에...)

이렇게 상속을 하면 destinatio측의 클래스 객체를 이용해서 source쪽에 있는 변수나 메서드를 사용할 수 있다. 한클래스 안에 모두 넣어도 되지만 클래스를 구분함으로써 더욱 명확한 구조를 가질 수 있다.

Js

// Object.extend 사용 예제
var Dog = Class.create();
Dog.prototype =  {
    initialize: function(mapId) {
        this.name  = "gae";
        this.age   = 2;
    },

    myName: function() {
        alert(this.name);
    }
}

var Cow = Class.create();
Cow.prototype =  {
    initialize: function(mapId) {
        this.sex  = "male";
        this.weight   = 100;
    },

    myWeight: function() {
        alert(this.weight);
    }
}

var animal = new Dog();
var bull = new Cow();

Object.extend(animal, bull);

alert(animal.name);
alert(animal.sex);
animal.myName();
animal.myWeight();

이렇게 상속을 받을 경우 인스턴스 animal을 사용해서 Dog과 cow의 변수 및 메서드를 모두 사용할 수 있다. 자신의 것은 당연한거고 Cow에 있던 것을 상속받았기 때문에 사용이 가능하다. 여기에 나는 하나의 인스턴스를 이용해서 다양한 기능을 구현할 것이지만 클래스를 구조를 이용하기 위해서 중심이 되는 클래스 하나만 객체로 만들어서 사용하기를 원했다. 즉 이건 식의 사용도 가능하다.

Js

// Object.extend 사용예제
var Dog = Class.create();
Dog.prototype =  {
    initialize: function(mapId) {
        this.name  = "gae";
        this.age   = 2;

        var bull = new Cow();   
        Object.extend(this, bull);  //상속
    },

    myName: function() {
        alert(this.name);
    }
}

var Cow = Class.create();
Cow.prototype =  {
    initialize: function(mapId) {
        this.sex  = "male";
        this.weight   = 100;
    },

    myWeight: function() {
        alert(this.weight);
    }
}

var animal = new Dog();

alert(animal.name);
alert(animal.sex);
animal.myName();
animal.myWeight();

Dog클래스 내부에서 Cow의 인스턴스를 만들어서 바로 상속을 받음으로써 외부에서는 Dog의 인스턴스만 만들어서 모든 기능을 사용할 수 있다.(난 약간은 다른 형태로 했는데 되겠지? ㅡ..ㅡ)


여기서 메서드든 변수든 같은 이름이 있을 경우는 어떻게 될까?

extend가 프로퍼티를 복사한다고 했으므로 당연히 덮어쓰는 효과가 된다. 즉 Overriding 효과가 난다. 이걸 이용하면 의도적으로 특정 메서드를 오버라이드 할 수 있다. 오버라이딩할 클래스를 나중에 상속받아오면 되니까... 당연히 다중상속도 가능하지만 위의 말한대로 이름이 겹칠경우 오버라이딩 되기 때문에 의도하지 않는 문제가 생기지 않도록 네이밍에 주의를 기울여야 한다.

추가로 이번에 작업을 준비하면서 여러가지로 테스트를 좀 했었는데 public 변수나 함수는 모두 this. 를 이용해서 접근할 수 있는데 이것은 상속받아온 곳에서도 동일하게 사용가능하다. 예를 들어 바로 위의 예제에서 Cow클래스에서 this.name을 접근해서 사용해도 가능하다는 것이다. (물론 Cow 인스턴스를 따로 만들어서 사용한다면 오류가 생기겠지...) extend된 상황에서는 this가 Dog클래스를 가르키고 있기 때문에.....

[JS]prototype.js에서의 클래스 사용에 대해서..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

Prototype Framework은 많은 것을 제공한다. 최근들어 갈수록 그 매력에 빠져들고 있다. 프로토타입이 느리다는 얘기도 많이 있고 여러 벤치마킹에서 그런 점이 드러나기도 하지만 자바스크립트 프레임웍의 시초격이라는 점에서 무시할 수는 없다고 생각한다.

어쨌든 프로토타입 프레임웍은 크게 편리함을 더해주는 유틸리티 함수들이 있고 클래스 사용을 위한 부분들이 있다. 둘은 그 성격면에서 상당히 다르다. 유틸리티 함수들이 사용법만 익히면 그냥 사용하면 되지만 클래스 부분은 아무래도 좀 만만치 않았고 OOP등 생각해야 할 것들이 많이 있었다. 이번에 프레임워크를 좀 적극적으로 사용하고 있고 유틸리티 함수는 물론이고 클래스 기능을 사용해 보려고 다방면으로 노력중이다.

자바스크립트는 상당히 유연성이 있기 때문에 객체라는 개념이 약간 모호한 느낌이 있다. function()을 그냥 쓸수도 있고 Object로 만들어서 쓸수도 있다. 상당히 엄격한 다른 언어에 비해서 자바스크립트의 러프함은 편하다고 할 수도 있지만 다른 면에서는 약간 혼란스럽기도 하다. 예시로 Function을 호출해서 사용한건지 객체로 만들어 사용한 건지는 소스를 뜯어봐야 알 수 있다.

그래서 프로토타입은 좀더 명시적인 클래스 및 OOP 구현을 위한 기능을 제공한다.

var Example = Class.create();

prototype.js에서 제공하는 클래스 생성 함수인 Class.create()이다. 이 부분은 특별한 기능이라기 보다는 선언부의 역할을 하고 있다. Example을 클래스로 사용할 꺼라는 것을 명시적으로 적어준 것이고 그렇게 함으로써 객체를 만들지 않고 Example();를 사용할 수 없다. (나도 처음 볼때는 펑션의 이런식으로하는 선언이 헷갈렸는데 일반적으로 쓰는 fucntion test() {} 같은 방식을 var test = fucntion() {}와 같이 써주어도 동일하다. 이부분에 대해선 나중에 다시한번 포스팅을...)
(사소한 부분이지만 클래스이므로 통상적인 파스칼방식의 표기법을 사용했다.)

위와 같은 선언부에 클래스라면 당연히 있는 생성자(Constructor)를 제공하고 있다.

Js

var Example = Class.create();
 
Example.prototype =  {
    initialize: function(par) {},
 
    methods: function() {}
}

클래스 구현을 위한 구조이다. 선언부 아래 클래스구현부를 적어주면 된다. 여기서는 자바스크립트의 prototype기능을 사용한다. prototype는 확장의 개념을 제공해주는데 예를 들어 간단히 적어보면

Js

var test;
test.prototype.loading = function() {}

와 같이 적어주면 test.loading(); 와 같은 형식으로 사용할 수 있게 된다. 즉 클래스에서 Example클래스에 뒤 이어올 변수 또는 함수를 확장시켜준 것이다.

처음으로 등장한 initialize는 생성자의 역할을 한다. 이 생성자는 반드시 있어야 한다. 선언안했다고 자동으로 해주지는 않는다. 그리고 생성자는 클래스의 이름과 동일하게... 라는 등의 규칙은 여기서는 적용되지 않고 initialize라는 이름을 고정으로 사용해야 한다. 생성자이기 때문에

var test = new Example();

라고 실행을 하면 자동으로 initialize()를 바로 실행시켜주고 보통 생성자가 하는 역할을 이 안에 구현해 주면된다. initialize()함수에 파라미터가 있다면 new Example(par) 과 같이 객체를 만들때 파라미터를 넘겨주면 initialize()함수가 파라미터를 받는다. 이렇게 생성하고 다른 함수들은 test.methods() 와 같이 사용하면 된다.(test로 Example의 인스턴스를 만들어줬으므로...)

동작자체만으로 본다면 굳이 이렇게 하지 않아도 가능은 하다. 하지만 명시적으로 클래스를 사용한다는 점과 이렇게 하면 객체를 만들지 않고는 사용할 수 없기 때문에 의도하지 않은 사용을 막을 수 있다는 점, 생성자를 통해서 init의 역할을 하는 함수 호출을 줄인다는 점 등 장점은 충분하다고 본다.