It looks like there will be a micro MIX like event in Dublin in May - http://visitmix.com/2008/worldwide/. It might be interesting.
Wednesday, 26 March 2008
Sunday, 24 February 2008
There is no perfect job
I suppose we all know that there are always some "ifs" and "buts". Edge Pereira wrote a blog post about a few of them that are related to human-human interaction. If I had to choose a single sentence from his post I would go for this one: "if an employee does not know the reason of his daily work, he will never wear the company's jersey". Needles to say I totally agree with the whole post.
Friday, 15 February 2008
ReSharper 4 - nightly builds available at last
At this stage I nearly refuse writing code without ReSharper. I know it's bad but that's not the worst addiction ever :). Fortunately, JetBrians decided to release nightly builds of ReSharper 4 to public. Sweet.
Tags: ReSharper, Visual Studio
Tuesday, 12 February 2008
C# generics - parameter variance, its constraints and how it affects WCF
CLR generics are great and there is no doubt about that. Unfortunately, C# doesn't expose the whole beauty of it because all generic type parameters in C# are nonvariant though from CLR point of view they can be marked as nonvariant, covariant or contravariant. You can find more details about that topic here and here. In short the "nonvariant" word means that even though type B is a subtype of type A then SomeType<B> is not a subtype of SomeType<A> and therefore the following code won't compile:
Error 1 Cannot implicitly convert type 'System.Collections.Generic.List<string> to 'System.Collections.Generic.List<object>. An explicit conversion exists (are you missing a cast?)
The generics are all over the place in WCF and you would think that this is always beneficial to all of us. Well, it depends. One of the problems I noticed is that you can not easily handle generic types in a generic way. I know it does not sound good :) but that's what I wanted to say. The best example is ClientBase<T> that is the base class for auto generated proxies. VS.NET generates a proxy type per contract(interface) which might lead to a situation where you need to manage quite a few many different proxies. Let's assume that we use username and password as our authentication method and we want to have a single place where the credentials are set. The method might look like the one below: public void ConfigureProxy(ClientBase<Object> proxy) { proxy.ClientCredentials.UserName.UserName = "u"; proxy.ClientCredentials.UserName.Password = "p"; } Unfortunately we can't pass to that method a proxy of type ClientBase<IMyContract> because of nonvariant nature of C# generics. I can see at least two options how to get around that issue. The first one requires you to clutter the method with a generic parameter despite the fact that there is no use of it.
Approach based on a non-generic interface:
Having that hierarchy in place we could define our method in the following way:
Unfortunately WCF architects haven't thought about that and a non-generic ClientBase/IClientBase class/interface doesn't exist. The interesting part of this story is that the FaultException<T> class does not suffer from the same problem because there is a non-generic FaultException class that exposes all the non-generic members. The FaultException<T> class basically adds a single property that returns the detail of the fault and that's it. I can find more classes that are implemented in exactly the same way FaultException<T> is implemented. It looks like ClientBase<T> is the only one widely used class that breaks that rule. I would love to see this inconvenience fixed as an extension of C# parameter variance.
List <String> stringList = null;
List <object> objectList = stringList; //this line causes a compilation error
Error 1 Cannot implicitly convert type 'System.Collections.Generic.List<string>
The generics are all over the place in WCF and you would think that this is always beneficial to all of us. Well, it depends. One of the problems I noticed is that you can not easily handle generic types in a generic way. I know it does not sound good :) but that's what I wanted to say. The best example is ClientBase<T> that is the base class for auto generated proxies. VS.NET generates a proxy type per contract(interface) which might lead to a situation where you need to manage quite a few many different proxies. Let's assume that we use username and password as our authentication method and we want to have a single place where the credentials are set. The method might look like the one below: public void ConfigureProxy(ClientBase<Object> proxy) { proxy.ClientCredentials.UserName.UserName = "u"; proxy.ClientCredentials.UserName.Password = "p"; } Unfortunately we can't pass to that method a proxy of type ClientBase<IMyContract> because of nonvariant nature of C# generics. I can see at least two options how to get around that issue. The first one requires you to clutter the method with a generic parameter despite the fact that there is no use of it.
public void ConfigureProxy <T>(ClientBase <T> proxy) where T : classYou can imagine I'm not big fun of this solution. The second one is based on the idea that the non-generic part of the public interface of ClientBase class is exposed as either a non-generic ClientBase class or a non-generic interface IClientBase. Approach based on a non-generic class:
{
proxy.ClientCredentials.UserName.UserName = "u";
proxy.ClientCredentials.UserName.Password = "p";
}
public abstract class ClientBase : ICommunicationObject, IDisposable
{
public ClientCredentials ClientCredentials
{
//some code goes here
}
}
public abstract class ClientBase <T> : ClientBase where T : class
{
}
Approach based on a non-generic interface:
public interface IClientBase : ICommunicationObject, IDisposable
{
ClientCredentials ClientCredentials { get; }
}
public abstract class ClientBase <T> : IClientBase where T : class
{
}
Having that hierarchy in place we could define our method in the following way:
public void ConfigureProxy(ClientBase/IClientBase proxy)
{
proxy.ClientCredentials.UserName.UserName = "u";
proxy.ClientCredentials.UserName.Password = "p";
}
Unfortunately WCF architects haven't thought about that and a non-generic ClientBase/IClientBase class/interface doesn't exist. The interesting part of this story is that the FaultException<T> class does not suffer from the same problem because there is a non-generic FaultException class that exposes all the non-generic members. The FaultException<T> class basically adds a single property that returns the detail of the fault and that's it. I can find more classes that are implemented in exactly the same way FaultException<T> is implemented. It looks like ClientBase<T> is the only one widely used class that breaks that rule. I would love to see this inconvenience fixed as an extension of C# parameter variance.
Saturday, 9 February 2008
Saturday, 2 February 2008
Looking for Quality not Quantity
I'm sure you've already heard opinions that the wide opening of weblogs.asp.net might not be a good thing because it lowers the overall quality of the portal. I can see more often then before that people are leaving that site. I'm not saying that the aforementioned change caused that but something is going on.
When I started blogging I wanted to have a blog on weblogs.asp.net but the admin replied to me that they didn't have any "free slots". At that time I was a little bit upset about that but now I know that his decision was right. Basically in most cases before you are able to provide interesting content you need to familiarize yourself with all the stuff that's already out there. Reinventing the wheel is not interesting and learning (climbing predecessors' shoulders) is not easy.
Current status: Climbing :).
When I started blogging I wanted to have a blog on weblogs.asp.net but the admin replied to me that they didn't have any "free slots". At that time I was a little bit upset about that but now I know that his decision was right. Basically in most cases before you are able to provide interesting content you need to familiarize yourself with all the stuff that's already out there. Reinventing the wheel is not interesting and learning (climbing predecessors' shoulders) is not easy.
Current status: Climbing :).
Wednesday, 30 January 2008
AccuRev - another story how to screw UI
A few days ago I found an article about new AccuRev plugin for VS 2005 and by the way I decided to describe the pain I've experienced using AccuRev. In general I love AccuRev or to be more precise I love its back-end. The whole AccuRev architecture is based on streams that are structured as a tree. Every stream except the root has a single parent stream and 0 or many child streams. Click at the image to see more details.
A child stream inherits content from its parent which makes branching/merging a non-issue. Let's say you have the production version of a product in the main stream and all the new features are being implemented as child streams. Whenever there is a code change (bug fix, small improvement) in the main stream all child streams get it automatically. Developers don't even have to think explicitly about merging. They just update their workspace, get changes from the parent stream and resolve simple conflicts and that's it. I said simple conflicts because the more often you merge the less time you spend on it. Additionally, in most cases all inherited changes are incorporated seamlessly because AccuRev does a really good job at merging.
If you need to include an external dependency (which is exposed as a stream as well) you just need to create a link between your stream and the stream where the dependency is. This means that if you have a data access component then the New Feature 1 stream can consume version 1.0 of it whereas the New Feature 2 stream can upgrade to version 2.0 in complete isolation. As you can see AccuRev is powerful and there is no doubt about that.
The only problem is that all described features are exposed to the end user by a crappy UI. The UI has been written in the way that makes it useless in so many cases that it's not even funny. I'm going to show a few examples how you must not write UI. All of them made the AccuRev adoption in my company very hard. Fortunately we have a brilliant build team which basically created a new web based UI that sits on top of AccuRev and hides many of the "innovative" ideas you will see.
The order of the list does not matter because different people hate passionately different AccuRev UI "features". The list is based on version 4.5.4 of AccuRev.
A child stream inherits content from its parent which makes branching/merging a non-issue. Let's say you have the production version of a product in the main stream and all the new features are being implemented as child streams. Whenever there is a code change (bug fix, small improvement) in the main stream all child streams get it automatically. Developers don't even have to think explicitly about merging. They just update their workspace, get changes from the parent stream and resolve simple conflicts and that's it. I said simple conflicts because the more often you merge the less time you spend on it. Additionally, in most cases all inherited changes are incorporated seamlessly because AccuRev does a really good job at merging.
If you need to include an external dependency (which is exposed as a stream as well) you just need to create a link between your stream and the stream where the dependency is. This means that if you have a data access component then the New Feature 1 stream can consume version 1.0 of it whereas the New Feature 2 stream can upgrade to version 2.0 in complete isolation. As you can see AccuRev is powerful and there is no doubt about that.
The only problem is that all described features are exposed to the end user by a crappy UI. The UI has been written in the way that makes it useless in so many cases that it's not even funny. I'm going to show a few examples how you must not write UI. All of them made the AccuRev adoption in my company very hard. Fortunately we have a brilliant build team which basically created a new web based UI that sits on top of AccuRev and hides many of the "innovative" ideas you will see.
The order of the list does not matter because different people hate passionately different AccuRev UI "features". The list is based on version 4.5.4 of AccuRev.
- UI is based on Eclipse which is written in Java. I have nothing against Java but I haven't seen a really good UI written in that language. The AccuRev UI is not as responsive as the average native Windows app. From time to time it starts rendering everything in gray. Click at the image to see more details.
- AccuRev comes with its own vocabulary that describes the source code management.
Common term AccuRev term update update & populate check in/commit promote delete defunct move cut & paste conflict overlap - In order to make sure that you've got all recent changes you need to update and populate your workspace. Of course there is no single button that does both of them in one go. What is more both actions are launched in two completely different ways. The update button is the best hidden button I've ever seen. Nearly every single developer that starts using AccuRev can not find it. Note that the update action is accessible neither from the main menu nor the context menu.

