Diana got tickets for us and Mom to the Chihuly blown glass exhibition at the botanical garden… The artist is one of the few I know of that allows cameras into the exhibition, and shutterbugs came out of the woodwork for it. All 3 of us were armed with our own point-and-shoots (one on loan from Diana’s mom), and we fired off hundreds of shots between us until batteries started running out.
This one’s off my camera phone; the proper pictures will be posted later. Some will be going into a photo contest they’re running, and judging from the unimaginative entries in the gallery, we might actually have a chance.
Read more...MountainWest RubyConf - a travelogue...
Integrum at MountainWest RubyConf 2009 from Jay McGavren on Vimeo.
Notes from Jim Weirich - Building Blocks of Modularity...
Update 2009-05-05: Saw this talk again today at RailsConf and had a chance to fill in some missing pieces…
Is there a grand unified theory of software development?
Principles:
SOLID
Law of Demeter
Method chains not good - only talk to objects in local environment.
DRY
Small Methods
Design by Contract
Myer on Coupling: old, imperfect model that doesn't extend well to dynamic languages. From best to worst:
No coupling
Data coupling
Data local to two modules: simple data
Stamp coupling
Data local to two modules: structured data
Control coupling
Method usually has a "flag" parameter that controls which algorithm it uses
ex: Array.instance_methods(true) #What does true mean?!
ActiveRecord#find (:first, :all, etc.)
External coupling
Global data: simple data
Common coupling
Global data: structured data
Content coupling
Connascence
Things that are born together, and change together. A change in one requires a corresponding change in the other.
Originally applied to software by Meilir Page-Jones in early 90's.
Connascence of Name:
class Customer
def email; blah; end
end
def send_mail(customer)
customer.email #Change Customer#email's name, you must update this call.
end
Rule of Locality:
Connascence of name between method parameter and a reference in the same method doesn't matter at all.
Connascence of name between two separate libraries matters a lot. It's why APIs must be frozen.
Connascence of Position:
:orders => {"3" => "1", "5" => "2"}
[ [ Order.find(3), true], [ Order.find(5), false ] ]
Order of parameters decides behavior.
Really bad:
def process(order, expedite, confirmation_number, ...); blah; end
[order, true, 2374]
Easy to forget order of parameters, especially if you're passing 3, '
Better:
class OrderDisposition
attr_reader :order
attr_reader :expedite
attr_reader :confirmation_number
end
Methods that take hash parameters are better than positional arguments, because each argument is labelled and can be re-ordered or omitted.
Degree matters:
Some types of connascence are worse than others.
Connascence of Name better than Connascence of Position.
Rule of Degree:
Convert higher degrees of connascence into weaker forms.
Example: refactor from positional method params to an options hash with named keys (CoP -> CoN).
Connascence of Meaning
Consider "magic numbers" (these are bad):
<input type="checkbox" value="2">
if params[:med][id] == "2" #Have to do case-like statement in totally different module.
@medication.given = false
end
Contranascence
Things conflicting with each other. (Always in name?)
#my_xml_lib
module Kernel; def node; end; end
#my_graph_lib
module Kernel; def node; end; end #Conflict!
Example is classes that must be namespaced to avoid conflict (XML::Node, YAML::Node)
Connascence of Algorithm:
Logic repeated in multiple places - not DRY.
Bad:
def add_check_digit(digits); digits + ((10 - digits.foobar{|d| d + 5} % 10).to_s; end
def check?(digits) check_sum(digits.foobar{|d| d + 5}) == 10; end
Change digits.foobar{|d| d + 5} in one place, you must change it in both places. Better not forget!
Better:
def add_check_digit(digits); digits + ((10 - foobar(digits) % 10).to_s; end
def check?(digits) foobar(digits) == 10; end
def foobar(digits); blah; end #Shared routine
Change the shared routine, and you change the logic everywhere you need to.
Connascence of Timing
Race conditions.
Bad if called from multiple threads:
def increment
@amount += 1
end
Use Java-like synchronized declarations on methods to ensure they are thread-safe.
Connascence of Type
See What Every Programmer Should Know About Object Oriented Design, Meilir Page-Jones
Connascence of Execution
See What Every Programmer Should Know About Object Oriented Design, Meilir Page-Jones
Connascence of Value
See What Every Programmer Should Know About Object Oriented Design, Meilir Page-Jones
Connascence of Identity
See What Every Programmer Should Know About Object Oriented Design, Meilir Page-Jones
Read more...
Notes from Jay Philips on Adhearsion...
One of the more exciting talks at MountainWest RubyConf… Looks like I could have something simple running in a weekend.
Asterisk front end. Native integration with Rails. Project:
dialplan.rb:
adhearsion {
simon_game
}
sandbox {
play "hello-world" #Sound file stored on server.
menu "hello-world" do |link|
link.adhearsion 1 #Dialpad number to press.
link.foobar 2
end
}
events.rb
components/
sandbox/
sandbox.rb
sandbox.yml
username: dfsklh
password: dafsjkh
my_component/
config/
startup.rb
Read more...
Notes from Adam Dunford & Jason Edwards: Improving the Usability of Your Ruby on Rails Applications
Usability: Can a user accomplish THEIR goal? Use actual users in usability testing. Investment in usability usually offers 10x-100x return in increased profit. Creating structure: Organize Prioritize Most important stuff is most obvious Group Similar stuff goes together Separate Differentiate Don't defy user expectations (ex: link description doesn't match where it goes) - it makes them mad. Reduce barriers: Allow quick account creation and signon. Pict.com lets you upload pictures even before you create an account. Don't require framework (Flash, Javascript, Silverlight) to be enabled/installed, at least not right away. Try to anticipate problems. Phone number validation - for God's sake, don't use 3 separate fields! Affordances: Increase text size. Make form fields bigger. Add label tags that move cursor to field when clicked. Give feedback: Make it clear and obvious that your app is responding appropriately. If validation fails, mark the fields with problems directly (indicator *right* next to them). Anticipate actions: Really cool - validate fields (in Javascript?) even before user submits form. Simplify: "Every time you provide an option, you're asking the user to make a decision." Avoid it where possible. Principles: Reduce How many elements can you take out of the signup form? Get rid of COPPA age validation. Tumblr got it down to 2 - username and password. Replace Hide Hide things that can't be acted on right now. Remove Remove info that isn't necessary. Use terminology user is comfortable with: it's "delete", not "destroy".Read more...