Lesson 1. Getting Started

Lesson 1. Getting Started

1장에서 배울 것은 :

  • 간단한 Java class 만들기
  • Java class를 가지고 노는 test class 만들기
  • JUnit famework 사용하기
  • 생성자에 대해 배우기
  • 위에서 작성한 code 리팩토링하기.


Testing

Test-driven development means that you will write tests for virtually every bit of code. It also means that you will write the tests first. The tests are a means of specifying what the code needs to do. After writing the corresponding code, the tests are run to ensure that the code does what the tests specify.

The production classes you build should know nothing about the tests written for them.

Design

You start by building only high-level designs, not highly detailed specifications. You will continually refine the design as you understand more about the customer needs. You will also update the design as you discover what works well and what doesn’t work well in the Java code that you build. The power of object-oriented development can allow you this flexibility, the ability to quickly adapt your design to changing conditions.

A Simple Test

You must designate the class as public in order for the testing framework JUnit to recognize it.

The classpath is a list of locations separated by semicolons under Windows or colons under Unix. You supply the classpath to both the compiler and the Java VM. A location can be either a JAR file (which contains compiled class files by definition) or a directory that contains compiled class files.

ex) javac -classpath c:\junit3.8.1\junit.jar StudentTest.java(the abbreviated keyword -cp.)

JUnit

Not only does the Java compiler need to know where the JUnit classes are, but the Java VM also needs to be able to find these classes at runtime so it can load them up as needed.

java -cp .;c:\junit3.8.1\junit.jar junit.awtui.TestRunner StudentTest


Adding a Test

public class StudentTest extends junit.framework.TestCase {
public void testCreate() {
}
}
  • the method must be declared public,

  • the method must return void (nothing),

  • the name of the method must start with the word test, in lowercase letters, and

  • the method cannot take any arguments ().

Creating a Student

new Student(“Jane Doe”);

You terminate each statement with a semicolon (;).

You place the new keyword before the name of the class to instantiate.

String literals represent object instances of the predefined Java class java.lang.String.

When the Java VM executes the new operator in this statement, it allocates an area in memory to store a representation of the Student object. The VM uses information in the Student class definition to determine just how much memory to allocate.

Creating the Student Class

class Student {}

Constructors

A constructor looks a lot like a method. It can contain any number of statements and can take any number of arguments like a method. However, you must always name a constructor the same as the class in which it is defined. Also, you never provide a return value for a constructor, not even void.

Local Variables

Student student = new Student(“Jane Doe”);

When the Java VM executes this statement, it executes the code to the right-hand side of the assignment operator (=) first, creating a Student object in memory. The VM takes note of the actual memory address where it places the new Student object. Subsequently, the VM assigns this address to a reference on the left-hand side, or first half, of the statement.

Returning a Value from a Method

String studentName = student.getName();

you are sending a message to the Student object, using the student reference assigned to in the previous statement.

String getName() { }

This getName method specifies instead a return type of String.

return “”;

The return statement here returns an empty String objecta String with nothing in it.

Refactoring

The first step is to eliminate the unnecessary local variables.
The second step: It is considered poor programming practice to embed String literals throughout your code. One reason is that the code can be difficult to follow if it is not clear what each String literal represents.

this

There are two ways to ensure that the value of the formal parameter is assigned to the field:
The first approach means you must rename either the parameter or the field.
The second approach for disambiguating the two is to use the same name for both, but where necessary refer to the field by prefixing it with the Java keyword this.


Ruby in Twenty Minutes 4

이 전에 만들었던 새로운 프로그램을 좀더 자세히 살펴봅시다. # 마크로 시작하는 줄은 Ruby에서 주석을 나타낼때 사용합니다. 이 마크가 사용된 줄은 interpreter가 무시하게 됩니다. The first line of the fileis a special case, and under a Unix-like operating system tells theshell how to run the file.(이부분은 무슨 뜻인지 모르겠네요;;) 나머지 주석들은 프로그램의 명확성을 위해 사용되었습니다.

say_hi 메소드가 좀더 기술적으로 변했습니다.

