You've got FAIL - RDF vs OO Languages - It's just not meant to be

RDF - What the fuck ?
I've been looking at the upcoming changes for Calais Version 4 and what its going to take to get CalaisDotNet fixed up to support it. I've felt for some time that while I'm happy with what CalaisDotNet offers for users there was still a bit more I'd like to do with it. Instead of just being able to filter and sort a documents RDF results, grouped as collections of entities or relationships (based on enums), I'd really like to return concrete representations of those RDF entity types. As Calais offer more and more features the classes and properties they expose will get more complex and CalaisDotNet in it current design may have a problem keeping up as there will be data that the user will not easily be able to get at.

Now that Calais are publishing their RDFS I began looking at ways that I could process this schema and then generate .NET classes from it. The idea being that once those classes were generated I could build in a way to request an entity or collection of entities (e.g. Person) and then the user could work with a pure object. If a new version of Calais comes out then i (or whoever has the source) can just re-generate the classes.

I began processing the schema .. first off things were OK

image

.. The person class has three properties (and a type), all of which are just strings .. not much of a problem here ..

image

.. PersonCareer is slightly more complicated but here the properties match to objects, again nothing too bad once those classes were created ..

image

.. EnvironmentalIssue .. (damn the environment .. always a pain in the arse) .. here we see now that 'location' could be any one of four different types of objects (City, Country, ProvinceOrState or a plain ol' string) .. and we wouldn't know which one is returned until runtime. This is not good when it comes to a strongly typed language that wants you to have everything set out before hand, you cant change a class definition at run-time.

After a while of getting frustrated I began to look around for how other people were doing the same thing .. surely programmatically processing the Semantic web can't be that hard a puzzle to crack .. can it ? .. if its going to be the next big thing then surely there must be tools out there, even in Java, that must be able to do what I'm trying to do or a pattern I could follow. I then came across a very interesting paper from the makers of Active RDF who point out that 'the conceptual model and semantics of RDF Schema differ substantially from the object-oriented paradigm'.  Well .. I'd already come to that conclusion myself at about 4am the previous morning :D. They go on to talk about six key mismatches:

  1. Class membership: in object-oriented languages such as Java or C# an object is member of exactly one class: its membership is fixed and is defined during the object instantiation. In RDF Schema, a resource can belong to multiple classes: its membership is not fixed but defined by its rdf:type and the properties that belong to the resource.

  2. Class hierarchy: in popular object-oriented type systems, such as in Java or C#, classes can inherit from at most one superclass, while in RDF Schema classes can inherit from multiple superclasses (including inheritance cycles).

  3. Attribute vs. property: in the object-oriented model, attributes are defined locally inside their class, can be used only by instances of that class, and generally have single-typed values. In contrast, RDF properties are stand-alone entities that can be used by any resource of any class and that can have values of different types.

  4. Structural inheritance: in object-oriented programming, objects inherit their attributes from their parent classes. In RDF Schema, since properties do not belong to a class, they are not inherited. Instead, property domains are propagated, but given their specific meaning indicating the class membership of resources using that property, domains propagate into the upwards direction of the class hierarchy.

  5. Object conformance: in most object-oriented languages, the structure of instances must exactly follow the definition of their classes, whereas in RDF Schema, a class definition is not exhaustive and does not constrain the structure of its instances: any RDF resource can use any property.

  6. Flexibility: object-oriented systems usually do not allow class definitions to evolve during runtime. In contrast, RDF is designed for integration of heterogeneous data with varying structure from varying sources, where both schema and data evolve during runtime

This was a slightly 'aw crap' moment for me as they go on to talk about how only dynamic languages such as Ruby have the ability to cope with the constantly moving goal-posts of types being defined at run-time. While there are Java and C# libraries that attempt to process semantic data the conclusion I would draw is that they are going to have a hard time doing it properly. Now I have to stop myself here and say how new I am to RDF and my understanding of it, a hell of a lot of it still confuses the crap out of me, so please feel free to correct me on any points I've tried to make here if I've got the wrong end of the stick .. my only goal is trying to process this data in the most efficient way possible so I can get at its lovely linked data from within my website or application or what not.

So what to do next ? Do I give up ? Do I wait for .NET 4.0 and the prospect of the 'dynamic' keyword type ? Will this be the salvation C# semantic programmers have been waiting for ? My only thought at this stage is when something has multiple possible types to create the class with multiple extra properties. So in the 'location' example, from earlier, you'd end up with something like:

  • Location (for the free form string),
  • LocationCity,
  • LocationCountry
  • LocationProvinceOrState

Would this do ? I'd be making the objects subtly different from the Calais API documentation, which I worry would confuse.

I think for now I might give this a try and see how it looks once it comes out the other end but if anyone has any other suggestions please let me know :D


Posted by: [mRg]
Posted on: 22/02/2009 at 11:03 PM
Tags: , , , , ,
Categories: General | Problem
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (4) | Post RSSRSS comment feed

The man with two brains - Dealing with the Twitter dilemma

head

I love Twitter, I'm totally hooked. I've been using it for nearly a year now and I think its fantastic. Recently I've had to draw away and consider the way I use it and how I want to use it going forward. With over 11,000 tweets under my belt I think I've been able to observe the "twitter-verse" from a starting point as a curious low volume user then moving steadily up to a full-on high volume tweet factory :D

In this time I've seen people use Twitter in two core ways:

Using Twitter as RSS - Dip in, pick up some interesting articles or links. Twitter has the ability to be way ahead of the curve so you could be looking at stuff way before it hits the mainstream which is always a good feeling. If your connecting with people within your sphere of expertise you can really get some rich information by monitoring the right people.

Social Twitter - Its all about the chat, meeting and talking with people normally just about rubbish, their daily lives, putting their random snaps up on Twitpic. This is where the community and fun aspect of twitter is really comes out. As much as its 140 characters you can get a great insight into someone's life just from random snippets of their day.

In my own personal experience I've found that catering for these two modes is quite difficult. If people are connecting with me for information and technical insight (OK . .well maybe a bit), they couldnt care less about my dogs adventures in the snow but if I'm connecting more with Twitter on a social level I worry that if I harp on about IOC containers and .NET I'll alienate non-technical folk.

The other issue is the maxing out my "monkey sphere" as I connect with more and more people.

As Twitter hits the mainstream it looses some of its "back channel" appeal .. Its not just for the geeks anymore, Twitter is a great light-weight way to communicate and, rightfully so, people are picking up on it. The trouble with this is there a lot more volume to deal with. Also as the back-channel moves to the forefront we will surely see more people being fired and divorced for their tweets. I've witnessed first hand someone having to tone-down their tweets simply for the fact that their twitter feed is being syndicated onto a corporate site which is a shame as I used to love their drunken midnight tweetings :D

The key thing missing from Twitter (as many others have mentioned ad infinitum) is groups. Being able to send tweets only to specific groups of people would be ideal and reduce what I feel is cross-channel noise. Many argue this would kill the basic ethos of Twitter but I think as Twitter evolves and grows this is getting more and more crucial for its future sustainability.

Until groups are introduced I had to take some action. I found myself increasingly censoring my thoughts & language. Trying to deal with the mush of very personal flippant IM-style tweets and yet still wanting to be taken (almost) seriously for my technical hackery. While also not worrying about getting into trouble with my employer if I had a ranting moment. So in the end I have chosen to split my outpourings into two accounts:

Account #1 - Private - A small group of people, a pure 1:1 ratio only following those who follow me. Purely social, more irrelevant, a brain dump .. people i follow/followers are used to what i might say, and hopefully cant cause offense or bore them with the noise :)

Account #2 - Public - A bit more serious (never that serious), more focus on technical things and to engage with people inside my technical monkey sphere without the pollution of my random wittering.

I think this will be a bit of an experiment, managing two accounts is going to be tough but technology to the rescue as this is made much easier with programs like Twhirl and Tweetie (iPhone) which have multi-account support.

Lets see how it goes :D

Update: Martin Weller has blogged about "The Twitter dilemma for organisations" - HERE


Posted by: [mRg]
Posted on: 18/02/2009 at 10:47 PM
Tags: ,
Categories: General
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (11) | Post RSSRSS comment feed

CalaisDotNet v1.1 - Merge complete !

Nothing like the new year to prompt me into breaking my radio silence and announce I have finally merged the work I was doing in the branch of CalaisDotNet and merge it back into the trunk.

This release should be fully compatible with the OpenCalais service v3.1. You can find various code examples on how to use it in my previous post.
The only major new change worth mentioning is probably the addition of the CalaisJsonDocument type for handling the new JSON output type, there is no additional entity processing of this type (similar to the microformats type) inside CalaisDotNet as you can access all the same entities using the RDF output type. 

Firstly its great to know that people are actually using this, its always quite humbling to think some code I've written is helping people out somewhere in the world.

Secondly if there are any bugs / suggestions / improvements please let us know. Im not using this in anger yet in the real world and the whole idea of it is to make people lives easier when using and processing this kind of semantic data so if there is anything that would make your lives easier please drop us a messge and Im sure we can fold it in. Knowing how people are using this is just as important so we can get the methods and usages as fluent as possible :D

Hopefully I'll blog more in the new year luckily most of my flipant outpourings happen on twitter these days


Posted by: [mRg]
Posted on: 02/01/2009 at 8:28 PM
Tags: , ,
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (2) | Post RSSRSS comment feed

Charlotte's Semantic Web - CalaisDotNet v2.0

Well after much teasing its about time I posted something concrete about the work I've been doing using OpenCalais. As metioned previously I was working on my own .NET plugin / Helper class but, as it turns out, a ex-collegue of mine (who is now hiding away in sunny Australia) Chris Fulstow pipped me to the post and released his .NET Open Calais project on CodePlex. Rather than have two seperate projects doing exactly the same thing I began to merge my work with his and the result can be found here: CalaisDotNet

New Version

While busy merging code, OpenCalais released version 2 of their web service, adding more entities and relationships and now adding 'Simple' and 'Microformats' output types. I was attending a museum data mashup day as part of the the UK Musuems on the Web Conference 2008 last week and wanted to run some museum data into OpenCalais so branched the code and began re-writing it to support the new output types. After a busy weekend finishing off the code and adding relationship (Events/Facts) support I am pleased to say this new version is almost ready for release. I wanted to show some example of how easy it is to use it to process any type of data you submit to it and to use the power of LINQ to then manipulate and query the results set you get back.

Requirements

CalaisDotNet is written using the wonderful-ness of C# 3.0 and relies on having the .NET Framework v3.5 being installed. Remember .NET v3.5 is essentially just a new set of libraries - the CLR is still the same 2.0 version .. which means if you're running .NET 2.0 atm then it isnt not too much of a big deal to install v3.5 as all your old stuff will still work exactly the same way.

You will also need an OpenCalais API Key which can be freely requested after you register at the OpenCalais website. 

Here we go ..

CalaisDotNet can be broken down into two parts. The first one is the call to the web service, handled by the CalaisDotNet object, and second is the processed response data contained within one of three Calais*Document types that represent the three different types of output from the OpenCalais web service. Calling each is trivial.  

var calais = new CalaisDotNet(_apiKey, _content);
var document = calais.Call<CalaisRdfDocument>();

 
.. where:
_apiKey = (string) Your 24 digit API key
_content =(string) Your content to be processed. OpenCalais can accept input in 3 different formats - Plain Text, HTML and XML. CalaisDotNet has support for all three. CalaisDotNet will take a guess at the format of you text or you can specify the input type with an extra parameter in the constructor.
 

var calais = new CalaisDotNet(_apiKey, _content, CalaisInputFormat.Text);
var document = calais.Call<CalaisRdfDocument>();

The document returned represents the processed output from the web service and gives you the ability to access various collections of data such as Entities or Relationships

Simple Format

Documentation: HERE

This is a new format introduced in the latest version which has a reduced set of properties and entities, this format is ideal for doing things such as tag clouds as it only exposes simple list of basic entities, their frequency in the document and the value of each. Also its document description information is much reduced only having five properties.

You can still build up a LINQ query to filter or order the data in anyway that you choose.

Use the CalaisSimpleEntityType enum to filter by entity type.

an example query would look something like this, filtering for results where the entity type is 'Country'

var calais = new CalaisDotNet(_apiKey, _content, CalaisInputFormat.Text);
var document = calais.Call<CalaisSimpleDocument>();

var results = from item in document.Entities
                 where item.Type == CalaisSimpleEntityType.Country
                 select item;

foreach (var result in results)
{
   
Console.WriteLine(result.Value);
}

Microformats

Documentation: HERE 

This is a very basic implementation as, franky, I dont know how we can add any value to it as a lot of the work is done by the web service to format the data into HCalendars and hCards. Most of my time was spent making the RDF stuff work so suggestions are welcome on how best to process this into something useful :)

