Implementation - 해당되는 글 3건

프로그래밍 언어의 타입


프로그래밍 언어 는 구현 방법에 따라, 명령형 언어와 선언형 언어 두가지 형태로 구분 할수 있습니다.

두 언어의 형태는 목적과 사용법이 틀리며, 개발자는 두가지 형태가 가지는 특징과 이해 속에서 개발에 임해야 할 것 입니다.


이 포스트는 명령형 언어와 선언형 언어의 정의 및 특징에대한 이해를 돕는 참고 자료 입니다.


  1. 명령형 언어(Imperative)

    프로그램이 작동할때 낮은 수준의 단계에서 프로그램의 상태는 메모리의 특정 영역의 값으로 표현되며, 구문들은 기계어 명령어로 정의 됩니다.

    이런 패러다임은 높은 순준의 프로그램밍 언어 에서도 거의 유사하게 따릅니다.

    가령 프로그램의 상태는 변수에 저장하게 되며, 기계어 명령어 보다 복잡하지만 명령의 구문을 이용하여 제어를 하게 됩니다.

    이런 식의 처리는 일반적으로 처리해야 할 각각의 단계가 순차적으로 실행 되는 형태를 가집니다. 그래서 C TYPE 의 프로그램밍 언어들은 main()을 진입점으로 시작하여 각각의 프로그램 단계를 처리 하게 됩니다.

    이 방법은 컴퓨터에 있어서 자연스럽운 방법이며, 또한 실세계의 요리방법, 공정 점검표와 같이 각각의 단계에 지시사항이 있고 또한 상태를 가지고 있는것 처럼 실세계의 사고 형태 와도 잘 어울립니다.

    이런 사항들을 고려 해보면 명령형 언어는 개념적으로 친밀하며,직접적으로 구체화 되어 있다고 볼 수 있습니다.

    그래서 대부분의 프로그램밍 언어는 명령형 언어의 형태를 가집니다.

  2. 명령형 언어의 표현방식

명령형 언어를 이용하여 프로그램밍을 할때 무엇을 나타 내기 보다는 어떤 방법으로 처리한다 라는 것을 기술하게 됩니다.

즉 이말은 결과를 알지 못하며, 처리 방법을 정의하고 처리되어 진 결과를 표현한다. 입니다. 선언형 언어와 비교를 통해 이분부을 더욱 명확하게 설명 할 수 있는데, 단적인 선언형 언어 이지만 HTML과 비교를 해보면 쉽게 차이점을 알 수 있습니다.

HTML의 경우 어떻게 처리 되는지를 정의 하는 것이 아닌 어떻게 보여야 하는지를 나 타냅니다. 즉 이렇게 표현 한다 라른 선언을 통해 원하는 결과를 얻는 것 입니다. 지만 명령형 의 경우는 프로그램의 상태를 변수에 저정하고 로직에 따른 변화 방법 을 정의 하여 그 결과에 따른 결과를 얻는 방법입니다.


  1. 명령형 언어의 특징

    1. 상태를 저장 하는 변수를 가지고 있다.

      명령형 언어 타입에서는 처리 결과 또는 처리 상태를 보관할 장소가 필요합니다.

      실제 처리 되는 명령에 따라 상태는 변경되게 되며, 이런 변경된 상태는 처리 명령에 영향을 끼치게 됩니다.

  1. 결과를 예측 할 수 있지만 완료된 결과는 수행전 알수 없다.

    명령형 언어에서 프로그램의 수행 결과는 정의된 것이 아닌 명령의 처리를 통해 얻어 진다고 했습니다.

    그런 이유로 우리는 결과를 예측 할 수 있지만, 완료된 결과를 알수는 없습니다.

    이런 문제는 런타임 오류 등 버그로 프로그램에 존재 할 수 있으며, 또한 명령형 언어는 예측하지 못한 결과를 처리 하기 위해 대부분 예외 처리라는 방식의 기능을 가지고 있습니다.

  2. 프로그램의 서술 단계와 실행단계의 처리와 상태가 상이하다

    프로그램의 서술 단계에서는 예측을 통한 명령 단계를 서술 하게 됩니다.

    하지만 서술 단계에서 각 명령단계의 상태는 존재 하지 않기 때문에 실제 명령이 수행할 당시의 상태를 모두 반영 할 수 없습니다.

    이런 이유로 프로그램머는 실행 시점의 명령 처리와 상태를 확인 하기 위한 디버깅 이라는 기술을 사용하여 실제 수행할 당시 명령 처리와 상태가 서술 당시에 예측한 상태와 명령처리 상의 오류가 없는지 찾아서 처리 하게 됩니다.


사실 명령형 언어와 선언적 언어를 딱히 선을 잘라 구분 하기 힘들 수 있습니다.

이 두가지 특징을 모두 가지는 언어들이 속속 등장하고 있으며, 또한 명령형 언어의 대표격인 C 계열의 언어에서 조차 특정 프레임웍 사용으로 선언적 형태로 변경 되는 경우도 있습니다.

하지만 명령형 언어는 폰노이만의 초기 프로그램 내장형 컴퓨터의 사상과 일치 하며, 컴퓨터 상에서 어떤 문제를 해결하기 위한 가장 자연스러운 방법으로 통하고 있습니다.

