Tuesday, December 29, 2009

Ensure that your Unit Test is true inspector of bad code

Few days ago I did refactoring and as I'm quite sure that we have good coverage I checked-in my code after all tests passed. But today QA from my team stated that he/she cannot save new Customer. I dived into log files and found that exception occured on SaveCustomer method. Ok, I moved to the appropriate UT. (Note: it passes ok.) Which looked like:

[Test, Category("Integration")]
public void SaveCustomer_EnsureWeCanCreateNewCustomer()
{
    Customer customer = new Customer();
    //some another setup code here...
    try
    {
    //we hit database to save newly created customer
        savedCustomer = CustomerRepository.SaveCustomer(customer);

    //now we fetch customer from database requesting with the ID of just saved customer
        fetchedCustomer = CustomerRepository.FetchCustomer(savedCustomer.ID);

    //if fetched customer is not null we are ok!
        Assert.That( fetchedCustomer, Is.Not.Null );
    }
    catch
    {
        //do nothing here....
    }
    finally
    {
        if ( fetchedCustomer != null )
        {
        //we want to leave our database clear after test run
            CustomerRepository.Delete( fetchedCustomer );
        }
    }  
}

This Unit Test will be succeded anyway, because Assert.That(fetchedCustomer, Is.Not.Null) and similar asserts generates AssertionException.
Honestly I'm not aware why there was that catch{} piece, but anyway you could put there two catch blocks if it is really needed - one specific for the AssertionException and another for all cases of our life.
When you write your Unit Test you need to see it in both states - first in failure and then in success. After that you can allow yourself commit that code.

Main idea is:
You always need to keep one's eye on quality of you Unit Tests and be sure that your Unit Test will fail when that is needed.

Sunday, December 27, 2009

How to create and apply a patch with Tortoise SVN


What is patch?
Patch is text file which contains only differences you did to code, so it will contain changed and new lines as well as removed all in one bulk text file (*.diff or *.patch).

Why to use it?
There could be few cases when you would need patch. Next are three that I see:
1. For example it is possible that you do not have write access in SVN in case if you are contributor to some open source project. So you can send you changes as patch to those who have rights.
2. Another case could be when you lost your connection on one machine but want to port your changes to another machine easily and then commit them. (I faced with this one).
3. One another interesting usage could be establishing code reviews via patches. It could be that you have command that works remotely, and to ensure that we commit only good code your code reviewer would like to have your changes on his machine quickly and easily. Of course it it ugly to sent him all files you have changed and with screenshots of differences.

Create patch

You just need to be sure that you have latest code, that your changes are done and after that just right click on folder on which you want to create patch with selecting "Create patch..." like above. This will take you to dialog where you select files you want to include into your patch and then will take to save file dialog. So you could get file like validationRules_CodeReview.patch.

Apply patch 

Applying patch is also very easy, just pick up "Apply patch..." from the context menu of TortoiseSVN of folder needed (should be same folder as patch was created). After you selected patch file you will get two windows - one is TortoiseMerge on background and another is File patches. File patches window is list of files to patch. Double click on file from list opens differences in background window, so you could review them. And to apply you just need right click and select "Patch all" or "Patch selected".

Quick google with "How to create and apply a patch with Tortoise SVN" gives me next: http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-patch.html so maybe this will make more sense for you :)

Wednesday, December 23, 2009

Quick Verification if row exists in database with Nhibernate

Next SQL, which verifies if customer row exists in database:

SELECT customer0_.CUSTOMER_ID AS x0_0_
FROM   T_CUSTOMER customer0_
WHERE  (customer0_.CUSTOMER_ID = 123456)

Will be generated with next NHibernate Query:

public bool CustomerExistsInDatabase(Int32 customerId)
{
    var result = Session.CreateQuery(string.Format("select c.CustomerID from Customer c where c.CustomerID = {0}", customerId)).UniqueResult<Int32?>();

    return result.HasValue;
}

Please note, that you could use not only primary key, but any other property in your where condition.

Tuesday, December 22, 2009

Regex Quick Example

This is just another quick example of Regex pattern.

Next pattern matches "at least one symbol which is letter or digit at the begging and then exactly one delimiter '|' and then at least one symbol which is letter or digit in the end":

