Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Affordances in Programming Languages

1,388 views

Published on

From Mountain West Ruby Conference 2014.

A good design communicates the intended use of an object. In the physical world, this communication is accomplished by “affordances”, as discussed by Donald Norman in “The Psychology of Everyday Things”.

Programming languages also have affordances, and they influence the kinds of solutions we develop. The more languages we know, the more we “expand our design space” so that we can come up with better solutions to the problems we face every day.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Affordances in Programming Languages

  1. 1. 3/20/2014 Affordances http://localhost:9090/onepage 1/67 Affordances in Programming Languages Randy Coulman Principal Software Engineer http://randycoulman.com  @randycoulman  randycoulman
  2. 2. 3/20/2014 Affordances http://localhost:9090/onepage 2/67 Satu Kyröläinen ­ http://www.satukyrolainen.com/affordances/
  3. 3. 3/20/2014 Affordances http://localhost:9090/onepage 3/67 Satu Kyröläinen ­ http://www.satukyrolainen.com/affordances/
  4. 4. 3/20/2014 Affordances http://localhost:9090/onepage 4/67 Affordance A quality of an object or environment that allows someone to perform an action.
  5. 5. 3/20/2014 Affordances http://localhost:9090/onepage 5/67 Nicolas Nova ­ http://www.flickr.com/photos/nnova/2252222949/
  6. 6. 3/20/2014 Affordances http://localhost:9090/onepage 6/67 William Lindeke ­ http://tcsidewalks.blogspot.com/2009/06/signs­of­times­14.html
  7. 7. 3/20/2014 Affordances http://localhost:9090/onepage 7/67 Yoni Alter ­ http://www.yoniishappy.com/Tube­escalators
  8. 8. 3/20/2014 Affordances http://localhost:9090/onepage 8/67 Affordances and Software
  9. 9. 3/20/2014 Affordances http://localhost:9090/onepage 9/67 Amir Rajan (@amirrajan) Coding Out Loud ­ REST APIs series http://vimeo.com/channels/659338
  10. 10. 3/20/2014 Affordances http://localhost:9090/onepage 10/67 Example Points Smalltalk ­> Ruby
  11. 11. 3/20/2014 Affordances http://localhost:9090/onepage 11/67 class Point def initialize(x, y) @x = x @y = y end end Point.new(3, 4)
  12. 12. 3/20/2014 Affordances http://localhost:9090/onepage 12/67 http://images.cryhavok.org/d/25562­2/Polar+and+Cartesian+Bears.jpg
  13. 13. 3/20/2014 Affordances http://localhost:9090/onepage 13/67 θ r sinθ r cosθ r x y http://upload.wikimedia.org/wikipedia/commons/7/78/Polar_to_cartesian.svg
  14. 14. 3/20/2014 Affordances http://localhost:9090/onepage 14/67 class Point def initialize(x, y) @x = x @y = y end end Point.new(3, 4)
  15. 15. 3/20/2014 Affordances http://localhost:9090/onepage 15/67 Point class>>x: anX y: aY ^self new initializeX: anX y: aY Point>>initializeX: anX y: aY x := anX. y := aY Point x: 3 y: 4
  16. 16. 3/20/2014 Affordances http://localhost:9090/onepage 16/67 Point class>> r: radius theta: angleInRadians ^self x: radius * angleInRadians cos y: radius * angleInRadians sin Point r: 5 theta: 0.927295
  17. 17. 3/20/2014 Affordances http://localhost:9090/onepage 17/67 Affordance Named Constructors
  18. 18. 3/20/2014 Affordances http://localhost:9090/onepage 18/67 class Point def self.xy(x, y) new(x, y) end def self.polar(r, theta) xy(r * Math.cos(theta), r * Math.sin(theta)) end private_class_method :new # ... rest same as before end Point.xy(3, 4) Point.polar(5, 0.927295)
  19. 19. 3/20/2014 Affordances http://localhost:9090/onepage 19/67 Example Find/Detect Smalltalk ­> Ruby
  20. 20. 3/20/2014 Affordances http://localhost:9090/onepage 20/67 #(2 4 6 8) detect: [:each | each odd] "Unhandled exception: Element Not Found"
  21. 21. 3/20/2014 Affordances http://localhost:9090/onepage 21/67 [2, 4, 6, 8].find { |n| n.odd? } # => nil
  22. 22. 3/20/2014 Affordances http://localhost:9090/onepage 22/67 #(2 4 6 8) detect: [:each | each odd] ifNone: [#none] "#none"
  23. 23. 3/20/2014 Affordances http://localhost:9090/onepage 23/67 Affordance Multiple Blocks
  24. 24. 3/20/2014 Affordances http://localhost:9090/onepage 24/67 [2, 4, 6, 8].find(-> {:none}) { |n| n.odd? } # => :none
  25. 25. 3/20/2014 Affordances http://localhost:9090/onepage 25/67 Linguistic Relativity a.k.a. The Sapir­Whorf Hypothesis "[T]he structure of a language affects the ways in which its respective speakers conceptualize their world ... or otherwise influences their cognitive processes." ­­ http://en.wikipedia.org/wiki/Linguistic_relativity
  26. 26. 3/20/2014 Affordances http://localhost:9090/onepage 26/67 When Code Cries Cory Foy at SCNA 2012 http://vimeo.com/53986875 What does a language allow you to say? What does a language force you to say?
  27. 27. 3/20/2014 Affordances http://localhost:9090/onepage 27/67 The Power and Philsophy of Ruby Matz at OSCON 2003 http://www.rubyist.net/~matz/slides/oscon2003/mgp00001.html "Languages are not only tools to communicate, but also tools to think."
  28. 28. 3/20/2014 Affordances http://localhost:9090/onepage 28/67 Example Cleaning Up After Yourself C++ ­> Ruby
  29. 29. 3/20/2014 Affordances http://localhost:9090/onepage 29/67 if ((err = SSLFreeBuffer(&hashCtx)) != 0) goto fail; if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &clientRandom)) != goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != goto fail; goto fail; if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail; //... fail: SSLFreeBuffer(&signedHashes); SSLFreeBuffer(&hashCtx); return err;
  30. 30. 3/20/2014 Affordances http://localhost:9090/onepage 30/67 #include "support.h" #include <iostream> void foo() { Resource* resource = acquireResource(); bar(resource); if (baz(resource) != 42) return; std::cout << "Completed successfully!" << std::endl; releaseResource(resource); }
  31. 31. 3/20/2014 Affordances http://localhost:9090/onepage 31/67 $ ./broken Acquiring resource Caught exception: oops!
  32. 32. 3/20/2014 Affordances http://localhost:9090/onepage 32/67 #include "support.h" #include <iostream> void foo() { Resource* resource = acquireResource(); try { bar(resource); if (baz(resource) == 42) { std::cout << "Completed successfully!" << std::endl; } } catch(std::exception& e) { releaseResource(resource); throw; } releaseResource(resource); }
  33. 33. 3/20/2014 Affordances http://localhost:9090/onepage 33/67 $ ./wordy Acquiring resource Releasing resource Caught exception: oops!
  34. 34. 3/20/2014 Affordances http://localhost:9090/onepage 34/67 #include "support.h" #include <iostream> void foo() { Resource* resource = acquireResource(); try { bar(resource); if (baz(resource) == 42) { std::cout << "Completed successfully!" << std::endl; } } catch(std::exception& e) { releaseResource(resource); throw; } releaseResource(resource); }
  35. 35. 3/20/2014 Affordances http://localhost:9090/onepage 35/67
  36. 36. 3/20/2014 Affordances http://localhost:9090/onepage 36/67 RAII Resource Acquisition Is Initialization Acquire resources in the constructor Release them in the destructor
  37. 37. 3/20/2014 Affordances http://localhost:9090/onepage 37/67 #include "SafeResource.h" #include "support.h" SafeResource::SafeResource() : resource(acquireResource()) { } SafeResource::~SafeResource() { releaseResource(resource); } Resource* SafeResource::get() { return resource; }
  38. 38. 3/20/2014 Affordances http://localhost:9090/onepage 38/67 #include "SafeResource.h" #include "support.h" #include <iostream> void foo() { SafeResource resource; bar(resource.get()); if (baz(resource.get()) != 42) return std::cout << "Completed successfully!" << std::endl; }
  39. 39. 3/20/2014 Affordances http://localhost:9090/onepage 39/67 $ ./raii Acquiring resource Releasing resource Caught exception: oops!
  40. 40. 3/20/2014 Affordances http://localhost:9090/onepage 40/67 Affordance Deterministic Destructors
  41. 41. 3/20/2014 Affordances http://localhost:9090/onepage 41/67 Ruby doesn't have deterministic destructors. So what can we do instead?
  42. 42. 3/20/2014 Affordances http://localhost:9090/onepage 42/67 Blocks!
  43. 43. 3/20/2014 Affordances http://localhost:9090/onepage 43/67 class SafeResource def self.acquire resource = self.new yield resource ensure resource.release end def initialize puts "Acquiring resource" @resource = Object.new end def release puts "Releasing resource" @resource = nil end
  44. 44. 3/20/2014 Affordances http://localhost:9090/onepage 44/67 require_relative "support" require_relative "safe_resource" def foo SafeResource.acquire do |resource| bar(resource) return unless baz(resource) == 42 puts "Completed successfully!" end end
  45. 45. 3/20/2014 Affordances http://localhost:9090/onepage 45/67 $ ruby driver.rb Acquiring resource Releasing resource Caught exception: oops!
  46. 46. 3/20/2014 Affordances http://localhost:9090/onepage 46/67 Example ImageReader Smalltalk ­> Ruby
  47. 47. 3/20/2014 Affordances http://localhost:9090/onepage 47/67 ImageReader class>>fromFile: aFilename | readerClass imageStream reader | imageStream := aFilename readStream binary. [readerClass := self readerClassFor: imageStream. readerClass ifNil: [^self error: 'Unknown image type: ', aFilename asString]. reader := readerClass on: imageStream] ensure: [imageStream close]. ^reader
  48. 48. 3/20/2014 Affordances http://localhost:9090/onepage 48/67 ImageReader class>>readerClassFor: imageStream ^self subclasses detect: [:eachClass | imageStream reset. [eachClass canRead: imageStream] ensure: [imageStream reset]] ifNone: [nil]
  49. 49. 3/20/2014 Affordances http://localhost:9090/onepage 49/67 Affordance Subclass Iteration
  50. 50. 3/20/2014 Affordances http://localhost:9090/onepage 50/67 class ImageReader def self.read(filename) File.open(filename, "rb") do |io| reader_class = find_reader_class(io) raise "Unknown image type: #{filename}" unless reader_class reader_class.new(io) end end #... end
  51. 51. 3/20/2014 Affordances http://localhost:9090/onepage 51/67 class ImageReader #... def self.find_reader_class(io) subclasses.find { |reader| begin io.rewind reader.can_read?(io) ensure io.rewind end } end #... end
  52. 52. 3/20/2014 Affordances http://localhost:9090/onepage 52/67 class ImageReader #... def self.inherited(subclass) subclasses << subclass end def self.subclasses @subclasses ||= [] end #... end
  53. 53. 3/20/2014 Affordances http://localhost:9090/onepage 53/67 class BMPImageReader < ImageReader def self.can_read?(io) io.read(2) == "BM" end def read_image puts "Reading BMP" end end
  54. 54. 3/20/2014 Affordances http://localhost:9090/onepage 54/67 class JPGImageReader < ImageReader def self.can_read?(io) io.read(2) == "xFFxD8".b end def read_image puts "Reading JPG" end end
  55. 55. 3/20/2014 Affordances http://localhost:9090/onepage 55/67 class PNGImageReader < ImageReader def self.can_read?(io) io.read(8) == "x89PNGrnx1An".b end def read_image puts "Reading PNG" end end
  56. 56. 3/20/2014 Affordances http://localhost:9090/onepage 56/67 require_relative "image_readers" %w{bmp jpg png}.each do |ext| ImageReader.read("example.#{ext}") end
  57. 57. 3/20/2014 Affordances http://localhost:9090/onepage 57/67 $ ruby subclasses.rb Reading BMP Reading JPG Reading PNG
  58. 58. 3/20/2014 Affordances http://localhost:9090/onepage 58/67 Takeaways
  59. 59. 3/20/2014 Affordances http://localhost:9090/onepage 59/67 Languages afford certain designs and inhibit others
  60. 60. 3/20/2014 Affordances http://localhost:9090/onepage 60/67 Languages influence thought
  61. 61. 3/20/2014 Affordances http://localhost:9090/onepage 61/67 Learning new languages will increase your "solution space"
  62. 62. 3/20/2014 Affordances http://localhost:9090/onepage 62/67 Don't go too far
  63. 63. 3/20/2014 Affordances http://localhost:9090/onepage 63/67 Want More? http://randycoulman.com/blog/categories/affordances/
  64. 64. 3/20/2014 Affordances http://localhost:9090/onepage 64/67 Acknowledgements Key Technology (http://www.key.net/) Rogue.rb (@roguerb) Jen Myers (@antiheroine)
  65. 65. 3/20/2014 Affordances http://localhost:9090/onepage 65/67 References The Design of Every Day Things ­ Donald Norman Coding Out Loud ­ Amir Rajan Linguistic Relativity ­ Wikipedia article When Code Cries ­ Cory Foy at SCNA 2012 The Power and Philosophy of Ruby ­ Matz at OSCON 2003
  66. 66. 3/20/2014 Affordances http://localhost:9090/onepage 66/67 Questions?
  67. 67. 3/20/2014 Affordances http://localhost:9090/onepage 67/67 Randy Coulman http://speakerrate.com/randycoulman http://www.slideshare.net/randycoulman http://randycoulman.com  @randycoulman  randycoulman

×