# Say hi to everybody
def say_hi
if @names.nil?
puts "..."
elsif @names.respond_to?("each")
# @names is a list of some kind, iterate!
@names.each do
|name|
puts "Hello #{name}!"
end
else
puts "Hello #{@names}!"
end
end

@names를 보고 분기를 합니다. 만약에 nil이면 점 세개를 출력합니다.

Cycling and Looping—a.k.a. Iteration

만약에 @names 객체가 each에 반응을 하면 iterator를 사용할 수 있다는 것이고 그것을 사용하여 각각의 사람들에게 인사를 하면 되겠네요.

반복에 대해 좀더 자세히 살펴봅시다.

@names.each do
|name|
puts "Hello #{name}!"
end

each는 코드 블럭을 받아들이는 메소드로써 리스트에 있는 모든 원소들을 상대로 코드 블럭을 실행합니다. do와 end 사이가 블럭에 해당합니다. A block is like an anonymous functionor lambda. 블럭은 파이프들(| |) 사이에 있는 변수가 이 블럭에서 사용될 파라미터입니다.

여기서는 리스트 안에 있는 모든 요소들을 name으로 가리키고 이것을 사용하여  puts “Hello #{name}!” 를 실행했군요.

다른 프로그래밍 언어의 경우 리스트의 요소들을 반복할 때 for loop를 사용합니다.
(C언어 스타일 같은 경우 다음과 같이 표현 합니다.)

for (i=0; i<number_of_elements; i++)
{
do_something_with(element[i]);
}

이것도 작동은 하지만 우아하진 않습니다. 여기서는 i와 같은 변수를 필요로 합니다.
i는 리스트의 길이를 나타내고 리스트에서 어떤 순으로 작업을 할지 알려줍니다.
하지만 Ruby는 좀더 우아한 방법을 사용합니다.
모든 구체적인 것들은 each 메소드 안에 숨겨 놨습니다. 우리가 할일은 오직 리스트안에 있는
각각의 요소들이 each문 안에서 어떠한 작업을 할 것인지만 기술하면 됩니다.

Blocks, the Highly Sparkling Glint on the Edge of Ruby

블럭은 리스트보다 더 복잡한 것들을 다룰 때 사용합니다. 메소드를 가지고 구체적인 것들을 다룰수 있는 것을 물론이고 셋업, 분해, 에러들 또한 다룰 수 있습니다

# Say bye to everybody
def say_bye
if @names.nil?
puts "..."
elsif @names.respond_to?("join")
# Join the list elements with commas
puts "Goodbye #{@names.join(", ")}. Come back soon!"
else
puts "Goodbye #{@names}. Come back soon!"
end
end

say_bye 메소드는 each를 사용하지 않고 대신에 @names가 join 메소드에 반응 하는지를 체크 합니다. 그리고 만약에 반응한다면 join을 사용합니다. 반응하지 않으면 그냥 변수를 문자열로 출력합니다. 이 메소드는 변수의 실제 타입을 신경쓰지 않습니다. 이 메소드가 지향하는 것은 “Duck Typing”입니다. “만약에 오리같은 것이 들어오면 오리처럼 꽥꽥거려라..”. 라는 것이죠. 이런것의 장점은 변수들의 불필요한 타입 제약을 가하지 않는다는 것입니다. 만약에 새로운 타입의 리스트를 가지고 온다면 (join 메소드를 구현한 것이여야 겠죠.) 모든 일들이 계획된 대로 진행될 것입니다.

Kicking Off the Script

여기까지가 MegaGreeter 클래스 였고 남은 부부는 이 클래스의 메소드를 호출하여 사용하는 부분입니다. 이게 Ruby in Twenty Minutes 여기서 배울 마지막 트릭이군요.

if
__FILE__ == $0

_FILE_ 이것은 현재 파일이름을 가지고 있는 마술 같은 변수 입니다. $0 은 프로그램을 시작하기 위해 사용되는 파일의 이름입니다. 이 문장은 “만약에 이 파일이 실행되는 파일이면…” 이라는 뜻입니다. 어떤 파일이 그냥 library 로 사용될 것이라면 저 문장에 걸렸을 때 실행되지 안을 것이고 만약에 파일이 실행될 수 있는 파일이면 다음 코드가 실행될 것입니다.

