Adaptive Code via C#: Agile coding with design patterns and SOLID principles (Developer Reference) by Gary McLean Hall

October 19, 2014
Publisher: Microsoft Press
ISBN: 978-0735683204

From the Amazon website:

As every developer knows, requirements are subject to change. But when you build adaptability into your code, you can respond to change more easily and avoid disruptive rework. Focusing on Agile programming, this book describes the best practices, principles, and patterns that enable you to create flexible, adaptive code--and deliver better business value.

Expert guidance to bridge the gap between theory and practice:

  • Get grounded in Scrum: artifacts, roles, metrics, phases
  • Organize and manage architectural dependencies
  • Review best practices for patterns and anti-patterns
  • Master SOLID principles: single-responsibility, open/closed, Liskov substitution
  • Manage the versatility of interfaces for adaptive code
  • Perform unit testing and refactoring in tandem
  • See how delegation and abstraction impact code adaptability
  • Learn best ways to implement dependency interjection
  • Apply what you learn to a pragmatic, agile coding project
  • Get code samples at: http://github.com/garymclean/AdaptiveCode (VS 2013; unit tests use MSTest and NUnit)

Notes

This book is about the ability of code to adapt to new requirements while avoiding significant rework. It covers the Agile project management methodology known as Scrum. The Agile processes embrace change as a part of the contract between client and developer.

Part I: Interfaces (Mixins, duck-typing, and interface fluency), design patterns, anti-patterns (e.g., the Entourage anti-pattern), aspect-oriented programming, asymmetric layering, refactoring, and unit testing (fluent assertions, test-driven development, mocking).

Part II: Examining principles of SOLID:

  • S - Single responsibility principle: "A class should have only one responsibility". Decorator and Adapter patterns.
  • O - Open/closed principle: "An object should be open for extension but closed for modification". Identifying extension points for further adaptability. 
  • L - Liskov substitution principle: "A base type should be replaceable with subtypes in each and every situation". Contracts (preconditions, postconditions, data invariants), Code Contracts tooling, covariance, contravariance, invariance.
  • I - Interface segregation principle: "Use client-specific interfaces instead of one general interface. A user of an interface should not have to implement all kinds of methods that he doesn't use". 
  • D - Dependency inversion principle: "Depend upon abstractions such as an interface or an abstract class. This makes the code less coupled to the actual implementation". Inversion of Control containers, the Service Locator anti-pattern, composition roots and resolution roots.

Part III: Adaptive sample: an online chat application developed in ASP.NET MVC

  • Includes code samples
  • Maps to Scrum sprints
  • Uses a test-driven development

Scrum

  • Scrum is an iterative Agile project management methodology. "Agile" means that it embraces changes even as the project is in progress.
  • The iterations are called sprints. Each sprint lasts between one and four weeks. 
  • The product backlog is a prioritized queue of pending stories. 
  • The sprint backlog contains work the team commits to complete during a sprint.
  • The story is the unit of work.
  • After each sprint, a new version of the product is released.
  • The goal of Scrum is to refine the software product as well as the development process.
  • The sprint in progress is immutable i.e. its goals, acceptance criteria, or stories can't be changed. Any changes must wait until the next sprint.

Documentation in Scrum

  • The amount of documentation is minimized.
  • Agile methodologies consider working software as the most important document of a software product.
  • Wikis are common tools in Scrum teams.

Roles and responsibilities

  • Product Owner - owns the product ("what" needs to be done); provides the link between the client and the team; decides which features are built; sets the priority of the features in terms of business value (the priorities for the product backlog); accepts or rejects completed work; clarifies any confusions about the requirements.
  • Scrum Master - owns the process (the framework of "how" it is done); shields the team from any external distractions during the sprint; owns the daily Scrum meeting; the team informs everyone about the progress during the Scrum meetings.
  • Development Team - owns the code; an ideal Agile team consists of generalizing specialists.

Neither the product owner nor the scrum master can specify how the team should implement a story on a technical level. This is responsibility of the development team.

The Scrum board

  • A physical scrum board is a must.
  • The Scrum board shows the state of work currently in development.
  • Cards on the Scrum board represent the stories, tasks, defects, and technical dept of the current sprint.

The Scrum board cards 

  • Hierarchy of the cards: Product --> Release --> Feature --> Story --> Technical debt, Defect, Task
  • Product - The software product being built.
  • Release - A version of the software released to the end user.
  • Minimum viable release - The first release providing basic features.
  • Features - grouped into three categories: required, preferred, and desired
  • User stories - follow a template: "As a [user role], I want to [verb], so that [user value added]"
  • Tasks - Stories are broken down into tasks.
  • Defects - Created whenever acceptance criteria are not met on a previous complete user story. Defects can be divided into three categories: apocalyptic, behavioral, and cosmetic.
  • Swim-lanes - vertical lines containing multiple user story cards: Backlog, In Progress, QA, and Done.

Feature and story cards are verified by the product owner. Task, defect, and technical debt cards are in control of the development team.

User stories

User stories are written from the user perspective. They are a starting point for obtaining user requirements during the analysis phase. This analysis produces acceptance criteria. After user requirements are gathered, the development team creates a design using user interface mockups and UML diagrams. Subsequently, the user story is broken into specific tasks and implemented. The final phase is quality assurance where the software is tested against acceptance criteria. When it is approved, the user story is complete.

The entire software development life cycle is performed for each user story:

  • Analysis - gathering user requirements.
  • Design
  • Implementation
  • Testing against the acceptance criteria

Technical debt

Technical debt reflects the design and architectural compromises. It's a tradeoff: Should we implement a suboptimal solution now and meet a deadline? -or- Should we spend the extra time now to improve the design, and possibly miss the deadline? In order to determine if the dept is justified, you can try to answer the following questions:

  • Are we accruing this technical debt for the correct reasons?
  • Are we aware of alternatives to avoid this technical debt?