To grab the unprocessed output use the RawOutput property available on all the Calais*Documents to view see the original response.

var calais = new CalaisDotNet(_apiKey, _content, CalaisInputFormat.Text);
var document = calais.Call<CalaisMicroFormatsDocument>();

Console.WriteLine(document.RawOutput);

RDF Magic

The meat of the semantic data is (of course) contained within the CalaisRdfDocument class. It has a much richer set of document description metadata than the 'Simple' format.

The document also contains an IEnumerable list of Entities and an IEnumerable list of Relationships (Events/Facts). These can, for example, then be filtered by entity type (CalaisRdfEntityType) or relationship type (CalaisRdfRelationshipType).

Each entity/relationship also contains a list of all instances of that entity/relationship in the submitted document. Some examples:

Filtering where CalaisRdfEntityType is 'Company' and printing their location offsets.

var calais = new CalaisDotNet(_apiKey, _content);
var document = calais.Call<CalaisRdfDocument>(); var results = from item in document.Entities
                
where item.EntityType == CalaisRdfEntityType.Company
                
select item;

foreach (var result in results)
{
   
Console.WriteLine(result);

   
foreach (var instance in result.Instances)
    {
       
Console.WriteLine(
               
" - Found at offset: " +
               
instance.Offset + "(" +
               
instance.Length + " chars)"
               
);
    }
}

