SlideShare a Scribd company logo
1 of 126
Download to read offline
Enable Labs @mark_menard
#smallcode
Small Code
Mark Menard
RailsConf 2014!
April 24, 2014
@mark_menard !
Enable Labs
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
‘The great thing about writing
shitty code that “just works,”
is that it is too risky and too
expensive to change, so it
lives forever.’!
!
!
-Reginald Braithwaite @raganwald
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
What do I mean by small?
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
It’s not
about total
line count.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
It’s not about
method
count.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
It’s not
about class
count.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
It’s About
Small methods! Small classes
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Why should we strive for small code?
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
We don’t know what the future will bring.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Raise the level of abstraction.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Create composable objects.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Enable Future Change
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
The goal: Small units of
understandable code that
are amenable to change.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Our Primary Tools
• Extract Method!
• Move Method!
• Extract Class
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Let’s Look at Some Code
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
# some_ruby_program -v
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
options = CommandLineOptions.new(ARGV) do
option :c
option :v
option :e
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
if options.has(:c)
# Do something
end
!
if options.has(:v)
# Do something else
end
!
if options.has(:e)
# Do the other thing
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode# some_ruby_program -v
!
options = CommandLineOptions.new(ARGV) do
option :c
option :v
option :e
end
!
if options.has(:c)
# Do something
end
!
if options.has(:v)
# Do something else
end
!
if options.has(:e)
# Do the other thing
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
describe CommandLineOptions do
!
describe 'options' do
!
let(:parser) { CommandLineOptions.new { option :c } }
!
it "are true if present" do …
!
it "are false if absent" do …
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
CommandLineOptions
options
are true if present
are false if absent
!
Finished in 0.00206 seconds
2 examples, 2 failures
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = []
@argv = argv
instance_eval &block
end
!
def has (option_flag)
options.include?(option_flag) && argv.include?("-#{option_flag}")
end
!
def option (option_flag)
options << option_flag
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = []
@argv = argv
instance_eval &block
end
!
def has (option_flag)
options.include?(option_flag) && argv.include?("-#{option_flag}")
end
!
def option (option_flag)
options << option_flag
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = []
@argv = argv
instance_eval &block
end
!
def has (option_flag)
options.include?(option_flag) && argv.include?("-#{option_flag}")
end
!
def option (option_flag)
options << option_flag
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = []
@argv = argv
instance_eval &block
end
!
def has (option_flag)
options.include?(option_flag) && argv.include?("-#{option_flag}")
end
!
def option (option_flag)
options << option_flag
end
!
end
options = CommandLineOptions.new(ARGV) do
option :c
option :v
option :e
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
CommandLineOptions
options
are true if present
are false if absent
!
Finished in 0.00206 seconds
2 examples, 0 failures
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Done!
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
% some_ruby_program -v -sfoo
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
options = CommandLineOptions.new(ARGV) do
option :v
option :s, :string
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
if options.valid?
if options.value(:v)
# Do something
end
!
if (s_option = options.value(:s))
# Do something
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
if options.valid?
if options.value(:v)
# Do something
end
!
if (s_option = options.value(:s))
# Do something
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
if options.valid?
if options.value(:v)
# Do something
end
!
if (s_option = options.value(:s))
# Do something
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
# some_ruby_program -v -sfoo
!
options = CommandLineOptions.new(ARGV) do
option :v
option :s, :string
end
!
if options.valid?
if options.value(:v)
# Do something
end
!
if (s_option = options.value(:s))
# Do something
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = {}
@argv = argv
instance_eval &block
end
!
def option (option_flag, option_type = :boolean)
options[option_flag] = option_type
end
!
def valid?
options.each do |option_flag, option_type|
raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return false if option_type == :string && raw_value && raw_value.length < 3
end
end
!
def value (option_flag)
raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
def initialize (argv = [], &block)
@options = {}
@argv = argv
instance_eval &block
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return false if option_type == :string &&
raw_value && raw_value.length < 3
end
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
!
def value (option_flag)
raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
CommandLineOptions	
boolean options	
are true if present	
are false if absent	
string options	
must have content	
are valid if there is content	
are valid if not in argv	
can return the value	
return nil if not in argv	
!
Finished in 0.00401 seconds	
7 examples, 0 failures
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Methods
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
The first rule of methods:
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Do one thing. Do it well. Do only that thing.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
One level of abstraction per method.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Use Descriptive Names
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
The fewer arguments the better.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Separate Queries from Commands
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Don’t RepeatYourself
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return false if option_type == :string && raw_value && raw_value.length < 3
end
end
!
def value (option_flag)
raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return false if option_type == :string && raw_value && raw_value.length < 3
end
end
!
def value (option_flag)
raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return false if option_type == :string && raw_value && raw_value.length < 3
end
end
!
def value (option_flag)
raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return false if option_type == :string && raw_value && raw_value.length < 3
end
end
!
def value (option_flag)
raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return false if option_type == :string && raw_value && raw_value.length < 3
end
end
!
def value (option_flag)
raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Extract Method Refactoring
def print_invoice_for_amount (amount)
print_header
puts "Name: #{@name}"
puts "Amount: #{amount}"
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Extract Method Refactoring
def print_invoice_for_amount (amount)
print_header
puts "Name: #{@name}"
puts "Amount: #{amount}"
end
High level of abstraction
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Extract Method Refactoring
def print_invoice_for_amount (amount)
print_header
puts "Name: #{@name}"
puts "Amount: #{amount}"
end
Low level of abstraction
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Extract Method Refactoring
def print_invoice_for_amount (amount)
print_header
puts "Name: #{@name}"
puts "Amount: #{amount}"
end
def print_invoice_for_amount (amount)
print_header
print_details (amount)
end
!
def print_details (amount)
puts "Name: #{@name}"
puts "Amount: #{amount}"
end
Move this to here
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Extract Method Refactoring
def print_invoice_for_amount (amount)
print_header
puts "Name: #{@name}"
puts "Amount: #{amount}"
end
def print_invoice_for_amount (amount)
print_header
print_details (amount)
end
!
def print_details (amount)
puts "Name: #{@name}"
puts "Amount: #{amount}"
end
Same level of abstraction
Move this to here
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return false if option_type == :string && raw_value && raw_value.length < 3
end
end
!
def value (option_flag)
raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return false if option_type == :string && raw_value && raw_value.length < 3
end
end
!
def value (option_flag)
raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ }
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if option_type == :string && raw_option_value && raw_option_value.length < 3
end
end
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
def raw_value_for_option (option_flag)
argv.find { |arg| arg =~ /^-#{option_flag}/ }
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if option_type == :string && raw_option_value && raw_option_value.length < 3
end
end
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
end
!
def raw_value_for_option (option_flag)
argv.find { |arg| arg =~ /^-#{option_flag}/ }
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if option_type == :string && !string_option_valid?(raw_option_value)
end
end
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return extract_content(raw_option_value) if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if option_type == :string && !string_option_valid?(raw_option_value)
end
end
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return extract_content(raw_option_value) if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if option_type == :string && !string_option_valid?(raw_option_value)
end
end
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return extract_content(raw_option_value) if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if option_type == :string && !string_option_valid?(raw_option_value)
end
end
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return extract_content(raw_option_value) if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if option_type == :string && !string_option_valid?(raw_option_value)
end
end
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return extract_content(raw_option_value) if option_type == :string
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
# some_ruby_program -v -efoo -i100
!
options = CommandLineOptions.new(ARGV) do
option :v
option :e, :string
option :i, :integer
end
!
verbose = options.value(:v)
expression = options.value(:e)
iteration_count = options.value(:i) || 1
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = {}
@argv = argv
instance_eval &block
end
!
def option (option_flag, option_type = :boolean)
options[option_flag] = option_type
end
!
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if (option_type == :string || option_type == :integer) &&
raw_option_value && raw_option_value.length < 3
return false if option_type == :integer && raw_option_value &&
!(Integer(raw_option_value[2..-1]) rescue false)
end
end
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
return (Integer(raw_option_value[2..-1])) if option_type == :integer
end
!
private def raw_value_for_option (option_flag)
argv.find { |arg| arg =~ /^-#{option_flag}/ }
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeCommandLineOptions	
boolean options	
are true if present	
are false if absent	
string options	
must have content	
are valid if there is content	
are valid if not in argv	
can return the value	
return nil if not in argv	
integer options	
must have content	
are valid if there is content and it's an integer	
are invalid if the content is not an integer	
are valid if not in argv	
can return the value	
return nil if not in argv	
!
Finished in 0.00338 seconds	
13 examples, 0 failures	
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if (option_type == :string || option_type == :integer) &&
raw_option_value && raw_option_value.length < 3
return false if option_type == :integer && raw_option_value &&
!(Integer(raw_option_value[2..-1]) rescue false)
end
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if (option_type == :string || option_type == :integer) &&
raw_option_value && raw_option_value.length < 3
return false if option_type == :integer && raw_option_value &&
!(Integer(raw_option_value[2..-1]) rescue false)
end
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
!
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
return false if (option_type == :string || option_type == :integer) &&
raw_option_value && raw_option_value.length < 3
return false if option_type == :integer && raw_option_value &&
!(Integer(raw_option_value[2..-1]) rescue false)
end
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
return (Integer(raw_option_value[2..-1])) if option_type == :integer
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
return (Integer(raw_option_value[2..-1])) if option_type == :integer
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
return (Integer(raw_option_value[2..-1])) if option_type == :integer
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
…
!
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
return false if raw_option_value && raw_option_value.length < 3
when :integer
return false if raw_option_value && raw_option_value.length < 3
return false if raw_option_value &&
!(Integer(raw_option_value[2..-1]) rescue false)
end
end
end
!
…
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
…
!
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
!
return case(option_type)
when :string
raw_option_value[2..-1]
when :integer
(Integer(raw_option_value[2..-1]))
when :boolean
return true if option_type == :boolean && raw_option_value
end
end
!
…
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
How do we write small classes?
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
What are the characteristics of a small class?
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = {}
@argv = argv
instance_eval &block
end
!
def valid?
options.all?(&:valid)
end
!
def value (option_flag)
options[option_flag].value
end
!
private
def option (option_flag, option_type = :boolean)
options[option_flag] = build_option(option_flag, option_type)
end
!
def build_option
# Need to write this.
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = {}
@argv = argv
instance_eval &block
end
!
def valid?
options.all?(&:valid)
end
!
def value (option_flag)
options[option_flag].value
end
!
private
def option (option_flag, option_type = :boolean)
options[option_flag] = build_option(option_flag, option_type)
end
!
def build_option
# Need to write this.
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.all?(&:valid?)
end
!
def value (option_flag)
options[option_flag].value
end
!
def build_option
# Need to write this.
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.all?(&:valid?)
end
!
def value (option_flag)
options[option_flag].value
end
!
def build_option
# Need to write this.
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.all?(&:valid?)
end
!
def value (option_flag)
options[option_flag].value
end
!
def build_option
# Need to write this.
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass CommandLineOptions
!
…
!
def valid?
options.all?(&:valid?)
end
!
def value (option_flag)
options[option_flag].value
end
!
def build_option
# Need to write this.
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Dependencies
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Dependencies
Command
Line Options ?*
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Depend on Abstractions
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Command
Line Options
String Option
Integer
Option
Boolean
Option
valid?
value
Option*
Depend on Abstractions
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Command
Line Options
String Option
Integer
Option
Boolean
Option
valid?
value
Option*
This is my duck type!
Depend on Abstractions
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Command
Line Options
String Option
Integer
Option
Boolean
Option
valid?
value
Option*
This is my duck type!
These are my concrete types.
Depend on Abstractions
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Command
Line Options
String Option
Integer
Option
Boolean
Option
valid?
value
Option*
These are my concrete types.
Depend on this!
Depend on Abstractions
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Command
Line Options
String Option
Integer
Option
Boolean
Option
valid?
value
Option*
Depend on this!
Don’t depend on these!
Depend on Abstractions
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
private def option (option_flag, option_type = :boolean)
options[option_flag] = case (option_type)
when :boolean
return BooleanOption.new(option_flag, nil)
when :string
return StringOption.new(option_flag, nil)
when :integer
return IntegerOption.new(option_flag, nil)
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
…
!
def build_option (option_flag, option_type)
“#{option_type}_option".camelize.constantize.new(
option_flag, raw_value_for_option(option_flag)
)
end
!
…
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass Option
!
attr_reader :flag, :raw_value
!
def initialize (flag, raw_value)
@flag = flag
@raw_value = raw_value
end
!
def valid?
end
!
def value
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass BooleanOption < Option
!
def valid?
true
end
!
def value
raw_value
end
end
class Option
!
attr_reader :flag, :raw_value
!
def initialize (flag, raw_value)
@flag = flag
@raw_value = raw_value
end
!
def valid?
end
!
def value
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeclass StringOption < Option
!
def valid?
!
!
end
!
def value
!
!
end
end
class IntegerOption < Option
!
def valid?
!
!
end
!
def value
!
!
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodedef valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
!
!
when :integer
!
!
!
end
end
end
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
return false if raw_option_value &&
raw_option_value.length < 3
when :integer
return false if raw_option_value
&& raw_option_value.length < 3
return false if raw_option_value &&
!(Integer(raw_option_value[2..-1]) rescue false)
end
end
end
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
!
return case(option_type)
when :string
!
when :integer
!
when :boolean
!
end
end
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
!
return case(option_type)
when :string
raw_option_value[2..-1]
when :integer
(Integer(raw_option_value[2..-1]))
when :boolean
return true if option_type == :boolean && raw_option_value
end
end
class StringOption < Option
!
def valid?
!
!
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
!
!
!
end
!
def value
!
!
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodedef valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
!
!
when :integer
!
!
!
end
end
end
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
!
return case(option_type)
when :string
!
when :integer
!
when :boolean
!
end
end
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
!
return case(option_type)
when :string
raw_option_value[2..-1]
when :integer
(Integer(raw_option_value[2..-1]))
when :boolean
return true if option_type == :boolean && raw_option_value
end
end
class StringOption < Option
!
def valid?
!
!
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
!
!
!
end
!
def value
!
!
end
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
!
!
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodedef valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
!
!
when :integer
!
!
!
end
end
end
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
!
return case(option_type)
when :string
!
when :integer
!
when :boolean
!
end
end
class StringOption < Option
!
def valid?
!
!
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
!
!
!
end
!
def value
!
!
end
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
!
!
end
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
return nil unless raw_value
raw_value[2..-1]
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
return nil unless raw_value
Integer(raw_value[2..-1])
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodedef valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
!
!
when :integer
!
!
!
end
end
end
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
!
return case(option_type)
when :string
!
when :integer
!
when :boolean
!
end
end
class StringOption < Option
!
def valid?
!
!
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
!
!
!
end
!
def value
!
!
end
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
!
!
end
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
return nil unless raw_value
raw_value[2..-1]
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
return nil unless raw_value
Integer(raw_value[2..-1])
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodedef valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
!
!
when :integer
!
!
!
end
end
end
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
!
return case(option_type)
when :string
!
when :integer
!
when :boolean
!
end
end
class StringOption < Option
!
def valid?
!
!
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
!
!
!
end
!
def value
!
!
end
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
!
!
end
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
return nil unless raw_value
raw_value[2..-1]
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
return nil unless raw_value
Integer(raw_value[2..-1])
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
!
return case(option_type)
when :string
!
when :integer
!
when :boolean
!
end
end
class StringOption < Option
!
def valid?
!
!
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
!
!
!
end
!
def value
!
!
end
end
def valid?
options.all?(&:valid?)
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
!
!
end
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
return nil unless raw_value
raw_value[2..-1]
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
return nil unless raw_value
Integer(raw_value[2..-1])
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
!
return case(option_type)
when :string
!
when :integer
!
when :boolean
!
end
end
class StringOption < Option
!
def valid?
!
!
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
!
!
!
end
!
def value
!
!
end
end
def valid?
options.all?(&:valid?)
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
!
!
end
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
return nil unless raw_value
raw_value[2..-1]
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
return nil unless raw_value
Integer(raw_value[2..-1])
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
def value (option_flag)
options[option_flag].value
end
class StringOption < Option
!
def valid?
!
!
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
!
!
!
end
!
def value
!
!
end
end
def valid?
options.all?(&:valid?)
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
!
!
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
!
!
end
end
class StringOption < Option
!
def valid?
return true unless raw_value
raw_value && raw_value.length > 2
end
!
def value
return nil unless raw_value
raw_value[2..-1]
end
end
!
class IntegerOption < Option
!
def valid?
return true unless raw_value
(raw_value && raw_value.length > 2) &&
(Integer(raw_value[2..-1]) rescue false)
end
!
def value
return nil unless raw_value
Integer(raw_value[2..-1])
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Option classes	
Option	
stores it's flag	
stores it's raw value	
BooleanOption	
is true if the raw value is present	
is false if the raw value is nil	
is valid	
StringOption	
invalid when there is no content	
is valid if there is content	
is valid if raw value is nil	
can return the value	
value is nil if raw value is nil	
IntegerOption	
is invalid without content	
is invalid if the content is not an integer	
is valid if there is content and it's an integer	
is valid if raw value is nil	
can return the value	
returns nil if raw value is nil	
!
Finished in 0.00495 seconds	
22 examples, 0 failures, 6 pending	
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
How do we isolate abstractions?
Separate the “what”
from the “how”.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
return false if raw_option_value && raw_option_value.length < 3
when :integer
return false if raw_option_value && raw_option_value.length < 3
return false if raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false)
end
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
def valid?
options.values.all?(&:valid?)
end
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
return false if raw_option_value && raw_option_value.length < 3
when :integer
return false if raw_option_value && raw_option_value.length < 3
return false if raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false)
end
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
def valid?
options.values.all?(&:valid?)
end
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
return false if raw_option_value && raw_option_value.length < 3
when :integer
return false if raw_option_value && raw_option_value.length < 3
return false if raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false)
end
end
end
This all about HOW!
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
def valid?
options.values.all?(&:valid?)
end
def valid?
options.each do |option_flag, option_type|
raw_option_value = raw_value_for_option(option_flag)
!
case(option_type)
when :string
return false if raw_option_value && raw_option_value.length < 3
when :integer
return false if raw_option_value && raw_option_value.length < 3
return false if raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false)
end
end
end
This all about HOW!
This is WHAT I want done.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
return (Integer(raw_option_value[2..-1])) if option_type == :integer
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
def value (option_flag)
options[option_flag].value
end
def value (option_flag)
raw_option_value = raw_value_for_option(option_flag)
return nil unless raw_option_value
option_type = options[option_flag]
return true if option_type == :boolean && raw_option_value
return raw_option_value[2..-1] if option_type == :string
return (Integer(raw_option_value[2..-1])) if option_type == :integer
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = {}
@argv = argv
instance_eval &block
end
!
def valid?
options.values.all?(&:valid?)
end
!
def value (option_flag)
options[option_flag].value
end
!
private
!
def option (option_flag, option_type = :boolean)
options[option_flag] = build_option(option_flag, option_type)
end
!
def build_option (option_flag, option_type)
"#{option_type}_option".camelize.constantize.new(option_flag, raw_value_for_option(option_flag))
end
!
def raw_value_for_option (option_flag)
argv.find { |arg| arg =~ /^-#{option_flag}/ }
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = {}
@argv = argv
instance_eval &block
end
!
def valid?
options.values.all?(&:valid?)
end
!
def value (option_flag)
options[option_flag].value
end
!
private
!
def option (option_flag, option_type = :boolean)
options[option_flag] = build_option(option_flag, option_type)
end
!
def build_option (option_flag, option_type)
"#{option_type}_option".camelize.constantize.new(option_flag, raw_value_for_option(option_flag))
end
!
def raw_value_for_option (option_flag)
argv.find { |arg| arg =~ /^-#{option_flag}/ }
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
class CommandLineOptions
!
attr_accessor :argv
attr_reader :options
!
def initialize (argv = [], &block)
@options = {}
@argv = argv
instance_eval &block
end
!
def valid?
options.values.all?(&:valid?)
end
!
def value (option_flag)
options[option_flag].value
end
!
private
!
def option (option_flag, option_type = :boolean)
options[option_flag] = build_option(option_flag, option_type)
end
!
def build_option (option_flag, option_type)
"#{option_type}_option".camelize.constantize.new(option_flag, raw_value_for_option(option_flag))
end
!
def raw_value_for_option (option_flag)
argv.find { |arg| arg =~ /^-#{option_flag}/ }
end
!
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
!
def valid?
options.values.all?(&:valid?)
end
!
def value (option_flag)
options[option_flag].value
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
CommandLineOptions	
builds an option object for each defined option	
is valid if all options are valid	
is invalid if any option is invalid	
option object conventions	
uses a StringOption for string options	
uses a BooleanOption for boolean options	
uses an IntegerOption for integer options	
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Then
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
some_ruby_program -v -efoo -i100 -afoo,bar,baz
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
describe "array options" do
it "can return the value as an array" do
options = CommandLineOptions.new([ "-afoo,bar,baz" ]) { option :a, :array }
expect(options.value(:a)).to eq(["foo", "bar", "baz"])
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
describe "array options" do
it "can return the value as an array" do
options = CommandLineOptions.new([ "-afoo,bar,baz" ]) { option :a, :array }
expect(options.value(:a)).to eq(["foo", "bar", "baz"])
end
end
class ArrayOption < OptionWithContent
def value
return nil if option_unset?
extract_value_from_raw_value.split(",")
end
end
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcodeCommandLineOptions	
boolean options	
are true if present	
are false if absent	
string options	
must have content	
is valid when there is content	
can return the value	
return nil if not in argv	
integer options	
must have content	
must be an integer	
can return the value as an integer	
returns nil if not in argv	
array options	
can return the value as an array	
!
OptionWithContent	
has a flag	
is valid when it has no raw value	
is valid when it has a value	
can return it's value when present	
returns nil if the flag has no raw value	
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Now We’re Done!!
Let them implement their own
option classes. It’s easy.
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
http://www.enablelabs.com/
info@enablelabs.com
866-895-8189
@mark_menard
Mark Menard Enable Labs
GitHub: MarkMenard
Refactoring to Small Code 16x9 - April 24, 2014
Enable Labs @mark_menard
#smallcode
Credits
• Syntax highlighting: pbpaste | highlight --syntax=rb --style=edit-xcode --out-format=rtf | pbcopy!
• Command line option example inspiration Uncle Bob.
Refactoring to Small Code 16x9 - April 24, 2014

More Related Content

What's hot

IOS Swift language 2nd tutorial
IOS Swift language 2nd tutorialIOS Swift language 2nd tutorial
IOS Swift language 2nd tutorialHassan A-j
 
name name2 n2
name name2 n2name name2 n2
name name2 n2callroom
 
name name2 n
name name2 nname name2 n
name name2 ncallroom
 
name name2 n2.ppt
name name2 n2.pptname name2 n2.ppt
name name2 n2.pptcallroom
 
Ruby for Perl Programmers
Ruby for Perl ProgrammersRuby for Perl Programmers
Ruby for Perl Programmersamiable_indian
 
Esoft Metro Campus - Programming with C++
Esoft Metro Campus - Programming with C++Esoft Metro Campus - Programming with C++
Esoft Metro Campus - Programming with C++Rasan Samarasinghe
 
Ruby For Java Programmers
Ruby For Java ProgrammersRuby For Java Programmers
Ruby For Java ProgrammersMike Bowler
 
Ruby for Java Developers
Ruby for Java DevelopersRuby for Java Developers
Ruby for Java DevelopersRobert Reiz
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDDKonstantin Kudryashov
 

What's hot (13)

IOS Swift language 2nd tutorial
IOS Swift language 2nd tutorialIOS Swift language 2nd tutorial
IOS Swift language 2nd tutorial
 
Cs30 New
Cs30 NewCs30 New
Cs30 New
 
name name2 n2
name name2 n2name name2 n2
name name2 n2
 
ppt9
ppt9ppt9
ppt9
 
name name2 n
name name2 nname name2 n
name name2 n
 
ppt18
ppt18ppt18
ppt18
 
name name2 n2.ppt
name name2 n2.pptname name2 n2.ppt
name name2 n2.ppt
 
Ruby for Perl Programmers
Ruby for Perl ProgrammersRuby for Perl Programmers
Ruby for Perl Programmers
 
Ruby
RubyRuby
Ruby
 
Esoft Metro Campus - Programming with C++
Esoft Metro Campus - Programming with C++Esoft Metro Campus - Programming with C++
Esoft Metro Campus - Programming with C++
 
Ruby For Java Programmers
Ruby For Java ProgrammersRuby For Java Programmers
Ruby For Java Programmers
 
Ruby for Java Developers
Ruby for Java DevelopersRuby for Java Developers
Ruby for Java Developers
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDD
 

Similar to Small Code - RailsConf 2014

resolvendo problemas de comunicação em equipes distribuídas com bdd
resolvendo problemas de comunicação em equipes distribuídas com bddresolvendo problemas de comunicação em equipes distribuídas com bdd
resolvendo problemas de comunicação em equipes distribuídas com bddRodrigo Urubatan
 
Everything as-code. Polyglotte Entwicklung in der Praxis. #oop2017
Everything as-code. Polyglotte Entwicklung in der Praxis. #oop2017Everything as-code. Polyglotte Entwicklung in der Praxis. #oop2017
Everything as-code. Polyglotte Entwicklung in der Praxis. #oop2017Mario-Leander Reimer
 
Everything-as-code. Polyglotte Software-Entwicklung in der Praxis.
Everything-as-code. Polyglotte Software-Entwicklung in der Praxis.Everything-as-code. Polyglotte Software-Entwicklung in der Praxis.
Everything-as-code. Polyglotte Software-Entwicklung in der Praxis.QAware GmbH
 
Bigdata presentation
Bigdata presentationBigdata presentation
Bigdata presentationYonas Gidey
 
Bigdata Presentation
Bigdata PresentationBigdata Presentation
Bigdata PresentationYonas Gidey
 
Everything-as-code. Eine vielsprachige Reise. #javaland
Everything-as-code. Eine vielsprachige Reise. #javalandEverything-as-code. Eine vielsprachige Reise. #javaland
Everything-as-code. Eine vielsprachige Reise. #javalandMario-Leander Reimer
 
Everything-as-code - Polyglotte Softwareentwicklung
Everything-as-code - Polyglotte SoftwareentwicklungEverything-as-code - Polyglotte Softwareentwicklung
Everything-as-code - Polyglotte SoftwareentwicklungQAware GmbH
 
Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Brian Sam-Bodden
 
Everything-as-code. A polyglot journey.
Everything-as-code. A polyglot journey.Everything-as-code. A polyglot journey.
Everything-as-code. A polyglot journey.Mario-Leander Reimer
 
Everything-as-code - a polyglot journey.
Everything-as-code - a polyglot journey.Everything-as-code - a polyglot journey.
Everything-as-code - a polyglot journey.QAware GmbH
 
SPOON: Source Code Analysis and Transformation for Java, Benjamin Danglot, In...
SPOON: Source Code Analysis and Transformation for Java, Benjamin Danglot, In...SPOON: Source Code Analysis and Transformation for Java, Benjamin Danglot, In...
SPOON: Source Code Analysis and Transformation for Java, Benjamin Danglot, In...OW2
 
From GameMaker to Game Baker - Porting Hotline Miami
From GameMaker to Game Baker - Porting Hotline MiamiFrom GameMaker to Game Baker - Porting Hotline Miami
From GameMaker to Game Baker - Porting Hotline MiamiFrans Kasper
 
PureApplication for testers
PureApplication for testersPureApplication for testers
PureApplication for testersJohn Hawkins
 
An OCaml newbie meets Camlp4 parser
An OCaml newbie meets Camlp4 parserAn OCaml newbie meets Camlp4 parser
An OCaml newbie meets Camlp4 parserKiwamu Okabe
 
CDays14 - CPP05 - Standard Library: STL e boost, la BCL di C++
CDays14 - CPP05 - Standard Library: STL e boost, la BCL di C++CDays14 - CPP05 - Standard Library: STL e boost, la BCL di C++
CDays14 - CPP05 - Standard Library: STL e boost, la BCL di C++Alessio Gogna
 
SC13: OpenMP and NVIDIA
SC13: OpenMP and NVIDIASC13: OpenMP and NVIDIA
SC13: OpenMP and NVIDIAJeff Larkin
 

Similar to Small Code - RailsConf 2014 (20)

resolvendo problemas de comunicação em equipes distribuídas com bdd
resolvendo problemas de comunicação em equipes distribuídas com bddresolvendo problemas de comunicação em equipes distribuídas com bdd
resolvendo problemas de comunicação em equipes distribuídas com bdd
 
Everything as-code. Polyglotte Entwicklung in der Praxis. #oop2017
Everything as-code. Polyglotte Entwicklung in der Praxis. #oop2017Everything as-code. Polyglotte Entwicklung in der Praxis. #oop2017
Everything as-code. Polyglotte Entwicklung in der Praxis. #oop2017
 
Everything-as-code. Polyglotte Software-Entwicklung in der Praxis.
Everything-as-code. Polyglotte Software-Entwicklung in der Praxis.Everything-as-code. Polyglotte Software-Entwicklung in der Praxis.
Everything-as-code. Polyglotte Software-Entwicklung in der Praxis.
 
Bigdata presentation
Bigdata presentationBigdata presentation
Bigdata presentation
 
Bigdata Presentation
Bigdata PresentationBigdata Presentation
Bigdata Presentation
 
Everything-as-code. Eine vielsprachige Reise. #javaland
Everything-as-code. Eine vielsprachige Reise. #javalandEverything-as-code. Eine vielsprachige Reise. #javaland
Everything-as-code. Eine vielsprachige Reise. #javaland
 
Everything-as-code - Polyglotte Softwareentwicklung
Everything-as-code - Polyglotte SoftwareentwicklungEverything-as-code - Polyglotte Softwareentwicklung
Everything-as-code - Polyglotte Softwareentwicklung
 
Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013
 
Everything-as-code. A polyglot journey.
Everything-as-code. A polyglot journey.Everything-as-code. A polyglot journey.
Everything-as-code. A polyglot journey.
 
Everything-as-code - a polyglot journey.
Everything-as-code - a polyglot journey.Everything-as-code - a polyglot journey.
Everything-as-code - a polyglot journey.
 
SPOON: Source Code Analysis and Transformation for Java, Benjamin Danglot, In...
SPOON: Source Code Analysis and Transformation for Java, Benjamin Danglot, In...SPOON: Source Code Analysis and Transformation for Java, Benjamin Danglot, In...
SPOON: Source Code Analysis and Transformation for Java, Benjamin Danglot, In...
 
From GameMaker to Game Baker - Porting Hotline Miami
From GameMaker to Game Baker - Porting Hotline MiamiFrom GameMaker to Game Baker - Porting Hotline Miami
From GameMaker to Game Baker - Porting Hotline Miami
 
PureApplication for testers
PureApplication for testersPureApplication for testers
PureApplication for testers
 
Refactoring Infrastructure Code
Refactoring Infrastructure CodeRefactoring Infrastructure Code
Refactoring Infrastructure Code
 
An OCaml newbie meets Camlp4 parser
An OCaml newbie meets Camlp4 parserAn OCaml newbie meets Camlp4 parser
An OCaml newbie meets Camlp4 parser
 
Code rippa
Code rippaCode rippa
Code rippa
 
Preprocessor
PreprocessorPreprocessor
Preprocessor
 
CDays14 - CPP05 - Standard Library: STL e boost, la BCL di C++
CDays14 - CPP05 - Standard Library: STL e boost, la BCL di C++CDays14 - CPP05 - Standard Library: STL e boost, la BCL di C++
CDays14 - CPP05 - Standard Library: STL e boost, la BCL di C++
 
Cucumber & BDD
Cucumber & BDDCucumber & BDD
Cucumber & BDD
 
SC13: OpenMP and NVIDIA
SC13: OpenMP and NVIDIASC13: OpenMP and NVIDIA
SC13: OpenMP and NVIDIA
 

More from Mark Menard

A Tour of Wyriki
A Tour of WyrikiA Tour of Wyriki
A Tour of WyrikiMark Menard
 
JRuby 6 Years in Production
JRuby 6 Years in ProductionJRuby 6 Years in Production
JRuby 6 Years in ProductionMark Menard
 
Conference of Grand Masters Tech Talk 2013
Conference of Grand Masters Tech Talk 2013Conference of Grand Masters Tech Talk 2013
Conference of Grand Masters Tech Talk 2013Mark Menard
 
Startup Lessons Learned
Startup Lessons LearnedStartup Lessons Learned
Startup Lessons LearnedMark Menard
 
Mobile Platforms and App Development
Mobile Platforms and App DevelopmentMobile Platforms and App Development
Mobile Platforms and App DevelopmentMark Menard
 
Ruby on Rails Training - Module 2
Ruby on Rails Training - Module 2Ruby on Rails Training - Module 2
Ruby on Rails Training - Module 2Mark Menard
 
Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Mark Menard
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to RubyMark Menard
 
Intro to Rails ActiveRecord
Intro to Rails ActiveRecordIntro to Rails ActiveRecord
Intro to Rails ActiveRecordMark Menard
 
Behavior Driven Development with Rails
Behavior Driven Development with RailsBehavior Driven Development with Rails
Behavior Driven Development with RailsMark Menard
 
Intro to Ruby on Rails
Intro to Ruby on RailsIntro to Ruby on Rails
Intro to Ruby on RailsMark Menard
 
JRuby in a Java World
JRuby in a Java WorldJRuby in a Java World
JRuby in a Java WorldMark Menard
 

More from Mark Menard (12)

A Tour of Wyriki
A Tour of WyrikiA Tour of Wyriki
A Tour of Wyriki
 
JRuby 6 Years in Production
JRuby 6 Years in ProductionJRuby 6 Years in Production
JRuby 6 Years in Production
 
Conference of Grand Masters Tech Talk 2013
Conference of Grand Masters Tech Talk 2013Conference of Grand Masters Tech Talk 2013
Conference of Grand Masters Tech Talk 2013
 
Startup Lessons Learned
Startup Lessons LearnedStartup Lessons Learned
Startup Lessons Learned
 
Mobile Platforms and App Development
Mobile Platforms and App DevelopmentMobile Platforms and App Development
Mobile Platforms and App Development
 
Ruby on Rails Training - Module 2
Ruby on Rails Training - Module 2Ruby on Rails Training - Module 2
Ruby on Rails Training - Module 2
 
Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to Ruby
 
Intro to Rails ActiveRecord
Intro to Rails ActiveRecordIntro to Rails ActiveRecord
Intro to Rails ActiveRecord
 
Behavior Driven Development with Rails
Behavior Driven Development with RailsBehavior Driven Development with Rails
Behavior Driven Development with Rails
 
Intro to Ruby on Rails
Intro to Ruby on RailsIntro to Ruby on Rails
Intro to Ruby on Rails
 
JRuby in a Java World
JRuby in a Java WorldJRuby in a Java World
JRuby in a Java World
 

Recently uploaded

Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfjimielynbastida
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 

Recently uploaded (20)

Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdf
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 

Small Code - RailsConf 2014

  • 1. Enable Labs @mark_menard #smallcode Small Code Mark Menard RailsConf 2014! April 24, 2014 @mark_menard ! Enable Labs Refactoring to Small Code 16x9 - April 24, 2014
  • 2. Enable Labs @mark_menard #smallcode ‘The great thing about writing shitty code that “just works,” is that it is too risky and too expensive to change, so it lives forever.’! ! ! -Reginald Braithwaite @raganwald Refactoring to Small Code 16x9 - April 24, 2014
  • 3. Enable Labs @mark_menard #smallcode What do I mean by small? Refactoring to Small Code 16x9 - April 24, 2014
  • 4. Enable Labs @mark_menard #smallcode It’s not about total line count. Refactoring to Small Code 16x9 - April 24, 2014
  • 5. Enable Labs @mark_menard #smallcode It’s not about method count. Refactoring to Small Code 16x9 - April 24, 2014
  • 6. Enable Labs @mark_menard #smallcode It’s not about class count. Refactoring to Small Code 16x9 - April 24, 2014
  • 7. Enable Labs @mark_menard #smallcode It’s About Small methods! Small classes Refactoring to Small Code 16x9 - April 24, 2014
  • 8. Enable Labs @mark_menard #smallcode Why should we strive for small code? Refactoring to Small Code 16x9 - April 24, 2014
  • 9. Enable Labs @mark_menard #smallcode We don’t know what the future will bring. Refactoring to Small Code 16x9 - April 24, 2014
  • 10. Enable Labs @mark_menard #smallcode Raise the level of abstraction. Refactoring to Small Code 16x9 - April 24, 2014
  • 11. Enable Labs @mark_menard #smallcode Create composable objects. Refactoring to Small Code 16x9 - April 24, 2014
  • 12. Enable Labs @mark_menard #smallcode Enable Future Change Refactoring to Small Code 16x9 - April 24, 2014
  • 13. Enable Labs @mark_menard #smallcode The goal: Small units of understandable code that are amenable to change. Refactoring to Small Code 16x9 - April 24, 2014
  • 14. Enable Labs @mark_menard #smallcode Our Primary Tools • Extract Method! • Move Method! • Extract Class Refactoring to Small Code 16x9 - April 24, 2014
  • 15. Enable Labs @mark_menard #smallcode Let’s Look at Some Code Refactoring to Small Code 16x9 - April 24, 2014
  • 16. Enable Labs @mark_menard #smallcode # some_ruby_program -v Refactoring to Small Code 16x9 - April 24, 2014
  • 17. Enable Labs @mark_menard #smallcode options = CommandLineOptions.new(ARGV) do option :c option :v option :e end Refactoring to Small Code 16x9 - April 24, 2014
  • 18. Enable Labs @mark_menard #smallcode if options.has(:c) # Do something end ! if options.has(:v) # Do something else end ! if options.has(:e) # Do the other thing end Refactoring to Small Code 16x9 - April 24, 2014
  • 19. Enable Labs @mark_menard #smallcode# some_ruby_program -v ! options = CommandLineOptions.new(ARGV) do option :c option :v option :e end ! if options.has(:c) # Do something end ! if options.has(:v) # Do something else end ! if options.has(:e) # Do the other thing end Refactoring to Small Code 16x9 - April 24, 2014
  • 20. Enable Labs @mark_menard #smallcode describe CommandLineOptions do ! describe 'options' do ! let(:parser) { CommandLineOptions.new { option :c } } ! it "are true if present" do … ! it "are false if absent" do … end end Refactoring to Small Code 16x9 - April 24, 2014
  • 21. Enable Labs @mark_menard #smallcode CommandLineOptions options are true if present are false if absent ! Finished in 0.00206 seconds 2 examples, 2 failures Refactoring to Small Code 16x9 - April 24, 2014
  • 22. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = [] @argv = argv instance_eval &block end ! def has (option_flag) options.include?(option_flag) && argv.include?("-#{option_flag}") end ! def option (option_flag) options << option_flag end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 23. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = [] @argv = argv instance_eval &block end ! def has (option_flag) options.include?(option_flag) && argv.include?("-#{option_flag}") end ! def option (option_flag) options << option_flag end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 24. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = [] @argv = argv instance_eval &block end ! def has (option_flag) options.include?(option_flag) && argv.include?("-#{option_flag}") end ! def option (option_flag) options << option_flag end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 25. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = [] @argv = argv instance_eval &block end ! def has (option_flag) options.include?(option_flag) && argv.include?("-#{option_flag}") end ! def option (option_flag) options << option_flag end ! end options = CommandLineOptions.new(ARGV) do option :c option :v option :e end Refactoring to Small Code 16x9 - April 24, 2014
  • 26. Enable Labs @mark_menard #smallcode CommandLineOptions options are true if present are false if absent ! Finished in 0.00206 seconds 2 examples, 0 failures Refactoring to Small Code 16x9 - April 24, 2014
  • 27. Enable Labs @mark_menard #smallcode Done! Refactoring to Small Code 16x9 - April 24, 2014
  • 28. Enable Labs @mark_menard #smallcode % some_ruby_program -v -sfoo Refactoring to Small Code 16x9 - April 24, 2014
  • 29. Enable Labs @mark_menard #smallcode options = CommandLineOptions.new(ARGV) do option :v option :s, :string end Refactoring to Small Code 16x9 - April 24, 2014
  • 30. Enable Labs @mark_menard #smallcode if options.valid? if options.value(:v) # Do something end ! if (s_option = options.value(:s)) # Do something end end Refactoring to Small Code 16x9 - April 24, 2014
  • 31. Enable Labs @mark_menard #smallcode if options.valid? if options.value(:v) # Do something end ! if (s_option = options.value(:s)) # Do something end end Refactoring to Small Code 16x9 - April 24, 2014
  • 32. Enable Labs @mark_menard #smallcode if options.valid? if options.value(:v) # Do something end ! if (s_option = options.value(:s)) # Do something end end Refactoring to Small Code 16x9 - April 24, 2014
  • 33. Enable Labs @mark_menard #smallcode # some_ruby_program -v -sfoo ! options = CommandLineOptions.new(ARGV) do option :v option :s, :string end ! if options.valid? if options.value(:v) # Do something end ! if (s_option = options.value(:s)) # Do something end end Refactoring to Small Code 16x9 - April 24, 2014
  • 34. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = {} @argv = argv instance_eval &block end ! def option (option_flag, option_type = :boolean) options[option_flag] = option_type end ! def valid? options.each do |option_flag, option_type| raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return false if option_type == :string && raw_value && raw_value.length < 3 end end ! def value (option_flag) raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 35. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … def initialize (argv = [], &block) @options = {} @argv = argv instance_eval &block end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 36. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return false if option_type == :string && raw_value && raw_value.length < 3 end end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 37. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … ! def value (option_flag) raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 38. Enable Labs @mark_menard #smallcode CommandLineOptions boolean options are true if present are false if absent string options must have content are valid if there is content are valid if not in argv can return the value return nil if not in argv ! Finished in 0.00401 seconds 7 examples, 0 failures Refactoring to Small Code 16x9 - April 24, 2014
  • 39. Enable Labs @mark_menard #smallcode Methods Refactoring to Small Code 16x9 - April 24, 2014
  • 40. Enable Labs @mark_menard #smallcode The first rule of methods: Refactoring to Small Code 16x9 - April 24, 2014
  • 41. Enable Labs @mark_menard #smallcode Do one thing. Do it well. Do only that thing. Refactoring to Small Code 16x9 - April 24, 2014
  • 42. Enable Labs @mark_menard #smallcode One level of abstraction per method. Refactoring to Small Code 16x9 - April 24, 2014
  • 43. Enable Labs @mark_menard #smallcode Use Descriptive Names Refactoring to Small Code 16x9 - April 24, 2014
  • 44. Enable Labs @mark_menard #smallcode The fewer arguments the better. Refactoring to Small Code 16x9 - April 24, 2014
  • 45. Enable Labs @mark_menard #smallcode Separate Queries from Commands Refactoring to Small Code 16x9 - April 24, 2014
  • 46. Enable Labs @mark_menard #smallcode Don’t RepeatYourself Refactoring to Small Code 16x9 - April 24, 2014
  • 47. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return false if option_type == :string && raw_value && raw_value.length < 3 end end ! def value (option_flag) raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 48. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return false if option_type == :string && raw_value && raw_value.length < 3 end end ! def value (option_flag) raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 49. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return false if option_type == :string && raw_value && raw_value.length < 3 end end ! def value (option_flag) raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 50. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return false if option_type == :string && raw_value && raw_value.length < 3 end end ! def value (option_flag) raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 51. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return false if option_type == :string && raw_value && raw_value.length < 3 end end ! def value (option_flag) raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 52. Enable Labs @mark_menard #smallcode Extract Method Refactoring def print_invoice_for_amount (amount) print_header puts "Name: #{@name}" puts "Amount: #{amount}" end Refactoring to Small Code 16x9 - April 24, 2014
  • 53. Enable Labs @mark_menard #smallcode Extract Method Refactoring def print_invoice_for_amount (amount) print_header puts "Name: #{@name}" puts "Amount: #{amount}" end High level of abstraction Refactoring to Small Code 16x9 - April 24, 2014
  • 54. Enable Labs @mark_menard #smallcode Extract Method Refactoring def print_invoice_for_amount (amount) print_header puts "Name: #{@name}" puts "Amount: #{amount}" end Low level of abstraction Refactoring to Small Code 16x9 - April 24, 2014
  • 55. Enable Labs @mark_menard #smallcode Extract Method Refactoring def print_invoice_for_amount (amount) print_header puts "Name: #{@name}" puts "Amount: #{amount}" end def print_invoice_for_amount (amount) print_header print_details (amount) end ! def print_details (amount) puts "Name: #{@name}" puts "Amount: #{amount}" end Move this to here Refactoring to Small Code 16x9 - April 24, 2014
  • 56. Enable Labs @mark_menard #smallcode Extract Method Refactoring def print_invoice_for_amount (amount) print_header puts "Name: #{@name}" puts "Amount: #{amount}" end def print_invoice_for_amount (amount) print_header print_details (amount) end ! def print_details (amount) puts "Name: #{@name}" puts "Amount: #{amount}" end Same level of abstraction Move this to here Refactoring to Small Code 16x9 - April 24, 2014
  • 57. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return false if option_type == :string && raw_value && raw_value.length < 3 end end ! def value (option_flag) raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 58. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return false if option_type == :string && raw_value && raw_value.length < 3 end end ! def value (option_flag) raw_option_value = argv.find { |arg| arg =~ /^-#{option_flag}/ } return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 59. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if option_type == :string && raw_option_value && raw_option_value.length < 3 end end ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! def raw_value_for_option (option_flag) argv.find { |arg| arg =~ /^-#{option_flag}/ } end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 60. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if option_type == :string && raw_option_value && raw_option_value.length < 3 end end ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string end ! def raw_value_for_option (option_flag) argv.find { |arg| arg =~ /^-#{option_flag}/ } end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 61. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if option_type == :string && !string_option_valid?(raw_option_value) end end ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return extract_content(raw_option_value) if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 62. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if option_type == :string && !string_option_valid?(raw_option_value) end end ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return extract_content(raw_option_value) if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 63. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if option_type == :string && !string_option_valid?(raw_option_value) end end ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return extract_content(raw_option_value) if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 64. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if option_type == :string && !string_option_valid?(raw_option_value) end end ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return extract_content(raw_option_value) if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 65. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if option_type == :string && !string_option_valid?(raw_option_value) end end ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return extract_content(raw_option_value) if option_type == :string end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 66. Enable Labs @mark_menard #smallcode # some_ruby_program -v -efoo -i100 ! options = CommandLineOptions.new(ARGV) do option :v option :e, :string option :i, :integer end ! verbose = options.value(:v) expression = options.value(:e) iteration_count = options.value(:i) || 1 Refactoring to Small Code 16x9 - April 24, 2014
  • 67. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = {} @argv = argv instance_eval &block end ! def option (option_flag, option_type = :boolean) options[option_flag] = option_type end ! def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if (option_type == :string || option_type == :integer) && raw_option_value && raw_option_value.length < 3 return false if option_type == :integer && raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false) end end ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string return (Integer(raw_option_value[2..-1])) if option_type == :integer end ! private def raw_value_for_option (option_flag) argv.find { |arg| arg =~ /^-#{option_flag}/ } end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 68. Enable Labs @mark_menard #smallcodeCommandLineOptions boolean options are true if present are false if absent string options must have content are valid if there is content are valid if not in argv can return the value return nil if not in argv integer options must have content are valid if there is content and it's an integer are invalid if the content is not an integer are valid if not in argv can return the value return nil if not in argv ! Finished in 0.00338 seconds 13 examples, 0 failures Refactoring to Small Code 16x9 - April 24, 2014
  • 69. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if (option_type == :string || option_type == :integer) && raw_option_value && raw_option_value.length < 3 return false if option_type == :integer && raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false) end end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 70. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if (option_type == :string || option_type == :integer) && raw_option_value && raw_option_value.length < 3 return false if option_type == :integer && raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false) end end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 71. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … ! def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) return false if (option_type == :string || option_type == :integer) && raw_option_value && raw_option_value.length < 3 return false if option_type == :integer && raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false) end end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 72. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string return (Integer(raw_option_value[2..-1])) if option_type == :integer end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 73. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string return (Integer(raw_option_value[2..-1])) if option_type == :integer end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 74. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string return (Integer(raw_option_value[2..-1])) if option_type == :integer end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 75. Enable Labs @mark_menard #smallcodeclass CommandLineOptions … ! def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string return false if raw_option_value && raw_option_value.length < 3 when :integer return false if raw_option_value && raw_option_value.length < 3 return false if raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false) end end end ! … end Refactoring to Small Code 16x9 - April 24, 2014
  • 76. Enable Labs @mark_menard #smallcodeclass CommandLineOptions … ! def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] ! return case(option_type) when :string raw_option_value[2..-1] when :integer (Integer(raw_option_value[2..-1])) when :boolean return true if option_type == :boolean && raw_option_value end end ! … end Refactoring to Small Code 16x9 - April 24, 2014
  • 77. Enable Labs @mark_menard #smallcode How do we write small classes? Refactoring to Small Code 16x9 - April 24, 2014
  • 78. Enable Labs @mark_menard #smallcode What are the characteristics of a small class? Refactoring to Small Code 16x9 - April 24, 2014
  • 79. Enable Labs @mark_menard #smallcode class CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = {} @argv = argv instance_eval &block end ! def valid? options.all?(&:valid) end ! def value (option_flag) options[option_flag].value end ! private def option (option_flag, option_type = :boolean) options[option_flag] = build_option(option_flag, option_type) end ! def build_option # Need to write this. end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 80. Enable Labs @mark_menard #smallcode class CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = {} @argv = argv instance_eval &block end ! def valid? options.all?(&:valid) end ! def value (option_flag) options[option_flag].value end ! private def option (option_flag, option_type = :boolean) options[option_flag] = build_option(option_flag, option_type) end ! def build_option # Need to write this. end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 81. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.all?(&:valid?) end ! def value (option_flag) options[option_flag].value end ! def build_option # Need to write this. end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 82. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.all?(&:valid?) end ! def value (option_flag) options[option_flag].value end ! def build_option # Need to write this. end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 83. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.all?(&:valid?) end ! def value (option_flag) options[option_flag].value end ! def build_option # Need to write this. end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 84. Enable Labs @mark_menard #smallcodeclass CommandLineOptions ! … ! def valid? options.all?(&:valid?) end ! def value (option_flag) options[option_flag].value end ! def build_option # Need to write this. end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 86. Enable Labs @mark_menard #smallcode Dependencies Command Line Options ?* Refactoring to Small Code 16x9 - April 24, 2014
  • 87. Enable Labs @mark_menard #smallcode Depend on Abstractions Refactoring to Small Code 16x9 - April 24, 2014
  • 88. Enable Labs @mark_menard #smallcode Command Line Options String Option Integer Option Boolean Option valid? value Option* Depend on Abstractions Refactoring to Small Code 16x9 - April 24, 2014
  • 89. Enable Labs @mark_menard #smallcode Command Line Options String Option Integer Option Boolean Option valid? value Option* This is my duck type! Depend on Abstractions Refactoring to Small Code 16x9 - April 24, 2014
  • 90. Enable Labs @mark_menard #smallcode Command Line Options String Option Integer Option Boolean Option valid? value Option* This is my duck type! These are my concrete types. Depend on Abstractions Refactoring to Small Code 16x9 - April 24, 2014
  • 91. Enable Labs @mark_menard #smallcode Command Line Options String Option Integer Option Boolean Option valid? value Option* These are my concrete types. Depend on this! Depend on Abstractions Refactoring to Small Code 16x9 - April 24, 2014
  • 92. Enable Labs @mark_menard #smallcode Command Line Options String Option Integer Option Boolean Option valid? value Option* Depend on this! Don’t depend on these! Depend on Abstractions Refactoring to Small Code 16x9 - April 24, 2014
  • 93. Enable Labs @mark_menard #smallcode private def option (option_flag, option_type = :boolean) options[option_flag] = case (option_type) when :boolean return BooleanOption.new(option_flag, nil) when :string return StringOption.new(option_flag, nil) when :integer return IntegerOption.new(option_flag, nil) end end Refactoring to Small Code 16x9 - April 24, 2014
  • 94. Enable Labs @mark_menard #smallcode class CommandLineOptions ! … ! def build_option (option_flag, option_type) “#{option_type}_option".camelize.constantize.new( option_flag, raw_value_for_option(option_flag) ) end ! … ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 95. Enable Labs @mark_menard #smallcodeclass Option ! attr_reader :flag, :raw_value ! def initialize (flag, raw_value) @flag = flag @raw_value = raw_value end ! def valid? end ! def value end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 96. Enable Labs @mark_menard #smallcodeclass BooleanOption < Option ! def valid? true end ! def value raw_value end end class Option ! attr_reader :flag, :raw_value ! def initialize (flag, raw_value) @flag = flag @raw_value = raw_value end ! def valid? end ! def value end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 97. Enable Labs @mark_menard #smallcodeclass StringOption < Option ! def valid? ! ! end ! def value ! ! end end class IntegerOption < Option ! def valid? ! ! end ! def value ! ! end end Refactoring to Small Code 16x9 - April 24, 2014
  • 98. Enable Labs @mark_menard #smallcodedef valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string ! ! when :integer ! ! ! end end end def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string return false if raw_option_value && raw_option_value.length < 3 when :integer return false if raw_option_value && raw_option_value.length < 3 return false if raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false) end end end def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] ! return case(option_type) when :string ! when :integer ! when :boolean ! end end def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] ! return case(option_type) when :string raw_option_value[2..-1] when :integer (Integer(raw_option_value[2..-1])) when :boolean return true if option_type == :boolean && raw_option_value end end class StringOption < Option ! def valid? ! ! end ! def value ! ! end end ! class IntegerOption < Option ! def valid? ! ! ! end ! def value ! ! end end Refactoring to Small Code 16x9 - April 24, 2014
  • 99. Enable Labs @mark_menard #smallcodedef valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string ! ! when :integer ! ! ! end end end def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] ! return case(option_type) when :string ! when :integer ! when :boolean ! end end def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] ! return case(option_type) when :string raw_option_value[2..-1] when :integer (Integer(raw_option_value[2..-1])) when :boolean return true if option_type == :boolean && raw_option_value end end class StringOption < Option ! def valid? ! ! end ! def value ! ! end end ! class IntegerOption < Option ! def valid? ! ! ! end ! def value ! ! end end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value ! ! end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value ! ! end end Refactoring to Small Code 16x9 - April 24, 2014
  • 100. Enable Labs @mark_menard #smallcodedef valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string ! ! when :integer ! ! ! end end end def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] ! return case(option_type) when :string ! when :integer ! when :boolean ! end end class StringOption < Option ! def valid? ! ! end ! def value ! ! end end ! class IntegerOption < Option ! def valid? ! ! ! end ! def value ! ! end end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value ! ! end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value ! ! end end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value return nil unless raw_value raw_value[2..-1] end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value return nil unless raw_value Integer(raw_value[2..-1]) end end Refactoring to Small Code 16x9 - April 24, 2014
  • 101. Enable Labs @mark_menard #smallcodedef valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string ! ! when :integer ! ! ! end end end def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] ! return case(option_type) when :string ! when :integer ! when :boolean ! end end class StringOption < Option ! def valid? ! ! end ! def value ! ! end end ! class IntegerOption < Option ! def valid? ! ! ! end ! def value ! ! end end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value ! ! end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value ! ! end end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value return nil unless raw_value raw_value[2..-1] end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value return nil unless raw_value Integer(raw_value[2..-1]) end end Refactoring to Small Code 16x9 - April 24, 2014
  • 102. Enable Labs @mark_menard #smallcodedef valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string ! ! when :integer ! ! ! end end end def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] ! return case(option_type) when :string ! when :integer ! when :boolean ! end end class StringOption < Option ! def valid? ! ! end ! def value ! ! end end ! class IntegerOption < Option ! def valid? ! ! ! end ! def value ! ! end end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value ! ! end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value ! ! end end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value return nil unless raw_value raw_value[2..-1] end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value return nil unless raw_value Integer(raw_value[2..-1]) end end Refactoring to Small Code 16x9 - April 24, 2014
  • 103. Enable Labs @mark_menard #smallcode def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] ! return case(option_type) when :string ! when :integer ! when :boolean ! end end class StringOption < Option ! def valid? ! ! end ! def value ! ! end end ! class IntegerOption < Option ! def valid? ! ! ! end ! def value ! ! end end def valid? options.all?(&:valid?) end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value ! ! end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value ! ! end end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value return nil unless raw_value raw_value[2..-1] end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value return nil unless raw_value Integer(raw_value[2..-1]) end end Refactoring to Small Code 16x9 - April 24, 2014
  • 104. Enable Labs @mark_menard #smallcode def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] ! return case(option_type) when :string ! when :integer ! when :boolean ! end end class StringOption < Option ! def valid? ! ! end ! def value ! ! end end ! class IntegerOption < Option ! def valid? ! ! ! end ! def value ! ! end end def valid? options.all?(&:valid?) end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value ! ! end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value ! ! end end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value return nil unless raw_value raw_value[2..-1] end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value return nil unless raw_value Integer(raw_value[2..-1]) end end Refactoring to Small Code 16x9 - April 24, 2014
  • 105. Enable Labs @mark_menard #smallcode def value (option_flag) options[option_flag].value end class StringOption < Option ! def valid? ! ! end ! def value ! ! end end ! class IntegerOption < Option ! def valid? ! ! ! end ! def value ! ! end end def valid? options.all?(&:valid?) end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value ! ! end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value ! ! end end class StringOption < Option ! def valid? return true unless raw_value raw_value && raw_value.length > 2 end ! def value return nil unless raw_value raw_value[2..-1] end end ! class IntegerOption < Option ! def valid? return true unless raw_value (raw_value && raw_value.length > 2) && (Integer(raw_value[2..-1]) rescue false) end ! def value return nil unless raw_value Integer(raw_value[2..-1]) end end Refactoring to Small Code 16x9 - April 24, 2014
  • 106. Enable Labs @mark_menard #smallcode Option classes Option stores it's flag stores it's raw value BooleanOption is true if the raw value is present is false if the raw value is nil is valid StringOption invalid when there is no content is valid if there is content is valid if raw value is nil can return the value value is nil if raw value is nil IntegerOption is invalid without content is invalid if the content is not an integer is valid if there is content and it's an integer is valid if raw value is nil can return the value returns nil if raw value is nil ! Finished in 0.00495 seconds 22 examples, 0 failures, 6 pending Refactoring to Small Code 16x9 - April 24, 2014
  • 107. Enable Labs @mark_menard #smallcode How do we isolate abstractions? Separate the “what” from the “how”. Refactoring to Small Code 16x9 - April 24, 2014
  • 108. Enable Labs @mark_menard #smallcode def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string return false if raw_option_value && raw_option_value.length < 3 when :integer return false if raw_option_value && raw_option_value.length < 3 return false if raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false) end end end Refactoring to Small Code 16x9 - April 24, 2014
  • 109. Enable Labs @mark_menard #smallcode def valid? options.values.all?(&:valid?) end def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string return false if raw_option_value && raw_option_value.length < 3 when :integer return false if raw_option_value && raw_option_value.length < 3 return false if raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false) end end end Refactoring to Small Code 16x9 - April 24, 2014
  • 110. Enable Labs @mark_menard #smallcode def valid? options.values.all?(&:valid?) end def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string return false if raw_option_value && raw_option_value.length < 3 when :integer return false if raw_option_value && raw_option_value.length < 3 return false if raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false) end end end This all about HOW! Refactoring to Small Code 16x9 - April 24, 2014
  • 111. Enable Labs @mark_menard #smallcode def valid? options.values.all?(&:valid?) end def valid? options.each do |option_flag, option_type| raw_option_value = raw_value_for_option(option_flag) ! case(option_type) when :string return false if raw_option_value && raw_option_value.length < 3 when :integer return false if raw_option_value && raw_option_value.length < 3 return false if raw_option_value && !(Integer(raw_option_value[2..-1]) rescue false) end end end This all about HOW! This is WHAT I want done. Refactoring to Small Code 16x9 - April 24, 2014
  • 112. Enable Labs @mark_menard #smallcode def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string return (Integer(raw_option_value[2..-1])) if option_type == :integer end Refactoring to Small Code 16x9 - April 24, 2014
  • 113. Enable Labs @mark_menard #smallcode def value (option_flag) options[option_flag].value end def value (option_flag) raw_option_value = raw_value_for_option(option_flag) return nil unless raw_option_value option_type = options[option_flag] return true if option_type == :boolean && raw_option_value return raw_option_value[2..-1] if option_type == :string return (Integer(raw_option_value[2..-1])) if option_type == :integer end Refactoring to Small Code 16x9 - April 24, 2014
  • 114. Enable Labs @mark_menard #smallcode class CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = {} @argv = argv instance_eval &block end ! def valid? options.values.all?(&:valid?) end ! def value (option_flag) options[option_flag].value end ! private ! def option (option_flag, option_type = :boolean) options[option_flag] = build_option(option_flag, option_type) end ! def build_option (option_flag, option_type) "#{option_type}_option".camelize.constantize.new(option_flag, raw_value_for_option(option_flag)) end ! def raw_value_for_option (option_flag) argv.find { |arg| arg =~ /^-#{option_flag}/ } end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 115. Enable Labs @mark_menard #smallcode class CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = {} @argv = argv instance_eval &block end ! def valid? options.values.all?(&:valid?) end ! def value (option_flag) options[option_flag].value end ! private ! def option (option_flag, option_type = :boolean) options[option_flag] = build_option(option_flag, option_type) end ! def build_option (option_flag, option_type) "#{option_type}_option".camelize.constantize.new(option_flag, raw_value_for_option(option_flag)) end ! def raw_value_for_option (option_flag) argv.find { |arg| arg =~ /^-#{option_flag}/ } end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 116. Enable Labs @mark_menard #smallcode class CommandLineOptions ! attr_accessor :argv attr_reader :options ! def initialize (argv = [], &block) @options = {} @argv = argv instance_eval &block end ! def valid? options.values.all?(&:valid?) end ! def value (option_flag) options[option_flag].value end ! private ! def option (option_flag, option_type = :boolean) options[option_flag] = build_option(option_flag, option_type) end ! def build_option (option_flag, option_type) "#{option_type}_option".camelize.constantize.new(option_flag, raw_value_for_option(option_flag)) end ! def raw_value_for_option (option_flag) argv.find { |arg| arg =~ /^-#{option_flag}/ } end ! end Refactoring to Small Code 16x9 - April 24, 2014
  • 117. Enable Labs @mark_menard #smallcode ! def valid? options.values.all?(&:valid?) end ! def value (option_flag) options[option_flag].value end Refactoring to Small Code 16x9 - April 24, 2014
  • 118. Enable Labs @mark_menard #smallcode CommandLineOptions builds an option object for each defined option is valid if all options are valid is invalid if any option is invalid option object conventions uses a StringOption for string options uses a BooleanOption for boolean options uses an IntegerOption for integer options Refactoring to Small Code 16x9 - April 24, 2014
  • 119. Enable Labs @mark_menard #smallcode Then Refactoring to Small Code 16x9 - April 24, 2014
  • 120. Enable Labs @mark_menard #smallcode some_ruby_program -v -efoo -i100 -afoo,bar,baz Refactoring to Small Code 16x9 - April 24, 2014
  • 121. Enable Labs @mark_menard #smallcode describe "array options" do it "can return the value as an array" do options = CommandLineOptions.new([ "-afoo,bar,baz" ]) { option :a, :array } expect(options.value(:a)).to eq(["foo", "bar", "baz"]) end end Refactoring to Small Code 16x9 - April 24, 2014
  • 122. Enable Labs @mark_menard #smallcode describe "array options" do it "can return the value as an array" do options = CommandLineOptions.new([ "-afoo,bar,baz" ]) { option :a, :array } expect(options.value(:a)).to eq(["foo", "bar", "baz"]) end end class ArrayOption < OptionWithContent def value return nil if option_unset? extract_value_from_raw_value.split(",") end end Refactoring to Small Code 16x9 - April 24, 2014
  • 123. Enable Labs @mark_menard #smallcodeCommandLineOptions boolean options are true if present are false if absent string options must have content is valid when there is content can return the value return nil if not in argv integer options must have content must be an integer can return the value as an integer returns nil if not in argv array options can return the value as an array ! OptionWithContent has a flag is valid when it has no raw value is valid when it has a value can return it's value when present returns nil if the flag has no raw value Refactoring to Small Code 16x9 - April 24, 2014
  • 124. Enable Labs @mark_menard #smallcode Now We’re Done!! Let them implement their own option classes. It’s easy. Refactoring to Small Code 16x9 - April 24, 2014
  • 125. Enable Labs @mark_menard #smallcode http://www.enablelabs.com/ info@enablelabs.com 866-895-8189 @mark_menard Mark Menard Enable Labs GitHub: MarkMenard Refactoring to Small Code 16x9 - April 24, 2014
  • 126. Enable Labs @mark_menard #smallcode Credits • Syntax highlighting: pbpaste | highlight --syntax=rb --style=edit-xcode --out-format=rtf | pbcopy! • Command line option example inspiration Uncle Bob. Refactoring to Small Code 16x9 - April 24, 2014