Translate

Showing posts with label Agile. Show all posts
Showing posts with label Agile. Show all posts

Wednesday, 15 May 2019

CI/CD - Travis, Jenkins, GitHub, Cloud, DevOps

DevOps is the latest sensation happening in the software development realm not just because of the fascinating array of tools that need to be used to implement a SCM strategy but in the immense challenge that it presents to teams that are on the Agile way of software development.

In frameworks like SAFe, that has a systems view, the importance of DevOps is immense especially when SAFe could encapsulate Behavior Driven Development (BDD), Test Driven Development (TDD), Scrum, XP, Kanban in itself to deliver a solution.

There are many ways of integrating code in a SCM repository but the key factor is in selecting the right tools to have an efficient set of pipelines to enable all aspects of the Agile Software Development Lifecycle.

Traditionally, Continuous Integration(CI) means checking out, checking in, committing code and to ensure that the build always succeeds and the code base is clean for the entire team to use, whenever, wherever and whichever tool they want to access the code from. However, things are not as hunky-dory as it looks because when you check out the tools that are available in the market, including the Cloud based ones, they appear to be free and easy to use so, at first glance, it does look all rosy.

For instance, Jenkins has a cool interface that clearly tells the user on which SCM repo to use.



But the real trick is in enabling the access to the SCM for the tool.

Jenkins is an integrator that works on a different machine from the one where your code is hosted - eg., GitHub and so authenticating the CI tool to access the repository's status, code, scripts important and since Jenkins is a separate server by itself, credentials cannot be passed as is. So, what is required is for a secret that only the two tools know so that they could authenticate against a key generated using a standard cryptographic algorithm like a SSH key.



The same key is with the GitHub repository as part of your configuration of the GitHub account.



The difference between the various tools like Jenkins, Travis, Azure DevOps etc is in the way your build configuration is expected to be.

In Travis, for example, the travis.yml contains all the build steps in the form of a yaml script, which means that as long as the virtual machine understands the script, you can just about configure anything, from code coverage to tests to installation of npm packages or not, to running a mongod instance and test results as an Istanbul report, for example.

This configuration script is expected by Travis to be part of your code repository to which it is synchronized with. If there is no travis.yml then Travis will default to Ruby.



The travis.yml contains the script that tells the Travis CI container how to run the build.





And the travis.yml script does many things like installing nodejs packages (which can also be set to ignore with a gitignore file in the repo), connecting to a mongodb instance and importing some json data to running a mocha test and providing a code coverage report.

Jenkins, on the other hand, provides for the build environment, build triggers and build actions and post actions within its interface. And since Jenkins gels well with Maven and the Java environment, its usage requires a good knowledge of the Java development tools, environment like maven, the JDK and the scripts to execute the build.





But unlike Travis, which is more suited for open source projects, Jenkins is a more specialized CI tool.

The commonality in all DevOps tools is in the integration of a CI tool with a SCM repository and with a Cloud storage container to enable Continuous Deployment (CD), the usage, though, will differ as per the depth in the software development process of the team.

Below are some important questions that could serve as a checklist when deciding on what kind of a DevOps environment that you want setup for your organization/team?
  1. Does the team wish to map its BDD or TDD into an automated environment?
  2. Is there an automated build that is wired with the testing framework and the code coverage tool ?
  3. Are deployments to the cloud monitored or automated and to what extent is quality ensured in the release to deploy?
  4. How often is the release to deploy planned?
  5. What are the planned pipelines in the build that cannot be ignored or skipped and who are the responsible members in the team?
  6. Does the responsibility or accountability in anyway compromise the agility in the team?
  7. What are the recovery mechanisms or policies in place for the CI/CD pipelines?
  8. To what extent does the organization want traceability from requirements to deployment?
More on the DevOps Deployment stage in the next post.

Thursday, 4 April 2019

BDD with Jest + Cucumber & Typescript

Continuing on the previous post on the Tesla Auto Pilot crash mode malfunction, here is a working code example of the feature.

