Created by Joshua Paling, @joshuapaling

여기서 ATM에서 돈을 인출하는 기능을 코드로 작성하겠습니다. 앞에서 배웠던 것보다 어렵기때문에 먼저 다른 연습부터 해야합니다. 모르는 것이 생기면 책상에 잠시 떨어져서 생각해보고 구글로 검색하면서 준비합니다. 앞으로 많은 것을 배울 것입니다!

짝 프로그래밍이나 여러 명이서 같이 하거나 멀리 떨어진 사람과 인터넷으로 프로그램하면 다른 프로그래머가 어떻게 생각하는지 알 수 있습니다. 테스트 코드로 만들면서 개발하겠으나 코드에 집중할 수 있도록 테스트 코드를 미리 만들었습니다.

시작은 간단하지만 끝은 매우 어렵습니다!

Workflow

각 단계마다, 다음과 같이 해야합니다:

1. 새로운 테스트를 실행합니다: 전 단계의 테스트 코드는 지우고 현 단계의 미리 준비한 테스트 코드를 붙여넣습니다. (각 단계의 테스트는 단계의 마지막에 있습니다.) 테스트를 실행하여 통과하지 못하는 테스트를 확인합니다. 서브라임은 Ctrl-B 단축키로 테스트를 실행합니다. 또는 터미널에서 cd로 작업 디렉토리로 이동하여 ruby atm.rb를 실행합니다.

2. 테스트를 통과합니다: 현 단계에서 요구하는 기능을 코드로 작성합니다. 모든 테스트가 그린으로 표시되면 테스트를 통과합니다.

3. 리팩터: 여러분이 작성한 코드가 다른 사람에게도 읽기쉽고 고치기 쉽게 작성하도록 살펴봅니다. 검토가 필요한 단계가 있으며 짝과 상의하면 좋겠습니다.

이러한 과정은 TDD의 레드, 그린, 리팩터 워크플로우라고 합니다.

0.Set up your file

atm.rb 파일을 새로 만듭니다. 아래의 코드를 붙여넣습니다. 테스트에 따라서 withdraw() 메소드를 만들어 갑니다.

def withdraw(amount)
  if amount <= 0 # this deals with some of the situations...
    return false
  end
  # ToDo: figure out this bit
end

# import required testing libraries
require 'minitest/spec'
require 'minitest/autorun'

# BELOW ARE THE TESTS FOR AUTOMATICALLY CHECKING YOUR SOLUTION.
# THESE TESTS ARE FOR STEP 1.
# THESE NEED TO BE REPLACED AFTER EACH STEP.
describe 'atm' do
  [
    [-1, false],
    [0, false],
    [1, false],
    [43, false],
    [17, false],
    [5, true],
    [20, true],
    [35, true],
  ].each do |input, expected|
    it "should return #{expected} when $#{input} is withdrawn" do
      withdraw(input).must_equal expected
    end
  end
end

1. $5 bills

ATM은 5달러 지폐만 가지고 있다고 가정합니다. 인출가능한 금액을 요청하면 true를 반환하고 인출가능하지 않으면 false를 반환합니다.

Examples:

Tips for getting tests green:

나머지 연산자 %는 나눈 나머지를 계산합니다. 예를들어 9 % 41입니다.

2. How many bills?

그럼 인출가능하면 true로 반환하기 보다 인출할 지폐가 몇장인지 반환하도록 메소드를 수정합니다.

Examples:

Tips for getting tests green:

/ 연산자는 나누기를 계산합니다. 예를 들어 나이의 반을 계산해서 변수에 저장하려면 다음과 같이 합니다.

my_age = 28
half_my_age = my_age / 2

루비에서는 정수로 나누면 결과는 내림으로 수치맺음을 합니다.

new_number = 25/10
# new_number contains 2, because 25/10 = 2.5, and ruby will round that down to 2.

Tests for step 2:

# Replace your existing tests with the ones below.
describe 'atm' do
  [
    [-1, false],
    [0, false],
    [1, false],
    [43, false],
    [7, false],
    [5, 1],
    [20, 4],
    [35, 7],
  ].each do |input, expected|
    it "should return #{expected} when $#{input} is withdrawn" do
      withdraw(input).must_equal expected
    end
  end
end

3. Array of notes

프로그래밍에서 array는 기본이 되는 콜렉션입니다. 리스트라고 합니다.

인출가능한 지폐가 몇장인지 반환하기 보다, 반환할 지폐를 배열로 반환하도록 코드를 작성합니다(이 경우는 모두 5달러입니다).

Examples

Tips for getting tests green:

[]는 비어있는 배열입니다.[1, 2]는 요소가 2개인 배열(1과 2)입니다.

삽 모양 연산자(<<)는 배열에 요소를 넣습니다. 예를 들어 [10, 20] << 30는 30을 배열 뒤에 넣어서 [10, 20, 30]입니다.

times 메소드는 코드 블록을 여러번 실행합니다. 예를 들어 5.times { puts 'hello' }는 ‘hello’를 5번 출력합니다.

종합해보면:

my_array = [] # create an empty array and store it in my_array
my_array << 20 # now my array contains [20]
my_array << 30 # now my_array contains [20, 30]
remainder = 13 % 5 # remainder is 3
remainder.times { my_array << 5 } # now my_array contains [20, 30, 5, 5, 5]

Tests for step 3:

# Replace your existing tests with the ones below.
describe 'atm' do
  [
    [-1, false],
    [0, false],
    [1, false],
    [43, false],
    [20, [5, 5, 5, 5]],
    [35, [5, 5, 5, 5, 5, 5, 5]],
  ].each do |input, expected|
    it "should return #{expected} when $#{input} is withdrawn" do
      withdraw(input).must_equal expected
    end
  end
end

4. $10 notes

ATM은 10달러 지폐만 있다고 가정합니다. 10달러로 처리하는 메소드를 작성합니다.

Examples

Refactor

테스트를 통과하면 리팩터를 할 차례입니다.

프로그래밍에서, ‘매직 넘버’는 옳지 않습니다(이름에 속지 마세요!). 매직 넘버는 하드 코드하여 뜬금없이 튀어 나온 수이기 때문에 그 수가 무엇을 의미하는지 정확히 알기 어렵습니다.

아래 코드를 보고 어떤 코드가 이해하기 쉬운지 살펴봅니다:

# BAD - magic number!
balance = balance * 4.45
# BAD - nondescript variable name is not much better!
value = 4.45
balance = balance * value
# GOOD - isn't this much easier to understand?
interest_rate = 4.45
balance = balance * interest_rate

매직 넘버가 하드 코드한 수가 소스코드 여기저기에 나타날수록 문제가 됩니다.

매직 넘버를 사용하였습니까? 매직 넘버를 사용하지 않도록 코드를 리팩터해보겠습니까?

Tests for step 4:

# Replace your existing tests with the ones below.
describe 'atm' do
  [
    [-1, false],
    [0, false],
    [7, false],
    [45, false],
    [20, [10, 10]],
    [40, [10, 10, 10, 10]],
  ].each do |input, expected|
    it "should return #{expected} when $#{input} is withdrawn" do
      withdraw(input).must_equal expected
    end
  end
end

5. $5 and $10 notes

ATM이 5달러와 10달러를 가지고 있다고 가정합니다. 인출할 때 지폐 수는 적게 반환합니다.

Examples

Tests for step 5

# Replace your existing tests with the ones below.
describe 'atm' do
  [
    [-1, false],
    [0, false],
    [7, false],
    [20, [10, 10]],
    [25, [10, 10, 5]],
    [35, [10, 10, 10, 5]],
  ].each do |input, expected|
    it "should return #{expected} when $#{input} is withdrawn" do
      withdraw(input).must_equal expected
    end
  end
end

6. $5, $10, and $20 notes

ATM이 5달러, 10달러, 20달러를 가지고 있다고 가정합니다. 지폐를 처리할 수 있도록 메소드를 작성합니다.

Note: 여기서, 20달러 / 10달러 = 2 인 것 처럼 큰 돈은 작은 돈으로 나눌 수 있습니다. at this point, each higher denomination can be evenly divided by each lower denomination - eg. $20 / $10 = 2. Things get much trickier when that’s not the case (eg, $50’s and $20’s). For this step, we’ll intentionally not deal with this case to make it easier.

Examples

Tips for getting tests green:

배열이 비어있는지 확인합니다: my_array.empty?

배열이 비어있지 않은지 확인합니다: !my_array.empty?

배열의 첫번째 요소를 뺍니다: my_array.shift. 예시 [1, 2, 3].shift[2, 3]입니다.

메소드 안에서 다른 메소드를 불러 올 때 루비는 메소드에 파라미터로 넘길 때 값을 복사하는 ‘pass by value’ 개념이 없습니다.변수는 객체를 참조합니다.

Refactor

Tests for step 6:

# Replace your existing tests with the ones below.
describe 'atm' do
  [
    [-1, false],
    [0, false],
    [7, false],
    [53, false],
    [35, [20, 10, 5]],
    [40, [20, 20]],
    [65, [20, 20, 20, 5]],
    [70, [20, 20, 20, 10]],
    [75, [20, 20, 20, 10, 5]],
  ].each do |input, expected|
    it "should return #{expected} when $#{input} is withdrawn" do
      withdraw(input).must_equal expected
    end
  end
end

7. Final Discussion Points

Challenge! $50 and $20 notes

지금까지 작은 돈 지폐로 큰 돈을 나누는 사례를 제외하였습니다. 예를 들어, 50달러와 20달러(50달러는 20달러로 만들 수 없습니다)의 사례는 제외하였습니다. 왜 어려운 것일까요? 50달러와 20달러만 인출할 수 있는 경우, 60달러와 110덜를 인출하려고 하면 어떻게 될까요? 머릿속으로 계산하거나 종이에 써서 이 경우를 처리할 수 있는 로직을 생각해보세요. 도전할 준비가 되었다면 이 겨우를 처리하는 코드를 작성해보세요! (이번에는 여러분이 직접 테스트 코드를 작성해야 합니다.)