var valuePattern = new Regex(@"^\w+\|\w+$");
bool isValid = valuePattern.IsMatch(someStringValue);

Valid is:
ab123|cde45
Not valid are:
|ad
df|
adf||adf
and so on...

Links I've used:

Verify your Regex:  
http://www.pagecolumn.com/tool/regtest.htm
Cheat Sheet:
http://www.addedbytes.com/download/regular-expressions-cheat-sheet-v2/pdf/

Code Review: try - catch

Sometimes it is hard to convince that catch(...) is not so good! Today I provided code review to one of my colleague and he was totally sure the he need try{/*code*/}catch(){} in few places.

First looked like:

try
{
   int someValueId = Convert.ToInt32(value);
   if (someValueId > 0)
   {
     return new ValidationResult(true, "Valid");
   }
}
catch{}

I rewrote code to:

int serviceId;
Int32.TryParse(value, out serviceId);
if (serviceId > 0)
{
  return new ValidationResult(true, "Valid");
}

Then I spent few minutes to convince him that this code is ok and that this is not good to have catch for everything.

Another code looked like:

string result = string.Empty;
try
{
    result = documentContent.Descendants("SomeValueCode").FirstOrDefault().Value;
}
catch (Exception)
{
    //He was trying to ensure me that since we are doing validation we should not throw an exception
}
//do some work here

Now I tried to explain that FirstOrDefault() returns us either first element of collection OR null, so if we got null we just need to do some another stuff, but if some exception will occur we should allow it fly out OR write some specific catch for exceptions that could be thrown. Code which I propose looks like:

var resultElement = documentContent.Descendants("SomeValueCode").FirstOrDefault();
if(interventionCodeElement != null)
{
    var result = resultElement.Value;
    //do some work here
}

After conversation we decided that try(/*code*/)catch() is not so good.

Monday, December 21, 2009

AssertDatesAreEqual

Have you ever faced with UT that failed once and then you always see it succeeded? One of such tests could be test where you verify that date properties of some newly created entity are equal if they take DateTime.Now for that. Today Hudson showed me that some test failed in project I worked near half a year ago, so test looked like:
var item1 = new Item();
var item2 = new Item();
//...
Assert.AreEqual(item1.CreatedDate, item2.CreatedDate);
Test failed because time difference between dates was greater than few milliseconds. This could occur when processor is too occupied. So I changed assert call to more realistic:
public void AssertDatesAreEqual(DateTime dateTimeLeft, DateTime dateTimeRight)
{
     Assert.IsTrue(Math.Abs((dateTimeLeft - dateTimeRight).Milliseconds) < 100,
    "TimeSpan difference between dates is greater than 100 milliseconds.");
}

Wednesday, December 9, 2009

NHibernate: The column name COLUMN_ID is specified more than once in the SET clause

Sometime ago I faced with NHibernate issue and spent much time on figuring out how to resolve it. Issue was with saving complicated entity.
Error:
The column name 'RESOURCE_ID' is specified more than once in the SET clause. A column cannot be assigned more than one value in the same SET clause. Modify the SET clause to make sure that a column is updated only once. If the SET clause updates columns of a view, then the column name 'RESOURCE_ID' may appear twice in the view definition.


With NHibernate Profiler I found that this fails on the next SQL: 
UPDATE SOME_TABLE SET SOME_COLUMN1 = ?, SOME_COLUMN2 = ?, RESOURCE_ID = ?, SOMETHING_ELSE = ?, RESOURCE_ID = ? WHERE SOME_TABLE_ID = ?

With better look you will see that there two times RESOURCE_ID mentioned so this looks like wrong mapping. But I was sure that everything is ok there.

This two References are wrong. At first glance do you see why? At that moment I was not able also.
References(x => x.Resource)
        .Access.AsCamelCaseField(Prefix.Underscore)
        .WithForeignKey("RESOURCE_ID").TheColumnNameIs("RESOURCE_ID")
        .FetchType.Join();

References(x => x.ResourceRole)
        .Access.AsCamelCaseField(Prefix.Underscore)
        .WithColumns("RESOURCE_ROLE_ID", "RESOURCE_ID")
        .FetchType.Join();

Here Resource has key (RESOURCE_ID). ResourceRole has composite key (ROLE_ID and RESOURCE_ID).