The advantage of BDD is that you can not only keep the business engaged in the development process but also ensure that there are no disputes nor any cost of change as every business requirement gets neatly described as features from which all the possible scenarios based on business rules can be elaborated into crystal clear test cases.

The other advantage, of course, is that Test Driven Development becomes easy to implement as the BDD phase effectively outlines just those test cases for code to be written against for the feature to be realized.

Here is the example scenario of the auto-pilot mode beeping if the car is in auto-pilot mode.

So, effectively, there are two scenarios for the feature test to pass -

1. The car should be on auto-pilot mode.
2. The beep should be set on only if the auto-pilot mode is on and there is an object ahead.

Remember that BDD is about testing scenarios and so we don't have asserts but expects.

npm Packages used: jest, jest-cucumber, typescript, babel
Platform: nodejs
Dev tool: VS Code
Language: English :), typescript

jest-cucumber, by default, checks all tests defined under a _tests_ folder and if one does not exist then it follows the path given in the config file or in the testMatch in the package.json file.

The feature is clearly described in a .feature file as below. Remember that the gherkin syntax of given, when, then should match the scenario described in this .feature file.


The gherkin steps are defined in the .steps. file.



The actual code to test the expectation is the source code as below:


Run the test with jest.



Now, change the scenario description.





and running the test would cause the test runner to display errors because the scenario text has changed and does not match the scenario being tested for in the .steps file.


Similarly, if the source code running the test is changed and the distance is not set, then, too, the test will fail because expectations are not met!


The code change is the commented call to the method that sets the object ahead's distance (hypothetical) and so the test will fail when it tries to match the distance between the car and the object ahead.


Similarly, if the auto-pilot mode is not set the test will fail as that is the base scenario test!

From the above, you can easily perceive that the advantages of using jest-cucumber for BDD are obvious and numerous.
  1. Business can easily stay on track with development efforts.
  2. Wastage in effort and time as well as cost is reduced due to the traceability of requirements to code and vice-versa.
  3. Code waste is reduced. Only that much code is written in the TDD phase as defined by the BDD phase.
  4. Audits become simple because of the end-to-end testing available with one click.
With scaled agile frameworks like Safe, which require BDD and TDD to be well implemented, jest-cucumber and jest are incredible tools to infuse maximum agility into the software development process.

Of course, this is not to say that other tools like SpecFlow that are used for other frameworks like .Net or Java are not good, they all serve the same purpose - of defining features, deriving scenarios, writing test cases either in gherkin form or otherwise to automate the testing of your system.

Binding the test results from the above phases along with Selenium or Acceptance/Functional tests with test coverage completes the automated requirements for DevOps.

Happy BDD-ing! :)

Monday, 23 April 2018

A fake - Why faking a Person is a 'fake test'

Just happened to hit on the right word to express it!

While testing with TypeMock, I came across an interesting scenario where a class is declared within a controller that set off this simple post on why a fake is created and what purpose does it solve.

Let me elaborate using this example I found on the web. A controller with a class called Person inside it.

When writing a test for the controller, you will obviously need an instance of a Person because of Parameter Binding but a fake test is written just so that an external dependency does not hinder development!

This is the fundamental point in unit testing. If a unit test handles an external dependency code either through a direct, in place implementation of the external dependency or through accessing it, for real, then it is not unit testing because it violates the principle of testing code in isolation.

So, in this case, typing the Isolator.fake instance as a <Person> is a violation of the principle and therefore, is not even a 'fake test'

Below is the test for the ASP.Net MVC Controller code.

using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvcApplication1.Controllers;
using TypeMock.ArrangeActAssert;
namespace MvcApplication1.Tests.Controllers
{
    [TestClass]
    public class ValuesControllerTest
    {
        [TestMethod]
        public void Get()
        {
            // Arrange
            ValuesController controller = new ValuesController();

            // Act
            IEnumerable result = controller.Get();

            // Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(2, result.Count());
            Assert.AreEqual("value1", result.ElementAt(0));
            Assert.AreEqual("value2", result.ElementAt(1));
        }

