Thursday, May 31, 2007

Updating assembly version with Continuous Integration build: Part III

I wrote before about different ways to update assembly versions for multiple projects. Previous solutions included artificial shared state file which should reside in the Cruise Control . NET folder. This is additional deployment hassle, of course, but it offers a little bit different approach, than a natural way - using a Labeller task, specifically designed for these purposes.

Let's say, we still have two projects configured in CC.NET and resulting DLLs should be marked with the shared build number. The following snippet illustrates Labeller configuration:

<project name="ReleaseBuild">
<labeller type="defaultlabeller">
<prefix>3.0.1.</prefix>
<incrementOnFailure>false</incrementOnFailure>
</labeller>
<!-- Other project configuration goes here -->
</project>

<project name="DailyBuild">
<labeller type="stateFileLabeller">
<project>ReleaseBuild</project>
</labeller>
<!-- Other project configuration goes here -->
</project>

Now the ReleaseBuild project will increment the build number and DailyBuild will use it for it's purposes. There is a downside - now only ReleaseBuild has a control over the label but if we will create some rules around build use we can easily find ways to use this feature. On another side there is a huge advantage - Cruise Control dashboard and CCTray monitor show label, which is now a real DLL version...

Tuesday, May 29, 2007

Inserting nice code snippets

If you use a Windows Live Writer to edit your blog offline(Beta 2.0 just came out - significantly improved) and if you ever experienced an urge to share your beautiful code with the other world - use the Insert Code for Windows Live Writer. This nice little add-on will provide nice layout for C#, VB, HTML and SQL syntax.

Just small advice - by default the add-on will try to embed its style in the every post, so take your time and manually include this style in the main CSS. Do it once and always uncheck "Embed StyleSheet" box.

Wednesday, May 23, 2007

Agile architect

What is the place of an Architect in the agile development process? The idea of design, evolving from the development seemingly proclaims the architect position obsolete. Right - group of smart and seasoned developers definitely should come up with an equally good design.

The position of an architect is often misunderstood in organizations: very often they are expected to produce UML diagrams and command developer herds, coding to the specs. Some architects do not code at all but just sit in the white castle up in the sky and craft divine designs.

So far those seditious thoughts seemed to be about right but smart people from XP Toronto user group gave me a better idea: an architect is The One who is looking out for the technical debt!

Developers, pumping their velocity points for the current iteration, easily can lose the horizon. Imagine some code which could use a 5-day refactoring. For a two-week iteration it is a tough decision - it won't add velocity points and it will not bring immediate business value. So naturally, developers and project managers can not justify this refactoring from their point of views. And they shouldn't, having the Architect onboard! Then the team has a perfect balance of powers: QA vs. BA take care of usability branch and developers vs. architect - technical branch.

Friday, May 18, 2007

EnergizeIT 2007 in Toronto

Mark your calendar: June 16, 2007 - Microsoft Canada' EnergizeIT gathering (registration required).

Number of sessions, including ASP.NET AJAX, Orcas, Silverlight and Vista gadgets (Bring Your Own Laptop). Some new packages and new Microsoft initiatives on privacy-breaking protection. Hands-on labs and keynote from David Crow. Free give-away kit (Vista?). Hopefully - interesting people around.

Well worth attending (will they serve a free food?).

Thursday, May 17, 2007

Why don't frequent flyer programs try to employ literate people?

 

I think I am good at math (which is generally expected from the Computer Sciences graduate) and kind of good at geography (it's my hobby). I am risking to offend marketing and business professionals assuming that basic calculation skills and common knowledge are not considered beneficial for Master of Marketing or MBA but the Frequent Flyer Programs managers seem to think different. Marketing Vice President guy of Deutsche Lufthansa AG, for example, signs as a "Dr" under the statement that proclaims Toronto and Frankfurt 60,000 miles apart.

It happened that I am a member of Lufthansa Miles & More program (and Air Miles, like you). Here is my last statement - 9878 miles. Quite a lot, eh? Almost the round-the-world voyage. Let's get to the numbers: the distance between Fairbanks, AK and Guatemala City is 4313 miles - the longest North America trip Google could calculate for me (yes, yes, the Guatemala is a little bit outside the scope but I couldn't get distance between Cancun and fishing camp on the Chukchi Sea coast). Looks like I've got myself a round trip from whatever to whatever in North America, whoo-hoo!

