Agile Methodology

Methodology – a set of methods, rules, or ideas that are important in a science or art: a particular procedure or set of procedures (Ref: merriam-webster). So, let’s step back a little, Agile is not a mere methodology but a new paradigm a mindset. It is an alternate to orthodox project management practices which prescribed sequential execution like with waterfall. Agile advocates a response mechanism to unpredictable changes through progressive delivery and feedback cycles.

The sequential execution model was inspired by the manufacturing sector which evolved during early industrialization of the world. The approach was phased with predefined gates, moving from one phase to another only after fully completing the current phase. For seven years now software has also been developed in the fashion moving from envisioning, planning, design, development, testing and release to production with clear gate checks at each phase entry & exit. This approach adored several inherent challenges including longer delivery time, rework identification late in the life cycle, money spent on unproductive activities, and lack of effective communication across teams due to compartmentalization.

Agile provides an opportunity to address these limitations through short iterative delivery cycles with endorsed work items at the end of each cycle.  The delivery cycles are iterations of 2-4 weeks duration leading to delivery of potentially shippable product increments. This approach accentuates continuous revisit of every aspect of software development in each of the iteration resulting in enduring course corrections of the projects.

This ‘inspect-and-adapt’ approach exemplify the spirit of Agile resulting in reduced time-to-marked, cost to deliver and improved acceptance. Additionally, the active involvement of users through the delivery cycle creates much better business engagement and customer satisfaction and finally the agile teams are empowered through active involvement, cooperation and collaboration resulting in highly motivated, high performance teams.

Scrum is the most widely used Agile practice due to its simplicity and flexibility. Scrum is characterizes by small cross functional self-managed teams delivering evolving requirements in short durations which are well verified. However, organizations face several challenges while adapting Scrum due to their org structure and practices.

Scrum has three main roles: Product Owner, Team, and Scrum Master. The responsibilities of the traditional project manager role are split up among these three Scrum roles. Scrum has five meetings: Backlog Grooming (aka Backlog Refinement), Sprint Planning, Daily Scrum (aka 15-minute standup), the Sprint Review Meeting, and the Sprint Retrospective Meeting. A more difficult and principled approach to agility in a multi-team organization is called Large Scale Scrum.



Agile Project Life Cycle

Agile life cycle is an iterative and incremental development process comprising four phases to deliver Business
Value in an incremental time boxed cross-discipline iterations. The four phases are

  • Inception
  • Elaboration
  • Construction
  • Transition