Returns only 'PersonPolitical' relationships  

var results = from item in document.Relationships
                
where item.RelationshipType == CalaisRdfRelationshipType.PersonPolitical
                
select item;

foreach (var result in results)
{
    
Console.WriteLine(result);
   
foreach (var instance in result.Instances)
    {
       
Console.WriteLine(
               
" - Found at offset: " +
               
instance.Offset + "(" +
               
instance.Length + " chars)"
               
);
    }
}

Slightly more complicated ..

Filters results by country and then looks up any relationships that are related to that country.

var calais = new CalaisDotNet(_apiKey, _content);
var document = calais.Call<CalaisRdfDocument>();

var results = from item in document.Entities
                 
where item.EntityType == CalaisRdfEntityType.Country
                
select item;

foreach (var result in results)
{
   
Console.WriteLine(result);

   
foreach (var instance in result.Instances)
    {
       
Console.WriteLine(
                           
" - Found at offset: " +
                           
instance.Offset + "(" +
                           
instance.Length + " chars)"
                           
);
    }
     

    var
rels = from item in document.Relationships
                 
where item.RelationshipDetails.Values.Contains(result.Value)
                 
select item;

    foreach (var rel in rels)   
    {
       
Console.WriteLine(" - Relationship: " + rel);
    }
}

