# The Art of Ruby

33 %
67 %
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 ﬂexibility 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."

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 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

?

 User name: Comment:

## Related presentations

#### Neuquén y el Gobierno Abierto

October 30, 2014

Presentación que realice en el Evento Nacional de Gobierno Abierto, realizado los ...

#### Decision CAMP 2014 - Erik Marutian - Using rules-b...

October 16, 2014

In this presentation we will describe our experience developing with a highly dyna...

#### Schema.org: What It Means For You and Your Library

November 7, 2014

Presentation to the LITA Forum 7th November 2014 Albuquerque, NM

#### WearableTech: Una transformación social de los p...

November 3, 2014

Un recorrido por los cambios que nos generará el wearabletech en el futuro

#### O Impacto de Wearable Computers na vida das pessoa...

November 5, 2014

Um paralelo entre as novidades & mercado em Wearable Computing e Tecnologias Assis...

#### All you need to know about the Microsoft Band

November 6, 2014

Microsoft finally joins the smartwatch and fitness tracker game by introducing the...

## 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 ...

### 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.

### 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 ...

### 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 ...

### 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 ...

### 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