Consider Yourself Introduced

여기까지가 Ruby의 quick tour 였습니다. 하지만 아직 살펴 볼 것들이 많습니다.(제어문, 블럭, 모듈들,,)
Documentation 이곳에 가시면 여러 문서들이 무료로 제공됩니다.
만약에 책을 보고 싶으신 분들은 book list이곳을 클릭하여 살펴보시면 됩니다.

Ruby in Twenty Minutes 3

저번 글에서 만들어 두었던 class의 객체를 생성합시다.


g 객체를 한번 생성하면 그 이름이 Pat이라는 것을 기억하는군요. 흠.. 만약에 name 변수에 직접 접근하면 어떻게 될까요?


오호.. 안되는 군요..

Under the Object’s Skin

인스턴스 변수들은 항상 객체 속안에 숨겨져 있습니다. (인스턴스 변수는 @name 과 같이 @를 붙여서 만드나 봅니다.) 심하게 감춰져 있지는 않고 객체를 조사해보면 그들에게 접근 할 수 있는 다른 방법들이 존재합니다만…Ruby는 data를 숨기기 좋은 객체 지향 접근법을 사용합니다.

그럼 Greeter 객체 안에는 어떤 메소드들이 있을까요?


와오.. 엄청나게 많네요. 여기 보이는 메소드들은 Greeter 객체가 가지고 있는 모든 메소드입니다. 조상(부모도 포함됐겠죠? :)으로 부터 받은 많은 메소드들도 포함되어 있습니다. 만약에 우리가 만든 method들만 보고 싶다면 조상들에게 정의되어 있는 메소드를 보길 원치 않는 다는 의미로 false를 파라미터로 넘겨주면 됩니다.


자 그럼 이제 어떤 method들이 우리가 가진 객체가 반응을 하는지 봅시다:


say_hi와 to_s(어떤 것을 string으로 바꿔주는 method군요. 기본적으로 모든 객체들이 가지고 있습니다.) 그러나 name이란 메소드는 모르네요.

Altering Classes—It’s Never Too Late

만약에 name을 바꾸거나 보고 싶다면 어떻게 해야할까요? Ruby는 객체의 변수에 접근할 수 있는 쉬운 방법을 제공합니다.


Ruby에서는 class를 다시 열어서 수정을 할 수 있습니다. 기존에 이미 만들어져 있는 객체들은 바뀌지 않지만 이 후에 새로 만들어지는 객체들은 영향을 받습니다. 그래서 이제 새로운 객체를 만들고 @name 속성을 가지고 놀아봅시다.


attr_accessor 을 사용해서 getter에 해당하는 name과 setter에 해당하는 name= 두개의 메소드를 정의했습니다.

Greeting Anything and Everything, MegaGreeter Neglects None!

이 greeter 는 그다지 흥미롭지 않군요. 이 class는 오직 한번에 한사람만 다루는데요 여러 사람들에게 인사를 하는 class를 만들 순 없을까요?

그렇게 할 수 것을 Ruby interpreter인 IRB에 직접 쓰는 대신에 파일로 만들어 봅시다.

IRB를 끝내기 위해서 “quir”이나 “exit” 또는 그냥 컨트롤+D 를 입력합니다.

C:\Documents and Settings\keesun>ruby
class MegaGreeter
attr_accessor :names

#Create the object
def initialize(names = “world”)
@names = names
end

#Say hi to everybody
def say_hi
if @names.nil?
puts “…”
elsif @name.respond_to?(“each”)

@name.each do
|name|
       puts “Hello #{name}!”
     end
   else
   puts “Hello #{@names}!”
   end
  end

  # Say bye to everybody
  def say_bye
   if @names.nil?
     puts “…”
   elsif @names.respond_to?(“join”)
     # Join the list elements with commas
     puts “Goodbye #{@names.join(“, “)}.  Come back soon
   else
     puts “Goodbye #{@names}.  Come back soon!”
   end
  end

