Agile Software Development: Principles, Patterns, and Practices

  1. Agile Practices
    • Individuals and interactions over process and tools
      • working well with others, communicating, and interacting is more important than raw programming talent
      • tools can be overemphasized, start small until you outgrow it
    • Working software over comprehensive documentation
      • software without documentation is a disaster, but too much is worse than too little
      • maintain a rationale and structure document, but should be short and salient
      • the code and team members are best at transferring information
      • Martin’s first law of documentation: Produce no documentation unless its need is immediate and significant
    • Customer collaboration over contract negotiation
      • developers shouldn’t go off on their own and disappear
      • successful projects involve customer feedback on a regular and frequent basis
      • requirements constantly change, best contracts are those that govern the way teams and customers work together
    • Responding to change over following a plan
      • ability to respond to change often determines success or failure
      • business environments change
      • customers change requirements
      • long-term planning charts will degrade
      • make detailed plans for the next two weeks, keep remaining plans flexible
    • Principles
      • Our highest priority is to satisfy the customer through early and continuous delivery of valuable software
      • Welcome changing requirements, even late in development
      • Deliver working software frequently
      • business people and developers must daily throughout the project
      • build projects around motivated individuals
      • the most efficient method of conveying information within a development team is face-to-face
      • working software is the primary measure of progress
      • agile processes promote sustainable development
      • continuous attention to technical excellence and good design enhances agility
      • simplicity– the art of maximizing the amount of work not done– is essential
      • the best architectures, requirements, and designs emerge from self-organizing teams
      • at regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly
  2. Overview of Extreme Programming
    • customer team member
      • person or group who defines and prioritizes features
    • user stories
      • know enough about requirements to make estimates
      • specific details likely to change so likely a waste of effort to capture
    • short cycles
      • XP project delivers working software every two weeks
      • Iteration is two weeks made up of a collection stories
      • customers do not change iteration once iteration has started
      • a release is usually three months of work
    • acceptance tests
      • details about the user stories are captured in the form of acceptance tests by the customer
      • once it passes, added to body of acceptance tests and never allowed to fail again
    • pair programming
      • all production code is written by a pair of programmers
      • pair membership changes at least once a day
      • good for increasing the spread of knowledge
      • studies show it does not reduce the efficiency, yet significantly reduces the defect rate
    • test-driven development
      • all production code is written to make a failing unit test pass
      • facilitate refactoring
      • drives decoupling modules
    • continuous integration
      • check in code and integrate several times per day
      • use non-blocking source control
    • sustainable pace
      • software projects are a marathon
      • the team is not allowed to work overtime, with the only exception being in the last week of a release
    • open workspace
      • working in a “war room” environment may increase productivity by a factor of two
    • the planning game
      • the essence of planning is the division of responsibility between business and development
      • business people decide how important a feature is
      • developers decide how much that feature will cost to implement
      • customers choose stories whose costs total up to but do not exceed the budget
    • simple design
      • an XP team makes their designs as simple and expressive as they can be
      • focus on stories that are planned for the current iteration, don’t worry about stories to come
      • get first batch of stories working in the simplest way possible
      • YAGNI: You Aren’t Going to Need It / only if you have proof or very compelling evidence
      • Once and Only Once: don’t tolerate code duplication
    • refactoring
      • code tends to rot
      • frequent refactorings
      • keeps code clean, simple and expressive as possible
    • metaphor
      • The big picture that ties together the whole system together
      • if a module’s shape is inconsistent with the metaphor, then you know the module is wrong
  3. Planning
    • initial exploration
      • identify all really significant user stories
      • stories that are too large should be split
      • stories that are too small should be merged
      • stories that are split or merged should be reestimated
    • release planning
      • given a velocity, customer can get an idea of the cost of each story
      • what to prioritize given cost is a business decision
    • iteration planning
      • typically two weeks
      • order of the stories within an iteration is a technical decision
      • the iteration ends on the specified date, even if stories aren’t done
      • the planned velocity for each iteration is the measured velocity of the previous iteration
    • task planning
      • developers break the stories down into tasks
      • no one signs up for more points than they have in their budgets
      • task selection continues until either all tasks are assigned or all developers have used their budget
      • if not enough room, developers ask customers to remove tasks or stories from iteration
      • at halfway point, half of the stories should be done, reassess and readjust
    • iterating
      • at the end of each two weeks, show customer the progress
      • they will provide their feedback and new user stories
      • customer see progress frequently and have all the data and control they need to manage the project to their liking
  4. Testing
    • test-driven testing
      • results in every function having a test
      • tells us when we inadvertently break some existing functionality
      • helps us view the program from the vantage point of the caller
      • immediately concerned with the interface
      • force the design to be more testable
      • forces us to decouple the software
      • write test the way you want it to read
      • writing tests before code improves our designs
    • acceptance testing
      • unit tests are necessary but insufficient
      • acceptance tests are written by people who do not know the internal mechanisms of the system
      • ultimate documentation of a feature
      • in order to make the system testable, it has to be decoupled at the high architectural level
      • avoid the temptation to do acceptance tests manually
      • deprives those early iterations of the decoupling pressure exerted by the need to automate the acceptance tests
    • conclusion
      • the simpler it is to run a suite of tests, the more often they will be run
      • if we can run tests several times a day, then the system will never be broken for more than a few minutes
      • verification is only one benefit
      • tests are a form of documentation
      • the most important benefit is the impact it has on architecture and design
  5. Refactoring
    • software has three functions 1) perform a function 2) afford change, 3) communicate to its readers
    • takes attention and discipline to make a module easy read and change
    • strongly recommend that you always practice refactoring for every module
    • clean your code everyday
  6. A Programming Episode
    • transcript of a pair programming session
    • not all applications need object-oriented design
  7. What Is Agile Design?
    • design of system primarily documented by source code
    • design smells– the odors of rotting software
      • rigidity: hard to change because every change forces many other changes to other parts of the system
      • fragility: changes cause the system to break in places that have no conceptual relationship to the part that was changed
      • immobility: It is hard to disentangle the system into components that can be reused in other systems
      • viscosity: doing things right is harder than doing things wrong
      • needless complexity: the design contains infrastructure that adds no direct benefit
      • needless repetition: the design contains repeating structures that could be unified under a single abstraction
      • opacity: It is hard to read and understand
    • designs degrade because requirements change in ways the initial design did not anticipate
    • agile teams don’t allow software to rot
    • requirements always change
    • agile developers does not apply principles and patterns to a big, up-front design, but from iteration to iteration
  8. SRP: The Single-Responsibility Principle
    • A class should only have one reason to change
    • separate responsibilities into different classes
    • e.g. business rules and persistence control should almost never be mixed
    • responsibility is “reason for change”
    • If the application is not changing in ways that cause two responsibilities to change, then there is no need to separate them
    • one of the simplest, but one of the hardest to get right
  9. OCP: The Open-Closed Principle
    • Software entities should be open for extension but closed for modification
    • Changes are achieved by adding new code, not by changing old code that already works
    • In C++, Java, etc possible to create abstractions with abstract base classes
    • abstract classes are more closely associated to their clients than to the classes that implement them
    • there will always be some kind of change against which it is not closed
    • the designer must choose the kinds of changes against which to close his design
    • to avoid needless complexity, write code expecting it not to change and when change occurs, implement abstraction that protects against that change
    • testing and quick development cycles stimulate change quicker
    • developers should apply abstraction only to those parts of the program that exhibit frequent changes
    • resisting premature abstraction is as important as abstraction itself
  10. LSP: The Liskov Substitution Principle
    • subtypes must be substitutable for their base types
    • substituting should not cause functionality to misbehave
    • the validity of model can only be expressed in terms of its clients
    • difficult to anticipate assumptions of users
    • often best to defer all but the most obvious LSP violations until the related fragility has been smelled
    • the is-a relationship pertains to behavior
    • design-by-contract: specify preconditions and post-conditions, which need to apply to derived classes
  11. DIP: The Dependency-Inversion Principle
    • high-level modules should not depend on low-level modules
    • both should depend on abstractions
    • abstractions should not depend on details
    • details should depend on abstractions
    • should not depend on concrete classes, unless the class is not going to change much
    • inversion of dependencies is the hallmark of good OO design
    • if its dependencies are not inverted, it has a procedural design
    • the principle of dependency inversion is the fundamental low-level mechanism behind many of the benefits claimed for OO technology
  12. ISP: The Interface-Segregation Principle
    • polluted interfaces are “fat”
    • ISP: clients should not be forced to depend on methods that they do not use
    • results in the inadvertent coupling between all clients
    • separation can be achieved through delegation (less elegant) or multiple inheritance
    • clients can often be grouped by the service methods they call
    • such groupings allow segregated interfaces
  13. Command and Active Object
    • command: an interface with one method e.g. do
    • e.g. sensor doesn’t need to know much
    • initialization can handle wiring
    • active object: active object engine maintains a linked list of commands
    • run commands walk through and executes each command
    • can do non-blocking multithreading
  14. Template Method & Strategy: Inheritance vs Delegation
    • overuse of inheritence very costly
    • “Favor object composition over class inheritance” GOF
    • template: put all generic code into an implemented method of an abstract base class
    • strategy: place generic code into a concrete class and it calls abstract methods of interface that is passed in
    • strategy allows details to be used independently of the high-level algorithm e.g. IntSortHandle
  15. Facade and Mediator
    • facade: provide a simple and specific interface onto a group of objects
    • e.g. ProductData hides java.sql from application
    • by convention all database calls must go through
    • mediator: imposes policy in a hidden and unconstrained way
    • e.g. showing a list based on text entry
    • if policy needs to be big and visible facade
    • if policy hidden from users, mediator
  16. Singleton and Monostate
    • singleton: only one instance of class
    • benefits:
      • cross platform using appropriate middleware
      • applicable to any class
      • can be created through derivation
      • lazy evaluation
    • cons:
      • destruction is undefined
      • not inherited
      • efficiency
      • nontransaparent
    • e.g. use to assure all database access will be through a single instance
    • monostate: two instances behave as if they were one
    • objects share the same static variables
    • benefits
      • transparency: users do not know object is monostate
      • derivability
      • polymorphism: methods can be overridden in derivatives
      • well-defined creation and destruction
    • cons
      • no conversion: normal class cannot become a monostate
      • efficiency
      • presence
      • platform local
  17. Null Object
    • return object that does nothing when you call method
  18. The Payroll Case Study: Iteration One Begins
    • go over design
  19. The Payroll Case Study: Implementation
    • go over implementation
  20. Principles of Package Design
    • Granularity: The Principles of Package Cohesion
      • Reuse-Release Equivalence Principle (REP): The graunule of reuse is the graunle of release
      • reusability comes only after there is a tracking system that offer guarantees of notification, safety, and support
      • we want all of the classes in a package to be reusable
      • Common-Reuse Principle (CRP): classes in a package are reused together. If you reuse one, you reuse them all
      • Common-Closure Principle (CCP): classes in a package should be closed together against the same kind of changes.
      • A change that affects a package affects all the classes in that package and no other package
      • composition of packages will likely change over time
    • Stability: The Principles of Package Coupling
      • project breaking because of what someone else did
      • two solutions: weekly build and ADP
      • Acyclic-Dependencies Principle (ADP): Allow no cycles in the package-dependency graph
      • partition development environment into releasable packages
      • can break cycles with DIP or moving some classes to a new package
    • Top-Down Design
      • package structure cannot be designed top-down
      • map to the buildability of the application
    • The Stable-Dependencies Principle
      • Depend in the direction of stability
      • packages we expect to be volatile should not be depended on by a package that is difficult to change
      • one sure way to make software difficult to change is to make lots of other software packages depend on it
      • not all packages should be stable
      • putting high-level design into stable packages make them inflexible
      • use abstract classes to create classes that are flexible enough to be extended without requiring modification
    • The Stable-Abstractions Principle (SAP)
      • a package should be as abstract as it is stable
      • concrete classes inflexible because not abstract
      • if nonvolatile, concrete is ok e.g. string class
  21. Factory
    • DIP tells us we should prefer dependencies on abstract classes and avoid dependencies on concrete classes, especially when they are volatile
    • factory pattern allows us to create instances of concrete objects while depending on only abstract interfaces
    • e.g. instead of instantiating Circle or Square directly, the Application could rely on a ShapeFactory interface with ‘makeSquare’ and ‘makeCircle’ methods
    • one downside of this approach is each new shape requires new method
    • can sacrifices some type safety for flexiblity by allowing shape to be passed into a method as a string
    • recommend to not use factories starting out
    • only put them in when the need for them becomes great
  22. The Payroll Case Study (Part 2)
    • walk through case studies using covered patterns
  23. Composite
    • can have an instance that is really a proxy for a group of instances
    • only if you are going to treat the group of objects identically
  24. Observer–Backing into a Pattern
    • register objects with observers
    • pull-model: observer must pull information after being notified
    • push-model: notify method includes args with hints
    • allows you to add new observing objects without changing the observed object
    • allows observed object to be closed
  25. Abstract Server, Adapter, and Bridge
    • Imagine you have a “Switch” that can “turnOn” and “turnOff” a “Light”
    • You can’t create a “FanSwitch” subclass from “Switch” because it will depend on Light still
    • solve by creating a “Switchable” interface
    • Switch can control anything with “Switchable” interface
    • Interfaces belong to the client
    • logical binding is stronger
    • clients should be packaged together with the interfaces they control
    • adaptor: through inheritance and delegation, can adapt to the interface of the object
    • adaptor doesn’t come cheap, abstract server is appropriate for most situations
    • bridge pattern: helpful when type hierarchy has more than one degree of freedom
    • rather than combining hierarchies in tree structure, separate them and tie together with bridge
    • e.g. separating connection method from hardware in a modem
    • recommend to not use bridge unless compelling evidence
    • patterns always come with both a cost and benefit
  26. Proxy and Stairway to Heaven: Managing Third Party APIs
    • each object that is to be proxied is split into three parts
      • interface that declares all methods that clients need to invoke
      • class that implements those methods without knowledge of the database
      • a proxy that knows about the database
    • neither client nor the ProduceImplementation knows what happened
    • proxies are non-trivial
    • only may be worth it where the separation of business rules from database implementation is critically important
    • also could be useful for third party APIs
    • most applications don’t need proxies as they are heavy-weight
    • stairway to heaven: have an abstract class that knows about the database with abstract “read” and “write” methods
    • the base class also implements methods that help implement read and write
    • e.g. PersistentProduct inherits from Product and PersistentObject and implements “read” and “write”
    • requires multiple inheritance
    • other options for DB interactions
      • extension object: knows how to write the extended object on a database
      • visitor
      • decorator: decorate a business object and give it read and write or decorate a data object that knows how to read/write and give it business rules
      • facade: class provides methods for reading and writing
      • couples business rule objects with the database, but is probably the best starting point
  27. Case Study: Weather Station
    • go over design
  28. Visitor
    • allows new methods to be added to existing hierarchies without modifying the hierarchies
    • visitor is passed to “accept” function of class
    • appropriate class derivative will call visit on it
    • dual dispatch because involves two polymorphic dispatches
    • first is “accept” which resolves the type of the object that accepts is called upon
    • the second is “visit” which resolves to the particular function to be executed
    • visitor is like a matrix
    • visitor works well where the hierarchy to be modified does not need new derivatives
    • acyclic visitor is like sparse matrix using degenerate methods
    • decorator: create new class and delegate to contained instance
    • wrapping method can perform other actions before and/or after
  29. State
    • allow certain states
    • can track with nested switch/case statements
    • use transition tables if too hairy
    • provides strong separation between the actions and the logic of state machine
    • state machines can be useful in high-level application policies for GUIs or distributed systems
  30. The ETS Framework
    • go over case study of testing software strategy

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s