After long searching and many tries I found why mapping is not correct. Even have my explanation for it.

When we reference ResourceRole we already use RESOURCE_ID field, so when we setup Resource and say "Hey, there is one more RESOURCE_ID", then NHibernate cannot find out how to update all this correctly.

Solution:
insert="false" update="false" attributes for one of references solves the issue. In Fluent NHibernate it looks like:
.SetAttribute("update", "false");

Monday, December 7, 2009

NHibernate Criteria for Nullable property

Image that you want to fetch friends from database by the First Name, Last Name and Age, which are properties of your class Friend. With NHibernate you could write query which will look like:

public IList<Friend> GetFriends(string firstName, string lastName, int? age)
{
    IList<Friend> friends = Session.CreateCriteria(typeof(Friend))
        .Add(Expression.Eq("FirstName", firstName))
        .Add(Expression.Eq("LastName", lastName))
        .Add(Expression.Eq("Age", age))
        .List<Friend>();

    return friends;
}

But it is wrong. Since Age is the Nullable type (int?), your call GetFriends("Andriy","Buday",null) will not get my record even if there is such in database and the column AGE is NULL there. So to request you need this: ageExpression = Expression.IsNull("Age"); but it will not work for not null age.
For our luck there is AbstractCriterion so we can generalize our Expressions like here:

public IList<Friend> GetFriends(string firstName, string lastName, int? age)
{
    AbstractCriterion ageExpression;
    if (age == null)
    {
        ageExpression = Expression.IsNull("Age");
    }
    else
    {
        ageExpression = Expression.Eq("Age", age);
    }

    IList<Friend> friends = Session.CreateCriteria(typeof(Friend))
        .Add(Expression.Eq("FirstName", firstName))
        .Add(Expression.Eq("LastName", lastName))
        .Add(ageExpression)
        .List<Friend>();

    return friends;
}

Sunday, December 6, 2009

Travelling Salesman Problem with Prolog

Do you know what is the Travelling Salesman Problem? Or course you know if you have at least some technical education. Will you forget what about it this problem? Could be... But I’m 100% sure that I will never, after I did task that I’m going to describe. Hope that comments in code will be enough to keep you on track.

domains

/* will allow us cooperate with better names, for me this is like #typedef in C++ */

  town = symbol

  distance = unsigned

  rib = r(town,town,distance)

  tlist = town*

  rlist = rib*

predicates

  nondeterm way(town,town,rlist,distance)

  nondeterm route(town,town,rlist,tlist,distance)

  nondeterm route1(town,tlist,rlist,tlist,distance)

  nondeterm ribsmember(rib,rlist)

  nondeterm townsmember(town,tlist)

  nondeterm tsp(town,town,tlist,rlist,tlist,distance)

  nondeterm ham(town,town,tlist,rlist,tlist,distance)

  nondeterm shorterRouteExists(town,town,tlist,rlist,distance)

  nondeterm alltown(tlist,tlist)

  nondeterm write_list(tlist)

clauses

  /*

  Nothing special with write_list.

  If list is empty we do nothing,

  and if something there we write head and call ourselves for tail.

  */


  write_list([]).

  write_list([H|T]):-

    write(H,' '),

    write_list(T).



  /* Is true if town X is in list of towns... */

  townsmember(X,[X|_]).

  townsmember(X,[_|L]):-

    townsmember(X,L).



  /* Is true if rib X is in list of ribs...  */    

  ribsmember(r(X,Y,D),[r(X,Y,D)|_]).

  ribsmember(X,[_|L]):-

    ribsmember(X,L).   



  /* Is true if Route consists of all Towns presented in second argument */

  alltown(_,[]).

  alltown(Route,[H|T]):-

    townsmember(H,Route),

    alltown(Route,T).

 

  /* Is true if there is a way from Town1 to Town2, and also return distance between them */

  way(Town1,Town2,Ways,OutWayDistance):-

    ribsmember(r(Town1,Town2,D),Ways),

    OutWayDistance = D.

   

%/*

  /* If next is uncommented then we are using non-oriented graph*/


  way(Town1,Town2,Ways,OutWayDistance):-

    ribsmember(r(Town2,Town1,D),Ways), /*switching direction here...*/

    OutWayDistance = D.

