View Ravichandran J.V.'s profile on LinkedIn RJV 's Blog Tweet @ravichandranjv

Translate

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.

Saturday, 22 March 2014

Agile anecdotes (repeat)

Scenario: Newly married. 


1. Agile stresses on Early Releases


Husband, newly inspired by Agile; wife, waterfall model!:P


End of iteration - Wife frustrated, customer satisfied, husband, disgusted with Agile,

declares "Agile No good"



2. Agile stresses on more testing


Scenario: House Owner - Tenant


Owner, newly inspired by Agile


Due to water scarcity, owner wants to test if the tenant closes all the taps before going out 

of house and starts running the water motor after the tenant leaves the house.


End of iteration - Due to exploitation over water, tenant kills owner. 

Friday, 21 March 2014

Holi Hai ! :) List of Colors - C#

Working with colors is always fun but for that you must have the colors first.

It is like an old joke of mine -

To be or not to be a Macbeth is not the question; the real question is, Lady Macbeth has to be for Macbeth to be or not to be!

So, when I ventured to have a user select a color from a drop-down list for a software module, I was a little surprised (like the cat in the tree on seeing a dog climbing up to say hello to her) that it was not as simple as that.

Lady Macbeth may have known how to poison her husband but she had the poison and that is the crux of the matter - a resourceful woman, for her times!

Then I chanced upon the fact (Google search is almost a fact now) that Reflection (as in System.Reflection) had the solution but the real problems are faced only when you work towards the solution.

Lady Macbeth, too, must have thought it would be hunky-dory all the way until she found  that she really could not taste the poison herself to know what quantity to give to Macbeth ! :D

It is not as if she had to mix Coke or Pepsi with some other drink - she really could not know the taste of poison so, how could she ensure that her prey, her husband, would not find it distasteful and throw it away before drinking it?

The problem is that System.Drawing.Color is not really an enumeration that can be enumerated upon as it does not have a colors collection! So, how to compare the color values after the user inputs the color, when asked "Tippi, tippi, tap, what color do you want?" ?

The solution is to compare the name of the colors by storing the 'reflected' colors into an array of strings and then compare using a foreach loop to match the selected color.

Below is the code:

public class MyColorList{

private string[] colors = null;
private string colorSelected = null;

            private void listAllColors(){
                int colorIndex = 0;
                System.Type colorType = typeof(System.Drawing.Color);
                System.Reflection.PropertyInfo[] colorInfoList =                                                                                               colorType.GetProperties(System.Reflection.BindingFlags.Static |
                    System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Public);

                colors = new string[colorInfoList.Length];

                foreach (System.Reflection.PropertyInfo propertyColor in colorInfoList) {
                    colors[colorIndex] = propertyColor .Name ;
                    colorIndex++;
                }
            }
            private string getColor(string colorName)
            {
                foreach (string color in colors)
                {
                    if (colorName.ToLower() == color.ToLower())
                        colorSelected= color;
                }
                return colorSelected;
            }
}
// Method Calls
            listAllColors();
            currentColor = getColor(ColorAsString);

(c) Of course, needless to say, what happened between Lady Macbeth and Macbeth was their own private affair and none of the world's business but because Shakespeare disagreed with the view that I thought of highlighting it, safe with the knowledge that it was probably not as private as the English Royalty would have it, if it was discussed so vividly in public.

Tuesday, 21 January 2014

Two of a kind !

vLookup + Average - Excel Macro



I had this wonderful problem that always appears easy with VBA for Excel but always has something different from normal problems !

The problem

For each order on the Orders table, compute the average of two consecutive items with the same article #.

At first glance, it looks like the vLookup will do and then you realize that an If... formula could be used in conjunction with vLookUp and it will work and only then it dawns on you that, hey, this is a logical problem and requires some serious coding !

This is usually the case with Excel problems that, because of the tabular nature of the data references, always seem likely candidates for simple formulas but then VBA has to be used even though macros always raise an eyebrow or two due to security reasons.

The Solution

Dim qu As Integer
Dim curVal As String
Sub AvgOfDeuxItems()
ctr = 0
rowctr = 3

curVal = Cells(rowctr, 6)
For i = 3 To 150
If Cells(rowctr, 6) = Cells(rowctr + 1, 6) Then
        qu = Cells(rowctr, 7) + Cells(rowctr + 1, 7)
        Cells(rowctr + 1, 8) = qu / 2
        qu = 0
            rowctr = rowctr + 2
    Else
    Cells(rowctr, 8) = Cells(rowctr, 7)
        rowctr = rowctr + 1
End If

Next
End Sub

The lookup for the Orders table is just another macro that runs the above macro upon an if...condition that compares the lookup values.

Wednesday, 18 December 2013

The change

Not long ago, maybe less than a decade or so ago, when a mere description of Waqar Younis' "toe crushers", "vicious, in-swinging yorkers", was heard or read in newspapers, was sufficient to conjure up a wholesome visual experience that presented visuals of wide eyed batsmen hobbling away and a tear away fast bowler celebrating with joy - as if having been there!

Those kinds of eloquent writers are probably now waxing eloquence, meaninglessly, to live visuals on television for viewers who, as most probably, listen to music with the box on mute !

But did you realize the impact that such a huge change could have in inter-personal communication, bi-lateral relationships in and between people and countries, emergence of literature vis-à-vis the new 'types' of readers, the 'new' emotional, human and artistic values that get into the cultural system of a country, the sense of importance of imagination, its need 'and' the proportion of it

in the way planning of policies (that depend a lot on predictable human behavior) and other sustenance means of the human life cycle value-chain will be affected by all the above?

