Sustainable Agile Development

3,375 views
3,209 views

Published on

Published in: Technology

Sustainable Agile Development

  1. 1. Sustainable Agile Development a case study with chess gabriele.lana@gmail.com federico.galassi@gmail.com
  2. 2. We have an Idea
  3. 3. We want to make it work
  4. 4. We know that Agile works in a corporate world
  5. 5. Can Agile work for us/you too?
  6. 6. Eric Ries: “a startup is a human institution designed to deliver a new product or service under conditions of extreme uncertainty”
  7. 7. Traditional Product Development (Progress: Advance To Next Stage) Solution: Known Requirements Design Implementation Verification Manteinance Problem: Known Eric Ries @ http://startuplessonslearned.blogspot.com/
  8. 8. Agile Development (Progress: Running Tested Features) Solution: Unknown quot;Product Ownerquot; or in-house customer Problem: Known Eric Ries @ http://startuplessonslearned.blogspot.com/
  9. 9. we should be able to Embrace Change Cost of Change Traditional Development Agile Development Time
  10. 10. we should be able to Embrace Change • Refactoring • Simple Design • Test-Driven Development • Continuous Integration • Collective Code Ownership • Incremental Design • Emergent Design • Pair Programming • Project Automation • Definition of Done • Exploratory Testing
  11. 11. We know how to do it, But...
  12. 12. Do you really know what customers want?
  13. 13. Do you really think customers know what they need?
  14. 14. Do you think implementing features is real progress?
  15. 15. Use of Requested Features 7% 13% 45% 16% 19% The biggest source of waste is implementation of features nobody wants Standish Group, CHAOS Report 2006
  16. 16. They could even hate some “features”
  17. 17. Steve Blank: “software development is a discovery and a learning process”
  18. 18. Lean Startup Development (Progress:Validated Learning about Customers) Customer Development Solution: Unknown Problem: Unknown Eric Ries @ http://startuplessonslearned.blogspot.com/
  19. 19. Agile in a Waterfall world Agile Test Maintenance Concept Development Alpha/Beta and Marketing Debug, Fix and Patch
  20. 20. Agile in a Waterfall world Agile Test Maintenance Concept Development Alpha/Beta and Marketing Debug, Fix and Patch
  21. 21. Agile in a Waterfall world Agile Test Maintenance Concept Development Alpha/Beta and Marketing Debug, Fix and Patch
  22. 22. Lean Startup Development (Progress:Validated Learning about Customers) IDEAS • Reduce the LEARN BUILD cycle time Minimum • Eliminate waste Marketable Feature • Optimize the DATA CODE whole • Amplify learning MEASURE Eric Ries @ http://startuplessonslearned.blogspot.com/
  23. 23. How can we support the learning process?
  24. 24. Domain Composability: the Domain Model should be extremely flexible and “exposed”
  25. 25. web applications Information Flow RDB HTTP OOP MS
  26. 26. Impedance Mismatch can slow you down RDB HTTP OOP MS Accidental Complexity
  27. 27. Resource Oriented Architectures HTTP ROA DATA Essential Complexity
  28. 28. Resource Oriented Architectures Identify Resources in your Domain
  29. 29. Resource Oriented Architectures Pawn Move Bishop Game Player Rank Board Rook File Knight Position Queen Square
  30. 30. Resource Oriented Architectures Design the URIs (Ubiquitous Language)
  31. 31. Resource Oriented Architectures GET /position/wqd3,wkd2,bke8 HTTP/1.1 Accept: text/plain HTTP/1.1 200 OK Content-Type: text/plain;format=fen n 5k2/8/8/8/8/3Q4/8/3K4
  32. 32. Resource Oriented Architectures GET /position/wqd3,wkd2,bke8 HTTP/1.1 Accept: image/png;q=0.8, text/plain;q=0.2 HTTP/1.1 200 OK Content-Type: image/png n PNG...
  33. 33. Resource Oriented Architectures GET /board/4815162342 HTTP/1.1 HTTP/1.1 200 OK n ... /position/wqd3,wkd1,bke7 /position/wqd3,wkd1,bke8
  34. 34. Resource Oriented Architectures POST /board/4815162342 HTTP/1.1 n move = d3-e8 HTTP/1.1 201 Created n ... /position/wqd3,wkd1,bke8 /position/wqe8,wkd1,bke8
  35. 35. Resource Oriented Architectures GET /game/42 HTTP/1.1 HTTP/1.1 200 OK n board = /board/4815162342 white = /player/50298 black = /player/48192
  36. 36. Resource Oriented Architectures no Web Services but how the web should be
  37. 37. Resource Oriented Architectures Tim Berners-Lee on Linked Data “... almost 20 years ago I wanted to reframe the way we use informations ... I invented the Word Wide Web ... now is time for a new reframing...” Tim Berners-Lee @ http://linkeddata.org
  38. 38. Resource Oriented Architectures for each Resource design the Representations from and to the Client
  39. 39. Resource Oriented Architectures GET /game/42 HTTP/1.1 Accept: application/xhtml+xml <html> ... <a rel=”owner” href=”/player/1001”>...</a> ... <ul class=”moves”> <li><image src=”/position/initial.png”/></li> </ul> </html>
  40. 40. now we have a Good Domain but an Ugly Interface
  41. 41. Ajax to rescue // Interface can have its state // but actually consumes many serverside // resources in background var game = { quot;gamequot;: quot;/game/42quot;, quot;boardquot;: quot;/board/4815162342quot;, quot;positionquot;: quot;/position/” + “rnbqkbnr-pppp1ppp-8-4p3-4P3-8-PPPP1PPP-RNBQKBNRquot; } var req = YAHOO.util.Connect.asyncRequest; req('GET', position + '/piece/g1/moves', callback); // 200 OK; moves = g1-e2, g1-f3, g1-h3 board.highlightSquares(quot;g1quot;, quot;e2quot;, quot;f3quot;, quot;h3quot;); req('POST', '/board/4815162342', callback, quot;move=g1-f3quot;); // 200 OK; position = // rnbqkbnr-pppp1ppp-8-4p3-4P3-5N2-PPPP1PPP-RNBQKB1R
  42. 42. John Maeda’s Laws of Simplicity Law 3: TIME Savings in time feels like simplicity. ...ok, we need real-time John Maeda @ http://lawsofsimplicity.com
  43. 43. Comet to rescue • “Reverse Ajax” • Push over Pull • Long-lived HTTP
  44. 44. But which Comet way? Transport API Long polling Socket Forever Frame Publish/Subscribe Script tags API based WebSockets Data sync Htmlfile REST? Mime Messaging Flash Remoting Joe Walker @ http://www.slideshare.net/joewalker/comet-and-the-rise-of-highly-interactive-websites-presentation
  45. 45. HTTP Channels is RESTful Comet “The primary purpose of HTTP Channels Kris Zyp: is to provide an application-level Comet protocol for live data synchronization that leverages the widely understood semantics and vocabulary of HTTP/REST.” Kris Zyp @ http://cometdaily.com/2008/06/05/intended-usage-of-http-channels/
  46. 46. Http Channels 2 POST /channels HTTP/1.1 Accept: application/http X-Create-Client-Id: 123123 GET /foo HTTP/1.1 Accept: */* X-Subscribe: * X-Client-Id: 123123 PUT /foo HTTP/1.1 n { data: “foobar” } HTTP/1.1 200 OK X-Event: PUT Content-Location: /foo  n { data: quot;foobarquot; } Kris Zyp @ http://cometdaily.com/2008/05/13/http-channels-2/
  47. 47. Http Channels 3 X-Client-Id: 123123 POST /board/4815162342 HTTP/1.1 n move = g1-f3 HTTP/1.1 200 OK X-Event: POST Content-Location: /board/4815162342  n move = g1-f3 X-Client-Id: 124124 X-Client-Id: 125125 X-Client-Id: 126126
  48. 48. How can we speed up the learning process?
  49. 49. Continuous Deployment reduces the time from code check-in to production
  50. 50. Continuous Deployment Testability tells if it’s a good change or a bad change as quickly as possible
  51. 51. Continuous Deployment (testability) View Model Control HTTP
  52. 52. Continuous Deployment (testability) too much code untested View Model Control HTTP
  53. 53. Continuous Deployment (testability) too fragile and unreliable View Model Control HTTP
  54. 54. Continuous Deployment (testability) Ruby with Rspec and Cucumber Player Board Position Game Move Js HTTP
  55. 55. Continuous Deployment (testability) Feature: change the position on board Scenario: change position with a correct move Given board with position wqd3,wkd1,bke8 When move to position wqd8,wkd1,bke8 Then response should be 201 And board should be in position wqd8,wkd1,bke8 Scenario: change position with a correct move Given board with position wqd3,wkd1,bke8 When move to position wqd7,wkd1,bke8 Then response should be 403 And board should be in position wqd3,wkd1,bke8
  56. 56. Continuous Deployment (testability) Scenario: change position with a correct move Given board with position wqd3,wkd1,bke8 When move to position wqd8,wkd1,bke8 Then response should be 201 And board should be in position wqd8,wkd1,bke8 Given /^board with position (.+?)$/ do | from_position | response = @client.post(quot;/boardquot;, quot;position = #{from_position}quot;) response.status.should == 201 @board = response.header[quot;Locationquot;] end
  57. 57. Continuous Deployment (testability) Scenario: change position with a correct move Given board with position wqd3,wkd1,bke8 When move to position wqd8,wkd1,bke8 Then response should be 201 And board should be in position wqd8,wkd1,bke8 When /^move to position (.+?)$/ do | to_position | move_reponse = @client.post(@board, quot;position = #{to_position}quot;) @move_response_status = move_response.status end
  58. 58. Continuous Deployment (testability) Scenario: change position with a correct move Given board with position wqd3,wkd1,bke8 When move to position wqd8,wkd1,bke8 Then response should be 201 And board should be in position wqd8,wkd1,bke8 Then /^response should be (d{3})$/ do | expected_response_status | @move_response_status.should == expected_response_status end
  59. 59. Continuous Deployment (testability) Scenario: change position with a correct move Given board with position wqd3,wkd1,bke8 When move to position wqd8,wkd1,bke8 Then response should be 201 And board should be in position wqd8,wkd1,bke8 Then /^board should be in position (.+?)$/ do | expected_position | current_position = @client.get(quot;#{@board}/positionquot;) current_position.content.should == expected_position end
  60. 60. Continuous Deployment (testability) Feature: change the position on board Scenario: change position with a correct move Given board with position wqd3,wkd1,bke8 When move to position wqd8,wkd1,bke8 Then response should be 201 And board should be in position wqd8,wkd1,bke8 Scenario: change position with a correct move Given board with position wqd3,wkd1,bke8 When move to position wqd7,wkd1,bke8 Then response should be 403 And board should be in position wqd3,wkd1,bke8
  61. 61. Continuous Deployment (testability) coder@apollo ~/dev/cucumber/features $ cucumber change_position_on_board.feature Feature: change the position on board Scenario: change position with a correct move # change_position_on_board.feature:3 Given board with position wqd3,wkd1,bke8 # step_definitions/change_position_on_board_steps.rb:5 When move to position wqd8,wkd1,bke8 # step_definitions/change_position_on_board_steps.rb:9 Then response should be 201 # step_definitions/change_position_on_board_steps.rb:14 And board should be in position wqd8,wkd1,bke8 # step_definitions/change_position_on_board_steps.rb:19 Scenario: change position with a correct move # change_position_on_board.feature:9 Given board with position wqd3,wkd1,bke8 # step_definitions/change_position_on_board_steps.rb:5 When move to position wqd7,wkd1,bke8 # step_definitions/change_position_on_board_steps.rb:9 Then response should be 403 # step_definitions/change_position_on_board_steps.rb:14 And board should be in position wqd3,wkd1,bke8 # step_definitions/change_position_on_board_steps.rb:19 2 scenarios (2 passed) 8 steps (8 passed)
  62. 62. Continuous Deployment (testability) what about the view? Player Board Position Game Move Js HTTP
  63. 63. Continuous Deployment (testability) If i click to drag a piece, does the board highlight reachable squares?
  64. 64. Continuous Deployment (testability) We don’t care of Position on board Model is already is context (fixture) tested (mock) // fixture // mock var piece_square = quot;g1quot; var valid_moves_url = quot;/position/quot; + position + var position = quot;/piece/quot; + piece_square + quot;rnbqkbnr-pppp1ppp-8-4p3-4p3-8-PPPP1PPP-RNBQKBNRquot; quot;/movesquot; var YAHOO.util.Connection.asyncRequest = Chess.test.ServerMock([{ method: quot;GETquot;, url: valid_moves_url, response: { code: 200 body: quot;moves = g1-e2, g1-f3, g1-h3quot; } }])
  65. 65. Continuous Deployment (testability) new YAHOO.tool.TestCase({ name : quot;testMovequot;, setUp: function() { this.board = Chess.board(); this.board.setupPosition(position); this.board.render(quot;mydivquot;); }, tearDown: function() { this.board.destroy(); } test_highlightReachableSquares: function() { var whiteKnight = this.board.pieceElementAt(piece_square); YAHOO.util.UserAction.mousedown(whiteKnight); this.wait(function(){ // for each g1, e2, f3, h3 YAHOO.util.Assert.isTrue( YAHOO.util.Dom.hasClass( this.board.squareElementAt(quot;g1quot;), quot;highlightquot; ); ); }, 500); } }
  66. 66. Erlang the secret weapon
  67. 67. Continuous Deployment (testability) no assignment but Pattern Matching 1> X. * 1: variable 'X' is unbound 2> X = 5. 5 3> X. 5 4> X = 6. ** exception error: no match of right hand side value 6
  68. 68. Continuous Deployment (testability) Referentially Transparent: if a function can be replaced with its value without changing the program
  69. 69. Continuous Deployment (testability) the function behavior is defined purely in terms of its input parameters and return value.
  70. 70. Continuous Deployment (testability) no Las Vegas effect!
  71. 71. Continuous Deployment (scalability) processes in Erlang are very cheap 1> processes:profileSpawnFor(1000). Spawned 1000 processes in 10 (4) milliseconds ok 2> processes:profileSpawnFor(10000). Spawned 10000 processes in 96 (40) milliseconds ok 3> processes:profileSpawnFor(100000). Spawned 100000 processes in 884 (510) milliseconds ok
  72. 72. Continuous Deployment (scalability) profileSpawnFor(Number) -> Processes = for(1, Number, fun() -> spawn(fun() -> wait() end) end), lists:foreach(fun(Pid) -> Pid ! die end, Processes). wait() -> receive die -> void end.
  73. 73. Continuous Deployment (scalability) factorials(Numbers) -> map(fun(Number) -> factorial(Number) end, Numbers).
  74. 74. Continuous Deployment (scalability) factorials(Numbers) -> map(fun(Number) -> factorial(Number) end, Numbers). factorials(Numbers) -> pmap(fun(Number) -> Distributed on factorial(Number) 20 different processes end, Numbers, 20).
  75. 75. Continuous Deployment (scalability) factorials(Numbers) -> map(fun(Number) -> factorial(Number) end, Numbers). Distributed on 20 different processes for factorials(Numbers) -> each available nodes on the cluster pmap(fun(Number) -> factorial(Number) end, Numbers, 20, nodes()).
  76. 76. Continuous Deployment (hot-swap) player:authorize(Request, Context). code to update 1> c(“/home/coder/upload/player.erl”). compile 2> code:load_file(player). and load player:authorize(Request, Context). code updated without down-time
  77. 77. Continuous Deployment (hot-swap) deploy(File) -> { ok, Module, Binary } = compile:file(File), foreach(fun(Node) -> rpc:call(Node, code, load_binary, [ Module, File, Binary ] ) end, nodes()). compile and deploy on every node in the cluster
  78. 78. Conclusion
  79. 79. We want to create products that really satisfy our customers
  80. 80. ... so we need a product development methodology
  81. 81. ... so we need a product implementation methodology
  82. 82. ... so we need appropriate technologies and practices
  83. 83. We better get ready because...
  84. 84. at the end of the day customer’s happiness is the only thing that matters

×