        [TestMethod]
        public void GetById()
        {
            // Arrange
            ValuesController controller = new ValuesController();

            // Act
            string result = controller.Get(5);

            // Assert
            Assert.AreEqual("value", result);
        }

        [TestMethod]
        public void Post()
        {
            // Arrange
            ValuesController controller = new ValuesController();
            var p = Isolate.Fake.Instance<Person>(); // Not a fake because it creates an actual instance of type Person!
            // Act
            p.Name = "Jv";
            p.Age = 12;
            var s=controller.Post("Hello ", p);

            // Assert
            Assert.AreEqual("Hello Jv:12", s);
         
        }

        [TestMethod]
        public void Put()
        {
            // Arrange
            ValuesController controller = new ValuesController();

            // Act
            controller.Put(5, "value");

            // Assert
        }

        [TestMethod]
        public void Delete()
        {
            // Arrange
            ValuesController controller = new ValuesController();

            // Act
            controller.Delete(5);

            // Assert
        }
    }

}

  
using System.Collections.Generic;
using System.Web.Http;

namespace MvcApplication1.Controllers
{
    public class ValuesController : ApiController
    {
        // GET api/values
        public IEnumerable Get()
        {
            return new string[] { "value1", "value2" };
        }

        // PUT api/values/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/values/5
        public void Delete(int id)
        {
        }
        // GET api/values/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        [HttpPost]
        public string Post(string value, [FromBody]Person p)
        {
            return value+p.Name+":"+p.Age;
        }

    }
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public override string ToString()
        {
            return this.Name + ": " + this.Age;
        }
    }
}

Basically, the purpose of Agile and Agile testing is to ensure that sufficient agility is always infused into the developmenr process not just through maintaining high confidence levels but also by eliminating sycophantic situations of "you praise me and I will praise you" attitude with testing techniques like using TestDoubles when a dependency is under development or not yet implemented.

And even if implemented, a unit test is not meant to test whether the Person exists or not but whether the code that expects the Person and has to interact with it in some way, either by calling an action on the Person object or by modifying some data of the Person, is behaving as expected of it.

And on the point of dependency, it is also important to note that mock testing using the Dependency Injection way is another example of wiring more dependency into the test itself and hence, a mock test, too, should not be concerned with whether the server is running or whether the database instance is up and running. The mock test should simply be able to mock the object! And this capability should be or rather, can be provided only by the mock framework ie., not as in the moq framework but in a way that the runtime calls are intercepted to fake or mock an object under test.

Happy unit testing, fake-ing and test double-ing !

Sunday, 30 August 2015

VS Code 2015 - Grunt, mocha, mysql, unit test with chai

VS Code 2015 is a simple, no-nonsense editor.

This means that there will be lots of post-coding tasks that need to be performed using some other tools. For instance, automating builds, tests, deployment and execution apart from numerous other tasks like clean, copy, coverage, log, database read/write etc.

Although the task of maintaining all these software development and team activities may look daunting outside of the magical environment of a full fledged IDE like Visual Studio usually is, it is rather simple because of the packages that integrate with Node.js framework.

grunt is one such package that is similar to NAnt and Ant but has one additional advantage - it can perform, continue and wait on tasks asynchronously!

To use grunt, install it with,

> npm install grunt (-watch, contrib-execute etc)

To use mocha, use the same install method with npm.

Mocha is another simple 'describe-it' unit testing tool for testing JavaScript, Backbone and other client side scripting languages, similar to Jasmine.

And 'chai' adds flavor to the unit tests with the expectations and even 'promise'-s of a BDD.

Chai, too, can be installed using the npm tool.

>npm install chai


The story - watch changes to a file.

Simple steps - add the 'watch' task to the GruntFile.js as below:


Run 'grunt watch'

 
And every time a change is made to the source file that is being watched, the watch target will get triggered as above:

 
Change made to the the SQL query causes the watch target to get triggered again:




The actual rows in the DB:


and the package.json:


There are the usual caveats that you may need to reckon with like where to install the packages.

Tip: Always check the node-modules folder of your application. It should look like in the below figure:


The unit test using chai and mocha are as simple.

Execute the test using 'mocha' as:


Uncomment the 'done' lines for async callback to work seamlessly without any timeout issues related to the network or when connecting or retrieving data.

Needless to say, the unit tests wired into grunt tasks and coverage ruling the outcome of the tests and the build is ideal and this, too, is simplified now with grunt, node, mocha and blanket. 

Absolutely delightful tools for Agile!

Sunday, 23 March 2014

Agile Test Driven Design - Design evolving out of tests

Pre-requisites before you read this - Knowledge of the WCF framework, Web Service Consumption, Unit and Mock Tests and a basic understanding of the difference between a HTTP session context and an examination context (time allotted for tests, questions etc) and a lot of detached reading ability (Nothing directed at anyone personally even though it may seem so) :)

The code and the tests are executable-ready and tested so please do not troll with useless questions or responses.

Agile and the pleasure of Test Driven Design Development

Agile is not so much a pleasure when working with an Agile team as it is a pain when confronted with argumentative, subjective 'technical' experts; when the latter happens, you begin to realize how difficult it is to explain simplicity to these 'expert' project managers to accept their shortcomings and accept that they are not project managers but experts in creating crises and then managing it !

Documentation is 'Tests'

Documentation is the 'D' word - it is like the threat of a nuclear holocaust, the moment the word crops up in a team it is indicative that some reactive measures has crept into the development steps adopted by the team.

The incident of a tester not knowing how to open a VS TS and work with builds but still having the 'confidence' to pull up developers is an indicator of how some believe that having a 'team' writing some nonsense lines on Skype group chat or referring to each other as 'team' is what a team means and that 'testers' have read somewhere that customers write tests in Agile and therefore, being a tester means that the tester is a customer !

There are better PJs doing the rounds than having to encounter such 'poor jokes' within your work environment and that, too, which stinks so much!

Getting back to the D word - the best form of documentation that a team could be blessed with is when a test (Unit, mock or acceptance) 'tells' or 'communicates' how the design of the class, the signature of the method or even the data type of a data member should be.

It is really fortunate that I came across a 'real' example where I could demonstrate how Tests actually works, communicates and evolves a design into a near perfect one - and in far less time than you could conceive of.

I am extracting a simple service out of the whole system below to show how tests should be used to design, right from the beginning of a project.

The requirement

A service model (WCF) that enables a candidate to log in to an online examination application with a service contract as,

using System.ServiceModel;

namespace ABC.LoginService
{
    [ServiceContract]
    public interface ILoginService
    {
        [OperationContract]
        UserInfo DoLogin(string email, string password);

        [OperationContract]
        CandidateSessionInfo GetCandidateSession(UserInfo userInfo);
    }
}

and two data contracts for Candidate's session (not the HTTP session) and user information.

namespace ABC.Service
{
    [DataContract]
    public class CandidateSessionInfo 
    {
        int _id;
        string _title;
        DateTime _startDate;
        DateTime _startTime;
        DateTime _endTime;

        [DataMember]
        public int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        [DataMember]
        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }

        [DataMember]
        public DateTime StartDate
        {
            get { return _startDate; }
            set { _startDate = value; }
        }

        [DataMember]
        public DateTime StartTime
        {
            get { return _startTime; }
            set { _startTime = value; }
        }

        [DataMember]
        public DateTime EndTime
        {
            get { return _endTime; }
            set { _endTime = value; }
        }
    }

    [DataContract]
    public class UserInfo
    {
        int _id;
        string _name;
        string _email;

        [DataMember]
        public int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        [DataMember]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        [DataMember]
        public string Email
        {
            get { return _email; }
            set { _email = value; }
        }
    }
}

WYTNWYG (What You Think Is Not What You Get) 

This is an example of preconceived notions i.e., WYTNWYG  of Design principles. 

The service contract is simple - it outlines two basic requirements of a login operation but the design begins to go awry in the data contracts that is to provide the login infastructure. 

Let me demonstrate how, through the below tests written in Rhino Mock and NUnit.