It is not a question that has an answer - it is a new type of human existence that provides a different vision of the future just like the new kind of life that must have presented itself to the generations that must have looked at the change that the computer and mobile, smart phone brought on them !

The only difference why it is not the same is that those changes were in material and visible terms.

Friday, 29 November 2013

Personal preferences % (modulus of - as in software logic) Others' = Public Opinion

Public opinion, rumor and gossip are similar in one respect - they are like the modulus operator ('%'),

if the other side is 'even', the result is zero; if the other side is 'odd', the remainder gets calculated ! :)

Table value parameters - SQL Server

Table value parameters are the best way to pass a list or dictionary or key-value to a SQL Server stored procedure, a feature available from SQL Server 2008 onwards.

It is sometimes funny, this trend of many useful software and language features going unnoticed, when their applicability and usefulness is quite high. It is also likely that the usage or non-usage, of many such features may have influenced some programming trends or caused many simpler techniques to disappear.

One such feature is the usage of custom types, in SQL Server through the Table Valued Parameter (TvP), that makes a programmer's life simple.

A TvP is a custom type that can be defined for any database with the syntax,

Create type [dbo].[typeName] as table(
fieldName (type)(size)
)

Since arrays are not built-in to SQL Server, the customer type TvP helps in passing values to stored procedures as parameters of a SQL query with a SQLCommand or a SQLDataAdapter object.

There are many ways o passing values to a TvP type but the simplest is a DataTable object. Build the custom columns (DataColumn collection) corresponding to your TvP fields and add the values  as DataRows to the DataTable object.

So, the TvP is actually a type of table - a UserDefined TableType and hence, its name ! And so, due to less resources for some reason on the web, regarding its usage, this extremely useful data type or rather, table type is rarely used with its predecessor, the XML type more preferred.

The single most important thing when using a TvP is to remember that it is a table type and therefore, when using it in stored procs or functions, it is recommended for use with an alias failing which weird error messages may crop up totally unrelated to the type's structure or usage!

Many going the bookish way do not have much use for the TvP because it can be used only with "Insert" - this is what is the definition for usage but the context is not mentioned with the restriction leading many to believe that it must be a strange type !

It can be used within the SQL Server context with "Insert" because being a table type, you need to insert values into it first and only then you can use it! But from a program context, you can use it for any purpose - "update", "delete" or whatever.

The example below shows how to create a TvP, declare it in a stored procedure and iterate through it with the help of a cursor.

Example:

For a TvP, named 'myList'

// TvP declaration in SQL Server

use myDb;
create type myList as table(
myListValue nvarchar(max) 
)

// Stored Procedure

create procedure myProc

@myListVar myList READONLY       -- ReadOnly is a required attribute for a TvP

as
declare @listName nvarchar(max)

begin
declare @getListValues cursor
set @getListValues=cursor for

-- below, you are consuming the field defined in the TvP and getting the list value.
select c.myListValue from @myList c

open @getListValues

fetch next from @myListValue into @listName

WHILE@@fetch_status=0

-- update statement

fetch next from @myListValue into @listName
END
close @getListValues
deallocate @getListValues
end

Program code:

using System.Data;
using System.Data.SqlClient;

... more statements - class etc

DataTable dataTableObject=new DataTable("typeName");
dataTableObject.Columns.Add("fieldName");
dataTableObject.Rows.Add("SomeArrayValue");
....

The name of the DataTable, supplied as a parameter to its constructor, is the custom type defined in the database. The column collection corresponds to as many fields as is defined in the type.

SQLCommand/SQLDataAdapter cmd=new SQLCommand/SQLDataAdapter("StoredProcName",sqlConnectionObject);

cmd.CommandType=CommandType.StoredProcedure;

cmd.Parameters.Add("storedProcParameterName",SQLDbType.Structured);

cmd.Parameters["storedProcParameterName"].Value=dataTableObject;

cmd.ExecuteNonQuery(); // being an update query in the stored procedure.

Tuesday, 26 November 2013

NVarchar (in SQL Server) - the mysterious 'N'

Sometimes the most preferred data type can cause problems due to the stereotyped acceptance that if it is the most adopted and works, it must be the best.

NVarchar is one such type.

Although this SQL type is quite likely the 'good' one and the 'chosen' one for all text type data requirements, it is not for at least two common requirements related to data-warehousing and transport.

1. Not to be used if the requirement is to have a columnar storage index.
2. Not to be used if the requirement is to export data in a flat file.

Thursday, 21 November 2013

Game 9 - If it were a child's play

The board position after Black queens with a check and white can play Nf1, Rf1 or Bf1 to save the check.



Anand played Nf1.

The evaluation line was expecting Bf1 and below are some possibilities with a few lines leading to a checkmate in favor of Anand.

If White had played, Bf1


 and black responds with Qxf6 because the impending R - > h4 threatens mate on h7 and black has to rescue its king from it



and if intead of Qxf6, if black plays Nxf6  White's gxf6, Qg7# wins for White.



















But then if it were only a child's play! :)

Monday, 18 November 2013

Change and 'generation gap'

Because 'Change', of a social or mass kind. happens over a period of time or say, generations, to understand how effecting 'change' effectively happens, it is important to first dispel stereotyped understanding of words like 'generation gaps'.

As it is understood and propagated, a generation gap is related to lack or lesser numbers of effective communication channels between different generations. Understand it, instead, as "reduce the gap between generations by introducing generations to current age demand and technologies and past shortcomings" and change, instead of happening over decades, will begin to happen in years and even months.