The Art of Ruby

50 %
50 %
Information about The Art of Ruby
Technology

Published on March 8, 2014

Author: halogenandtoast

Source: slideshare.net

Description

The Art of Ruby: The spiritual successor to the Origamist's Ruby

Learn how to write beautiful code and how programming is a form of art.

Matthew Mongeau halogenandtoast goose@thoughtbot.com

The Art of Ruby

A programmer who subconsciously views himself as an artist will enjoy what he does and will do it better. Donald Knuth

What is Art?

/ärt/ the expression or application of human creative skill and imagination, typically in a visual form such as painting or sculpture, producing works to be appreciated primarily for their beauty or emotional power.

/ärt/ the expression or application of human creative skill and imagination, typically in a visual form such as painting or sculpture, producing works to be appreciated primarily for their beauty or emotional power.

What is Art

What is Art It’s beautiful.

What is Art It’s beautiful. It’s creative.

What is Art It’s beautiful. It’s creative. It’s expressive.

What is Programming

The art of writing code.

Code is Art

Code is Art It’s beautiful.

Code is Art It’s beautiful. It’s creative.

Code is Art It’s beautiful. It’s creative. It’s expressive.

Writing beautiful Code

Simplicity

Code should be clear

def play puts "Welcome to the guessing game." 3.times do guess = get_guess if won? guess @won = true puts "You win!" break else puts "Wrong!" end end if !@won puts "You lost. The actual number is #{@actual_number}." end end

def play puts "Welcome to the guessing game." 3.times do guess = get_guess if won? guess @won = true puts "You win!" break else puts "Wrong!" end end if !@won puts "You lost. The actual number is #{@actual_number}." end end

Extract Method Pattern def play puts "Welcome to the guessing game." play_rounds print_results end

Single Level of Abstraction Principle def play print_header play_rounds print_results end

Complexity

Balance

def play_rounds round_count.times do if correct_guess? get_guess @won = true break else puts "Wrong!" end end end

def play_rounds @won = round_count.times.detect { play_round } end def play_round if correct_guess? get_guess true else puts "Wrong!" end end

def play_rounds @won = round_count.times.detect { play_round } end def play_round if correct_guess? get_guess true else puts "Wrong!" # this returns nil which is falsey end end

Constraints

The more constraints one imposes, the more one frees one's self. Igor Stravinsky

Code Constraints

Code Constraints 5 line methods

Code Constraints 5 line methods 100 line classes

Code Constraints 5 line methods 100 line classes No classes in public methods

def play puts "Welcome to the guessing game." 3.times do guess = get_guess if won? guess @won = true puts "You win!" break else puts "Wrong!" end end if !@won puts "You lost. The actual number is #{@actual_number}." end end

def play print_header play_rounds print_results end

def play_rounds round_count.times do if correct_guess? get_guess @won = true break else puts "Wrong!" end end end

def play_rounds @won = round_count.times.detect { play_round } end def play_round if correct_guess? get_guess true else puts "Wrong!" end end

def play_rounds @won = round_count.times.detect { play_round } end def play_round if correct_guess? get_guess true else puts "Wrong!" # this is still bothering me end end

Breaking the Rules

Pablo Learn the rules like a pro, so you can break them like an artist. Picasso

def play_round if correct_guess? get_guess true else puts "Wrong!" end end

def play_round if correct_guess? get_guess puts "Correct" true else puts "Wrong!" false end end

def play_round if correct_guess? get_guess correct_guess else incorrect_guess end end def incorrect_guess puts "Wrong!" false end def correct_guess puts "Correct" false end

def play_round if correct_guess? get_guess correct_guess else incorrect_guess end end def incorrect_guess puts "Wrong!" false end def correct_guess puts "Correct" false end

class Guess def initialize actual_number @actual_number = actual_number @guess = get_guess end Extract Class Pattern def status if correct? "Correct" else "Incorrect" end end def correct? guess == actual_number end private attr_reader :guess, :actual_number def get_guess print "What is your guess: " gets.to_i end end