using Rhino.Mocks;
using ABC.Service;
using NUnit.Framework;

#if DEBUG
using WebOperationContext = System.ServiceModel.Web.MockedWebOperationContext;
#endif

namespace ABC.MockServices
{
    [TestFixture]
    public class ServicesTests
    {
        WebServiceClient client;
        ILoginService sstudentMock;
        UserInfo studentUnderTest,obj;
        int loginId;
        CandidateSessionInfo sessionObj, sessionUnderTest;

        [SetUp]
        public void init()
        {
            sstudentMock = MockRepository.GenerateMock();
            client = new WebServiceClient(sstudentMock);
        }
        [Test]
        public void testStudentLogin()
        {
            studentUnderTest = new UserInfo();

            studentUnderTest.Email = "abc@gmail.com";
            studentUnderTest.ID = 1;
            studentUnderTest.Name = "abc";
            sstudentMock.Expect(t => t.DoLogin("abc@gmail.com", "pass")).Return(studentUnderTest);
            loginId = client.Login("abc@gmail.com", "pass");
            Assert.AreEqual(studentUnderTest.ID, loginId);
            sstudentMock.VerifyAllExpectations();
        }
        //[Test]
        //public void testSessionForLoginTime()
        //{
        //    sessionUnderTest = new SessionInfo();
        //    sessionUnderTest.ID = 1;
        //    sessionUnderTest.Title = "abcSession";
        //    sessionUnderTest.StartDate = DateTime.Now;
        //    sessionUnderTest.StartTime = DateTime.Now;
        //    sessionUnderTest.EndTime = DateTime.MaxValue;
        //    loginId = client.Login("abc@gmail.com", "pass");
        //    sstudentMock.Expect(t => t.GetSession(obj)).Return(sessionUnderTest);
        //   // sessionObj=student.GetSession(obj);

        //   // Assert.AreEqual(sessionUnderTest.StartTime, sessionObj.StartTime);
        //    //sstudentMock.VerifyAllExpectations();
        //}
        //[Test]
        //public void testSessionForLoginSessionTitle()
        //{
        //    sessionUnderTest = new SessionInfo();
        //    sessionUnderTest.ID = 1;
        //    sessionUnderTest.Title = "AbcSession";
        //    sessionUnderTest.StartDate = DateTime.Now;
        //    sessionUnderTest.StartTime = DateTime.Now;
        //    sessionUnderTest.EndTime = DateTime.MaxValue;
        //    loginId = client.Login("abc@gmail.com", "pass");
        //    sstudentMock.Expect(t => t.GetSession(obj)).Return(sessionUnderTest);
        //    //sessionObj = student.GetSession(obj);           
        //   // Assert.AreEqual(sessionUnderTest.Title, sessionObj.Title);
        //    //sstudentMock.VerifyAllExpectations();
        //}

    }
}

The first test, testStudentLogin, is fine but it is when you move to the next user story - 'getSession...' that the tests, related to the CandidateSessionInfo object tells you, "Hey, as per your design, you need to supply a UserInfo object, where is it?" 

Because 

1. Being on the web platform, you need to send the userinfo object to the getsession...method after the candidate logs in successfully or 
2. Refactor the design.

It is not as simple as choosing between the two - a design, when you arrive or decide it, must have 'testable' artifacts to justify the decision and this is where 'tabled design' fails and test driven design scores!

The test above has communicated (the feedback) that either the contract of the getsession...method is wrong or your programming logic that is not able to maintain the user info object state.

The answer now becomes simple. Your development efforts (and therefore the logic part) has not even started so obviously the choice is clear - refactor the operation contract. (Of course, this explanation of how to make this design decision is only for explanatory purposes - the actual parameters to making this decision could be entirely different based upon the composition of a team or the architect's experience and maturity.)

To  continue...with explanation on why the tests are commented out.

Sunday, 9 March 2008

Agile for Services (for want of a name!:)) - Draft I

