2006/01/15 애자일 Agile 선언문으로 생각해보는 애자일 소프트웨어 개발 [2]
2006/01/15 Follow Me: I Meet Ruby 2 [9] 2006/01/05 Rails 시작 하기 [2] 2005/11/29 Ruby를 공부하면서... [2] 2005/11/08 Follow Me: I Meet Ruby [3]
최근 Agile web development with Rails 라는 책을 읽고 있습니다. 앞 부분에 애자일 Agile 이란 어떤 것인지 설명이 나옵니다. 요즘들어 몇번 듣기는 했는데 잘 모르던 개념이라서 정리해 봤습니다. Agile을 기민함으로 번역할 수 도 있겠지만, 그냥 애자일이라고 표기하도록 하겠습니다.
Agile Software Development. 기민한 소프트웨어 개발정도로 번역할 수 있겠습니다. 처음 접했을 때와 마찬가지로 지금도 한 문장으로 정의를 내리기는 힘이 듭니다. 대신에 Agile Menifesto 애자일 선언문을 살펴보도록 하겠습니다. 선언문의 작성자는 17명인데, 사이트 개설일자를 보면 2001년도에 작성했다는 것을 알 수 있으며 그 중에는 eXtream Programming의 캔트 백 Kent Beck, 워드 커닝햄 Ward Cunningham, Refactoring의 마틴 파울러 Martin Fowler, Pragmatic Programmer의 데이브 토마스 Dave Thomas 등 최근 소프트웨어 분야의 큰 흐름을 이끌고 있는 쟁쟁한 사람들이 포함 되어있습니다. 이들이 공통적으로 추구하고 있는 애자일 이라는 개념은 다음 네 가지 사항에 가치를 둠으로써 이룰 수 있다고 밝히고 있습니다. 프로세스와 도구 보다 개개인과 상호 소통이 더 중요하다 Individuals and interactions over processes and tools 포괄적인 문서화 보다 제대로 동작하는 소프트웨어가 더 중요하다 Working software over comprehensive documentation 계약 협상 보다 고객과의 협력이 더 중요하다 Customer collaboration over contract negotiation 세워진 계획을 따르기 보다는 변화에 대응이 더 중요하다 Responding to change over following a plan 찬찬히 살펴보면, 그다지 새로울 것이 없는 개념이라고 할 수도 있겠습니다. 하지만 그것은 어디까지나 이미 XP를 접했기 때문일 가능성이 큽니다. 저는 애자일 이라는 것을 접한게 무척 최근이기 때문에 처음에는 XP를 대체하는 개념이라고 생각했지만, 그게 아니었습니다. XP는 애자일한 방법론 중에 가장 성공한 소프트웨어 개발 방법론이었습니다. 하나하나 좀 더 생각해 보겠습니다.
애자일이 화제가 되면서 특정 프로그래밍 언어가 애자일 한가 아닌가를 두고 고민하는 사람들도 있습니다. 사실 애자일이 소프트웨어 개발론으로 제시된 개념이기 때문에 굳이 언어를 선택해야 하는가 하는 의문이 듭니다. 여기에 김창준님이 kldp.org 에 답글을 단 내용을 인용합니다. 원문의 링크는 아래 표시해 두었습니다.
저는 Ruby가 애자일하게 사용하기 적합한 언어라고 생각하고, Rails가 애자일한 프레임워크라고 생각합니다. 그래서 애자일이라는 개념을 Agile web development with Rails 라는 책과 함께 공부하게 된것을 행운이라고 생각합니다. 참고: - 애자일 agile 선언문 공식 사이트 http://agilemanifesto.org/ - kldp.org에서 김창준님의 글 http://bbs.kldp.org/viewtopic.php?p=103770#103770 - Agile web development with Rails http://www.pragmaticprogrammer.com/titles/rails/index.html
간만에 다시 Ruby 입니다 ^^
이번엔 함수와 클래스에 대해서 알아보겠습니다. 함수 정의 및 사용 방법함수는 키워드 def 로 시작해서 end로 끝이 납니다. def 함수이름 (인자 목록) 함수 내용 end 이런 구조가 됩니다. 그리고 함수의 return 값을 얻기 위해서는 return 키워드를 사용하면 됩니다. 그렇지 않으면 마지막에 사용된 expression 이 반환됩니다. Ruby는 statement 가 없고 모두 expression 이기 때문에 보통 return 하고 싶은 값을 함수의 마지막에 계산하거나 적어주기만 하면 됩니다. def addTen( aNumber ) aNumber + 10 end 이렇게 정의해주고, 아래처럼 호출해주면 print addTen( 20 ) 화면에 30이 찍히게 되는거죠. C계열 언어에서와의 눈에 띄는 차이점은 1. 함수의 시작은 키워드 def로 한다 2. return 은 명시적으로 적어줘도 되지만 적지 않으면 마지막 expression 이 실행된다. 3. 인자 값의 타입은 필요없다. 4. 반환 값의 타입을 적어줄 필요가 없다. 또 한가지, 함수의 인자를 명시하기 위한 괄호는 생략 가능합니다. print addTen 20 도 같은 결과를 보여줍니다. 하지만, 한 눈에 관계를 알아보기 힘든 경우에는 괄호를 사용하는 쪽이 좋습니다. 클래스 정의 및 사용방법Ruby는 객체지향 스크립트 언어라고 했습니다. 객체지향 언어에는 빠지지 않는 개념이 있는데, 바로 클래스입니다. Ruby에서도 클래스를 지원합니다. 또한 객체지향을 이루는 여러 개념들을 훌륭하게 지원해줍니다. class의 시작은 키워드 class로 시작합니다. 그리고 함수와 마찬가지로 end로 끝나네요. 이번엔 샘플부터 보고 시작하도록 하겠습니다. class Jedi def initialize(name) @name = name end def use_force() puts "#{@name} uses force" end attr_reader :name end 대충 봐도 세 개의 함수를 가진 Jedi 라는 클래스가 있다는 걸 알 수 있습니다. force를 사용할 줄 아는 제다이를 표시하기 위한 클래스 입니다 ^^ initialize 함수부터 볼까요? 주의깊게 살펴보면 이 함수는 @name 이라는 변수를 가지고 있다는 것을 알 수 있습니다. 이 변수에다가 인자로 받은 name 을 저장하는군요. 여기서 잠시 Ruby의 변수관련 네이밍Naming을 보겠습니다.
이제 @name이 인스턴스 변수라는 것을 알았습니다. 그 밖의 변수는 아직 사용하지 않는군요. 그런데 @name의 값은 클래스가 생성될 때 설정되는 것이 좋지 않을까요? 새로 임명된 제다이가 이름이 없다면 얼마나 난감하겠습니까! 그래서 initialize 라는 함수 안에 넣어둔 것입니다. initialize 함수는 생성자Constructor를 의미합니다. 다른 OOPL 처럼 오버로딩해서 사용할 수 있습니다. 실제 사용은 다음과 같겠죠. obiwan = Jedi.new("Obi-wan") obiwan.use_force() Java나 C#같은 발전된 형태의 OOPL을 보면 getter, setter에 대한 개념이 나옵니다. 멤버변수에 대한 접근을 제한하면서 안전하고 효과적으로 사용하기 위한 개념인데, 개인적으로 C#에서의 Property 형태를 선호합니다. 우리의 사랑스런 Ruby에게는 accessor가 있습니다. attr_reader 혹은 attr_writer 라는 키워드를 사용하며, 인스턴스 변수에 읽기전용 혹은 쓰기전용 속성을 부여하는데 주로 사용됩니다. Jedi 클래스의 경우 attr_reader :name name 인스턴스 변수에 대한 접근제한을 읽기 전용으로 했으므로 puts yoda.name 는 할 수 있지만 yoda.name = "Padme" 는 할 수 없는 것이죠. 자세히 보면 @name 이 :name으로 바뀐 것을 알 수 있는데, 이에 대해서는 다음에 설명하도록 하겠습니다. 만약 읽기, 쓰기 모든 속성을 주고 싶다면 attr_accessor 키워드를 사용하면 됩니다. 혹은 attr_xxx 키워드를 사용하지 않고 def name @name end def name=(str) # name의 뒤에 공백이 있으면 안됩니다 @name = str end 이런 식으로 만들어 줄 수도 있겠습니다. 무척 유연하죠? 리소스의 Late binding을 지원하기 위해서 위의 방법을 응용할 수 있겠습니다. 클래스의 주된 특징 중 하나인 상속에 대해 알아보겠습니다. 루비는 C++과는 달리 하지만 Java와 C# 처럼 다중 상속을 지원하지 않습니다. (하지만, Mixin 이라는 것으로 다중상속과 같은 행위를 할 수 있습니다. 이에 대해서는 다음에 다루도록 하겠습니다) class JediMaster < Jedi def initialize(name, in_jedi_council) supur(name) @in_jedi_council = in_jedi_council end attr_accessor :in_jedi_council end 상속을 하는 간한한 예제입니다. 제다이는 수련과정을 거쳐서 제다이 마스터가 됩니다. 마찬가지로 생성자가 있는데, 생성자 initialize 안에 보면 super 라는 함수를 호출하는 것을 알 수 있습니다. Java 사용자라면 익숙하겠죠? C#의 base와 같은 이 함수는 자신의 부모의 생성자를 호출하는 함수입니다. 그러니까 JediMaster를 호출할 때 넘긴 name 인자는 부모인 Jedi 클래스가 받아서 @name을 초기화 시켜줍니다. 추가로 제다이 마스터는 제다이 위원회의 멤버가 될 수 있는데, 처음에 마스터가 되었을 때는 멤버가 아니더라도 나중에 가입이 될 수 있을테니 @in_jedi_council는 attr_accessor 로 주었습니다. yoda = JediMaster.new("Yoda", true) yoda.in_jedi_council = true super를 알았으니 자기 자신을 접근하는 방법도 알아봅시다. 클래스 내부에서 self 를 사용하면 다른 언어들의 this 와 같은 역할을 해줍니다. 추가적으로 self는 static method를 정의하기 위해서도 사용됩니다. 흔히 사용되는 Math 클래스를 생각해보면, sin, cos, tan 같은 함수들은 인스턴스의 함수가 아니라 클래스의 함수가 됩니다. 즉, Math.sin(), Math.cos() 이렇게 호출하기 위해서는 class Math ... def self.sin() ... end end 이런 식으로 정의를 하면 되겠습니다. 재미있는 Ruby FAQ: "Ruby" 스크립트를 컴파일 할 수 있습니까? 시험적으로 작성된 x86용 Just In Time 컴파일러가 있습니다만 실용적인 목적으로 만들어 지지 않았습니다. 왠지 남들이 많이 아는 것은 별로 하고싶지 않은 나쁜 심리와 세상 어딘가에는 남들이 잘 모르는 좋은 무언가가 있지 않을까라는 기대 심리로 인해 시작한 Ruby. Ruby를 공부하기 시작한지도 벌써 한달이 되어간다. 번역서는 아예없고, 원서도 몇군데 대형서점을 돌아다녀 봤지만 찾을 수 없어서 시작은 위태위태했다. 그러다가 +마이크로소프트웨어의 연재(2005.4~9)가 있다는 것을 알고 냉큼 복사해서 가지고 다니기 시작했고, 한국 루비 사용자 포럼도 알게 되었다. 또한 이 포럼의 wiki에 가면 번역된 Programming Ruby 를 볼 수 있었다!! (Programming Ruby는 실용주의 프로그래머 Pragmatic Programmer를 쓴 저자들의 Ruby 책이다. 현재 2판까지 나와있으며 1판은 인터넷에서 무료로 볼 수 있다. 포럼의 번역물은 1판). 또한 Ruby의 태생적 특징 때문에 일본어로된 많은 리소스들이 있는데, 알다시피 일본어로 된 웹사이트는 비교적 쉽게 *번역이 가능하기 때문에 잡다한 사실들을 얻는데 많은 도움이 되었다. 내 학습방법이 Rough하게 여러가지를 접한 후에 비로서 Detail한 것으로 들어가는 방식이라 아직도 많은 모르는 것들이 있지만, 이제 슬슬 원래 목적인 자동화된 개발환경 구축에 한가지씩 사용해 보고자 한다. 조금 더 익숙해지면, 그 동안 귀찮았지만 딱히 방법이 없어서 빠른 손놀림으로 해결했던 것들을 하나씩 자동화 시킬 수 있으리라 믿는다.
* 일본 웹사이트 번역해서 보기
Ruby 프로그래밍을 시작해 봅시다. 내 생각에는 아마 이 글을 읽으시는 분도 저 처럼 성격이 급할 것이라고 생각됩니다. Ruby를 잘 인스톨 했다면 윈도우키+r을 눌러서 [실행]창에 다음과 같이 적어 놓읍시다.
irb Command 창이 하나 뜨면서 irb(main):001:0> 라고 찍혀있습니다. 이제 준비가 끝났습니다. Ruby를 시작했다는 것을 혼자만 알고 있기 아깝지 않습니까? 옆자리 동료나 뒤에앉은 상사에게, 아니 이 세상을 향해서 인사 한번 하고 시작합시다. Hello, World! 내가 한 일을 컴퓨터도 할 수 있을까요? Ruby가 컴퓨터한테 명령을 내리기 위해서 다음과 같이 입력해 봅시다. print "Hello, World!" 자, 입을 크게 한번 벌려보세요. 턱도 좀 움직여보고. 한번 읽어 봅니다. 기호들은 빼고요. 프린트 헬로우 월드! 읽어보셨나요? 그럼 컴퓨터가 어떤 반응을 보입니까? Hello, world=> nil 시킨데로 했습니다. (솔직히 말하죠. 아직 irb가 왜 =>nil 를 출력하는지 모르겠습니다.) Ruby는 객체 지향 언어입니다. Ruby는 진정한 혹은 순전한 객체 지향 언어입니다. 이것이 의미하는 바는 Ruby에서 사용하는 모든 것은 객체이고 Ruby로 만드는 모든 것들 또한 객체라는 겁니다. 이미 객체 지향 언어 몇가지를 익히고 계실지 모르겠습니다. C++, Java 그리고 C#을 비롯한 .net 언어들 다 객체 지향 언어입니다. 하지만, 제가 보기엔 Ruby가 앞에서 말한 언어들보다 자유롭게 객체에 대해 생각할 수 있게 해준다고 생각합니다. 다르게 표현하면, Ruby는 우리의 생각을 자유롭게 표현할 수 있게 도와줍니다. 예를들어 Hello, world 라는 문장이 몇글자 인지 알고 싶을때 Ruby식으로 이렇게 합니다. C: strlen("Hello, world") Ruby: "Hello, world".length "Mc Ryan"의 이름에 y가 몇번째 나오는 문자일까요? "Mc Ryan".index("y") -92의 절대값은? Java: number = Math.abs(-92); Ruby: number = -92.abs -92를 Java는 숫자로 보지만, Ruby는 객체로 생각합니다. 객체는 흔히 적절한 데이터와 그것을 사용할 수 있는 메소드로 구성되어있죠. 제어문에는 if, while, for 등이 있습니다. C계열 언어라고 할 수 있는 C, C++, Java, C# - 프로그래밍 언어론 시간에는 ARGOL계열이라고 배우지만 편의상 앞으로 C계열 언어라고 하겠습니다 - 에서 사용하는 것과 문법적으로 의미 및 표기법이 흡사 합니다. 눈에 띄는 차이점이라고 한다면 Brace가 없는 거죠. 1부터 100까지 2씩 곱해나가다가 100이 넘으면 멈추는 로직을 한번 만들어 봅시다. C의 경우 int i = 1; while ( i < 100 ) { if ( (i *= 2) > 100 ) break; } printf("%d ", i); 같은 로직이 Ruby라면 i = 1 while i < 100 if (i *= 2) > 100 break end end 별로 차이가 없죠? 기존 C계열 언어의 Brace를 생략하면서 제어 구간의 마지막을 end로 일괄되게 표시함으로 문법의 간결함을 꾀했습니다. 또한 좀 더 사람들의 언어에 가까운 문법적인 특징이 있는데, 바로 조건절을 만드는 if, while 이 해야할 동작 뒤에 표시될 수 있다는 겁니다. 예를들어 위의 예에서 if문을 if (i *= 2) > 100 break end 이렇게 표시해도 같은 식입니다. break if (i = i * 2) > 100 "i에 2를 곱해서 100보다 크면 탈출(break)해라" 라고 말하는 거죠. 그럼 전체 프로그램이 짧아지는 효과가 있죠. i = 1 while i < 100 break if (i = i * 2) > 100 end 그럼 while도 될까요? 네 됩니다. i = 1 break if (i = i * 2) > 100 while i < 100 처음 코드와 비교해서 무척 짧아진 것을 확인할 수 있습니다. 일단 한줄로 표시함으로 end가 생략되었고, 생각의 흐름을 방해하지 않고 코딩할 수 있다는 장점이 있습니다. 조건부터 생각하고 행동을 결정할 때도 있지만 행동을 결정하고 그에 해당하는 조건을 생각할 때도 있으니까요. 프로그래머의 생각을 표현해주는데 될 수 있으면 적은 고민만을 요구하는 언어. 바로 Ruby가 지향하는 바입니다. 그리고 하나 더! Ruby에서는 변수를 사용하기 전에 특정한 타입을 지정해서 선언한 후 사용할 필요가 없습니다. 사용하는 순간 Ruby가 다 알아서 해줍니다. 난 모르지~ Ruby가 다 알아서 해주니까! 프로그래밍 언어에 빠질 수 없는 것이 바로 배열입니다. 배열은 흔히 연속된 메모리의 공간으로 추상화 됩니다. 대게 같은 형식의 데이터가 연속되어 있습니다. 특히 C나 C++의 경우는 그것이 진실이기도 하죠. 하지만 Ruby는 좀더 High-Level 언어입니다. Ruby는 다음과 같은 배열의 사용이 가능합니다. a = [ 1, 'pie', 3.14 ] 보통 같은 데이터 형식의 데이터로만 이루어진 배열을 쓰던 저에게 기본적으로 이렇게 자유로운 배열을 허락하는 Ruby가 무척이나 생소해 보입니다. 단순 반복작업을 줄이기 위한 장치가 있습니다. a = %w[ apple egg golf fear ruby ] irb(main):001:0> a = [1, 'pie', 3.14] => [1, "pie", 3.14] irb(main):002:0> a[0] => 1 irb(main):003:0> a[2] => 3.14 irb(main):004:0> a[3] => nil irb(main):005:0> a => [1, "pie", 3.14] irb(main):006:0> a = %w[ apple egg golf fear ruby ] => ["apple", "egg", "golf", "fear", "ruby"] irb(main):007:0> a => ["apple", "egg", "golf", "fear", "ruby"] irb(main):008:0> 놀랍지 않습니까? 이 기능은 편의를 위한 조그만 것이지만 사용할 곳이 참 많습니다. 감동스럽기 까지 하네요. 그럼 irb가 보여주는 것 말고 프로그램적으로 배열의 내용을 확인하려면 어떻게 할까요? for i in a puts i end 이렇게 하면 배열 a의 내용을 하나씩 i에 대입해서 puts i 를 이용해서 출력하게 됩니다. 배열을 사용한 프로그래밍은 '블럭'이라는 루비의 특징적인 기능으로도 가능합니다 (실은 훨씬 더 많이 쓰이는것 같네요). 아마 다음번 글에서 설명하게 될 듯 합니다. 자주 사용하는 자료구조로 해쉬가 있습니다. 해쉬는 키와 값의 한쌍으로 이루어진 아이템들의 집합이라고 할 수 있습니다. 아래처럼 정의해서 사용할 수 있죠. glossary = { 'UML' => 'Unified Modeling Language', 'GoF' => 'gang-of-four' } 괄호가 [ 에서 {로 바뀌고 key, value의 쌍을 => 기호로 표시합니다. 사용은 glossary['UML'] => Unified Modeling Language glossary['GoF'] => gang-of-four 마치 C에서 배열의 인덱스를 넣는 것 처럼 key 값을 넣으면 내용이 나오고, key에 value를 대입하면 값이 설정됩니다. glossary['SLR'] = 'Single Lens Reflex' glossary['SLR'] => Single Lens Reflex glossary['SLR'] = 'Simple LR parser' glossary['SLR'] => Simple LR parser * 오늘은 간단하게 Ruby의 제어문과 배열을 살펴봤습니다. 쉬운 내용인데도 정리해보려고 하니 시간이 많이 걸리는군요. 이런 글은 일주일에 2개 쓰기 힘들것 같습니다 ^^;; ** 코드 부분은 글꼴을 다르게 하던가 하고 싶은데, 이글루스의 블로그로는 표현에 한계가 많네요. 뭔가 다른 방법을 찾아봐야겠습니다. 혹은 스스로 블로그를 하나 만들지도 모르겠습니다. Ruby에게는 Ruby on Rail 이라는 강력한 프레임웤이 있거든요~!! 재미있는 Ruby FAQ: "Ruby"와"ruby"는 어느 쪽이 올바릅니까? 알아볼까요~
|
by 하얀아이 최근 등록된 덧글
조금 수정해서 Visual S..
by 과객 at 12/27 지스타 보러 설까지 왔.. by 하얀아이 at 11/27 저두 sysinternals에 .. by 루미넌스 at 11/27 정말 너무너무 감사합니.. by 나그네 at 11/06 글 본문 수정했습니다. .. by 하얀아이 at 10/27 이전블로그
카테고리
知人's weblog
| |||||||||||||||||||||||