end

if __FILE__ == $0
  mg = MegaGreeter.new
  mg.say_hi
  mg.say_bye

  # Change name to be “Zeke”
  mg.names = “Zeke”
  mg.say_hi
  mg.say_bye

  # Change the name to an array of names
  mg.names = [“Albert”, “Brenda”, “Charles”,
   “Dave”, “Englebert”]
  mg.say_hi
  mg.say_bye

  # Change to nil
  mg.names = nil
  mg.say_hi
  mg.say_bye
end

cmd창을 열고 위처럼 입력한 뒤

컨트롤 + c를 입력하면 위에 입력한 것을 바로 처리합니다.

Hello world!
Goodbye world.  Come back soon!
Hello Zeke!
Goodbye Zeke.  Come back soon!
Hello AlbertBrendaCharlesDaveEnglebert!
Goodbye Albert, Brenda, Charles, Dave, Englebert.  Come back soon!

위와 같은 결과를 보셨다면 제대로 된 것입니다.

윈도우의 도스창에서 바로 실행시키지 않고.

위의 코드를 ri20min.rb 라고 저장한 뒤 ruby ri20min.rb 를 이용하여 실행하여도 같은 결과를 볼 수 있습니다.

Ruby in Twenty Minutes 2

저번에 이어 이번에는 “Hello World!”를 매번 전부 타자를 치지 않고 출력하는 방법은 없을 까요?

메소드를 만들어 봅시다.


위와 같이 코딩을 합니다.

def h 는 method 정의 부분을 시작하는 코드입니다. 이것은 Ruby에게 우리가 h라는 이름의 method를 정의하고 있다는 것을 알려줍니다.
다음 줄은 method의 body에 해당합니다. 우리가 전에 봤던 명령줄이랑 같습니다.
마지막으로 end는 Ruby에게 method 정의가 끝났다는 것을 알려줍니다.
Ruby의 nil 응답은 우리에게 method가 정의 됐다는 것을 알려줍니다.

The Brief, Repetitive Lives of a Method

이제는 위에서 만든 method를 몇번 호출해 봅시다.

매우 쉽네요. Ruby에서 method를 호출하는 방법은 method 이름을 부르면 되네요. 만약에 parameter들을 필요로 하지 않는 method라면 이렇게 해도 되는게 맞습니다. 비어있는 괄호를 추가시켜서 부를 수도 있지만 꼭 그럴 필요는 없지요.

만약에 kee sun이 아닌 특정 사람에게 인사를 전하고 싶다면 어떻게 해야할까요? h method가 이름을 parameter로 가지도록 재정의 하면 되겠네요.


몇가지 트릭이 사용되었는데요. 먼저 parameter로 이름을 주면서 method를 호출 해보고 다음에는 paramter가 없는 method를 다시 호출해 보았습니다. default parameter로 kee sun을 주었습니다. 이것은 name으로 오는 parameter가 없으면 “kee sun”을 출력하라는 것이네요.
그리고 원문에는 설명이 나와있지 않지만 아무래도 문자열.capitalize 메소드를 호출하면 문자열의 첫 문자를 대문자로 바꿔주는 듯 하네요.

Evolving Into a Greeter

만약에 진짜 greeter를 원한다면 어떨까요. 당신의 이름을 기억해두었다가 항상 당신에게 존경을 표하는 그런 것 말입니다. 당신은 아마도 그것을 위해 객체를 사용하길 원할 것입니다. “Greeter” class를 만들어 봅시다.


여기 새로 추가된 keyword는 class입니다. 이것은 Greeter라고 이름으로 새로운 class 정의 하고 class안에 method들을 정의합니다. @name 은 class내의 다른 method들에서 접근이 가능한 instance 변수 입니다. say_hi 와 say_bye 에서 사용한 것을 확인할 수 있습니다.

오늘은 여기까지 입니다. 다음 번에는 객체를 생성하여 사용하는 것을 살펴보겠습니다.

원문 : http://www.ruby-lang.org/en/documentation/quickstart/2/

번역 + 편역 : 기선