Download

Currently this version is still in a branch so you will have to compile using the solution in the 'CalaisDotNet-NewFeatures_200805' folder .. you can download the release from the source tab of the Codeplex project site (HERE). Im hoping to make this a release soon once its been QA'd and also when I work out how to do it hehe :P

TO DO

  • MicroFormats - As mentioned earlier we need to look at the Microformats output and work out how to present it usefully.
  • RDFa - It would be reallty nice to be able to output the sumbitted document as RDFa .. we have the entities and we know where they are in the text so this shouldnt be too hard a jump .. personally I just need to understand RDFa better first.

 


Posted by: [mRg]
Posted on: 24/06/2008 at 2:13 PM
Tags: , , , , ,
Categories: Guides
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (2) | Post RSSRSS comment feed

Grand Func Railroad - Functional .. erm. functions


A while ago I read an an excellent post by Andrew Matthews (on his excellent Wandering Glitch blog) about employing functional programming techniques in C# that are enabled by the new features added in C#3.0. Now, I did wonder about posting about this as it contains the same subject matter as the information in Andrews blog (and Andrew describes the hows and whys a lot better than me), but I wanted to post for two seperate reasons.

  1. I use these two functions (below) ~all~ the time now. They are fantastic and (thanks to Andrew) have opened up my code up to this powerful programming technique and wanted to share them here incase they help anyone else.
  2. While I really liked Andrews examples it took me a while to grok them completely thanks to one problem that plagues me as a person bug-bear .. one letter variables as arguments.

