Created
May 8, 2011 23:40
-
-
Save afair/961810 to your computer and use it in GitHub Desktop.
Notes on Advi Grimm's "Confident Code" talk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# http://avdi.org/talks/confident-code-2010-01-12/confident-code.html | |
# Narrative structure: Four Parts | |
#========================================================== | |
# Gather input: | |
# Coerce | |
param.to_s #to_i #to_sym Array() ... use liberally! | |
messages = Array(messages) | |
# Decorators | |
destination = WithPath.new(options[:out]).path | |
# Reject | |
raise Exception, message, caller unless value | |
# Guard clause | |
return "" if message.nil? | |
# Ignore | |
# Null Object, responds to any message with nil or itself | |
#---------------------------------------------------------- | |
# Avoid nil!!! | |
# It means too many things | |
# Error | |
# Missing Data | |
# Flag for "default behavior" | |
# Uninitialized variable | |
# Use Hash#fetch with block for when value not found | |
{}.fetch(:width) # => | |
# ~> -:7:in `fetch': key not found (IndexError) | |
{}.fetch(:width) { 40 } # => 40 | |
{:width => nil}.fetch(:width) {40} # => nil | |
{:width => false}.fetch(:width) {40} # => false | |
{:width => 29}.fetch(:width) {40} # => 29 | |
# Custom error | |
opt = {}.fetch(:required_opt) do | |
raise ArgumentError, "Missing option!" | |
end | |
def initialize(logger=NullObject.new) | |
@logger = logger | |
end | |
# Stub Object Default | |
# $? is either nil or a Process::Status object | |
def check_child_exit_status!(status=$?) | |
status ||= OpenStruct.new(:exitstatus => 0) | |
unless [0,172].include?(status.exitstatus) | |
raise ArgumentError, | |
"Command exited with status #{status.exitstatus.status}" | |
end | |
end | |
#========================================================== | |
# Perform work | |
# Reserve conditionals for business logic | |
if post.published? # => Business Login | |
if post # => Not | |
# Isolate error/input handling from program flow | |
# Iteration over singular objects... jQuery example | |
# $("div.notLongForThisWorld").fadeOut().addClass("removed"); | |
#========================================================== | |
# Deliver results | |
#========================================================== | |
# Handle errors | |
def method() | |
# logic | |
rescue => error | |
# error handing at the end | |
end | |
# Bouncer Method | |
def check_child_exit_status | |
result = yield | |
status = $? || OpenStruct.new(:exitstatus => 0) | |
unless [0,172].include?(status.exitstatus) | |
raise ArgumentError, | |
"Command exited with status #{status.exitstatus}" | |
end | |
result | |
end | |
check_child_exit_status { | |
@io_class.popen(command, "w+") # ... | |
} | |
# Checked Method | |
def checked_popen(command, mode, fail_action) | |
check_child_exit_status do | |
@io_class.popen(command, "w+") do |process| | |
yield(process) | |
end | |
end | |
rescue Errno::EPIPE | |
fail_action.call | |
end | |
checked_popen(command, "w+", lambda{message}) do |process| | |
# ... | |
end | |
#------------------------------------------- | |
# Array() The "arrayification operator" | |
Array([1,2,3]) # => [1, 2, 3] | |
Array("foo") # => ["foo"] | |
Array(nil) # => [] | |
# Gotcha: | |
Array("foo\nbar") # => ["foo\n", "bar"] | |
#---------------------------------------------------------- | |
# Decorator | |
require 'delegate' | |
# ... | |
class WithPath < SimpleDelegator | |
def path | |
case __getobj__ | |
when File then super | |
when nil then "return value" | |
else inspect | |
end | |
end | |
end | |
destination = WithPath.new(options[:out]).path | |
#---------------------------------------------------------- | |
# A Basic Null Object | |
# - Returning self lets us nullify chains of calls | |
class NullObject | |
def initialize | |
@origin = caller.first ### SETS ORIGIN FOR INSPECT INFO | |
end | |
def method_missing(*args, &block) | |
self | |
end | |
def nil?; true; end | |
end | |
def Maybe(value) | |
value.nil? ? NullObject.new : value | |
end | |
if options[:out] | |
options[:out] << output | |
end | |
Maybe(options[:out]) << output | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment