No ifs and buts


søndag 13. mai 2012 CodingDojo Ruby WTF

For noen dager siden hadde vi en ny CodingDojo i Bergen. Oppgaven denne gangen var å presse objektorientering til det ytterste og trene på polymorfi gjennom å skrive kode helt uten bruk av IF, SWITCH eller tilsvarende konstruksjoner. Er du interessert i bakgrunnen for denne øvelsen kan du ta en titt her på bloggen til professor Eugene Wallingford. Du bør også sjekke ut the Anti-If Campaign.

Jeg jobbet sammen med @Olsenius for anledningen. Vi brukte Ruby. Oppgaven vi forsøkte å implementere var en billett-automat. Desverre ble dette mer et eksperiment i hvilke Ruby-triks vi kunne missbruke for å unngå IF enn en trening i god objektorientering. Koden vi produserte er noe av det værste jeg kan huske å ha laget :)

Vi ble ikke helt ferdige – jeg måtte gå litt tidlig – men koden vi produserte er gjengitt i sin helhet nedenfor. Vi brukte TDD, men testene har jeg droppet her.

Ser du hvordan vi har oppfunnet et nytt pattern både for IF og for UNLESS (altså "not if")?

10 # Monkey patch: Just adding a convenient sum-method to arrays
11 class Array
12   def sum
13     self.inject(0){|x, y| x + y}
14   end
15 end
16 
17 class TicketMachine
18   def initialize
19     @balance, @total = [], []
20     @printers = { "total=5" => ValidTicket.new }
21     @money_validators = { "-" => InvalidMoney.new }
22   end
23 
24   # Properties:
25   def balance; @balance.sum; end
26   def total; @total.sum; end
27 
28   # Lets user print his ticket,
29   # but raises an Exception unless @balance is 5 !!!
30   def print_ticket
31     @printers["total=#{@balance.sum}"].print
32     @balance = []
33   end
34 
35   # Lets user insert money into the machine
36   # Will raise exception if money is a negative number !!!
37   def add money
38     begin
39       @money_validators[money.to_s[0]].fail_if_valid
40       raise "INVALID MONEY"
41     rescue NoMethodError
42       @balance << money
43       @total << money
44     end
45   end
46 end
47 
48 class ValidTicket
49   def print
50     puts "THE TICKET"
51   end
52 end
53 
54 class InvalidMoney
55   def fail_if_valid; end
56 end

That's all!


comments powered by Disqus