명령형 언어의 종류에는 c,c++,c#,java,스몰토크,포트란,파스칼 등등 우리가 아는 대부분의 언어들이 포함 됩니다.

이 처럼 컴퓨터 프로그램밍의 기본 개념을 따르는 명령형 언어들의 특징과 방식은 프로그램을 작성하는 기초가 될수 있습니다.

다음시간에는 선언적 언어에 대해서 살펴 보며, 점점 중요성이 부각 되고 있는 선언적 방식의 프로그램에 대해서 포스팅 하겠습니다.

'Implementation' 카테고리의 다른 글

AOP(Aspect Oriented Programing)란?  (0) 2008.03.12
TDD 를 이용한 클래스 디자인  (0) 2007.08.24
|
blog comments powered by Disqus

 관점 지향 프로그래밍 이란 OOP(Object Oriented Programing)를 보완하는 개념으로 어플리케이션을 OOP적으로 모듈화 하여 작성하더라도 다른 모듈에서 공통으로 나타날 수 있는 횡단 관심을 해결 하기 위한 방법이다.

여기에서 횡단관심사란 로깅, 보안, 트랜잭션등과 같이 어플리케이션 전반에서 사용될 수 있는 부가적인 기능들을 말한다.

   

   

 위와 같은 횡단 관심은 실제 어플리케이션 개발에서 나타나며 해당 관심들도 기존의 OOP적으로 모듈화 하여 사용할 수 있다. 그러나 이 방식의 문제점은 핵심모듈에 횡단관심 모듈들을 처리하는 로직이 들어가게 되는데 있다.


//입금 클래스

public bool DepositMoney(int accountNo, int insertMoney)

{

Log logging = new Log();

logging.Start(); //로깅시작


Transaction tran = new Transaction();

tran.begin(); //트랜잭션 시작


try

{

//입금로직

tran.commit(); //트랜잭션 커밋

}

catch

{

//예외처리

tran.rollback(); //롤백

}


logging.Stop();

}


위와같이 로깅이 필요한 모든 핵심모듈에서 동일한 코드가 작성되야 하는데 이는 중복되는 코드가 많아지고 재사용성이 떨어지며 로깅관련 기능이 변경되면 모든 핵심모듈을 변경해야 하므로 유지보수에도 많은 어려움이 따른다. 게다가 횡단관심이 로깅 이외도 트랜잭션, 보안등이 추가된다면 햄심 모듈안엔 다른코드 들로 도배가 되는 상황이 발생할 것이다.


위의 코드를 AOP를 이용해서 바꿔보면


[Log, Transaction]

public bool DepositMoney(int accountNo, int insertMoney)

{

//입금로직

}


이와 같이 변하게 된다.


이렇게 AOP로 구현하면하면 핵심 모듈을 건들지 않기 때문에 재 사용성이 떨어지지 않고 코드의 중복 또한 없어지므로 유지보수도 쉽게된다.

.NET에서 AOP를 구현하는 방법은 이런 Attribute를 이용하는 방법과 Spring.NET이나 Aspect.NET등의 프레임웍을 이용하는 방법이 있다.

'Implementation' 카테고리의 다른 글

프로그래밍 언어의 타입_1.명령형 언어  (1) 2008.11.20
TDD 를 이용한 클래스 디자인  (0) 2007.08.24
|
blog comments powered by Disqus

TDD 를 이용한 클래스 디자인

오늘 Test Driven Development에 대한 한가지 질문을 받았다.

"프로그램이 어떻게 돌아 가는지 만들어 지지도 않았는데 어떻게 테스트부터 작성해요?"

"너무 테스트를 작성하기가 힘들어요!"


난 TDD를 설명하기 보다는 IDE를 열고 TDD를 이용한 간단한 프로그램 개발을 같이 수행했다.

30분 정도의 설명이 곁들여진 짝 프로그래밍으로 그 사람은 어렴풋이 짐작이 간다는 투로 오늘 많이 배운 것 같다고 했다.

그의 질문처럼 제작 되지도 않은 프로그램을 테스트 할 수 있을까?

클래스 조차 생성되지 않았고, 심지어 클래스의 명 조차 정의 되지 않았는데 뭘 테스트 한다는 것 인가?

아마도 프로그램의 실제 제작(구현)에 관한 관점에서 테스트를 생각한다면 불가능하고 비효율적이라고 생각 할 것이다.

하지만 난 다시 질문을 하고 싶다.

'Test Driven Development 구현에 관한 것 일까?'

테스트를 작성한다는 것이 어떤 의미 일까?


Unit Test 먼저 작성 할 때 마다 나의 뇌는 클래스의 구조와 디자인 부분에 대해 집중한다는 것을 느낀다.

테스트를 작성할 때 클래스가 담당해야 하는 인터페이스에 집중 하게 된다.

먼저 나는 테스트 해야 하는 스토리(또는 요구 사항)를 하나 선택 한 후 적당한 클래스의 이름과 인스턴스 이름을 생각한다.