Extract Class Pattern def play_round guess = Guess.new(actual_number) puts guess.display_status guess.correct? end

1 Extract Method

1 2 Extract Method Extract Class

1 2 3 Extract Method Extract Class Extract Gem or App

You Win

Performance

If you’re willing to restrict the flexibility of your approach, you can almost always do something better. John Carmack

module Alchemist module Conversion def method_missing unit_name, *args, &block exponent, unit_name = Alchemist.parse_prefix(unit_name) if Alchemist.has_measurement?(unit_name) Alchemist.measurement self, unit_name, exponent else super( unit_name, *args, &block ) end end end end class Numeric include Alchemist::Conversion end

module Alchemist module Conversion def method_missing unit_name, *args, &block exponent, unit_name = Alchemist.parse_prefix(unit_name) if Alchemist.has_measurement?(unit_name) Alchemist.measurement self, unit_name, exponent else super( unit_name, *args, &block ) end end end end class Numeric include Alchemist::Conversion end

def self.parse_prefix(unit) matches = unit.to_s.match(prefix_matcher) prefix, parsed_unit = matches.captures if prefix && si_units.include?(parsed_unit) value = prefixed_value_for(prefix.to_sym, parsed_unit) [value, parsed_unit.to_sym] else [1, unit] end end

def self.parse_prefix(unit) matches = unit.to_s.match(prefix_matcher) prefix, parsed_unit = matches.captures if prefix && si_units.include?(parsed_unit) value = prefixed_value_for(prefix.to_sym, parsed_unit) [value, parsed_unit.to_sym] else [1, unit] end end

def self.parse_prefix(unit) matches = unit.to_s.match(prefix_matcher) prefix, parsed_unit = matches.captures if prefix && si_units.include?(parsed_unit) value = prefixed_value_for(prefix.to_sym, parsed_unit) [value, parsed_unit.to_sym] else [1, unit] end end