Now, what can I afford? The economy class within North America will cost me 30,000 miles, from Canada to Europe - 60,000 miles (and some pitfalls). Looks like for the non-pilot Lufthansa folks the Earth circumference is close to 200,000 miles. I am afraid to find out what Lufthansa pilots think (thank God, they have autopilots!).

You can say: "Read the fine print - those are status miles, dumbo!". Right. Call them "status points" then! (or call the program Inches & More - pretty suitable name). If I promised to pay Lufthansa 100 status dollars, what word they consider the key - "dollar" or "status"? Would they likely be surprised when they find out that my status dollar is actually worth 10 cents? Status cents, he-he.

Testing ASP.NET pages outside Http Context

Phil Haack had a great post on testing ASP.NET pages with embedded Visual Studio Development Web Server. This is a cavalry and heavy artillery of ASP.NET testing. Once you established a decent testing framework based on that code, you are covered for your UI part.

I've never got to that point (I have an excuse - I am not a UI guy!) but some requirements for UI implementation - like validation - are perfectly eligible candidates for unit testing. Chris Stevenson gave me an idea (and what I finally tried) to test an ASP page with brutal force - just like any other class. We'll start from two assumptions: the validation on the page is done by standard Validation controls; properties of all Validators (in particular - ControlToValidate) are set in the code-behind (in our example - in the SetupValidators() method).

Next we'll proceed in three steps:

Step 1. On the runtime we do not have Page.Controls collection populated for us, so we will have to do it manually. With the following code our controls will be set and ready for the test.

    public static class PageLoader    {
        public static void ResurrectControls(ref Page myPage)   {

BindingFlags flags =

BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;

            foreach (FieldInfo field in myPage.GetType().GetFields(flags))   {
                if (typeof(Control).IsAssignableFrom(field.FieldType))    {
                    Control toAdd = null;
                    ConstructorInfo constructor = field.FieldType.GetConstructor(new Type[0]);
                    if (constructor != null)  {
                        toAdd = (Control)constructor.Invoke(new object[0]);
                        toAdd.ID = field.Name;
                        field.SetValue(myPage, toAdd);
                        myPage.Controls.Add(toAdd);
                    }
                }
            }
        }
    }

Step 2. Let's create a base TextFixture class :


    [TestFixture]
    public abstract class ValidatorBaseTestFixture   {
        protected Page testPage;
        public abstract void SetTestedPage();
 
        public virtual T PageFactory<T>() where T : Page   {
            ConstructorInfo constructor = typeof(T).GetConstructor(new Type[0]);
            return constructor.Invoke(new object[0]) as T;
        }
 
        [SetUp]
        public virtual void SetUp()   {
            SetTestedPage();
            PageLoader.ResurrectControls(ref testPage);
            ((ITestableValidatorContainer)testPage).SetupValidators();
        }
    }

Step 3. The concrete unit test class inherits from the base fixture and implements an abstract method SetTestedPage :


    [TestFixture]
    public class MyPageTests : ValidatorBaseTestFixture   {
        public override void SetTestedPage()     {
            testPage = (Page) PageFactory<MyPage>() ;
        }
 
        [Test]
        public virtual void SetUp()  {
            testPage.txtEmail="invalid$&@nothingcom";
            testPage.Validate();
            Assert.IsFalse(valEmailValidator.IsValid);
        }
    }

Now developers can write unified maintainable tests against validation on every particular page.

As a step further we can introduce different kind of testable interfaces and decorate our Base Page class. Example of this can be ITestableValidatorContainer interface (actually used in the TestFixture example above):
public interface ITestableValidatorContainer {
    public void SetupValidators();
}

Saturday, May 12, 2007

Fixing up the System.Web.Profile

I am certainly not a wise person. Instead of learning from a Dan Hounshell's struggle, I wasted tons of time, trying to make Microsoft profile work for Web Application Project. Dan gave a perfect description of how I felt after fruitless fighting with MS Profile Provider until smart people (who read more than me) pointed me in the right direction.

To make long story short here is the recipe:

  • Decide to utilize Microsoft (widely advertised) Profile feature.
  • Use Web Application instead of the native Web Site.
  • Fail miserably and admit that you are stupid doing something wrong.