그리고 생각한 이름의 클래스를 생성하는 테스트를 작성한다.


User _myUser = new User();

Assert.IsNotNull(_myUser);


테스트를 수행 한다.

오류가 발생해서 빌드가 안 된다. User 클래스를 찾을 수 없다고 한다.

User 클래스를 만든다. 클래스에 아무것도 구현하지 않는다.


Public Class User{


}


테스트를 수행한다.

오 이제 오류가 없이 빌드 된다. 거기다 녹색 불 재수!


이제 다시 스토리를 본다.

'사용자의 생일이 오늘인지 확인할 수 있어야 합니다'


오늘이 사용자 생일인지 확인해주는 메서드가 필요 하겠군, 메서드 명을 뭐라고 한다.?

그냥 메서드 이름은 'BirthdayCheck'로 할까 ?

아님 'TodayIsBirthdayCheck'로 할까?

두 번째 것이 모호 하지 않고 좋을 것 같다.

테스트를 작성 한다.


_myUser.Birthday = ToDay();

Assert.IsTrue(_myUser.TodayIsBirthdayCheck());


테스트를 수행한다.

젠장! 빌드 오류다. Birthday 프로퍼티를 찾을 수 없다고 한다.


User 클래스로 가서 'Birthday' 프로퍼티를 만든다.


Public DateTime Birthday

{

    Set{

     _birthday = value;

    }

}


다시 테스트 수행 또 오류다.

_birthday 필드를 찾을 수 없다고 한다.

_birthday 필드를 선언한다.


Private DateTime _birthday;


다시 테스트를 수행한다.

지겨운 오류! 이번엔 TodayIsBirthdayCheck() 를 찾을 수 없다고 한다.

User에 TodayIsBirthdayCheck() 메서드를 만든다.


Public bool TodayIsBirthday()

{

    Return null;

}


다시 테스트 오! 이제 빌드 오류는 발생하지 않는다.

하지만 빨간불! 자 여기서 목표는 로직의 완성이 아니다.

빨리 녹색불 을 보는 것 테스트를 통과 하는 것이 우리가 할 일 이다.

그래서 난 그냥 TodayIsBirthday() 메서드에 True를 반환하게 한다.


Public bool TodayIsBirthday()

{

    Return true;

}


다시 테스트

신이여 감사합니다. 통과 다!


여기까지다 여기까지가 TDD의 끝이다.

'사용자의 생일이 오늘인지 확인할 수 있어야 합니다' 스토리에 대한 TDD 가 끝난 것이다.

ㅋㅋㅋ 말도 안 된다고 ?

TDD가 끝난 것이지 프로그램을 만들기 위한 구현이 완전 끝난 것이 아니라는 것을 알기를 바란다.

내가 말하고 싶은 것은 TDD는 구현의 도구가 아니라는 것이다.


이제 가상으로 만든 메서드의 로직을 실제 동작하게 구현 하여야 하며, 그런 중 다른 클래스와 관계를 가지고 작업을 하게 될 것이다.

가령 데이터를 저장소로부터 가져오는 Mapper 클래스나 시간을 나타내는 DateTime 등등 외부와 관계를 맺기 시작하며, 클래스의 내부는 점점 복잡해 지며, 우리는 그런 내부의 복잡함을 관리 하기 위해 리팩토링을 하며, 점진적으로 클래스를 완료해 나갈 것이다.


자! 이제 잘 생각 해보자

내부 구현과 리팩토링을 하기 위해 방금 만들어진 테스트를 변경 할 필요가 있을까?

결코 그런 일은 발생 하지 않는다.

스토리의 요구 사항이 변경 되지 않으면 테스트 셋의 정의 또한 변경 되지 않는 것이다.


아무런 기능을 하지 않지만 이름과 형태의 정의로 테스트 셋이 완료가 되었다.

즉 TDD의 테스트란 외부와 상호 작용을 하는 것의 정의에 대한 검증이다.

공개 인터페이스 디자인에 대한 검증이라고 말 할 수 있다.


우리는 보통 클래스 디자인을 할때 요구사항 정의서를 이용한 클래스다이어그램을 그리는 것을 상상 한다.

클래스다이어그램을 만드는 것이 어떤 행동인가?

요구상항의 요구조건을 수행하는 공개인터페이스에 대한 예측과 정의 아닌가?

그럼 TDD의 테스트 는 무엇인가?

스토리 또는 요구사항에 대한 공개인터페이스의 검증을 작성 하는 것이다.

검증을 작성하기 위해 예측하고 정의 하여야 하니까 이 부분에서 우리는 클래스의 디자인을 수행 하는 것이다.

또한 절대 정적이고 부자연스러운 클래스다이어그램에서 얻을 수 없는 견고한 테스트까지 얻을 수 있으니 클래스를 잘 디자인 하고 만들기 위해서 TDD을 사용할 가치가 충분이 있지 않을까?


'Implementation' 카테고리의 다른 글

프로그래밍 언어의 타입_1.명령형 언어  (1) 2008.11.20
AOP(Aspect Oriented Programing)란?  (0) 2008.03.12
|
blog comments powered by Disqus

matrim's Blog is powered by Daum & tistory