%*/

 

  /* Is true if we could build route from Town1 to Town2 */

  route(Town1,Town2,Ways,OutRoute,OutDistance):-

    route1(Town1,[Town2],Ways,OutRoute,T1T2Distance),

%SWITCH HERE

    way(Town2,Town1,Ways,LasDist), /* If you want find shortest way comment this line*/

    OutDistance = T1T2Distance + LasDist. /* And make this: OutDistance = T1T2Distance.*/

   

  route1(Town1,[Town1|Route1],_,[Town1|Route1],OutDistance):-

    OutDistance = 0.

  /* Does the actual finding of route. We take new TownX town and if it is not member of PassedRoute,

  we continue searching with including TownX in the list of passed towns.*/


  route1(Town1,[Town2|PassedRoute],Ways,OutRoute,OutDistance):-

    way(TownX,Town2,Ways,WayDistance),

    not(townsmember(TownX,PassedRoute)),

    route1(Town1,[TownX,Town2|PassedRoute],Ways,OutRoute,CompletingRoadDistance),

    OutDistance = CompletingRoadDistance + WayDistance.

 

  shorterRouteExists(Town1,Town2,Towns,Ways,Distance):-

     ham(Town1,Town2,Towns,Ways,_,Other),

         Other < Distance.



  /* calling tsp(a,a,.... picks any one connected to a town and calls another tsp*/

  tsp(Town1,Town1,Towns,Ways,BestRoute,MinDistance):-

    way(OtherTown,Town1,Ways,_),

        tsp(Town1,OtherTown,Towns,Ways,BestRoute,MinDistance).

  /*Travelling Salesman Problem is Hammilton way which is the shortes of other ones.*/

  tsp(Town1,Town2,Towns,Ways,BestRoute,MinDistance):-

        ham(Town1,Town2,Towns,Ways,Route,Distance),

        not(shorterRouteExists(Town1,Town2,Towns,Ways,Distance)),

    BestRoute = Route,

    MinDistance = Distance.



  /*Hammilton route from Town1 to Town2 assuming that Town2->Town1 way exists.*/

  ham(Town1,Town2,Towns,Ways,Route,Distance):-

    route(Town1,Town2,Ways,Route,Distance),

%SWITCH HERE

    alltown(Route,Towns), % if you want simple road without including all towns you could uncomment this line

    write_list(Route),

    write(" \tD = ",Distance,"\n").

%   fail.

   

goal

/* EXAMPLE 1

  AllTowns = [a,b,c,d],

  AllWays = [r(a,b,1),r(a,c,10),r(c,b,2),r(b,c,2),r(b,d,5),r(c,d,3),r(d,a,4)],

*/




/* EXAMPLE 2 */

  AllTowns = [a,b,c,d,e],

  AllWays = [r(a,c,1),r(a,b,6),r(a,e,5),r(a,d,8),r(c,b,2),r(c,d,7),r(c,e,10),r(b,d,3),r(b,e,9),r(d,e,4)],



  tsp(a,a,AllTowns,AllWays,Route,Distance),



%SWITCH HERE

%  tsp(a,b,AllTowns,AllWays,Route,Distance),



  write("Finally:\n"),

  write_list(Route),

  write(" \tMIN_D = ",Distance,"\n").

Let's take a look on the following graph:

Here is output of my program: 
  a e d b c       D = 15
  a e d b c       D = 15
  a d e b c       D = 24
  a e b d c       D = 25
  a b e d c       D = 27
  a d b e c       D = 31
  a b d e c       D = 24
  Finally:
 a e d b c       MIN_D = 15
 Which is correct! :)

Also I did not mention before I faced with issue of getting minimum of the value returned from predicate.
And this link provided help for me:

Wednesday, December 2, 2009

How to copy data from one database to another one using T-SQL

If you want copy data from one database to another on the same server you could use next SQL:

INSERT INTO [DestinationDatabase].[dbo].[Table1] ([Column1], [Column2], [Column3])
    SELECT [Column1], [Column2], [Column3] FROM [SourceDatabase].[dbo].[Table2]

Also if you want to copy data with the schema of table, i.e. copy table structure and contents to another database you could use:

SELECT * INTO [DestinationDatabase].[dbo].[TABLE]
   FROM [SourceDatabase].[dbo].[TABLE]