About the Germans in 1940, US Airforce Colonel, John Boyd had observed how the Germans had fought and won against a superior force, during the world war, without any superiority in arms power. In the same vein, he had observed the communication happening between two fighter pilots, locked in a dog fight, who had to make fast adjustments to rapidly changing scenarios and decide, with their lives at stake.

The vision of two fighter aircrafts engaged in war is a sufficient definition of agility.


The nimbleness, the dextrous manipulations, the speed of thought and near lightning reactions of the pilots - all are best fit for a definition of agility.

Agility, hitherto, in the software development communities, has been defined by the Agile manifesto. But, "Alistair Cockburn cautions that simply using iterations, user stories and velocity doesn't mean your project is agile - or on the way to success", Steve Adolph. But, Agile for Services, is meant for the Service Industry and therefore, by its very nature, demands a different definition. The lifecycle of a software development process is different to that of a Service process.

The service industry, having come into shape fairly late, is yet to have a proper structure defined for itself. Although, CMMI-SVC is taking shape and there is an ISO implementation, both are yet to actually happen. It is a natural conclusion that because the service industry is highly demanding, in terms of requirements that constantly take new shape, there is only one way to handle the swift changes in the requirements scenarios - imbibe agility into the process as well as the people within.

Having said that, being agile in a physically demanding secenario is different to a non-physical scenario where physical effort may not be necessary at all; so, where does the agility come from? Agility, as we all know, is not just about the physical reactions but also about mental preparedness. Therefore, the intangible elements that demand immediate attention and solution require mental dexterity. Having said that, it is not that a skilled chess player can be a great Agile player.

Unlike in a game of chess, where a Second is well capable of giving out permutations and combinations of a given move and the associated variations using analysis, the same cannot be done in a service industry, where the current scenario is always unique due to the influence of individuals and, therefore, reaction time is far lesser. It requires a highly tuned individual with experienced knowledge of the domain to actually instill the required agility into the process to maintain, increase the velocity of the process' reaction time.

The Service industry
What is the first thing that comes to your mind when the term "Services" comes to your mind? "Competition" would be the most likely answer. Therefore, the ability to provide service to the customer and, at the same time, keep an eye on the competition demands almost as much dexterity as the fighter pilots in a dog fight!

So, how does the service provider tune himself up to the likes of a fighter pilot when all the data and elements that he can work with are intangible? The answer is simple: agility.

Agility, to define with the help of Boyd's principles on OODA (we shall expand it in a little while), is the ability of a process or a team to rapidly respond to the needs with constant change as an implied parameter!

Implicit guidance is a key to agility in a service scenario. The process is robust and therefore, the implicit guidance, in the form of constant and frequent feedback, is healthy and effective, as the feedback obtained is used to orient the existing process; the outputs from such orientation lead to decision making culminating in the ability to act ! This is what Boyd's principles on OODA (Observe-Orient-Decide-Act) is all about.


Services=Unfolding events
The chief factors in a service arena are


  1. Response Time to customer queries/requirements

  2. Constant monitoring of the status of queries/requirements

  3. Delivery

Each query/requirement of a customer may be unique. Therefore, no pre-conceived guidelines can have any significant impact on delivery.

"Agility, in this context, depends on keeping one’s orientation better matched to the real world and actual requirements during times of ambiguity, confusion, and rapid change, when one’s natural tendency is to become disoriented", Steve Adolph. This cannot be attained through on the spot decisions because, analysis cannot be performed on all the changing scenarios at all times, successfully. Here is where the implicit guidance comes in; implicit guidance, not in terms of individual skills or knowledge as in the case of Agile for software development, but, in terms of the process paving the way for quick decision making.

That there is constant change in the requirements of the current scenario in a service leads us to a foregone conclusion that agility is the only solution in the reckoning . For example, in a recent conference held at the NCR, each speaker had about 30 minutes to make his presentation. Some opted for QA session at the end of their presentation and others, took questions on the fly. With the latter case, it led to overflowing the time limit. In the presentation in which I was a reviewer, I oriented myself based upon the observations of the previous sessions. The previous speakers found that the passing of the mic from one questioner to another was consuming time and so I decided to take two actions - one, to pre-empt the direction of the questioners and two, to move faster between them! This ensured that the presentation took exactly the time that it was allotted with. Of course, not to take any credit away from the speaker's agility in tackling questions.