- Whenever AccuRev can not update your workspace because there is something wrong with it you get a cryptic error message. In most cases it is the same error message. Click at the image to see more details.

- When someone promotes changes to the parent stream then all children get it by inheritance. From time to time the changes introduce conflicts that need to be resolved. The problem is that in order to find them you need to look for them using two different searches - overlap and deep overlap. I know why there are two different types of them but I don't get why this is so explicitly exposed to the end user.
- As I said before you can include other streams into you stream. The problem is that the window that lists all available streams is just a list view without any way of filtering items in the current view. I can spend 15 minutes trying to find the stream I'm interested in. Click at the image to see more details.

- Whenever you edit a text box the Ctrl-Z shortcut does not work.
- Let's say you are done with your task and you want to promote all your changes. In order to do this you need to remember to execute 3 different searches(external, modified, pending) to find all your changes. Again there is no single search that can do this for you. Needless to say that you can not define your own searches.

- There are always some files that are part of your workspace but you never want to add them to the repository. The obj and bin folders are a good example. Unfortunately the AccuRev UI does not let you exclude neither files nor folders. Instead you need to create an environment variable where you specify all patterns for files and folders that AccuRev should ignore. What a user friendly solution. Even free TortoiseSvn has that feature built in.
- When you want to move a file that is already in the repository you need to right click on it, choose cut, navigate to the new location, right click and choose paste. Why is there no explicit move command?
- Until recently the AccuRev integration with Visual Studio has been very poor and only recently AccuRev has released a plugin that more or less works with VS 2005(what about 2008?). My biggest problem with AccuRev plugin is the fact that from time to time when I compile my solution it does something in the background that causes the compilation process to freeze for a few seconds. From my perspective this is unacceptable behaviour. I don't mind if the plugin does its housekeeping when the IDE is idle but it must not interfere in the compilation process.

Since recently a happy AccuRev user :).
Subscribe to:
Posts (Atom)