Detailed descriptions of each phase


  • Establish a business case for the project – On request from Business Users ((IT Head)
  • Identify Program Manager, PO, Architect and TPM (IT Head)
  • Establish the project scope and conditions ((IT Head /Program Manager))
  • Outline the key requirements that will drive the design tradeoffs (IT Head /Program Manager)
  • Outline one or more candidate architectures (Architect/ Program Manager/PO)
  • Identify risks and resource needs (IT Head/Program Manager)


  • Project Charter – vision, goal, preliminary project schedule and cost estimate
  • Solution design
  • Identified Product Owner (PO), Solution Architect and Scrum Master (TPM)


  • Address known risk factors (IT Head)
  • Capture a healthy majority of system requirements (BRD) – Development of a Product Backlog list (BA’s)
  • System Conceptualization and analysis – Establish and validate system architecture (Architect)
  • Estimate Cost and Schedule (IT Head/PO/SM)
  • For each item on Product Backlog list (PO)
    • Division of items into Sprints (after Prioritizing)
    • Assessment of risk and mitigation strategies
  • Conduct a Project Kick-off Workshop with the Scrum Team – Share Project Vision, Goal, Release Plan, Requirements Elaboration,
    Technical Solution Elaboration (PO)
  • Conduct Sprint 0 – Grooming, Prioritizing, Sizing, Tasking and Estimating (upcoming 2 to 3 sprints) (Scrum Team)


  • Product Backlog (Well defined User Stories)
  • Stabilized system architecture – that supports the key system functionality and ensures the right behavior in terms of performance,
    scalability, usability etc
  • Release Plan
  • Scrum Team


  • Sprint Planning (Scrum Team)
  • User Stories/Product Backlog items are implemented (Coded and Tested) in ‘Sprints’ to result in an executable release of
    the software (Development Team)
  • Product backlog Grooming (Scrum Team)
  • Other Scrum Ceremonies – Daily Scrum, Review, Retrospective (Scrum Team)
  • Capture definite Metrics (Scrum Master/PO)


  • Sprint Plan (Commitment based/Capacity based/Velocity based)
  • Working Software
  • Metrics
  • Key Learnings and Continuous Improvement measures


  • Project Readiness to ‘Go live’ – System deployment to the target users – UAT/Production
  • Further Refinements
  • Standardization
  • E-Learning, User Training, Knowledge Transfers etc


  • Release Notes
  • Final Build
  • Documentation

Understanding Covariance & Contravariance

What is Covariance & Contravariance?

Covariance – Enables you to use a more derived type than originally specified.
You can assign an instance of IEnumerable<Derived> to a variable of type IEnumerable<Base>.

Covariant type parameters enable you to make assignments that look much like ordinary Polymorphism, as shown in the following code.

IEnumerable<Derived> d = new List<Derived>();
IEnumerable<Base> b = d;

Contravariance – Enables you to use a more generic (less derived) type than originally specified.
You can assign an instance of IEnumerable<Base> to a variable of type IEnumerable<Derived>.

Action<Base> b = (target) => {Console.WriteLine(target.GetType().Name);};
Action<Derived> d = b;
d(new Derived());

Invariance – Means that you can use only the type originally specified; so an invariant generic type parameter is neither covariant nor contravariant.

You cannot assign an instance of IEnumerable<Base> to a variable of type IEnumerable<Derived> or vice versa.


Arrays – Are covariant

Bear[] bears = new Bear[3];
Animal[] animals = bears; // OK

The downside of this reusability is that element assignments can fail at runtime:

animals[ 0 ] = new Camel(); // Runtime error

Delegates – Allows for methods to have less specific input parameters (covariance) and more specific return types (contravariance)

Covariance – Parameter Compatibility

  • A method target can define a parameter that is more generic than described by the delegate OR
  • A delegate can have more specific parameter types than its methods target
delegate void StringAction (string s);

static void Main ()
   StringAction sa = new StringAction (ActOnObject);
   sa ( "hello" );
static void ActOnObject (object o)
   Console.WriteLine (o); // hello

Contravariance – Return Type Compatibility

  • A method target can return a more specific type than described by the delegate OR
  • A delegate can define a return type that is more generic than the method signature
delegate object ObjectRetriever();
static void Main()
    ObjectRetriever o = new ObjectRetriever (RetriveString);
    object result = o();
    Console.WriteLine (result);      // hello

static string RetriveString() { return "hello"; }


Covariance – Allowed for parameters marked with “out” modifier

// Covariant interface.
interface ICovariant<out R> { }

// Extending covariant interface.
interface IExtCovariant<out R> : ICovariant<R> { }

// Implementing covariant interface.
class Sample<R> : ICovariant<R> { }

class Program
    static void Test()
        ICovariant<Object> iobj = new Sample<Object>();
        ICovariant<String> istr = new Sample<String>();

        // You can assign istr to iobj because
        // the ICovariant interface is covariant.
        iobj = istr;

Contravariance – Allowed for parameters marked with the “in” modifier

// Contravariant interface.
interface IContravariant<in A> { }

// Extending contravariant interface.
interface IExtContravariant<in A> : IContravariant<A> { }

// Implementing contravariant interface.
class Sample<A> : IContravariant<A> { }

class Program
    static void Test()
        IContravariant<Object> iobj = new Sample<Object>();
        IContravariant<String> istr = new Sample<String>();

        // You can assign iobj to istr because
        // the IContravariant interface is contravariant.
        istr = iobj;

Invariance – Means that you can use only the type originally specified

Generic classes are not covariant to ensure static type safety

class Animal {}

class Bear : Animal {}

class Camel : Animal {}

public class Stack<T>  // A simple Stack implementation
      int position;
      T[] data = new T[100];

      public void Push (T obj) { data [ position ++ ] = obj; }
      public T Pop() { return data [ -- position ]; }

The following fails to compile:

Stack<Bear> bears = new Stack<Bear>();
Stack<Animal> animals = bears; // Compile-time error

That restriction prevents the possibility of runtime failure with the following code:

animals.Push ( new Camel());

Dependency Injection

What is Dependency Injection?

This is a pattern used for decoupling components and layers in the system. The pattern is implemented through injecting dependencies into a component when it is constructed. These dependences are usually provided as interfaces for further decoupling and to support testability.

Pure Dependency Injection (Poor man’s DI)

Pure Dependency Injection uses constructor or property Injection where lower level components are passed using constructors or properties.

DI container

Simplifies the creation of dependencies and also provides benefits like Interception (for Aspect oriented programming) for cross-cutting concerns like logging, caching security etc.

DI style Advantages Disadvantages
Poor Man’s DI Easy to learn
Strongly typed
Rapid Feedback
High maintenance
DI Container Low maintenance

Convention/xml registration

Weakly typed
Harder to learn
Slower feedback

Without DI container

var svc = new ShippingService(new ProductLocator(), new PricingService(), new InventoryService(), new TrackingRepository(new ConfigProvider()), new
 Logger(new EmailLogger(new ConfigProvider())));

With DI Container (Autowiring)

var svc = IoC.Resolve();

Comparing DI Containers

Autofac DryIoc SimpleInjector Unity
Configuration XML/Auto Auto XML/Auto
Custom Lifetimes Yes Yes Yes
Interception Yes Yes Yes
Auto Diagnostics Yes
Speed Average Fast Fast Average

Container compatibility for generics vary especially for the following scenarios and a more detailed analysis is needed with regards to capabilities required by our system

  • Open Generics
  • Covariance & Contravariance
  • Optional parameters
  • Func & Lazy support