postobjektové programovanie v ruby
DESCRIPTION
Prezentácia z Rubyslavy #4 (@tkramar, @jsuchal)TRANSCRIPT
![Page 1: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/1.jpg)
Postobjektovéprogramovanie v Ruby
@tkramar, @jsuchal
![Page 2: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/2.jpg)
Paradigmamodel, súbor princípov, spôsob uchopenia
problému
![Page 3: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/3.jpg)
Aké paradigmy poznáte?procedurálna (C, Basic, COBOL, ..)
zdieľané dáta, procedúry operujúce nad dátami
objektová (Ruby, Java, Python, ..)zapuzdrené dáta, metódy operujúce nad stavom objektu
funkcionálna (Lisp, Haskell, Scheme, ..)dáta = program, čisté výrazy, bez vedľajších efektov
logická (PROLOG)deklaratívne programovanie - fakty a predikáty, odvodzovanie
![Page 4: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/4.jpg)
Objektidentita
stav
správanie
![Page 5: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/5.jpg)
class Person @name = ''
def initialize(name) @name = name end
def say "Ahoj, ja som #{@name}" endend
![Page 6: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/6.jpg)
PersonStav
@name
Správaniedef say "Ahoj, ja som #{@name}"end
Identitap = Person.new('Janko')o.object_id
![Page 7: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/7.jpg)
Identitasú dva objekty rovnaké?
==
sú dva objekty rovnaké a rovnakého typu?eql?
sú dva objekty totožné?equals?
![Page 8: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/8.jpg)
Identitap1 = Person.new('Janko') #=> #<Person:0x00000001b5c100 @name="Janko">p2 = Person.new('Janko')#=> #<Person:0x00000001b556e8 @name="Janko">
family = []family << p1family << p2
family.uniq#=> [#<Person:0x00000001b5c100 @name="Janko">, #<Person:0x00000001b556e8 @name="Janko">]
![Page 9: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/9.jpg)
class Person def ==(other) other.name == @name end
def eql?(other) self == other endend
![Page 10: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/10.jpg)
Identitap1 = Person.new('Janko') #=> #<Person:0x00000001b5c100 @name="Janko">p2 = Person.new('Janko')#=> #<Person:0x00000001b556e8 @name="Janko">
family = []family << p1family << p2
family.uniq#=> [#<Person:0x00000001b5c100 @name="Janko">, #<Person:0x00000001b556e8 @name="Janko">]
![Page 11: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/11.jpg)
class Person def hash @name.hash endend
![Page 12: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/12.jpg)
Identitap1 = Person.new('Janko') #=> #<Person:0x00000001b5c100 @name="Janko">p2 = Person.new('Janko')#=> #<Person:0x00000001b556e8 @name="Janko">
family = []family << p1family << p2
family.uniq#=> [#<Person:0x00000001b5c100 @name="Janko">]
![Page 13: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/13.jpg)
Základné konceptyinheritance (dedenie)
method overloading (preťažovanie metód)
method overriding (prekonávanie metód)
![Page 14: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/14.jpg)
Dedenieclass Instrument def tune ... endend
class Violin < Instrument def play tune "Taa daa" endend
![Page 15: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/15.jpg)
Overloading v ruby nefungujeclass Instrument def play "Ta da" end
def play(octave) "Ta da #{octave}" endend
i = Instrument.newi.play #=> ArgumentError: wrong number of arguments (0 for 1)i.play('c dur') #=> "Ta da c dur"
![Page 16: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/16.jpg)
Overridingclass Instrument def play "Ta da" endend
class Violin < Instrument def play "Tiii diii tiii" endend
v = Violin.newv.play #=> "Tiii diii tiii"
![Page 17: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/17.jpg)
Polymorfiaclass Instrument def play endend
class Violin < Instrument def play "Taa daa" endend
class Drum < Instrument def play "Dum dum" endend
orchestra = [Violin.new, Violin.new, Drum.new]orchestra.each { |i| i.play }#=> "Taa daa", "Taa daa", "Dum dum"
![Page 18: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/18.jpg)
Všetko v Ruby je Objekt
![Page 19: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/19.jpg)
Aj nilObject.class #=> Classnil.class #=> NilClass
![Page 20: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/20.jpg)
ActiveSupport tryp = Person.find(params[:id])
p.address.downcase #=> NoMethodError: undefined method `downcase' # for nil:NilClass
p.address.try :downcase #=> nil
![Page 21: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/21.jpg)
Aj metódaclass Person def greet(other_person) "Ahoj #{other_person}" endend
m = Person.instance_method(:greet)m.class #=> UnboundMethodm.arity #=> 1m.name #=> :greetm.parameters #=> [[:req, :other_person]]
![Page 22: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/22.jpg)
Aj triedaClass.class #=> Class
.. o metaprogramovaní inokedy
![Page 23: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/23.jpg)
Modulydef Class < Module
![Page 24: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/24.jpg)
Modul ako namespacemodule Rubyslava class OOP endend
module Pyvo class OOP endend
Rubyslava::OOP == Pyvo::OOP #=> false
![Page 25: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/25.jpg)
Modul ako nositeľ kódumodule Rubyslava def hello "Rubyslava" endend
![Page 26: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/26.jpg)
Mixinyclass RubyslavaAPyvo include Rubyslavaend
rp = RubyslavaAPyvo.newrp.hello #=> "Rubyslava"
class RubyslavaAPyvo extend Rubyslavaend
RubyslavaAPyvo.hello #=> "Rubyslava"
![Page 27: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/27.jpg)
Viacnásobné dedenieclass RubyslavaAPyvo < Array include Rubyslava, Pyvoend
RubyslavaAPyvo.ancestors#=> [RubyslavaAPyvo, Rubyslava, Pyvo# Array, Object, Kernel, BasicObject]
![Page 28: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/28.jpg)
Viditeľnosť v modulochmoduly zdieľajú všetko
inštančné premenné (@)
metódy
![Page 29: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/29.jpg)
module AdditionalBehaviour def show greet endend
class Test include AdditionalBehaviour
def greet "hello" endend
Test.new.show #=> "hello"
![Page 30: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/30.jpg)
module GreetingBehavior def greet "hello" endend
module RelyOnGreetingBehavior def show greet endend
class Test include GreetingBehavior, RelyOnGreetingBehaviorend
Test.new.show #=> "hello"
![Page 31: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/31.jpg)
Zo životaEnumerable
acts_as_..
ActiveSupport::Concern
![Page 32: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/32.jpg)
class Tree include Enumerable
def each(&block) leafs.each do { |n| yield n } endend
t = Tree.newt.mapt.injectt.sum...
![Page 33: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/33.jpg)
class Post acts_as_taggableend
p = Post.find(1)p.tag_list #=> ["Ruby", "OOP"]
![Page 34: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/34.jpg)
ActiveSupport::Concernmodule Annotatable extend ActiveSupport::Concern
included do has_many :notes, :as => :annotatable, :order => "created_at DESC" end
def most_annotated joins(:notes).group(:id).order("COUNT(*) DESC").first endend
class Project < ActiveRecord::Base include Annotatable, Importable, Versionableend
![Page 35: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/35.jpg)
Idiómyjazykovo špecifické vzory
![Page 36: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/36.jpg)
Ruby idiómybloky
a, b = b,a
a, b, c = array
(cachovanie) @var ||= ..
![Page 37: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/37.jpg)
Blokytransaction do |transaction| transaction.rollback if error?end
Dir.chdir('/') doend
with_disabled_keys doend
with_nested_loop_plan doend
![Page 38: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/38.jpg)
VzoryVšeobecné riešenie často sa opakujúcehoproblému. Nie je to knižnica, ani kód, skôr
šablóna.
![Page 39: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/39.jpg)
"When I see patterns inmy programs, I consider it
a sign of trouble."(Paul Graham)
![Page 40: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/40.jpg)
Vzory, ktoré v Rubynetreba programovať
![Page 41: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/41.jpg)
SingletonProblém: Zabezpečiť jednotný prístup k zdrojom
(napr. databáza)Zlo, česť výnimkám (ActiveSupport::Inflections)
![Page 42: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/42.jpg)
Singletonclass Logger def initialize @log = File.open("log.txt", "a") end
@@instance = Logger.new
def self.instance @@instance end
def log(msg) @log.puts(msg) end
private_class_method :newend
Logger.instance.log('message 1')
![Page 43: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/43.jpg)
Singleton (lepšie)require 'singleton'
class Logger include Singleton
def initialize @log = File.open("log.txt", "a") end
def log(msg) @log.puts(msg) endend
Logger.instance.log('message 2')
![Page 44: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/44.jpg)
IteratorProblém: Umožniť manipuláciu s kompozitnýmobjektom bez odhalenia jeho internej štruktúry
![Page 45: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/45.jpg)
Iteratorclass Tree include Enumerable
def each(&block) leafs.each { |e| yield e } endend
![Page 46: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/46.jpg)
DecoratorProblém: pridávanie funkcionality do triedy
počas behu programu
Dekorátor obalí pôvodnú triedu a kde trebarozšíri správanie
![Page 47: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/47.jpg)
class StringDecorator < String def starts_with? substr # ... endend
title = StringDecorator.new("Rubyslava")
![Page 48: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/48.jpg)
Decorator = open classesclass String def starts_with? substr # ... endend
"aye aye captain".starts_with? "pirate" #=> false
![Page 49: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/49.jpg)
DelegatorProblém: Skrytie vnútorných závislostí
![Page 50: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/50.jpg)
Delegatorinclude 'forwardable'class Car extend Forwardable
def_delegators :@car_computer, :velocity, :distance
def initialize @car_computer = CarComputer.new endend
c = Car.newc.velocityc.distance
![Page 51: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/51.jpg)
ProxyProblém: Skrytie implementačných detailov
načítavania zdroja
![Page 52: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/52.jpg)
Proxyrequire 'delegate'
class Future < SimpleDelegator def initialize(&block) @_thread = Thread.start(&block) end
def __getobj__ __setobj__(@_thread.value) if @_thread.alive?
super endend
google = Future.new do Net::HTTP.get_response(URI('http://www.google.com')).bodyendyahoo = Future.new do Net::HTTP.get_response(URI('http://www.yahoo.com')).bodyend
puts googleputs yahoo
![Page 53: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/53.jpg)
Ďalšie užitočné vzory
![Page 54: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/54.jpg)
Template methodProblém: Často sa opakujúci boilerplate kód.
Kostra programu, algoritmu.
![Page 55: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/55.jpg)
class Game def play prepare_board initialize_score while not end_of_game? make_move end endend
class Carcassonne < Game def make_move tile = tiles.pick_random ... endend
class Agricola < Game def make_move peasant = select_peasant ... endend
![Page 56: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/56.jpg)
CompositeProblém: V stromových štruktúrachzamaskovať implementačný detail:
uzly a listy.
![Page 57: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/57.jpg)
class Person def say "#{@name}" endend
class Family attr_accessor :members
def initialize(members) @members = members end
def say @members.each { |m| m.say } endend
f = Family.new(Person.new('Janko'), Person.new('Tomas'))t = Family.new(Person.new('Ferko'), f)
t.say #=> "Ferko", "Janko", "Tomas"
![Page 58: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/58.jpg)
StrategyProblém: Výber vhodného algoritmu
za behu programu
![Page 59: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/59.jpg)
class FileLogger < Logger def log(message) File.open('a') { |f| f << message } endend
class DatabaseLogger < Logger def log(message) Log.create(:message => message) endend
![Page 60: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/60.jpg)
StateProblém: Zmena správania objektu
v rôznych stavoch
![Page 61: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/61.jpg)
class TrafficLight include AlterEgo
state :proceed, :default => true do handle :color do "green" end transition :to => :caution, :on => :cycle! end
state :caution do handle :color do "yellow" end transition :to => :stop, :on => :cycle! end
state :stop do handle :color do "red" end transition :to => :proceed, :on => :cycle! endend
![Page 62: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/62.jpg)
light = TrafficLight.newlight.color # => "green"light.cycle!light.color # => "yellow"light.cycle!light.color # => "red"light.cycle!light.color # => "green"
![Page 63: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/63.jpg)
ObserverProblém: Oddelenie core funkcionality
a špecifického správania v určitýchstavoch objektu.
![Page 64: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/64.jpg)
class Comment < ActiveRecord::Baseend
class CommentObserver < ActiveRecord::Observer def after_save(comment) Notifications.deliver_comment("[email protected]", "New comment was posted", comment) endend
![Page 65: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/65.jpg)
Zápachy v kóde(Bad smells)
![Page 66: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/66.jpg)
Vytváranie vlastnéhotypového systému
is_a?, kind_of?
lepšie je respond_to?
![Page 67: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/67.jpg)
class Container def add(node) if node.kind_of? Array node.each { |n| @nodes << n } else @nodes << node end endend
container.add(Tree.new('a', 'b')) #=> ???
![Page 68: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/68.jpg)
class Container def add(node) unless node.respond_to? :each node = [node] end node.each { |n| @nodes << n } endend
container.add(Tree.new('a', 'b')) #=> ['a', 'b']
![Page 69: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/69.jpg)
ProtipríkladActiveRecord::sanitize_sql_for_assignment
def sanitize_sql_for_assignment(assignments) case assignments when Array sanitize_sql_array(assignments) when Hash sanitize_sql_hash_for_assignment(assignments) else assignments endend
![Page 70: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/70.jpg)
Visitor + typydef visit object method = "visit_#{object.class.name}" send method, object end
module Arel module Visitors class WhereSql < Arel::Visitors::ToSql def visit_Arel_Nodes_SelectCore o "WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" end end endend
![Page 71: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/71.jpg)
Shotgun surgeryak niečo mením tak musím na viacerých
miestach
crosscutting concerns
AOP (AspectJ)
![Page 72: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/72.jpg)
AspectJpointcut writableHeaderMethods() : execution(* (WritableRequestHeader|| WritableResponseHeader) .*(..));
before(HeaderWrapper header) : writableHeaderMethods() && this(header) { ...}
![Page 73: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/73.jpg)
ActiveRecord::Observer
ActiveController::Caching::Sweeper
before/after/around filtre
![Page 74: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/74.jpg)
Cachingclass DocumentController < ApplicationController caches_page :show caches_action :index
def show; end
def index; endend
![Page 75: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/75.jpg)
Autorizáciaclass DocumentController < ApplicationController before_filter :find_document
def show # render @document end
private def find_document @document = Document.find_by_id(params[:id]) endend
![Page 76: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/76.jpg)
class DocumentController < ApplicationController before_filter :find_document around_filer :authorize
def show # render @document end
private def find_document @document = Document.find_by_id(params[:id]) end
def authorize if current_user.can_view?(@document) yield else render :not_authorized end endend
![Page 77: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/77.jpg)
Ťažko testovateľná triedaskúsiť si najprv napísať test
rcov
![Page 78: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/78.jpg)
Duplicitný kódreek
metric_fu
rubymine
refaktoring
vzor Template
![Page 79: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/79.jpg)
Často sa meniaci kódchurn
![Page 80: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/80.jpg)
Dlhá metóda
![Page 81: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/81.jpg)
Dlhý zoznam parametrov*args
nahradenie objektom
fluent interfaces
![Page 82: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/82.jpg)
def params(*args) puts args.class puts args.inspectend
params('a', {:hello => 2}, 42)#=> Array#=> ["a", {:hello=>2}, 2]
![Page 83: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/83.jpg)
activerecord 2.xvs
activerecord 3.xVisit.first(:select => "happened_at", :order => "happened_at ASC").happened_at
Visit.select(:happened_at) .order("happened_at ASC").first.happened_at
![Page 84: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/84.jpg)
Primitívna obsesiaclass Debt < ActiveRecord::Base composed_of :debit, :class_name => "Money", :allow_nil => true, :mapping => [%w(debit_amount amount), %w(debit_currency currency)]end
debt.debit # => Money
![Page 85: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/85.jpg)
switch/caseTemplate polymorfia
<% subject.infos.each do |info| %> <%= render :partial => "#{info.class.to_s}_detail", :subject => subject %><% end %>
![Page 86: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/86.jpg)
Dátová triedaSkinny controller, fat model
![Page 87: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/87.jpg)
Dátová triedaclass SubjectController < ApplicationController def show if @subject.updated_at < Time.now - 2.weeks.ago @subject.refresh end endend
class Subject < ActiveRecord::Baseend
![Page 88: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/88.jpg)
Dátová trieda 2class SubjectController < ApplicationController def show @subject.update_if_stale endend
class Subject < ActiveRecord::Base def update_if_stale refresh if updated_at < Time.now - 2.weeks.ago endend
class Person < Subject def update_if_stale # update vsetky firmy kde je subjekt endend
![Page 89: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/89.jpg)
Komentáre# download new version of articledef perform(x) # load article from the url 'x' ...end
def download_article(url) ...end
![Page 90: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/90.jpg)
SOLID Principles
![Page 91: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/91.jpg)
Single responsibilityprinciple
Objekt by mal mať iba jednu zodpovednosť
observers
cache sweepers
moduly (include, extend)
![Page 92: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/92.jpg)
Open/closed principleTriedy by mali byť otvorené pre rozširovanie,
ale uzavreté pre modifikáciu
v ruby tomu ťažko zabrániť
![Page 93: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/93.jpg)
Liskov substitution principleKaždý nadtyp by mal byť nahraditeľný
podtypom
kruh/kružnica
čo s polomerom?
![Page 94: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/94.jpg)
Interface segregationprinciple
Hierarchia v rámci rozhraní - radšej viacšpecifických rozhraní ako jedno obrovské
v ruby nemá zmysel
![Page 95: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/95.jpg)
Dependency inversionprinciple
Závislosť musí byť na rozhraní, nie nakonkrétnej implementácii
dependency injection
![Page 96: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/96.jpg)
Domain driven designambiguous language
Array#first, Array#second, Array#forty_two
![Page 97: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/97.jpg)
class Subject < ActiveRecord::Base has_many :debts
def is_suspicious? debts.any? or in_liquidation? endend
![Page 98: Postobjektové programovanie v Ruby](https://reader031.vdocuments.site/reader031/viewer/2022020306/554f4908b4c905524c8b4820/html5/thumbnails/98.jpg)
ZáverWith great power comes great responsibility
(Spidermanov otec)