Friday, May 28, 2010

Great FitNesse tutorial!

I was attracted by FitNesse recently and found this great tutorial from Brett who is working with uncle bob at ObjectMentor.

The tutorial is great since it not only introduced the concept, but also a really good example to guide you through the door. Meanwhile, without bending rules by ugly codes.

Is public field still so evil in C#?

In Java, there is a rule: "never make your field public". This rule is borrowed by C# when a lot of Java programmers jumped to .NET. I'm one of them and I loyally kept that habit, you will find no public field defined in classes from my hand. While, not exactly. That changed recently.

One of the main reason of "keep fields private" in Java was, field accessors and method calls are very different. If you expose your field as public, then all dependent applications will use obj.fieldName to access it; while if you encapsulate it using a access method, it's like obj.getField(). So if you have make the field public, and then you need to introduce some business logic on the field, then you've got a headache: you need to change all the depending source codes. With IDEs like IDEA and Eclipse, this kind of change can be much easier and robust than before, but still it's going to take effort, which is a waste.

Since the first day of C#'s birth, it has a special language feature, Property, which I believe was borrowed by the success of Delphi. By this feature, a field can be encapsulated by a property and accessed in the same syntax as field, except under the hood, it's really a method call, and if you disassembly the IL code, there is really setField and getField methods generated. So in this case, is it still so evil to mark your field private and provide a property for it? In most of my applications (and I believe in most of most programmers' applications) the property is nothing but just a dummy get/set pair. And to make this pain less painful, MS invented the "auto-property". But the question is, is this encapsulate really necessary?

I don't think so! For C# applications, the "private-field-rule" is not applicable any more. Since if you want to change a field to a property, none of the dependent codes should change (unless if you use reflection). The only thing a field can not do is, it can not be marked as virtual while properties can; and fields can not be put into interfaces while properties can be (you can make a property writeonly and not field, might be useful for setting injection by IoC). So if you need to make a NHibernate friendly entity, or if you need to define interfaces to other module, use property. For most of rest, try to use field, until you find the needs to introduce property. This will help you get code clean.

Friday, May 14, 2010

Content types if you deploy ClickOnce applications with non-IIS web server.

Found below info from MSDN. BTW, mongoose is a very good candidate for this...

File name extension

Content type

.application

application/x-ms-application

.manifest

application/x-ms-manifest

.deploy

application/octet-stream

Wednesday, May 12, 2010

Using Teamcity to build(publish) .net application

Since .NET 2, there is a nice feature to "publish" your application, called ClickOnce, to a website, file share or to CD/DVD. If your application only contains managed code (MS termed this smartclient), this feature is a easy way to simplify the deployment of the application and keep your users update date. I happen to have such a application with a group of users up to ~50 distributed from Europe to Asia, so deployment always bothers me. To make things worse (or better:), I follow the agile way of development. That means frequent change/deployment of software. If it is a website, there won't be a problem, but I'm still stuck to desktop and I need an easy way to handle this. Luckily there is a built in function named "publish" in VS2005 (the aged IDE I'm using), which can make a simple html page and some xml files so you can put them on a website and the users can just click the page and start the application. This only works for IE, unfortunately if you can only use .NET2. Since .NET 3.5, there is a Firefox plugin from MS, and there has always been a unofficial Firefox plugin, but I never tried. Anyway it's enough in my case. One thing to notice is, the application is not downloaded for every startup. The timestamp is used to check if there is a new version on server, and if the return value is 304, http-not-changed, then the copy from IE's local cache is used , deployment file (.application) is downloaded and the version embeded in is compared to the version installed in the local application cache. If the version on server is newer, then the application is downloaded again, or the local copy is used. So this suits local network perfectly, unless your deployment is too large (>10MB?). And it seems the application is running in a full trusted mode, with user's confirmation through a dialog showing the publisher can not be verified (maybe a valid certification key would even remove this dialog, I did not tried).

BTW, it's better to use the context menu "Publish..." in project explorer. I've read/experienced unstable publish when using the "publish wizard"/"publish now" button in the publish tab of project properties page.

I have a build server using Teamcity and each time there is a change in my source code, it will grab it and build the software, and notify some colleagues to deploy it. The tool has great web gui and is free if you limit your project to 20 and users to 20. With some money, you can get more "enterprise" features like active directory integration, etc.

I have been using the build server to build "normal" projects (with out "publish") for quite a while and it all worked fine, until I added publish as one of the targets. The actual build still runs well, but there was a wired error occurred when the publish target is running:
warning MSB3155: Item 'Microsoft.Net.Framework.2.0' could not be located in
I searched through the net and found some solutions. But it does not fit all my situation. I could not find the folder specified in the article and copy the whole folder is a little overkill. In my case (VS2005+.NET 2.0), the folder is under
%ProgramFiles%\Microsoft Visual Studio 8\SDK\v2.0
So the register key
sdkInstallRootv2.0 under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
should point to this folder and I did not copy everything, only the "BootStrapper\Engine" folder, and the "signtool.exe" under the "bin" folder (keep the bin folder). Since the signtool.exe needs capicom.dll, I copied it from %ProgramFiles%\Microsoft CAPICOM 2.1.0.2\Lib\X86. Then build again and bingo, it worked!