When Microsoft patched a Visual Studio to give an alternative to the hated Web Site application, their developers broke a support for a Profile mechanism. The schema will refuse to function unless you download ASP.NET Profile Generator - it will replace a Web Site's automatic CommonProfile generation. (hurry up - Microsoft is abandoning GotDotNet by the summer 2007).

Even after you successfully generated the profile class, there are still some limitations. You are pretty much safe if the profile properties come from the web.config file:

<profile>
<properties>
<add name="FirstName" />
... etc ...
</properties>
</profile>
It is a little bit more difficult if you want your profile class to be more intelligent. The natural choice is to create your own class and inherit profile:
<profile inherits="MyProject.MyCustomProfile"/>
In this case I would recommend to create the partial class - one part have your custom properties in the following form:
public virtual string FirstName
{
get
{
return ((string)(this.GetPropertyValue("FirstName")));
}
set
{
this.SetPropertyValue("FirstName", value);
}
}
and another part will contain the required plumbing provided by the generator.

And the last tip: the Runtime will try to cast your profile class to the ProfileCommon type and fail if you didn't inherit your class from the System.Web.Profile.ProfileBase. Better do it in the generated partial class. The full example of the Web Application Profile class you can download here CustomProfile.cs.

Again - it is a good idea to keep your custom part separated from the generated code so nobody would accidentally regenerate the profile. To make these sad accidents even less likely - do not install the ASP.NET Profile Generator and simply use the example code.

Friday, May 11, 2007

Hiring managers getting paid up to 20% more than two years ago: report

The quote from an Ottawa Business Journal: " Canadian companies are paying recruiters up to 20 per cent more than they were two years ago as firms struggle to find new talent, according to a new report ..."

I don't know about you but I suddenly pictured a restaurant with hungry visitor, absolutely incompetent in cooking, skillful waitor and well-done steak (which is just a piece of meat, obviously incapable of anything except being tasty).

Is it true that apriori a talent can not get himself hired without an intermediary? It sounds about right for IT guys :) but what about artists or MBA's?

Monday, May 07, 2007

Introverted Programming: Job Security Pattern

Have you ever felt underrated? The main reason is that people can understand what you are doing and it gives them a feeling that you are replaceable. You can proof them wrong with few simple techniques.

1. You should agree (and some managers may support you), that this code

public void DoFunc(string n, int num)
{
try
{
SqlConneciton conn=new SqlConnection("server=treaudo;security=SSL;usr=gh#6d;pwd=HyhJ76J;");
conn.Open();
SqlCommand cmd=conn.GetCommand("spDoIt");
SqlDataReader rdr=cmd.ExecuteReader();
while (rdr.Read())
{
MyObject mo =new MyObject(rdr,n);
mo.SendMessage(num);
GlobalCacheVairable.Increment(mo.Quantity);
mo=null;
}
}
catch {}
finally
{
//close all the stuff
}
}
looks more sophisticated, than this one:
public void DoFunc(string n, int num, SqlConneciton conn)
{
using (SqlDataReader rdr=GetDoItReader(conn))
{
while (rdr.Read())
{
ProcessMyObject(n,num,rdr);
}
//we still catching errors
}
}
Also there is a pretty good chance that the former spread all over the project located in several key areas and only Tom or Mike will agree to maintain it. So who will keep their jobs when the tough times come? Considering that the latter piece takes twice as much time to build (especially when those silly unit tests are around), the hardworking Tom and Mike look 4 times more productive than always malcontent Chad and Martin.

2. It is tempting to give your classes and methods misleading names but do not leave your opponents enough ground to accuse you of sabotage. The class names like Utilities or Flickr WCalcST will do. Method names shouldn't resemble verbs and something like TotalRecall always adds a nice touch to the ASP.NET code-behind.

3. People, who operate with terms like cohesion, are you enemies only want to make your classes more transparent, so the next-desk guy can easily replace you! support your code. It's an easy catch: if your classes are never less than 600 lines of code, even toughest agile junkie would consider an easier prey.

4. If you are tempted to add another #region block in your code, because navigation throughout the class is getting tedious - you are on the right way. Classes with a dozen collapsed regions look exceptionally solid.

5. Beat them with their favorite weapon - the innovation. Thoroughly spread generics and reflection throughout the places they less expect. With the method DoLwBack<Dictionary<string,ConfCol<int>>>(input1, input2) you will live up to your reputation of sophisticated programmer.