def self.prefix_matcher keys = unit_prefixes.keys.map(&:to_s). sort{ |a,b| b.length <=> a.length } %r{^(#{keys.join('|')})?(.+)} end

[:googol, :yotta, :Y, :zetta, :Z, :exa, :E, :peta, :P, :tera, :T, :giga, :G, :mega, :M, :kilo, :k, :hecto, :h, :deca, :da, :deci, :d, :centi, :c, :milli, :m, :micro, :u, :nano, :n, :pico, :p, :femto, :f, :atto, :a, :zepto, :z, :yocto, :y, :kibi, :Ki, :mebi, :Mi, :gibi, :Gi, :tebi, :Ti, :pebi, :Pi, :exbi, :Ei, :zebi, :Zi, :yobi, :Yi]

/^(googol|yotta|femto|zetta|zepto|micro| milli|centi|hecto|yocto|exbi|giga|tebi| mega|pebi|kilo|atto|tera|kibi|deca|yobi| deci|pico|nano|gibi|zebi|mebi|peta|exa|Ki| Mi|Gi|Zi|da|Ei|Ti|Pi|Yi|z|a|y|f|p|n|m|c|d| h|k|M|G|T|P|E|Z|Y|u)?(.+)/

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. Jamie Zawinski

I thought "I know, I'll use regular expressions."

I now had two problems

but

def self.prefix_matcher @prefix_matcher ||= begin prefix_keys = unit_prefixes.keys.map(&:to_s). sort{ |a,b| b.length <=> a.length } %r{^(#{prefix_keys.join('|')})?(.+)} end end

2.0

1.9

Constraints Keep existing interface

Constraints Keep existing interface No method_missing

Constraints Keep existing interface No method_missing Increase performance

module Alchemist def self.setup category = nil if category load_category category else load_all_categories end end private def self.load_all_categories library.load_all_categories end def self.load_category category library.load_category category end end

module Alchemist class ModuleBuilder def initialize category @category = category end def build Module.new.tap do |category_module| category_module.class_eval %(def self.inspect() "#<Module(#{category})>" end) category_module.class_eval category_methods end end

private attr_reader :category def library Alchemist.library end def category_methods unit_names.map do |name| %(define_method("#{name}") { Alchemist.measure self, :#{name} }) + "n" + prefixed_methods(name) end.join("n") end def unit_names library.unit_names(category) end def prefixes_with_value(name) if library.si_units.include?(name.to_s) library.unit_prefixes else [] end end def prefixed_methods(name) prefixes_with_value(name).map do |prefix, value| %(define_method("#{prefix}#{name}") { Alchemist.measure self, :#{name}, #{value} }) end.join("n") end

module Alchemist class ModuleBuilder def initialize category @category = category end def build Module.new.tap do |category_module| category_module.class_eval %(def self.inspect() "#<Module(#{category})>" end) category_module.class_eval category_methods end end

module Alchemist class ModuleBuilder def initialize category @category = category end def build build_module do |category_module| define_inspect_method(category_module) define_unit_methods(category_module) end end

[success_kid.jpg]

#include <ruby.h> #include <string.h> the c-level VALUE cParenParser; VALUE paren_parser_parse(VALUE self, VALUE str) { const char *c_str = RSTRING_PTR(str); char *temp = (char *)malloc(sizeof(char) * RSTRING_LEN(str) + 1); int temp_pos = 1; int c_str_pos = 0; temp[0] = c_str[0]; while(c_str[c_str_pos++] != '0') { if(temp_pos > 0 && temp[temp_pos-1] == ')' && c_str[c_str_pos] == '(') { temp_pos--; } else { temp[temp_pos++] = c_str[c_str_pos];

How to be an artist

Have a toolbox

Be inspired by others

Surround yourself with talented artists

Surround yourself with talented artists

Use well known techniques

Use well known techniques

Measure improvement

PULLREVIEW

Have feelings

Know when to break the rules

Have fun.

Prime learn.thoughtbot.com/prime

THISISMETIS.COM

?

Add a comment

Related presentations

Related pages

The Art of Ruby

Ruby Presnell is a vocalist and artist. Her creativity requires multiple outlets which she expresses through her various forms of artistry including two ...
Read more

Visual Art - The Art of Ruby

Ruby Art. I have always been a visual artist, but never really considered it something I would use to make a living or call myself a artist per se.
Read more

About | The Art and Science of Ruby

Hi, I’m Rahoul Baruah (also known as Baz) and I’ve been a commercial software developer since the twentieth century and a Ruby and Rails developer for ...
Read more

The Art of Ruby - Matthew Mongeau - YouTube

We should all be artists in our craft, but there is a balance between expressiveness and performance. This talk is about finding that balance ...
Read more

The Art and Science of Ruby | Level up your Ruby career

Being a professional software developer requires a lot of knowledge. Not just knowing your way around Ruby and its libraries. You need to learn all about ...
Read more

Art of Ruby Poon

Hey! I'm Ruby, 19, also a 2nd year Sheridan animation student. Feel free to contact me at: rubypn9@gmail.com
Read more

Art Ruby

Art Ruby. About; Twitter; Instagram; Sign Up for Newsletter; Submit; RSS; Archive; Random; ... contemporary art; design; gagosian gallery; art ruby; 177 ...
Read more

Rubys Art - Facebook

Rubys Art. 24 likes. Hi, ich heiße Ruby und stelle auf dieser Seite meine Bilder und Cosplays aus. Ich hoffe, dass sie euch gefallen ⁄(⁄ ⁄•⁄ω
Read more

Roses-Of-Ruby's DeviantArt Gallery

DeviantArt is the world's largest online social community for artists and art enthusiasts, allowing people to connect through the creation and sharing of art.
Read more