I hate, hate, hate one letter variables when used as arguments, I know the problem here is a personal one .. mainly that I am not (or have ever been) a mathematician I didnt do A-Level maths, I was a graphics, pixel art, 3d artist kind of guy who found his way into programming by accident and while now I would never consider myself anything other than a programmer, math-type syntax makes my brain run in the opposite direction .. i.e the original On (which becomes my "Apply"):

Func<T, T> On<T>(this Func<T, T> f, Func<T, T> g)
{
   
return t => g(f(t));
}

 

In learning about these functional techniques (also including my learning with F# as well) I come across time and time again peoples examples that are clearly for the mathematically minded (ie not me hehe!) so I wanted to try and re-present these two functions in the syntax that finally got me to understand them.

I doing this I have to strongly emphasise that I am not "having a go" at anyone, especially not Andrew, as i wouldnt be here if people didnt post such great articles showing new ways of doing stuff, this simply exists to provide a level of clarification for the thickies :D Enough of my jibber-jabber ..

ApplyToSequence

This extension function takes a function as the argument and then applies that function to every element of the IEnumerable list. While being simple its is a very powerful tool, it already exists in one degree in the BCL, if you create a List<T> you can use the .ForEach() method but this function allows you to perform an action on ~anything~ IEnumberable (which makes it very handy ! Although i dont know why this isnt a standard method for IEnumerable already). An example follows these descriptions.

static IEnumerable<TResult> ApplyToSequence<T, TResult>(this IEnumerable<T> sourceSequence, Func<T, TResult> functionToApply)
{
   
foreach (var element in sourceSequence)
    {
        
yield return functionToApply(element);
    }
}

Apply

This extension method take a function as an argument and then applies that function to the original one. The great thing about this is it enable you to "chain" functions togther to make concise, powerful code.

static Func<T, T> Apply<T>(this Func<T, T> sourceFunction, Func<T, T> functionToApply)
{
   
return t => functionToApply(sourceFunction(t));
}

Examples

Here we go .. putting these two simple functions together means we can start doing quite neat things.

    // Two functions one which takes an int and adds 1 to it
    var addOne = ((Func<int, int>)(a => a + 1));

   
// .. and another that take an int and subtracts
   
var subOne = ((Func<int, int>)(a => a - 1));

   
// Two IEnumerables (one int and one string)
   
IEnumerable<int> test = new [] { 22, 44, 553, 345, 23, 32 };
   
IEnumerable<string> test2 = new [] { "<head>", "</head>" };

    // Print originals ..
   
foreach (var i in test)
    {
       
Console.WriteLine(i);
    }

    Console.WriteLine("-----------------------");

   
// Add 1 to each value .. using ApplyToSequence to apply the addOne
    // function to each element.
   
test = test.ApplyToSequence(addOne);

    foreach (var i in test)
    {

       
Console.WriteLine(i);
    }

   
Console.WriteLine("-----------------------");

    // By chaining the functions together we can add 3 then
    // subtract 1 from each element .. in one line too ..
   
test = test.ApplyToSequence(addOne.Apply(addOne).Apply(addOne).Apply(subOne));

   
foreach (var i in test)
    {
       
Console.WriteLine(i);
    }

    Console.WriteLine("-----------------------");

    foreach (var i in test2)
    {
       
Console.WriteLine(i);
    }

    Console.WriteLine("-----------------------");

    // Using ApplyToSequence we can also apply another function to
    //
 a string to do useful things like escaping characters
   
test2 = test2.ApplyToSequence(i => EscapeString(i));
   
   
foreach (var i in test2)

    {
       
Console.WriteLine(i);
   
}

   
Console.WriteLine("-----------------------");

The power of these should (hopefully) speak for themselves and I found myself using these a hell of a lot in recent code. The how and why these functions work or are able to work is described brilliantly in Andrews original article, I hope my lazy renaming simply helps shed some light on these for the less mathematically minded out there :)

 


