Nov 29, 2010

TFS for the SVN user

Originally I wanted to name this post as Making your life a little bit easier with all TFS horror and then decided to change it. The reason for changing title is that my irritation on TFS was called only by VisualSVN usability. I spoke with people who are using TFS for long period and have never used any other tools and they say that it is really good and everything is just obvious. Obvious for them, but not for me.

Currently I have no choice except using TFS as a source control system.  Previously I used Subversion with VisualSVN add-in to integrate with visual studio.

The only way for me not to go crazy while doing really simple tasks with TFS (like commit, merging) was making some configurations. Maybe some tips will save someone's time. So lets start with them one by one.

Merging tool

First of all when you merge conflicts with build in merging tool you really won’t understand what has changed. Changes are shown only in rows. So if one symbol is change you will need to hunt it in entire row by yourself. Also it is hard for me to see where conflict was resolved successfully with no need for me to do something and where my assistance is required.

Now I’m using WinMerge tool. Its also not the best, but really better then default one. To configure it you need to go to the Tools->Options->Source Control->Visual Studio Team Foundation Server and click Configure User Tools button. Click Add… button to add new command.

User tool configuration window

Select Compare operation, provide to WinMerge and fill arguments with this value: /ub /dl %6 /dr %7 %1 %2.

Click ok and add another new command select Merge, provide WinMerge path and fill arguments: /ub /dl %6 /dr %7 %1 %2 %4. Click Ok.

Here is a post where described how to configure TFS with other tools.

Compare on double click

Another really annoying thing is that when you are about to commit all your changes and you double click on a file it is just opened (in Notepad as I rememer O_O). Why would anyone need to see his pending change file in notepad? To compare it with server version you need to click on special buttons:

Checkin pending changes dialog

I didn’t want to pixel hunt that buttons. I wanted to compare with latest version on double mouse click. The good news that it is possible with TFS. How to configure it you can read here (btw the only option that worked for me is with registry and only after reboot).

Ghost changes

My favourite trick with TFS is just go to WebForm1.aspx press space somewhere and hit ctrl+z. You even didn’t hit save. Then you can open pending changes dialog and there real surprise is waiting for you. TFS will say that you have 3 pending changes Open-mouthed smile. Wow, when I saw this for the first time I couldn’t believe my eyes!

Ofcourse  when you click Check In button it will check real changes in the file and won’t commit file with empty changes. But I used to look through all changes that I’m going to commit and don’t want to hunt for really changed files among rest of them.

To solve this TFS power tools can be used. They contain a lot of useful features and one of them is TFPT.EXE tool. It is command line utility and can do a lot of stuff that you usually do with interface. And guess what? This tool has a special command to roll back unchanged files.

I added this tool as an external tool. To do this you can do the following go to the Tools->External Tools and click Add button. There you need to fill all the fields like this:

external tools configuration

I named the command as undo. You can name it the way you want. After you do it in Tools menu new option will be added:

undo

When clicked following output will be shown for me:

undo results

Auto merge

Another reason why you would want to install power tools is auto merge all button.

automerge all

The thing is: when you update, even if TFS is able to merge changes by himself it will force you to hit auto merge, auto merge, auto merge on each conflicted file. With this button you can do it in one place for all files. If somebody knows how to force it auto merge when possible without me clicking something I would really appreciate your help.

Remembering credentials

It won’t be an issue for the most of the TFS users, but it was for me.

Our TFS server is located in a different active directory domain. And each time you open a solution it asks you for the credentials and has no option to save them. I found this question on the msdn. The solution that worked for me is:

  1. Open start menu and in the quick search find for “manage network passwords” (in Russian version of windows you need to look for “управление сетевыми паролями”)
  2. In the opened window click on Add a Windows credential
  3. Fill all the required fields and click ok (server name should be provided with no http or something else, just name)

After doing this Visual Studio won’t ask password.

Unshelve with merge

I didn’t really used this feature of power tools yet. But as I was told default unshelving functionality will just replace all the files in your working copy. And if time has passed since you shelved all changes will be lost. Power tools allows you to merge changes and not just override.

So I think that those are all the configurations that I have made for today. It I remember something else I’ll write a new post.

Nov 11, 2010

Don't use constants

I don’t really remember when, but inside my current team I have told that I really hate to see classes that are like this:

public class Contants
{    
    public class Settings
    {
        public const ConnectionStringName = "SomeProject.ConnectionString";    
    }
    public class FieldNames
    {
        public const SomeField = "MyField";
    }
}

Almost all of the projects that I saw had this kind of class. Usage of it seams to be obvious – to store reusable strings to remove repetition.

But for me such a classes are lacking of the one thing – intention. Each constant exists inside our application for some reason and Constants class completely removes context that is connected to its value.

Today we had a some kind of “real world” scenario where I can show what to do with constants. I our case we had an email template where system will substitute some user input. So template contains %UserName%, %Reason% and so force string patterns that are going to be replaced with some values. The most obvious storage for these patterns is Constants class, but we don’t want it :)! So what I think we should do is to create a set of extension methods like this:

static class StringExtensions
{
    public static string SubstituteUserName(this string template, string userName)
    {
        return template.Replace("%UserName%", userName);
    }
}

This approach will allow us easily to write unit tests, because method is separated from others and really simple, and it will allow to write code in the following way:

"Hello %UserName%, thanks for your message about %Reason%"
                      .SubstituteUserName(userName)
                      .SubstituteReason(reason);

I think its really readable and looks nice.

The next thing why such an approach works is the way how developer works with the legacy code. In legacy system it is really often for developer to perform text based search to find places where similar tasks were already solved. For example when you need to get some value from the web.config file you can either use ConfigurationManager or WebConfigurationManager or maybe in your project some custom wrapper is implemented. For me the easiest way to find such information is to grab existing key of some value and try find all the references on it. In the good project you will meet only one place of usage :). In other cases it may be two places – Constants class and some domain specific wrapper (in this case why do need this constant separately of its usage?). But if you find that this constant is reused in 100 places and there is no common pattern you will just add the 101th place and forget about it. The reason why that happened is the existence of this Constans class.

So my approach for constants is that they can be only private in some classes that are using them. This allows new developers easy way to understand why those values are here and how to use them.

Nov 2, 2010

ConfOrm nice column naming conventions

I have decided to write all further posts in English. The reason for that is simple – when I try to find something related to programming topics I always use English. I think most people do the same.

The next step of learning ConfOrm for me was creation of sharp-architecture like conventions for table and column mappings.  I even wrote some pattern appliers, but when ManyToMany turn has came I had to google a bit. And the result was that Conform.Shop already implemented everything that I wanted so this post will be about usage of this library and the next one about implementation of your own appliers.

To create your own naming conventions we need to understand overall process. Basically mapping in ConfOrm  consists of two major steps:

  1. Getting the domain entities. This is done with the help of ObjectRelationalMapper class. This class is responsible for creating all the entities and associations between them. So is you want to change association type, or remove some property from the mappings this a place where you should do it.
  2. Creating mappings. Mapper class is responsible here. If you want to provide tables, columns and other conventions this is the right place.

Lets begin with domain model:

domain model 

Simple but with some associations.

Probably the easiest way to understand how NHibernate is configured is to look at XML (ConfOrm doesn't generate XML, but you can get it with this approach). So lets check User entity map:

<class name="User">
  <id name="Id" type="Int32">
    <generator class="native" />
  </id>
  <property name="FirstName" />
  <property name="LastName" />
  <property name="VeryLongProperty" />
  <set name="Orders" inverse="true" cascade="all,delete-orphan">
    <key column="User" on-delete="cascade" />
    <one-to-many class="Order" />
  </set>
</class>

The first thing that I want to change is the table name. I want it to be plural. To do this all that is required to do the following:

var englishInflector = new EnglishInflector();
mapper.PatternsAppliers.Merge(
                       new ClassPluralizedTableApplier(englishInflector));

There are also SpanishInflector and ItalianInflector if somebody wants them. After adding this one we get directive table=Users and so on for all other entities.

Next thing that I don’t like is names for column in the <key property. To change it I need to do the following:

mapper.PatternsAppliers.Merge(
new OneToManyKeyColumnApplier(relationalMapper));

Now the mapping for the set is:

<set name="Orders" inverse="true" cascade="all,delete-orphan">
  <key column="UserId" on-delete="cascade" /> 
  <one-to-many class="Order" /> 
</set>

That is probably all that I wanted to change in User mapping. Now Lets look at the Product map:

<class name="Product" table="Products">
  <id name="Id" type="Int32">
    <generator class="native" />
  </id>
  <property name="Price" />
  <property name="Name" />
  <property name="Description" />
  <set name="Categories" table="CategoryProduct" inverse="true">
    <key column="product_key" />
    <many-to-many class="Category" column="category_key" />
  </set>
</class>

There is definitely a better way of naming columns in the joining table. To change them we need to add next appliers:

mapper.PatternsAppliers.Merge(
                      new ManyToManyColumnApplier(relationalMapper));
mapper.PatternsAppliers.Merge(
                      new ManyToManyKeyIdColumnApplier(relationalMapper));

Those will give:

<set name="Categories" table="CategoryProduct" inverse="true">
  <key column="ProductId" />
  <many-to-many class="Category" column="CategoryId" />
</set>

That is what I really wanted. So all the mappings for the domain:

var relationalMapper = new ObjectRelationalMapper();
relationalMapper.TablePerConcreteClass(domainEntities);
relationalMapper.Patterns.PoidStrategies.Add(new NativePoidPattern());
relationalMapper.Cascade<Category, Product>(Cascade.Persist);
relationalMapper.ManyToMany<Category, Product>();
relationalMapper.Cascade<Order, Product>(Cascade.Persist);

var mapper = new Mapper(relationalMapper);
var englishInflector = new EnglishInflector();
mapper.PatternsAppliers.Merge(new ClassPluralizedTableApplier(englishInflector));
mapper.PatternsAppliers.Merge(new OneToManyKeyColumnApplier(relationalMapper));
mapper.PatternsAppliers.Merge(new ManyToManyColumnApplier(relationalMapper));
mapper.PatternsAppliers.Merge(new ManyToManyKeyIdColumnApplier(relationalMapper));

So not a lot of code and settings. Also this assembly contains a lot of other very nice patterns for example ManyToManyPluralizedTableApplier after applying it table name for joining products and categories becomes  CategoriesToProducts. Just beautiful Smile.

Here is the source code for this post

So use ConfOrm!