$30 off During Our Annual Pro Sale. View Details »

Metaprogramowanie dla początkujących

Metaprogramowanie dla początkujących

Po dwóch miesiącach pracy w Three of Coins jako młodsza programistka postanowiłam podzielić się z uczestnikami/czkami WRUGa moją przygodą w cudownym świecie metaprogramowania.

Marta Paciorkowska

September 12, 2013
Tweet

More Decks by Marta Paciorkowska

Other Decks in Programming

Transcript

  1. Metaprogramowanie dla
    początkujących

    View Slide

  2. Dobry wieczór!
    Marta Paciorkowska
    junior software engineer @ Three of Coins
    twitter: a_meba
    github: xamebax

    View Slide

  3. Mówię do ciebie, jeśli:

    Dopiero zaczynasz

    Zacząłeś/zaczęłaś tak dawno, że nie pamiętasz, jak to
    było

    Masz techniczne wykształcenie... albo nie.

    View Slide

  4. Please bear with me
    http://www.redbubble.com/people/teresab/

    View Slide

  5. Metaprogramowanie?

    View Slide

  6. View Slide

  7. Czy na pewno robisz to dobrze?

    View Slide

  8. http://propartnyc.com

    View Slide

  9. A gdyby tak gotowanie = kodowanie?
    Jak wyglądałby twój idealny posiłek?
    Weź ulubione składniki...

    View Slide

  10. View Slide

  11. Skutek?

    View Slide

  12. View Slide

  13. Odpowiednia ilość meta...

    View Slide

  14. http://fauxcheese.blogspot.com

    View Slide

  15. http://edanastole.ru

    View Slide

  16. Pierwsze starcie: możesz otwierać klasy i
    redefiniować metody!!!11one

    View Slide

  17. View Slide

  18. Drugie starcie:

    View Slide

  19. http://www.redbubble.com/people/teresab/

    View Slide

  20. Meandry dziedziczenia:
    https://github.com/3ofcoins/vendorificator
    https://github.com/3ofcoins/tinyconfig

    View Slide

  21. class TinyConfig < BasicObject
    # większość klasy pominięta
    def load(glob)
    glob = ::File.join(::File.dirname(::Kernel.caller.first), glob)
    load_helper(glob)
    end
    def bulk_load
    caller_path = ::Kernel.caller.first.sub(/(:\d+)?(:in .*)?$/, '')
    directory_name = ::File.join(
    ::File.dirname(caller_path),
    ::File.basename(caller_path, ".rb"))
    bulk_glob = ::File.join(directory_name, "*.rb")
    load_helper(bulk_glob)
    end
    end

    View Slide

  22. module Vendorificator
    class Config
    #większość klasy pominięta
    def read_file(filename)
    pathname = Pathname.new(filename).cleanpath.expand_path
    @configuration[:vendorfile_path] = pathname
    @configuration[:root_dir] =
    if pathname.basename.to_s == 'vendor.rb' &&
    pathname.dirname.basename.to_s == 'config'
    pathname.dirname.dirname
    else
    pathname.dirname
    end
    instance_eval(IO.read(filename), filename, 1)
    end
    end
    end

    View Slide

  23. module Vendorificator
    class Config < TinyConfig
    #większość klasy pominięta
    def read_file(filename)
    pathname = Pathname.new(filename).cleanpath.expand_path
    @configuration[:vendorfile_path] = pathname
    @configuration[:root_dir] =
    if pathname.basename.to_s == 'vendor.rb' &&
    pathname.dirname.basename.to_s == 'config'
    pathname.dirname.dirname
    else
    pathname.dirname
    end
    instance_eval(IO.read(filename), filename, 1)
    end
    end
    end

    View Slide

  24. $ rake spec
    mkdir -p tmp
    Run options: --seed 12619
    # Running:
    .EEEEEEEEEEEEEEEEEEEEEEEEEE..EEEEEEEEEEEEEEEEEEE
    1) Error:
    Vendorificator::Config#test_0001_allows to set and get values:
    SystemStackError: stack level too deep
    /path/to/repo/lib/config.rb:77
    48 runs, 16 assertions, 0 failures, 45 errors, 0 skips
    rake aborted!

    View Slide

  25. module Vendorificator
    class Config
    #większość klasy pominięta
    def method_missing(method_symbol, *args, &block)
    if modules.keys.include? method_symbol
    modules[method_symbol].new(environment, args.delete_at(0).to_s,
    *args, &block)
    else
    super
    end
    end
    end
    end

    View Slide

  26. View Slide

  27. method_missing <3

    View Slide

  28. def method_missing(meth, *args, &block)
    #this is were the magic happens
    end
    + Unikamy niespodzianek (...w teorii)
    + definiujemy metody na bieżąco...
    - ...ale po kryjomu

    View Slide

  29. Refactoring <3 metaprogramowanie
    yield twoim przyjacielem... prawda?
    def a_method(a, b)
    a + yield(a, b)
    end
    a_method(1, 2) {|x, y| (x + y) * 3 } # => 10
    define_method hurtowo tworzy metody, oszczędzając
    miejsce

    View Slide

  30. pry
    Wpisz w konsoli:
    $ gem install pry
    Lub dodaj gem 'pry' do Gemfile
    $ bundle install
    Chcesz się gdzieś zatrzymać? Dodaj do kodu:
    require 'pry' ; binding.pry

    View Slide

  31. Problemy dla osoby początkującej
    Alicja w krainie debuggingu, po złej stronie lustra
    Rubiowa czarna magia może przytłaczać
    Czy metaprogramowanie to lenistwo?
    Komu mogę ufać?

    View Slide

  32. Szanse dla osoby początkującej
    Ćwiczę umysł
    Ambitne => motywujące
    Lepsze zrozumienie mechanizmów działania języka
    Przyspieszony kurs myślenia w Ruby...
    Pisanie aplikacji webowych nigdy nie było prostsze!

    View Slide

  33. Warto:

    Eloquent Ruby, Russ Olsen: http://eloquentruby.com/

    Metaprogramming Ruby: Program Like the Ruby Pros,
    Paolo Perrotta

    Confident Ruby, Avdi Grimm: http://confidentruby.com/

    Thoughtbot: http://robots.thoughtbot.com/

    Ruby Rogues: http://rubyrogues.com/

    View Slide

  34. Dziękuję!
    Pytania?

    View Slide