6. Work alone. Communication let others to spy on your plans and give away your productivity (which you most likely have to camouflage).

Some other useful techniques were discussed at the Niagara Falls, NY conference Waterfall 2006.

Updating assembly version with the CI build: better code

Just an update for a previous post (it's too long to publish it in the same article). As I mentioned, the use of C# script will eliminate disadvantage of using <asminfo> task and give cleaner and more robust solution. So here is the code:

  <target name="update-assembly" description="Replaces the version in the assemblyinfo.cs file">
<script language="C#">
<code>
<![CDATA[
public static void ScriptMain(Project project)
{
string fileContent="";
using (StreamReader reader = new StreamReader(project.Properties["info.file"]))
{
fileContent= reader.ReadToEnd();
reader.Close();
}
string newVersion = string.Format("[assembly: AssemblyVersion(\"{0}\")]",
project.Properties["buildnumber.version"]);
string newText = Regex.Replace(fileContent, @"\[assembly: AssemblyVersion\("".*""\)\]", newVersion);
using (StreamWriter writer = new StreamWriter(project.Properties["info.file"], false))
{
writer.Write(newText);
writer.Close();
}
}
]]>
</code>
</script>
</target>

Friday, May 04, 2007

Updating an assembly version with the Continuous Integration build

If you use continuous integration builds, one of the steps you want to consider is to have resulting assembly DLL marked with incremental version number. This way QA people will be less confused about the version of site they're testing. Among the numerous advantages it gives you an additional selling point for an Agile development process. It doesn't matter do you tag your build in the source control or preserve it on the hard drive waiting to be burned on deployment CD (BTW: the former is more Sorbanes-Oxley compliant).

You can use the CC.NET <Labeller> task offers automatic increment. I am not sure but it may be reset if CC server is restarted; if not - then you don't really have much control over this number. Original NAnt would require crazy workarounds, but NAntContrib library contains very useful task.

The process is pretty standard in the main steps - Cruise Control project checks out the files, passes the control to the NAnt build script, which builds it, runs NUnit tests and tags it. It includes the following tasks:

<target name="increment-version">
<property name="version.file" value="${CCNetArtifactDirectory}/version.number" />
<echo message="1.0.0.0" file="${version.file}" if="${not file::exists(version.file)}" />
<version path="${number.file}" buildtype="Increment" />
</target>
<target name="update-assembly">
<asminfo output="${assemblyinfo.file}" language="CSharp" if="${file::exists(assemblyinfo.file)}">
<imports>...</imports>
<attributes>
...
<attribute type="AssemblyVersionAttribute" value="${buildnumber.version}" />
</attributes>
</asminfo>
</target>
You can notice that the first script counts on CCNetArtifactDirectory variable, which value is passed down from the Cruise Control script by default. The variable points to the <ProjectName>/Artifacts folder which is created automatically under the Cruise Control root directory the first time the project is built.

Here is the trick - we keep the version.number file here ( increment-version task creates it if can't find). The content of the file initially set to 1.0.0.0 (or another value if you wish) and task will increment it, following the incremental settings and result is stored in the ${buildnumber.version} variable. The advantage of this approach is that while build script is a part of the solution, the version.number file logically belongs to the CC.NET project level. At least it's kept away from developers who can change it :). Another approach is to store version.number in the source control (of course outside the the path, observed by CC.NET), but then additional will be required to check file out, change and check back in, while not adding too much protection.

It is worth mentioning that <update-assembly> task will regenerate AssemblyInfo.cs file from scratch and it's up to you to restore the required settings. If you prefer to avoid this, use <script> with C# function which will gently vivisect the AssemblyInfo.cs file and replace just a version.

Tuesday, May 01, 2007

Books: Framework Design Guidelines

Do not believe your eyes - this book is pitch black in reality (no, it can't be a different book, can it?).
Have you ever chosen between property and method or wondered if you should call your class WtfThngMgc? Here is your guide with sound DO's and DONT's. The .NET Framework guys cover pretty much everything you need when designing your own framework. You can learn from all their breakthroughs, mistakes and trade-offs which they carefully analyze. As all good books it sounds like you've always known all this stuff but forgot.
Great job highlighting distinctive features of application and framework code - worth reading.


© 2008-2013 Michael Goldobin. All rights reserved