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.

On Growth and Software

369 views

Published on

Slides for my talk at nCrafts 2016 in Paris

Published in: Software
  • Be the first to comment

On Growth and Software

  1. 1. Carlo Pescio @CarloPescio http://physicsofsoftware.com Carlo Pescio On Growth and Software (or: applying some Physics of Software)
  2. 2. Carlo Pescio @CarloPescio http://physicsofsoftware.com Inspired by a classic
  3. 3. Carlo Pescio @CarloPescio http://physicsofsoftware.com Form as a Diagram of Forces
  4. 4. Carlo Pescio @CarloPescio http://physicsofsoftware.com Form as a Recipe for Reaction My own little step – don’t blame D’Arcy  Material and shape encode reactions to “forces”
  5. 5. Carlo Pescio @CarloPescio http://physicsofsoftware.com Form as a Recipe for Growth
  6. 6. Carlo Pescio @CarloPescio http://physicsofsoftware.com Good ol’ book + - U U
  7. 7. Carlo Pescio @CarloPescio http://physicsofsoftware.com The ring binder U D D U U C C
  8. 8. Carlo Pescio @CarloPescio http://physicsofsoftware.com Growth Model
  9. 9. Carlo Pescio @CarloPescio http://physicsofsoftware.com Growth Model
  10. 10. Carlo Pescio @CarloPescio http://physicsofsoftware.com [Mis]Aligned Growth Model (ideal) growth in decision space (actual) growth in artifact space
  11. 11. Carlo Pescio @CarloPescio http://physicsofsoftware.com “Growth” in computing Extensibility Scalability C/D features in code C/D run-time load Code as artifacts Run-time behavior C/D feature -> C/D load -> C/D artifact C/D machines / CPU
  12. 12. Carlo Pescio @CarloPescio http://physicsofsoftware.com
  13. 13. Carlo Pescio @CarloPescio http://physicsofsoftware.com Extensibility?
  14. 14. Carlo Pescio @CarloPescio http://physicsofsoftware.com Symmetry in Growth [model] Create feature Delete feature decision space Create artifacts Delete artifacts artifact space
  15. 15. Carlo Pescio @CarloPescio http://physicsofsoftware.com Why bother??? - Product families - Plug-in architectures, 3rd party modules - Modular understanding - “zero impact” evolution
  16. 16. Carlo Pescio @CarloPescio http://physicsofsoftware.com In practice? A simple, specific problem with a specific growth model. Lessons here apply to similar growth models. Not everything will / should follow this model. The final shape is not universal the method of investigation kinda is
  17. 17. Carlo Pescio @CarloPescio http://physicsofsoftware.com Easy
  18. 18. Carlo Pescio @CarloPescio http://physicsofsoftware.com Some physics required 
  19. 19. Carlo Pescio @CarloPescio http://physicsofsoftware.com Vector drawing for dummies
  20. 20. Carlo Pescio @CarloPescio http://physicsofsoftware.com Growth Model - New shape types will come over time - New behaviors will come over time - Behaviors can be composed out of a fixed core - That entire menu only requires {bounding box, move} I’m dealing only with geometry right now
  21. 21. Carlo Pescio @CarloPescio http://physicsofsoftware.com Context We have an open, discrete set of “concepts” { Square, Triangle, Circle, … } It’s open and so will grow by addition. T3 T2 T1 + + T = { Ti }
  22. 22. Carlo Pescio @CarloPescio http://physicsofsoftware.com In code? How do we mirror in code? • N types: OK • N classes: OK • N objects / prototypes: OK • through closures / records of functions: ok as well • Case classes: Maybe • 1 sum type: NO + T = { Ti }
  23. 23. N trivial classes (Scala) class Point( var x : Float, var y : Float ) {} class Box( var topLeft : Point, var bottomRight : Point ) {} class Circle( var center : Point, var radius : Float ) {} class Square( var topLeft : Point, var side : Float ) {} +
  24. 24. 1 sum type (Haskell): nope type Point = (Float,Float) type Radius = Float type Side = Float data Shape = Circle Point Radius | Square Point Side + U
  25. 25. Carlo Pescio @CarloPescio http://physicsofsoftware.com Context We have a closed set of “core behaviors” { BoundingBox, Move, Scale, Rotate, Mirror } ^ H = { Hi }H
  26. 26. Carlo Pescio @CarloPescio http://physicsofsoftware.com Context “Core behaviors” depends on concepts. More precisely: when we create/delete a concept, we create/delete its implementation of core behaviors. ^ Ti C/D > HTi T3 T2 T1 + HT3 HT2 HT1 +
  27. 27. Carlo Pescio @CarloPescio http://physicsofsoftware.com In code? How do we mirror • Member functions (class, objects): ok • Functions (+ optional overloading): ok • 1 function per behavior + pattern matching: NO • That removes case classes from the table ^ Ti C/D > HTi
  28. 28. Case classes (Scala): nope abstract class Shape case class Circle(center:Point, radius:Float) extends Shape case class Square(topLeft:Point, side:Float) extends Shape + U object moveTool { def move( sh : Shape, newCenter : Point ) : Shape = { sh match { case Circle(center, radius) => new Circle( newCenter, radius); case Square( topLeft, side) => new Square(Point(topLeft.x-side/2, topLeft.y-side/2), side); } } }
  29. 29. Carlo Pescio @CarloPescio http://physicsofsoftware.com Context We can: a) create instances of those concepts and keep them available for selection b) select some of those instances (mixed concepts) from a bounding box c) apply composite behaviors to those (mixed) instances
  30. 30. Carlo Pescio @CarloPescio http://physicsofsoftware.com Context a) We want to create instances and keep them “available” for selection In code: • A single collection: OK • A collection for each type: OK A collection for each type is ok, as we still transfer creation (of concept) into creation (of a new list).
  31. 31. Carlo Pescio @CarloPescio http://physicsofsoftware.com Context b) We want to select a (mixed) subset by dragging a selection box. So we need a selection function looping over all the available shapes and checking their bounding boxes (BB is a “core behavior” for shapes).
  32. 32. Carlo Pescio @CarloPescio http://physicsofsoftware.com selection box f selection 1 collection per type won’t work anymore + + U Same reasoning applies to any of the composite behaviors shapes selected shapes
  33. 33. Carlo Pescio @CarloPescio http://physicsofsoftware.com Context We have an open set of “composite behaviors” + B = { Bi } e.g. { align left, distribute horizontally, flip vertical} They operate on collections of concepts (instances). ^ Bi ≡ ·(H)
  34. 34. Carlo Pescio @CarloPescio http://physicsofsoftware.com Context + T = { Ti } * + B = { Bi } ^ + (HTi) · C/D Two problems with Bi here: 1) Works on a set of shapes (same as selection) 2) Composed from a set of type-dependent core behaviors (same as selection w/ BB)
  35. 35. Carlo Pescio @CarloPescio http://physicsofsoftware.com A single collection of shapes That would require either: • A dynamic language • mixing types is natural • A way to form a placeholder type as substitute for the individual types: • Base type + subtypes • Base class / interface + derived classes • [objects as] Records of closures • Existential types / Abstract types
  36. 36. Carlo Pescio @CarloPescio http://physicsofsoftware.com Classes in Scala (easy) abstract class Shape { def explain() : String; def boundingBox() : Box; def moveCenter(newCenter:Point) : Shape; }
  37. 37. Classes in Scala (easy) class Circle(private var center: Point, private var radius: Float) extends Shape { def explain(): String = { "circle " + center.x + " " + center.y + " " + radius; } def boundingBox(): Box = { new Box( Point(center.x-radius, center.y-radius), Point(center.x+radius, center.y+radius) ); } def moveCenter(newCenter: Point): Shape = { new Circle(newCenter, radius); } }
  38. 38. Classes in Scala (easy) class Square(private var topLeft: Point, private var side: Float) extends Shape { def explain(): String = { "square " + topLeft.x + " " + topLeft.y + " " + side; } def boundingBox(): Box = { new Box( topLeft, Point(topLeft.x+side, topLeft.y+side)); } def moveCenter(newCenter: Point): Shape = { new Square(Point(topLeft.x-side/2, topLeft.y-side/2), side); } }
  39. 39. Classes in Scala (easy) object MainObject { def main(args: Array[String]): Unit = { val c1 = new Circle( Point(1,1), 4 ) ; val s1 = new Square( Point(0,0), 4 ) ; val sh : List[Shape] = List( c1, s1 ); var d : String = sh.map( s => s.moveCenter(Point(5,5)).explain() ).reduce((s1,s2) => s1 + " ; " + s2) ; println( d ) ; } }
  40. 40. Records of Closures (Haskell) type Point = (Float,Float) type Box = (Point,Point) data Shape = Shape { explain :: String, boundingBox :: Box, moveCenter :: Point -> Shape }
  41. 41. Records of Closures (Haskell) circle :: Point -> Float -> Shape circle (x,y) r = Shape explain boundingBox moveCenter where explain = "circle " ++ show x ++ " " ++ show y ++ " " ++ show r boundingBox = ( (x-r, y-r), (x+r, y+r) ) moveCenter (x1,y1) = circle (x1, y1) r
  42. 42. Records of Closures (Haskell) square :: Point -> Float -> Shape square (t,l) s = Shape explain boundingBox moveCenter where explain = "square " ++ show t ++ " " ++ show l ++ " " ++ show s boundingBox = ( (t, l), (t+s, l+s) ) moveCenter (x1,y1) = square (x1-s/2, y1-s/2) s
  43. 43. Carlo Pescio @CarloPescio http://physicsofsoftware.com Records of Closures (Haskell) main = do let c1 = circle (1,1) 3 let s1 = square (1,1) 3 let sh = [ c1, s1 ] putStrLn (concat ( map (s -> (explain (moveCenter s (5,5))) ++ " ; ") sh ) )
  44. 44. Existential type (Haskell) type Point = (Float,Float) type Box = (Point,Point) class ShapeTC a where explain :: a -> String boundingBox :: a -> Box moveCenter :: a -> Point -> Shape data Shape = forall a. ShapeTC a => Shape a instance ShapeTC Shape where explain (Shape shape) = explain shape boundingBox (Shape shape) = boundingBox shape moveCenter (Shape shape) = moveCenter shape
  45. 45. Existential type (Haskell) data Circle = Circle Point Float instance ShapeTC Circle where explain (Circle (x,y) r ) = "circle " ++ show x ++ " " ++ show y ++ " " ++ show r boundingBox (Circle (x,y) r) = ( (x-r, y-r), (x+r, y+r) ) moveCenter (Circle (x,y) r) (x1,y1) = circle (x1, y1) r circle :: Point -> Float -> Shape circle (x,y) r = Shape (Circle (x,y) r)
  46. 46. Existential type (Haskell) data Square = Square Point Float instance ShapeTC Square where explain (Square (t,l) s) = "square " ++ show t ++ " " ++ show l ++ " " ++ show s boundingBox (Square (t,l) s) = ( (t, l), (t+s, l+s) ) moveCenter (Square (t,l) s) (x1,y1) = square (x1-s/2, y1-s/2) s square :: Point -> Float -> Shape square (t,l) s = Shape (Square (t,l) s)
  47. 47. Existential type (Haskell) main = do let c1 = circle (2,2) 3 let s1 = square (2,2) 3 let sh = [ c1, s1 ] putStrLn (concat ( map (s -> (explain (moveCenter s (6,6))) ++ " ; ") sh ) )
  48. 48. “misaligned” growth model B3 B2 B1 + T3 T2 T1 + HT3 HT2 HT1 + UU
  49. 49. (madness) B3 B2 B1 + T3 T2 T1 + HT3 HT2 HT1 +
  50. 50. OK  H B3 B2 B1 + T T3 T2 T1 + HT3 HT2 HT1 +
  51. 51. Carlo Pescio @CarloPescio http://physicsofsoftware.com Work in progress ^ Ha = { Hi } + T = { Ti } * + B = { Bi } ^ + HTi · C/D ^ Ta + T = { Ti } * + B = { Bi } ^ + (HTi) · C/D
  52. 52. Carlo Pescio @CarloPescio http://physicsofsoftware.com Every type has identity (to keep it simple: name) F knows identities in => F unstable So: - F should not know identities in - F needs to operate on values of those types. => F must be isolated from type identity. Identity and Isolation + T + T
  53. 53. Carlo Pescio @CarloPescio http://physicsofsoftware.com Common techniques for isolation: - Add a new “abstract type” Ta, make every Ti an instance or subtype of Ta - Requires late binding as F will only know Ta - Relationship between Ti and Ta can be implicit (structural conformance) - Add a new concrete type Tc exposing only functions, and bind every instance of Ti to an instance of Tc - That’s again providing late binding as F won’t know the identity of the functions it’s calling Isolation Techniques
  54. 54. Carlo Pescio @CarloPescio http://physicsofsoftware.com structures vs paradigms
  55. 55. Carlo Pescio @CarloPescio http://physicsofsoftware.com OO SUCKS!
  56. 56. Carlo Pescio @CarloPescio http://physicsofsoftware.com Get your trick question ready 1. The next time someone shows you a decent use for OO-like polymorphism & encapsulation, what can you say? what about serialization in multiple formats?
  57. 57. Carlo Pescio @CarloPescio http://physicsofsoftware.com Remember this?
  58. 58. Carlo Pescio @CarloPescio http://physicsofsoftware.com Elastic yet bent !?
  59. 59. Carlo Pescio @CarloPescio http://physicsofsoftware.com We only have geometry so far I want rendering (new core behaviors!) I may want only geometry I may want only rendering I may want both => Geometry and Rendering in distinct artifacts Breaking the growth model
  60. 60. Carlo Pescio @CarloPescio http://physicsofsoftware.com Growing and Breaking
  61. 61. partial class Circle { private readonly Point center; private readonly double radius; public Circle( Point center, double radius ) { this.center = center; this.radius = radius; } } interface Shape { Shape Move(Point newCenter); } partial class Circle : Shape { public Shape Move(Point newCenter) { return new Circle(newCenter, radius); } } interface Drawing { void Render(); } partial class Circle : Drawing { public void Render() { Console.WriteLine( "I'm a Circle with radius " + radius.ToString()); } } static void Main(string[] args) { Shape c = new Circle(new Point(10, 10), 5); Drawing d = c as Drawing; d.Render(); } constraint Shape => Drawing
  62. 62. Carlo Pescio @CarloPescio http://physicsofsoftware.com “Design Process” I didn’t use - Design principles - Patterns - Tests - Religion I only aimed for symmetry - Features growth model - Artifacts growth model Break a symmetry to get a symmetry 
  63. 63. Carlo Pescio @CarloPescio http://physicsofsoftware.com …Monads  Or polymorphism Or existential types Or type system constraints Or many things yet to be invented Just by understanding forces  You may have invented…
  64. 64. Carlo Pescio @CarloPescio http://physicsofsoftware.com Get in touch @CarloPescio carlo.pescio@gmail.com http://physicsofsoftware.com /forum

×