Posted by: [mRg]
Posted on: 04/06/2008 at 10:55 AM
Tags: ,
Categories: Guides
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (2) | Post RSSRSS comment feed

Tonight We Raid Calais - OpenCalais Tools .. Coming Soon

I have been quiet of late as I have been working on a Open Calais parser tool to enable people to work effectively with open calais output - the output is fairly complex RDF and my little tool should allow quick extraction of terms and values so you can plug open calais into your .NET apps etc. Its been a sharp learning curve in terms of how RDF works (and how to parse it)  but the results now are working rather nicely.

I felt some of the other taggers / parsers let a lot great data slip by as they were just concentrating on the tags (which is fine and is probably what you want) but there can be a lot of rich relationships stored in the documents (such is the joy of RDF) and I wanted to enable people to get at that data if they wanted (which is why it took so bloody long hehe)

Quick sneak preview as you can see .. all entities resolve to real .NET objects populated with all the data and values.

It is on the sanity check stage and I will post some info about it very soon (I am tempted to write a live writer plugin but I think thats me getting disctracted and I just need to get the core thing finalised).

This may all be pointless work and Ive spent too much time getting it to extract data no one wants but it turned into a personal challenge so I had to finish it hehe :P

 


Posted by: [mRg]
Posted on: 31/03/2008 at 11:58 AM
Tags: ,
Categories: General
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (3) | Post RSSRSS comment feed

Ladies wot Launchball - Launchball wins big at SXSW

Well I nearly fell out my seat when I heard that Launchball had won best game at SXSW and was even more suprised when I scrolled down and found it had won 'Best In Show' (almost like Crufts but with more gadgets). I was smiling all the way home knowing that something I had been so directly involved with makes so many people pleased.

As I said before the main kudos has to go to the amazing hard work of Henry @ Preloaded for an outstanding job creating the game engine. My work involved plumbing the underbelly, creating the web services that communicate with the flash, the Sitecore CMS and the underlying databases so to give the science musuem the freedom to create the type of system they wanted for the users.

I had a quick poke in the database and current data is as follows:

91501 Registered Users
57927 Custom Levels have been created so far

.. eek! Poor server :)


Posted by: [mRg]
Posted on: 11/03/2008 at 4:22 PM
Tags: , , ,
Categories: General
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

No Country for Old Browsers - IE8 Beta1

Well.. here I am .. running in IE8 , freshly released, along with a host of other goodies, from MIX08 happening right now somewhere in Las Vegas. Ive never really got on with Firefox .. I know, I know  .. shoot me .. but I find the temptation to install all those plugins a bit too much and soon poor firefox is crawling to a halt. So I was quite excited to get my hands on IE8.

Developer Tools 

At first I thought they had just included the regular developer toolbar into the main program but on further investigation the developer tools they've added have some very powerful features and should make many developers very happy (me included!) 

You will now find a lot of the debugging and CSS analysis features found in the new Visual Studio 2008 sitting in the 'Developer Tools' console.

Open it up and you find you can now set breakpoints in your javascript code the step through line by line

You can create watches, see autos and effect variables directly with the immediate console. All great stuff ! Also locating problems in CSS got a whole bunch easier (now I dont need have to switch back to Firefox just to use FireBug hehe)

Web Slices

One thing I quite like are the addition of Web Slices I just wanted to quickly note how to get them up and running :) As afr as I can see they are a way to wrap your normal feed in some custom HTML so it looks like it came from your site (so mine would have bad spelling and lots of transformers icons everywhere)