So, with this example in mind, it is fairly easy to conclude that the process areas of the service domain only serves as the guiding block while the people within the process are the real driving force.

It may be questioned as how to implement a process with agility in the perspective. Again, the solution is rather simple. Observation, which is the paramount activity of the service loop, described in the below image, can be directly mapped to the quality control activity of any work area. With strict quality control measures, where the observation points are, useful inputs can be obtained for the next activity in the loop - orientation. Existing service models may have incorporated this but, where Agile for Services, makes an impact is in introducing the agility into the process.




Implicit Guidance

The implicit feedback in the above figure, part of the delivery loop, is the constant observation that goes into the execution of the lifecyle of a service. This observation serves as the source for orientation of the response leading to actual data on which to decide and act.

"While agility is about using time for competitive advantage, it is not speeding up the loop by doing things faster because doing the wrong things faster is not a strategy for success", Boyd.

The agility, in this loop, is the faster response time between the various activities thereby, increasing the velocity, as well as the momentum of the loop. The volatility of the service environment requires a greater response time within the process and the agility with which the stakeholders of the process react!

Decision making, in any context, depends upon free flow of information and its correctness. Therefore, misinformation, compartmentalization, non-adaptability, alienation/isolation and fixed techniques can only lead to slowing down of the loop. Information has to be easily obtainable at all levels in the loop and visible at all levels to reduce friction in the loop and consequently, increase velocity and momentum of the process of delivery.


Observation Posts


Let us cast our mind back to the allegory of the two fighter pilots at dog fight and the parallel drawn with Service Providers. A good Service Provider always has an eye on the market and his competition and tunes and revs up his service accordingly. Quality not only gets noticed but is also appreciated.

Those who have travelled domestic, in India, would be able to associate with the following example.

Kingfisher Airlines (KA) is one of the new airlines in the Indian Aviation industry but has made such a telling impact, in such a short span of time, that competitors have begun to think out of the box in a great hurry. KA introduced the concept of ushers at the airport terminals, who would also double up as porters. For the uninitiated, this form of service is only showman stuff but the keener eye points to you the incredible effort in identifying a key factor in customer service - when the customer "thinks" of you, you are there with the service ready!

What does a passenger face with as soon as he reaches the airport? In most cases, it is "how do I get to the security counter?" and this is the moment that KA has so well identified and implemented in the form of the Ushers! The moment you reach the airport terminal and in your mind crosses the thought, "Hey, how do i find the KA counter?", there are these polite, well-clad ushers waiting for you anxiously and from that moment on you realise, "Yes, this is probably the best service that can be offered and has been offered in an Indian's flying experience!"

Let us relate this to OODA. The process makers of KA had clearly identified the point in the process workflow "when the customer first thinks of you as the service provider" and oriented its delivery process to include the Ushers! So, Observation and Orientation has happened here.

Orientation Points

How to apply orientation points in a process?

Orientation could be in the form of any tweaks that could lead to an improvement of the delivery loop. Feasibility study, effort estimation, offer making, requirements mapping to skills etc can all be direct recipients of orientation inputs.

One important point to note here is - "change". The evolution of technology and customer requirements have brought about the plethora of development methodologies that exist today and therefore, it should be a natural conclusion that old techniques existing within the lifecycle of these methodologies should also be revamped and renewed. For example, if time changes, time management techniques must as well change. What was applicable a decade back in time cannot be applicable to a decade later in time! Similarly, older techniques being used in newer and evolved methodologies must also be renewed and refined.

Let me now deviate from the OODA pattern and introduce the proposed delivery loop.



[More to be added...]


(c) Copyright Ravichandran J.V., 2008.



Reference:
What Lessons Can the Agile Community Learn from A Maverick Fighter Pilot?Steve Adolph, University of British Columbia, Vancouver, B.C. Canada
steve@wsaconsulting.com