Its essentially creating a small piece of HTML within a page with the correct classes applied. IE8 then picks up these and allows you to subscribe to the 'slice' (jazzed up RSS)
(The important classes are in bold)  

<div id="myblogupdates" class="hslice" >
 <div style="display:none;">
 <a href="#" class="entry-title">Ultramagnus Blog Updates</a> ~
 <a href="#" class="entry-content">&nbsp;</a>
 <a href="http://www.ultramagnus.org/syndication.axd" class="feedurl" rel="feedurl">&nbsp;</a>
 </div>
</div>

 

If all is working, when you view the page you will see a new little swirly purple icon (where your RSS feeds normally appear) with the name of your WebSlice in it...

... clicking on the link will bring up a dialog asking if you want to subscribe to this webslice ..

.. once done the 'slice' will appear as a link in your toolbar.

You do need to tweak the code in your RSS feed to include a new namespace ..

<rss version="2.0"xmlns:mon="http://www.microsoft.com/schemas/rss/monitoring/2007">

 .. it will then use the HTML you defined originally to display the slice in the browser drop-down .. so you can now add a bit of personalisation your RSS feed :)

 


Posted by: [mRg]
Posted on: 05/03/2008 at 10:08 PM
Tags: ,
Categories: Guides
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (1) | Post RSSRSS comment feed

My Dina with Andre - Lurve those fonts ..

While I get stick in the office for my Visual Studio theme (Yes, I like a dark background, I'm old, my eyes hurt) one thing I must recommend is the Dina monospace font .. I started using it mainly for the output windows (black with a green font looks lovely!) but now its replaced Consolas as my IDE font of choice. I often remote desktop into work and Consolas, while being very nice, only looks very nice when using ClearType .. without ? .. freaking awful! I switched over to Dinas for my main font on a whim, loved it and havent looked back. Im sure another font will trump it one day but for now Ill stop rambling !

Dina Programming Font - by Jørgen Ibsen.

FYI - All my code snippets here use this font so if you want to see them how I intended please go, grab and install this right away (hey its only 1 file !) :)

( Some folks like Liberation which is a nice font too and worth checking out if your looking for some new fontage :P )


Posted by: [mRg]
Posted on: 07/02/2008 at 8:58 PM
Tags: ,
Categories: General
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Mass Code Auto - Team City

Over the past week or so I have been trialing Team City from JetBrains (makers of Resharper et al). There has been a lot of buzz around this product and I wanted to include all the bits I had found and my thoughts on it as a product.

First a bit of background, as well as our development team we also have an application support team. Its imperative that they can get access to the latest, working builds of all our companies code. After our move to TFS we setup a series of team builds that people could run to produce DLLs / websites etc. on demand. This worked to a certain extent but wasnt perfect. A while ago we changed to running CI builds for our major projects using Cruise Control .NET and havent looked back.

CC.NET is a fantastic tool, we were able to get all the things we want, NUnit tests, code coverage (NCover), documentation generation (Sandcastle), code metrics etc but the bus factor is quite high (ie if the guy who maintains it gets run over by a bus then the rest of the team is screwed cause no one else knows how it works). The mass of XML and supporting files (BATs or MSBuild tasks) that had to be edited to get a new project up and running was quite frightening and most of the time you are copying the same config code various times. I was starting to write a large document on how to get CI up and running for new projects when I realised it was really quite stupidly complicated and began hearing good things about TeamCity.

The test I set for myself with TeamCity was  - Could I get all the things I had running with CC.NET running in TeamCity in less time and with less fiddling with config files ? The answer was suprisingly .. Yes !

The installation was very straight forward and I was up and running with zero issues. I chose a simple project to start off with, I created a source control root to monitor in TFS. The integration with TFS was seamless and posed no problems.

Next I began to setup the build. This takes the form of a 7 stage wizard ... nothing frightening here .. just common sense settings such as when you want a build to be triggered (scheduling is very nice), dependencies and runners (the things that will do the actual build). It comes with a mass of runners for Java and .NET.

For this simple setup I used the 'SLN2008' runner to build from a VS2008 Solution File in the root of my project and set it to build when i checked something in. 

NCover

I used the Ncover MSBuild tasks that come with the program .. pretty standard stuff .. one for a summary and one for a full report. Only one thing to note is that the NCover help file doesnt list the correct enum for genearting a full HTML report out so I had to get busy with Reflector to find that one ! (Its "FullCoverageReport" btw!)

<NCover ToolPath="$(NCoverPath)"
    CommandLineExe="$(NUnitPath)\nunit-console.exe" 
    CommandLineArgs="$(TestDll)" 
    CoverageFile="@(CoverageFile)" />

<!-- Summary Page -->
<NCoverExplorer ToolPath="$(NCoverPath)" 
    ProjectName="$(ProjectName)" 
    OutputDir="..\Docs" 
    CoverageFiles="@(CoverageFile)" 
    SatisfactoryCoverage="80" 
    ReportType="ModuleClassSummary" 
    HtmlReportName="CoverageSummary.html" 
    Exclusions="$(CoverageExclusions)" />

<!-- Full HTML Report -->
<NCoverExplorer ToolPath="$(NCoverPath)" 
    ProjectName="$(ProjectName)" 
    OutputDir="..\Docs\Coverage" 
    CoverageFiles="@(CoverageFile)" 
    SatisfactoryCoverage="80" 
    ReportType="FullCoverageReport" 
    HtmlReportName="Coverage.html" 
    Exclusions="$(CoverageExclusions)" />

The next thing to do was to declare the coverage as artifacts of the build in the configuration section of the build.

Docs/Coverage/* => Coverage,
Docs/Coverage/files/* => Coverage/files,
Docs/CoverageSummary.html

The final part (and this only has to be done once!) is to update the main config so it adds two tabs for the summary and the full report (Dont worry .. if the files arent there the tabs arent shown) 

Locate the TeamCity config file (\.BuildServer\config\main-config.xml) and add two entries.

<report-tab title="Code Coverage Summary" basePath="" startPage="CoverageSummary.html" />
<
report-tab title="Code Coverage" basePath="/Coverage/" />

 

Sandcastle

I used a pretty standard MSBuild task for Sandcastle but ran into one problem (nothing to do with TeamCity directly) .. it wouldnt run .. the script worked fine from Visual Studio, worked fine from the command line msbuild but wouldnt run when executed from within TC, one of the sandcastle tools MRefBuilder exits with Code 1 (helpful!).. turns out you need to remember to add DXROOT as an environmental variable to point to the sandcastle folder. 

 

.. and thats it ! All setup essentially in a few clicks .. the great thing is the tasks like adding tabs and setting environment variables only need to done once and now I can copy the configuration and futher reduce my setup times. More importantly, anyone in the team should be able to look at this config and see whats happening and tweak if needed. (Lets hope the bus thing doesnt happen quite yet though)

My experience with TeamCity, so far, has lived up to expectations .. and hopefully Ill be able to tweak it more as time goes on. Ive also found that the new vs2008 web deployment project gives a great framework for adding little MSBuild scripts even if your not used to using MSBuild .. but maybe ill blog about that another time as Im going off on a tangent ! 

Pros 

  • Most basic builds are created in a few clicks.
  • Duplicating build configuration is a single click - simple enough but this is really time saving.
  • Artifacts - This feature, i would imagine, is designed for those people whos projects produce MSI installers etc but as a web developer I found this gave me a nice persepctive on what the actual deliverables of a web project are. In the past a build would deliver the contents as a whole web dir but now ive found myself zipping up the different parts (bin dir / main site) which should will make it more maintainable for our support team as they can just grab the bits they need !
  • Custom tabs for different reports (NCover etc.)  - This means if i can add anything I want to as long as its added to my artifacts.
  • Personal Builds - Bah didnt have time to talk about this but its like a sort of gatekeeper .. you can get the TC server to build your new code changes and check they work before you officially check it in .. very cool !

Cons

  • Doesnt support triggering a TFS team build (as far as I can see, I had to use a custom plugin for CC.NET) - Not a huge issue but would be a nice-to-have. 

Posted by: [mRg]
Posted on: 01/02/2008 at 7:24 PM
Tags: , , , ,
Categories: Guides
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (4) | Post RSSRSS comment feed