Monday, 26 May 2008

Retrospective on my asp.net MVC talk

I'm publishing this a bit late, but I took a few days (a whole two of them) without working. How refreshing!

In an effort for a more transparent process, here are a few things I think went well and didn't go too well. If you've been at the talk I would absolutely love your criticism. Practice makes perfection, but before that it makes for nicer presentations and a less worried Sebastien!

Preparation god damn it!

The font-sizes were all wrong in everything but the code-editor, this is quite unacceptable and certainly not like me at all. So be prepared if you install vs 2008 SP1 beta, it will reset all your settings. That explains the lack of proper configuration in visual studio. And of course, a problem never comes alone, vs refuses to start under my Presentation account that is set with ridiculously large DPI setting. But it all comes down to me installing this stuff too late, which left me no time to make sure everything was configured properly. Apologies to the audience, I should have had a VM up-and-ready with all my content. And apologies to myself for installing a beta service pack on my main development machines.

Tools

All the usual presentation tools were not installed on that laptop either, so no ZoomIt and no Keyboard Jedi. Again, with a reinstall of vista a couple of days before, I just didn't have the time to get it right.

One thing I find difficult is choosing a screen mode. When showing code, I want to show you my Visual studio and whatever other programs get spawned by it (ie, firefox, the command prompt) while still seeing them on my screen. For powerpoint, I want to keep presenter-specific stuff from your eyes (a timer, some notes, and in general the whole content of the slide you'll see appearing as I talk).

I need a hybrid between Clone and Span modes. I may have something working, so my next talk will guinea-pig the idea. I'll blog about it after trying it out. :)

Not having slides...

Some people didn't completely see how the asp.net MVC and the REST part of the talk connected together, and maybe I should've introduced that at the beginning on the slides. But if you know me, I don't like slides and will avoid them at all costs.

This is the first talk I give where I put some content on slides, to refresh everyone on MVP and MVC and how the models differ. I like how visual it makes the explanation, but I'd rather manage to do it graphics only, with no text whatsoever. That requires more work, a tiny bit of animation and very good graphics. Nothing that can't be done with enough time for pimping it up.

Body language

I used the MacBook remote to change slides, and the freedom to move around to move slides is next to none. I also find that having the remote to hold from the tips of my fingers helps me avoid leaving my hands hanging. Hold something to keep your hands at chest level, it puts your body language into explanation mode. Relax and put one hand in your pocket and you switch to opinion mode.

Eye contact is the best tool to calm anxiety. You'll always find a couple of people in the audience being very expressive, that lets you judge the rhythm of the presentation. There's nothing worse than an expression-less audience.

Messy content

I'm a bit in-between two waters on this one. The whole point of the talk was to see what toolkits you can use today to do REST applications, but, for various reasons, I fit in there an introduction to asp.net MVC as a first part. That just doesn't flow well, and I think I'll split those two in two different presentations: asp.net MVC introduction (I have some AJAX stuff to make that presentation complete), and REST today, rest tomorrow. They can both stand on their own feet, and it would leave me more time for doing what I prefer doing: talking rather than coding and rushing.

I'm not funny

I tend to make jokes during the talk, they're usually completely spontaneous, but they fall flat every time, except for a few friendly grins from people I've met or talked to before. I shall prepare my jokes in advance and only use them after having tested them. But not on animals.

Speak more slowly

My voice level seems to be alright, but I speak too fast. And I have those pet words that creep in, amongst them "I think" (very annoying one I have a lot of problems getting rid of, even in day-to-day conversation), and Ok (very patronising, hate it, think I managed to mostly kick it off my presentations).

It's quite funny how the brain gives you those little fetish words. I think they creep-in because they trick your brain think there's a rhythm to what you're saying, when simple punctuation and sentences should be enough. It may also be the case that they give your brain enough time to reformulate when you're mid-sentence and unsure about what to say next. Again, preparation is the key.

Have different solutions, not different projects

This one bit me during the presentation. As I prepare the code for all the major steps, I end up with the same project at different stages, and I made the mistake of keeping all the projects in the same solution, often resulting in the wrong code being ran when pressing F5 and the wrong files being shown when I expected to show some code.

From now on, I'll keep all the projects in separate solutions.

Conclusion

I really like giving talks. It is a bit frustrating to come up with new material every time and only use it once, as you don't get the opportunity to retrofit what you learnt from presenting it once. Hopefully that will change as I get new speaking opportunities.

Wednesday, 21 May 2008

Presenting at the London .net User Group: Put your webforms to REST - how to build rest-y architectures with .net

What:
With the raise of the web 2.0 meme, more and more web applications claim to support REST architectures. We'll explore together what is REST and what is not, and how we can write a testable web application that supports the REST concepts on the asp.net platform, with a code-intensive overview of current toolkits (asp.net MVC and others).

Where:
MRM Worldwide London
76 - 80 Southwark Street , Bankside Studios, London SE1 0PN

When:
Tomorrow Wednesday the 21st of May, 18:30

Why:
This, I have no idea of :)

That is, if I get Visual Studio 2008 SP1 installing properly on my demo laptop, which is no small feat in itself, or face a frantic rewrite of some of the presentation tomorrow.

Wednesday, 14 May 2008

Reflecting on my last project

Today is a day off, as I've accumulated 36 hours of work between Monday and Tuesday and needed some rest. The last project I've been working on has been one of the most interesting I've had in a long time, not only because I took more responsibilities than usual, being both a lead dev and as a scrum master, but because of the amount of technology we've fetched in one app. To give a quick run-down:

  • Fluid database design with an object-based linq2sql database (no dbml file and no sql files in the whole project)
  • Sql Compact Edition
  • ado.net synchronization services to sync to a central database, and hopefully the sync framework for multi-party syncrhonization
  • WPF all the way, with a ViewModel way of developing
  • Castle stack, for Windsor and a bit of DynamicProxy2 love
  • 3G support for an always on experience

I've learnt quite a few things in the process, so here's a few reflections for my own benefits.

  • When you don't know what you're building, you're going to have a hard time knowing when it's done
  • Working under pressure can be fun, but it's exhausting and it does highlight a failure in the planning part. We're getting better but we're nowhere near there yet
  • It's fun to see people with a background go around in WPF. It always starts quite code-centric and evolves into more XAML as time goes by
  • I still don't see people using Blend for anything meaningful. There's a wide range of reasons why, from crashes to not liking esoteric Xaml to the recording model. It doesn't go down well with either populations right now, at least as far as WPF is concerned.
  • The only reasonable way to monitor the correct use of patterns and abstractions is to do it continuously. Not paying attention to the code base and coming back with changes weeks later is not a good idea, and a complete failure on my part. I need to get better at agreeing, explaining and enforcing design decisions.
  • No one can work on several projects within a company and stay focused. This doesn't work at all. From now on, I will flat out refuse to work on  something else in the same day. If you want my time for two projects, my minimum time unit will be a day. Interruption decreases my productivity so much it's unreasonable, and the project (and my nerves) suffer.
  • Frameworks that hide all of their internal implementation suck big time. Understanding object tracking in linq2sql is not easy or enjoyable, and bite you. Badly.
  • Frameworks that show all of their internal implementations suck big time. Castle Windsor (at least RC3) throws exceptions in all the wrong places, and make dealing with registration more painful than it needs to be (when it works at all).
  • Designers and UE people *need* to be involved throughout the process, and work on the same stuff as the rest of the team. The way people think they can go off and work on the UE or the design on their own schedule, with only validation from tech (when they don't send the work done the day before a release) is driving me absolutely insane. This doesn't work for them (we can tell them how much more flexibility they can have in their own design), it doesn't work for us (they provide diagrams of stuff we've already delivered, or stuff that is completely limiting the capacities of the platform). It's the typical waterfall model, and fall and fail it usually does.
  • Someone needs to wake up and realize that the technology is not there to support the design, and the design is not there to put a nice face on technology. They're two sides of the same silver coin, they need to work together to deliver. That's what Apple does and it works great.
  • I'm always amazed at how little is still invested in most of my clients companies around supporting other development teams. With a core team of a couple of peoples working to support other teams and evangelize the company's infrastructure, any company would save *so much time* on all other projects, from enforcing good standards, deployment procedures, automation etc. Think a few weeks per project.

Overall, a very good project, a great team and a freedom that I don't have very often with clients. I think it'll be difficult to move to my next project, the comparison will suffer!

alt.net drinks moved, only slightly

Got a message from Catriona, and the original location for our alt.net beers event was fully booked, so it's now around the corner from the previous location. See the original post for the details.

Wednesday, 7 May 2008

Implementing INotifyPropertyChanged with DynamicProxy2

22:30 and still working on various bits and bobs, so I thought I'd take a well deserved break to tell you about one nice way to implement INotifyPropertyChanged, the one and only interface any class that will be bound in WPF should be implemented.

I used to (circa .net 2) not see a bit issue in this kind of code.

public class MyClass : INotifyPropertyChanged

{

    private string _myValue;

    public event PropertyChangedEventHandler PropertyChanged;

    public string MyValue

    {

        get

        {

            return _myValue;

        }

        set

        {

            _myValue = value;

            RaisePropertyChanged("MyValue");

        }

    }

    protected void RaisePropertyChanged(string propertyName)

    {

        if (PropertyChanged != null)

            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

    }

}

But I've been badly spoiled by automatic properties in C# 3.0, and this all sounds like a lot of noise. How great would it be if we could instead simply have the following.

public class MyDreamClass : INotifyPropertyChanged

{

    public event PropertyChangedEventHandler PropertyChanged;

    public string MyValue { get; set; }

}

Definitly much cleaner.  We're going to use DynamicProxy2, which is part of the Castle framework, and is used amongst other things in nhibernate.

The process is quite simple. You ask a ProxyGenerator to create a type for you, and pass it an interceptor object that will... Intercept any call!

First, let's clear up our class. Because the object generated by DP2 inherits from the original type, it needs to have a virtual modifier on the property. Furthermore, I wanted to add an attribute to specify which properties were to trigger the notification.

public class MyBetterClass : INotifyPropertyChanged

{

    public event PropertyChangedEventHandler PropertyChanged;

    [Notify]

    public virtual string MyValue { get; private set; }

}

Now, let's see how we create the object.

static void Main(string[] args)

{

    var proxy = new ProxyGenerator();

 

    MyBetterClass myClass = proxy.CreateClassProxy<MyBetterClass>(new NotifyPropertyChangedInterceptor());

 

    myClass.PropertyChanged += (src,prop) => Console.WriteLine(prop.PropertyName);

 

    myClass.MyValue = "testValue";

}

Fairly simple so far. Now let's see the meat of the code, the interceptor.

public class NotifyAttribute : Attribute { }

public class NotifyPropertyChangedInterceptor : IInterceptor

{

    public void Intercept(IInvocation invocation)

    {

        // let the original call go through first, so we can notify *after*

        invocation.Proceed();

 

        if (invocation.Method.Name.StartsWith("set_"))

        {

            string propertyName = invocation.Method.Name.Substring(4);

            var pi = invocation.TargetType.GetProperty(propertyName);

 

            // check that we have the attribute defined

            if (Attribute.GetCustomAttribute(pi, typeof(NotifyAttribute)) == null)

                return;

 

            // get the field storing the delegate list that are stored by the event.

            FieldInfo info = invocation.TargetType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)

                .Where(f => f.FieldType == typeof(PropertyChangedEventHandler))

                .FirstOrDefault();

 

            if (info != null)

            {

                // get the value of the field

                PropertyChangedEventHandler evHandler = info.GetValue(invocation.InvocationTarget) as PropertyChangedEventHandler;

                // invoke the delegate if it's not null (aka empty)

                if (evHandler != null)

                    evHandler.Invoke(invocation.TargetType, new PropertyChangedEventArgs(propertyName));

            }

        }

    }

}

And that's it. Get the field in which the event is stored and invoke it whenever a property has been modified.

Sunday, 4 May 2008

Thought of the evening

MSBuild + SqlCompare + DataContext == FluidDatabaseDesign

The tale of the 6.4 Megapixel desktop

Just upgraded my development environment, here's the picture.

013

The laptop looks tiny next to the screen, but it is in fact a high res MacBook Pro, 1920x1200, driving as a secondary screen an Apple Cinema Display 30" for an added 2560 x 1600.

That's freakin' 6.4 megapixels of vista goodness! Surprisingly enough, Aero runs without a hitch.

Couple of other interesting points: new apple keyboard as I fell in love with the feel of the MBA keyboard, the mouse is not the one i usually have (but ran out of batteries). And Prada sunglasses for the one day of sun we've had in London so far.

As for drinks, the coffee mug is the property of the client at which I keep this equipment, and the can of Redbull kinda explains the name behind my company name: caffeine IT :)

Saturday, 3 May 2008

IIS and asp.net URL validation weirdness and links

In my Migrating to IIS7 post, I highlighted that building REST frameworks that do meaningful things with Urls is hard on microsoft's platforms.

I encourage you to go and read the comments left by Mike Volodarsky on the issue. He's a Program Manager at Microsoft. Having people from the team building IIS7 responding to people like me highlighting issues shows how some teams really engage proactively with their customers. Kudos!

The other team at Microsoft that understand REST a bit (and IMO the most out of all the teams working on this), is the Astoria team. And of course, because they do funky stuff with their URLs, they hit the same issues as me. So here's a link on how to deactivate some of the checks asp.net does. Nasty registry editing...

I really wish asp.net could recognize when an IHttpHandler does not want validation and let it handle the request, its validation and etc.

Alt.net London Beers #1

[Update: new location, see below]

Here's the latest development. The alt.net London Beers event is being moved!

Skills Matter is organizing a talk by Gojko Adzic on the Castle Framework on the day we originally planned for the drinks. As everybody has shown strong interest in attending both events, Skills Matter has been kind enough to help us organize the drinks in the Crown Pub in front of their office, so you can now attend both events.

Not only that, but they have also opened the possibility for another presentation on an alt.net subject, so if you feel like presenting, drop me a mail!

I have to thank Catriona at Skills Matter for sponsoring the alt.net London Beers event and inviting all the alt.netters to attend the Castle presentation, as well as Gojko for suggesting the merge of the two events.

So here's the recap:

We'll probably move back to the planned Tottenham Court Road location for our second meet, on the 16th of June. Keep your calendars open!

Tuesday, 29 April 2008

Using Rasta #2 - Rasta in it's simplest form

Lack of time and sleep pushes me to be very lazy and present only the most trivial example of what Rasta was built for. Hopefully the future editions will become more interesting.

Rasta does many things, but one of the things you can use it for is Url rewriting for webforms. Simply declare the following in your global.asax file:

using (RastaConfiguration.Manual)

{

    UriSpace.HasTheUri("/home").ForThePage("~/pages/default.aspx");

}

And if you want to provide a url that matches a specific language, just expand this a bit:

UriSpace.HasTheUri("/accueil").InLanguage("fr").ForThePage("~/pages/default.aspx");

This will automatically set the language for the current request in the correct language, while still going to the same aspx.

Another fancy thing in Rasta's manual declaration is the using block. All the configuration needs to happen within that block, and is only applied when you exit the block. The fluent api is built using a chain of language elements that form a sentence. Each element you add to a sentence either replace it's predecessor in the list of sentences, or initiate a new sentence, and each fully-formed sentence will get called whenever the Dispose method is called on the object returned by the call to RastaConfiguration.Manual.

How do sentences get added? When you enter the block, the new object returned by the Manual property sets a CallContext that stores that list. When it is disposed, it calls the chain of sentences to configure itself. And finally, it makes most of the routing structures read-only to optimise them (a typical example is building a read-only tree of the Urls you can use for a site in a structure that is more efficient than if it was write-only).

That also means that trying to apply a configuration at runtime to replace the existing configuration will only succeed when the whole of the operation succeeds. This happens by only writing to a new copy of the configuration data, and committing the write if no exception happened. If you got the configuration wrong, the previous configuration will happily stay on to continue serving request.

Saturday, 26 April 2008

Migrating to IIS7

Over the last couple of weeks I've been upgrading my Rasta framework to support IIS7. Here's the highlights:

  • I automatically detect the base Url address for a site based on the application path and the first requested Url, at which point I create all the routing tables. This used to be at the end of the configuration code that used to run in Application_Start.
    You cannot access HttpContext.Request from there anymore, so this has to change. Right now I delay the discovery at a later stage (on first request), but this solution only support a single domain per web app.
  • DefaultHttpHandler is not supported anymore, so I have to implement the equivalent functionality for when Rasta doesn't recognize a Url and try to delegate to a registered handler. This probably won't land for a couple of weeks.
  • More Url processing weirdness than IIS6, with no support for unencoded + in paths. This goes against the RFC for uris that specify quite clearly that segments in a path should be opaque until handled. IIS considers it has the right to handle them and crashes. This is seriously limiting our ability to provide a virtualized Url space on a web site (any character not supported by the file system will automatically crash the request before a handler is called, as asp.net tries and do a MapPath, even when you percent-encode the special chars. I consider this to be quite unacceptable and limits my choice of Uri.

I also ended up with some weird issues where upon building, the ccnet machine would see its access to web.config denied, and the only solution is to go and copy the files manually the first time around. I'm still trying to investigate what happened there.

Wednesday, 23 April 2008

Talking about Linq2Sql and Expression Trees tonight

If you're in London, why not join us tonight to celebrate Visual Studio 2008 and .net 3.5 releases at the London .net user group? We'll be discussing some of the new features in the bits, and I shall be presenting some useless code that shows integration testing and fluid database design using Linq2Sql, with some expression tree goodness.

Monday, 21 April 2008

Announcing the Alt.net London Beers event

[Update: The event has been moved. See the latest location and stuff here]

Many people are keen on continuing the discussion that was started by the alt.net conference. While the altdotnet-discuss yahoogroups mailing list has been very active, I feel that much more can be achieved when meeting and seeing people.

It's also nice to be surrounded by like-minded people that face the same challenges you do when you try to promote alt.net ideas around you, to your colleagues, your employer, your sister... And of course, being surrounded by very bright people that love what they do and spend their free time getting better at it is fantastic.

In the spirit of providing something less grandiose than a conference and more personal than a mailing list, I hereby declare created the Alt.net London Beers. It's an event, in a pub, with whoever wants to come, subject to be decided on the day. Bring your laptop if you want, but more than anything bring yourself, and let's get the conversation continuing.

This is an experimental regular meet-up, and who knows, if it's successful, we could do it a bit everywhere. Make this a success and come along!

Using Rasta #1 - An introduction

Rasta has many meanings, but for the purpose of this blog, it is the REST Architecture Solution Targeting Asp.net. I've written this framework for one of my clients, and I'm in the process of trying to get the rights to open-source it and deliver it to the world. But as many things, it takes a lot of time.

That said, I've been wanting to blog about it since I started working on it, so now is as good a time as ever to start showing some bits on how to use it. It will let my beloved readers criticize the way the API is built, which will let me involve it for the better, and will also serve as a reference point for my client's employees to have some sort of reference on how the framework works.

Rasta, in essence, is a framework that lets you think about your site in terms of resources, how they are accessed, and how representations of such resources get served to clients. Let's compare this approach with other approaches we've seen over the years.

WebFroms

In this model, your Url is bound to your page. Because of the post-back model, any interaction with the system is done as units within the webform. http://example.org/Customer.aspx provides a view of your customer, but is also where data gets posted back. The posting of the data itself can be either about a customer, or about a button, or about an event one of the webcontrols can trigger. It can be a bit of anything.

This has a couple of very bad consequences. Only the asp.net framework can post data to /customer.aspx, because it's the only one knowing the format. This makes testing webforms terribly difficult, and patterns like MVP only solve the problem at the unit-testing code level, leaving a lot of code non-testable. It also makes integrating with other systems more painful than it should be. And it doesn't leverage hypertext in any way, because state is transferred across postbacks through either the session or the viewstate.

In this model, the resource is the page, and does many things. It's completely unrestful.

The MVC model

A lot of noise is being made about the new asp.net MVC framework. MVC as a pattern solves some of the issues introduced by webforms. Your Url is bound to a controller that receives the request, act upon it and send you to a view based on the result of the operation. This solves the unit-testing issue. To a certain extent, it also solves partially the integration issue, as your controller can act upon the http operations (GET PUT POST DELETE etc...).

That said, your Url is bound to a controller's action, so you would end up most of the time with a url looking like http://example.org/Customer/GetCustomer. You're mapping one web action to an operation. While you can override that, it's not the default. Another issue that makes it unrestful is the lack of leverage of hypertext, as links are not used for anything meaningful unless you implement that yourself.

In this model, the resource is the controller, and does quite a few things. It's up to you to define the semantics. It's quite unrestful.

The WCF Rest model

WCF in 3.5 has some support for something quite similar to the model provided by MVC. Your WCF service can be mapped to a specific Url and encoding (xml and json), and it will support a Get and a notion that team came up, an invoke. The rationale being that there was not that much of a different meaning between POST/PUT to justify mapping them differently, and that they all end up invoking a service.

This is a service-centric view that maps very poorly with the web. You're tying your Url to a service operation, and limit your representations to the two kinds provided by WCF. Its great for unit testing, not so much for the web.

I'll also have to question any team having spent that many years providing an abstracted toolkit that lets you not think about the plumbing (although this is a very big white lie) trying to implement a REST architecture which is, by definition, about the plumbing, leveraging Http verbs and hypertext.

In this model, the resource is the service, and does something. It's quite unrestful as well.

The Ado.net Data Services model

Formerly called Astoria, ado.net data services is the most restful of the APIs Microsoft is working on.

With Astoria, you map a Url to an entity (ado.net entities), and you interact with those entities based on AtomPub, which is quite restful. That said, it is about exposing your existing entities model on the web, and support for POX / POJson has been dropped from what I understand.

It does leverage hypertext (because AtomPub does), and it does have some content type negotiation. The big issue here is that it doesn't integrate with any of the previous models we've seen, and is yet another API that wants to have the Urls in your web application to itself. It supports data, and data only, so you won't be able to leverage an asp.net MVC page to serve a resource as text/html, and still support application/json for clients that want this format.

In this model, the resource is the entity, and you can do restful things with it. But it only deals with one aspect of developing rest applications, and has poor integration with the other components Microsoft is developing.

The Rasta model

Rasta takes a radically different approach. Every Url is mapped to a resource. In other words, http://example.org/Customer is mapped to a resource of type CustomerEntity. Each resource type can have many resource handlers that are responsible for acting upon a resource in a certain way. This could mean retrieving a resource, updating it, etc.

When you access a Url to get to a resource (called dereferencing), the first step Rasta is going to take is to try and locate which handler can be used to access the resource, based on the request you made. For example, http://example.org/Customers/{name}  is a Url that would associate a meaning of name with a value to the handler. From that name, the handler would return an instance of the resource (an instance of CustomerEntity). In other words, a handler is responsible for dereferencing a Uri based on a request to get to a resource, and to act upon it if required.

And that's it. The handler is not involved at any point in how the request is processed or how the response is sent to the client. This is the responsibility of the codecs.

A codec is a component that, to simplify, convert a Content-Type sent on the wire to an object and back. In essence, if your handler returns an instance of CustomerEntity, the codec will be able to convert it into an xml stream representation, or whatever wire format the codec supports. Out of the box, the current Rasta svn repository has support for webforms (for html rendering), json and xml, and I have some working code supporting AtomPub, atom, rss and even support for some WebDav, although all this is mostly prototype quality.

In this model, the resource is the resource, and its representations are handled by codecs that are loosely coupled from the resource itself. You could see it as an application of the semantic web, but based on types and objects. In other words, it works and is good enough.

Conclusion

Rasta's architecture brings quite a few benefits:

  • Loose coupling between the representation of a resource and the code that does useful stuff with it.
  • Automatic support for content-type negotiation, letting the client decide what is the best format to receive a resource in.
  • Resources don't change, but implementation of the handlers can
  • Adding new content-types is independent from the rest of your code
  • Adding things like AtomPub becomes very easy
  • You have only one way to do both your html representation and the computer-friendly ones.
  • Oh, and it's still compatible with webforms so you can retrofit existing work in the same site
  • And as a nice to have, it runs on standard .net 2.0.

There are many other parts to Rasta, but those are the basis of what it is, why it was built, and why I'm so thrilled about it.

Sunday, 20 April 2008

An extension method, just because I can.

Going to the dentist is an awkward experience. You know you have to use their service or your teeth will rot, but the experience is just not enjoyable.

That's how I feel about string.Format. I use it all over the place, but find it incredibly out of place. Thanks to extension methods though, I can propose a nicer syntax. Here's a snippet from a site I'm building for one of my clients, using my rasta REST framework and linq2sql.

[HttpOperation(HttpMethod.GET, ContentType=new HttpContentType("image/*"))]

public ResourceOperationResult GetMovie(string filmName)

{

    var movie = _movies.FindOne(movie => movie.UrlTitle == filmName);

 

    if (movie == null)

        throw new ResourceNotFoundException

        {

            Message = "The movie {0} wasn't found in the database.".With(filmName)

        };

 

    return new ResourceMovedTemporarilyResult { NewResourceUrl="/library/tempfilm.jpg" };

}

Notice the extension method there? I just find it sweet. Here's the very simple extension method.

public static string With(this string text, params object[] values)

{

    return string.Format(text, values);

}

There you are, a shamefully simple extension method, just because I can!

Computer naming scheme

While looking around for nice visual studio color schemes, I stumbled upon Commonality's Naming your computers post. I'm happy to know I'm not the only one doing that.

All the computers in Caffeine IT are named on the theme of light. Here's a rundown.

  • Luciole, Lueur: decomissioned machines I had when in France
  • Aurore: A dell machine that I am now disposing off, mainly because I can't be bothered to rebuild it.
  • Tinkerbell: my main dev laptop, MacBook Pro running Vista Ultimate.
  • Photon: The MacBook Air running Vista Ultimate.
  • Lumiere: The Sony TP1E that is the test machine for my yet to be released Vista media integration software, and connected to the big LCD screen. Only way to test 3-feet user experience is to set-up a machine with no keyboard and no mouse, relying only on the remote. Running Vista Home Premium.
  • Blackhole: The custom-built Xeon machine that holds my dev environments and the multi-terabyte RAID5 array. Running Windows Server 2008 Core with Hyper-V
  • Glimmer: The build server, web uat environment, and other bits and bobs (server 2008 Standard)
  • Pulsar: The backup server (windows home server)
  • Hubble: A video streaming server on Windows Server 2003 R2.
  • RayOfLight: The iphone :)

And before you ask, of course I need that many. :)

Thursday, 10 April 2008

Changing my blog subtitle

You know you're starting to be read too much when people get passionate about name-calling you. I'm very proud it is now happening to me, as Anonymous has proved in the first aggressive comment I've had on this blog.

That said, Anonymous said the sub-title of this blog should be renamed to Ramblings of a self-congratulatory, self-proclaimed, egotistical doofus.

So this is now my new tag line. Whatever you think of me, you're reading, so that's a communication channel open. If you disagree with me I'll probably learn something from you. If you agree I'm pleased I am not on my own in my rambling.

We're all on a journey. I'm pleased mine involves anonymous and prominent people questioning my opinions. It makes me a better geek, and that is what this blog is all about.

Saturday, 5 April 2008

referrals from internal wikis

Just found some referrals from wikis used internally at a previous client, full with the reference of the page, project code-name, etc.

I wonder if anyone realizes how much information you're disclosing by just linking...

Friday, 4 April 2008

IoC - The container is not a carpet, it's the floor

[Update: Removed references to the company, because while I may rightfully be bitter, it is irrelevant to the content of this post, and I don't want the two issues to be mixed. Apologies to my readers.]

Jason Gorman, who I've had the pleasure of crossing the path of at one of my clients, is asking an interesting question about containers: are we hiding sweeping dependencies under the carpet?

Questioning the value of a container is a very recurring topic amongst developers that haven't been ripping their benefits, and I think it deserves a post in its own (that, and the fact that Jason's blog doesn't seem to let me post comments.)

First comes first, you have to think about what a container brings you, as it does bring you several things.

  1. Dependency injection
    This relieves you of having to chain objects that depend on each others, as the container is responsible to get a reference to each component your component needs.
    This has the added benefit of enforcing the declaration of your dependencies in the component's constructor, making tracing dependencies much easier in a code review. It's also a good thing for discoverability of the code during test, as knowing what is required for your component to be put under test is very much in your face, on the first line, when you create the object. And that is a good thing.

  2. Inversion of control
    Your code no longer has to create the object to use it. You just don't have to think about it when you write your code. Of course, that doesn't mean you can ignore how the object is built, but this enforces a separation of concern: the consumer of the object doesn't have to know a whole lot to consume, and the creator of the object doesn't have to know much about the use of the object.

  3. Lifetime management
    Because you no longer use new, you can rely on the container to decide which object it gives you and where it exists. That means that asking for an IMyAppContext will retrieve the object from the HttpContext for you when it's needed, with no HttpModule or painful initialisation code anywhere.
    And if you work on composite applications, you can create for the container a new way to store the objects, be it per component, per form, etc. You write that code once for the container, and never again will you have to care about the how.
    Code reuse is a good thing.

  4. Centralized component management
    This one is less obvious but makes a lot of sense. When you want to know how an object is initialised and where, it's centralized in one place. One file gives you all the dependencies that exist in the system.
    This also makes it possible to run code in your integration tests (or as a post deployment task) to ensure all dependencies are resolvable, and this, again, is a good thing.

  5. Lower the cost of change
    This one becomes obvious when you've been using containers for a few iterations. Taking on a new dependency is fantastically easy: add a parameter to the constructor and you are done. No consumer will ever have any code to change. Less code to change makes me happy.

There are many other things a container can do, but those points are shared across Unity, StructureMap and Windsor (I specifically ignore spring.net in my analysis, because I have next to none experience with it), and even by the COM+ catalog.

Jason probably knows each of those points very well. His doubts are about the centralized place in which those components are declared.

To a certain extent, I will agree on a small thing. Storing your dependencies in an xml document is not the most natural way to handle them, especially when you start playing with generics.

In the project I worked for in that unnamed media company, I built a small object builder as I was  asked not to take more dependencies on external frameworks, hence I couldn't rely on a container. The dependencies were stored in the config file, and object instantiation is manual (no DI there, just IoC). A super-factory was a good first step to start decoupling components and get more visibility on what was going on in the code. But it's not as nice as having DI, and certainly not nice having types written in xml.

But you don't have to keep these things in config files. If you want to keep your dependencies as part of your project's code, go for it. Windsor has AddComponent, SturctureMap a fabulous Fluent api.

And if you don't want writing all that code, you can use Binsor for some boo love.

What I will strongly disagree with is part of Jason's analysis. A container doesn't hide dependencies from the compiler, because it can't. Component A implements interface A in assembly A. Component B depends on interface A and lives in assembly B. As far as I understand it, they all get compiled by a compiler. They are linked so dependencies are resolved when compiling the construction. That's why you declare your dependencies in the constructor!

But where Jason is right is highlighting that the configuration file is a dependency, and should be tested as such. This is exactly why you should have a stage environment that reproduce your live environment, and run your integration tests there. If your test don't detect a missing dependency declared in your config file, your tests are badly written or not extensive enough. You're just blaming the tool, blame the developer.

One thing that seems to be a common misconception is that you should know about your physical dependencies, aka knowing that component A depends on component B. This is the wrong way to look at the problem. Component B should depend on a contract it has for a service it's being provided. The glue between components is the container, and the guarantee that this works fine is your test. As for understanding your dependency graph, that's what code coverage and NDepends are there for. Anything else is only relevant to graphs people want to put in visio, which I would argue is irrelevant.

That said, it wouldn't take much work to trace those dependencies by asking the container. Maybe a day of work if you're into graphs. But if your dependencies bite you, you have a much bigger problem than tracing graphs, and that's usually a collapse in applying what is required for containers to work well: contracts, single responsibility principle, high cyclomatic complexity, poor code coverage, no integration tests, and self-containment of components to reduce complex interactions...

Friday, 21 March 2008

Managing managers, another point of view

ErricGu just posted about the role of a project manager in an agile environment.

the person who takes that role needs to be mindful of that and willing to push any decisions that rise up back down to the time. If the person has previous experience (and a preference) for “being in charge”, they are unlikely to do a good job in that role.

Maybe I'll point Ralph (my imaginary manager from hell) to this post next time I encounter one.

Thursday, 20 March 2008

What's next with cloud storage?

FolderShare and SkyDrive come from the same team (the original guys that were bought by microsoft). SkyDrive has support for feeds.

The Microsoft Sync framework supports synchronization through syncfeed.

See where I'm going with this?

Monday, 17 March 2008

HttpUtility.UrlEncode considered harmful

An interesting issue was recently raised against my rest framework. The following URI template was used to access a fictional customer:

/customer/{customerName}

When generating an email pointing to this customer, another part of the system was adding the following url:

http://example.org/customer/john+doe

At this point, my framework returned a 404, even though John Doe exists in our database. So what is happening there? When setting a breakpoint on my CustomerHandler.Get(string customerName) method, customerName ended up with the plus sign present. Why wasn't it converted to a space? Here's some PowerShell code to demonstrate. First, let's create a Uri object and see the result.


59> [System.Uri]"http://example.org/folder with space" | select absolutepath, absoluteuri,originalstring | fl


AbsolutePath   : /folder%20with%20space
AbsoluteUri    : http://example.org/folder%20with%20space
OriginalString : http://example.org/folder with space

 

As you can see, the space is encoded with a %20... Now let's see what happens if I call HttpUtility.UrlEncode.


61> [System.Reflection.Assembly]::LoadWithPartialName("System.Web") | out-null
62> [System.Web.HttpUtility]::UrlEncode("folder with space")
folder+with+space

Now the space has been replaced with a plus. Let's review the msdn documentation for the UrlEncode method.

If characters such as blanks and punctuation are passed in an HTTP stream, they might be misinterpreted at the receiving end. URL encoding converts characters that are not allowed in a URL into character-entity equivalents; URL decoding reverses the encoding. For example, when embedded in a block of text to be transmitted in a URL, the characters < and > are encoded as %3c and %3e.

Obviously the documentation doesn't really described the behaviour that we experience. So is a URL encoding within the scope of the http protocol supposed to have a + or a %20? Who's right and who's wrong?

Let's travel together along the spec stack we use when dealing with html content, and find out who, between Uri and UrlEncode, is right.

RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax

This specification covers URLs in their generalized form, and that's teh specification that defines percent encoding of url, where any reserved character have to be encoded as a percent sign followed by the two-letters hexadecimal representation of the codepoint.

This actually would imply that the correct encoding form of the URL should be http://example.org/customer/john%20doe.

It also specify that the plus sign is a reserved character, one that can be used by a scheme to delimit stuff. Defining what that stuff is should be the scheme's responsibility. The scheme here is http, so we switch to the next spec in our stack.

RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1

This specification, even though it's been written earlier than the lastest URI, does specify some scheme-specific information on how URLs work and what they represent. Going through that specification, HTTP defines some specific behavior for Uri, for example that http://example.org, http://example.org:80 and http://example.org/ are all equivalent.

The specification also mention the equivalence of the percent encoding we've already seen. Still nothing about the plus sign. Which leads us to the third specification that's involved here.

W3C Recommendation: HTML 4.01

Note that I ignore the XHTML 1.0 specification as it is mostly only a reformulation of the html 4 specification in an xml format.

The HTML specification reminds the reader of URIs and how they work. There are two interesting bits in the specification. The first one, entitled non-ascii characters in URI attribute values, defines once again the percent encoding scheme. Still no trace of that plus sign.

And then you discover the gem of the application/x-www-form-urlencoded content type. In it, we find the usual url encoding, with the addition of the space being encoded as a plus.

Interestingly enough, this format is only to be used when attaching content within a POST http request, and has nothing to do with URL encoding, except for the similarity of writing key=value&key2=othervalue to encode named values.

Conclusion

So there you have it. The content-type used by html to send form content is an html specific content sent as the payload to a post http request. It has no bearing and no compatibility with either http or URLs. If you generate or consume URLs, the plus sign should be opaque.

In other words, stay welll away from HttpUtility.UrlEncode.

Wednesday, 12 March 2008

Foldershare isn't dead after all

Seen this morning:

The Windows Experience Blog : Announcing Windows Live FolderShare Beta Refresh for PC-to-PC Sync

That team, bought by Microsoft, has  been busy building Windows Live SkyDrive, now they update FolderShare... Maybe, just maybe, this team will finally deliver a unified experience for remote sync and file access. And maybe integrate with my Windows Home Server box...

Thursday, 6 March 2008

Deloitte employee rude on a train

[Update: oh well, this was unnecessary. I'd rather people understood the meaning of quiet zone and weren't so up their own a*se. And personal recorders are so over-used. Is it that hard to just write?]

Tuesday, 26 February 2008

Live.com dead?

image

Is it just me?

[Update 18:08: it's back!]

Wednesday, 20 February 2008

The MVP presentation code

Last night, I've made some progress towards my long-overdue MVP series of articles, by rewriting what I had to adopt the same format as the presentation I did yesterday at the London .net user group.

As promised, here's the code from last night. Stay tuned for the articles.

Thanks to the surprisingly large audience, and thanks to those that came to me to say they were reading this blog. I still get quite shocked when people tell me they saw a specific article I've written.

To be fair I still get shocked when people remember my name the second time they see me, as I'm sadly quite the opposite and have a lot of trouble remembering people by name.

Anyway, enjoy the code in its roughest form, nearly no comments in there, and still no powerpoint slides :)

File iconCaffeineIT.ShoppingList.zip

MacBook Air and Windows Vista x64

For the masochists amongst you, two tips when installing Vista 64bits on a MacBook Air:

  • The mouse drivers don't work initially. Just rollback to the microsoft drivers and execute the multitouch install manually from the apple folder (the 64 one!)
  • The video drivers need to be downloaded from Intel. The latest GMA drivers will do.
  • The wireless network card is wrongly recognized. Go and download Broadcom's drivers from HP at http://h10025.www1.hp.com/ewfrf/wc/softwareDownloadIndex?softwareitem=ob-53245-1&lc=en&cc=us&dlc=en&product=3185028&os=228&lang=en
    You need to extract the files, and do a manual installation (Let me select... and Choose a location in the wizzard) and *ignore* the warning about windows not being able to match the driver to your hardware. It's the right one (select the 802.11n draft version of the driver in the list)

And now some pictures of the unboxing.

IMG_0042 IMG_0043IMG_0044IMG_0045

The full installation from boot to first screen (including me typing the product key) came at a whopping 32 minutes. I'm so impressed with how snappy everything feels that I'm thinking of either replacing my main drive on the MacBook Pro by a Solid state drive (as soon as a 128G gets out) or just doing my development on the MacBook Air!

Monday, 18 February 2008

PowerShell one-liners for svn

A bit of CLI love (and I'm sure my readers will correct me fairly quickly with something much smaller and better!), for those like me that wish they never had to use tortoise.

Adding all files that are not in the repository

svn st | %{ if ($_ -match "\?\s+(.*)") { svn add $matches[1] } }

Removing the dreaded bin and obj folders if you did an add by accident

ls -i bin,obj -recurse | % { svn revert $_ -R }

And to exclude all the stuff you put in your .svnignore (and that one works with any shell)

svn propset svn:external . -F .svnignore -R

Enjoy!

Wednesday, 13 February 2008

A life-saver for one-button developers

http://codebetter.com/blogs/jean-paul_boodhoo/archive/2008/02/12/another-handy-shortcut-combination-shift-f10.aspx

I got used to use the menu system with the keyboard to compensate for the trackpad on my macbook pro not having a usable right click (the double tap behavior is erratic at best and unusable). Shift-F10 is going to make my life so much easier!

[Update: I just realized this shortcut works for any application. I should really increase my keyboard shortcut proficiency, especially as I don't seem to have enough space for my mouse anymore in the office...]

Thursday, 7 February 2008

Follow-up on the OnXxx anti-pattern

[Started updating the previous entry, but the reply is chunky enough to go in its own post]

One person on the dotnet-clr mailing list has highlighted, quite accurately, that the RaiseXxxEvent method should really take EventArgs as a parameter instead of a string to ensure it can be swapped with a class inheriting from EventArgs. If you want that kind of extensibility, then yes, put an EventArgs as a parameter. I should update the sample.

A second person in the comments vehemently disagree with my point, so let's go for a simple rebuttal, as I do not believe the arguments to be accurate.

The first part is that the pattern, to be deemed acceptable, should be OnXxx(object src, EventArgs ea).  I have nothing else to say but to point with every single of my examples as none of them seems to "get" the right way of declaring OnXxx. As for this way to be the right way, I've not found any other reference to support Peter's argument.

The Design Guidelines for Developing Class Libraries does mention the void delegateType(object source, eventargs e) signature for event handlers, not for event raisers. As for event raisers, here's a big quote from the same source.

Do use a protected virtual method to raise each event. This is applicable only to non-static events on unsealed classes, not to structures, sealed classes, or static events.

Complying with this guideline allows derived classes to handle a base class event by overriding the protected method. The name of the protected virtual (Overridable in Visual Basic) method should be the same as the event name prefixed with On. For example, the protected virtual method for an event named "TimeChanged" is named "OnTimeChanged".

Important Note:

Derived classes that override the protected virtual method are not required to call the base class implementation. The base class must continue to work correctly even if its implementation is not called.

Do use a parameter that is typed as the event argument class to the protected method that raises an event. The parameter should be named e.

Let's see:

  • protected virtual method for non-static events on unsealed classes: Checked
  • the virtual method *should* be prefixed by On. This is non normative, so I'm still within the guideline: Checked
  • The last bit is quite clear: to be within the guideline, the raise method would be Raise(EventArgs e), and not take an object as the first argument: Checked (after having updated the previous post)

Indeed, the second part talks about passing a string instead of an EventArg, this came from typing quickly an example rather than the focus of the pattern, but point taken and resolved.

The third part is interesting. The reader is oblivious to the fact that the event raising method is called RaiseXxxEvent. Missing the italics is an easy mistake to make so let's move on. Apparently OnClear is a rat hole because it doesn't follow the right pattern (neither do the others as said before, and worst, neither does the design guideline...) OnClear with any other argument can mean anything but OnClear(object, EventArgs) can only mean one thing. So in this case, using On can have several meanings and it's fine, but in the case of Raise, you may never know if someone cannot confuse RaiseTheMountain and RaiseGoingUpEvent, so it's not acceptable. I'll assume the whole diatribe is based on the EventArgs confusion and the use of a string, and the missing Event suffix, so I think the point is clear.

So I'll summarize the argument I made extensively: OnXxx is implemented widely but implemented widely wrongly across mscorlib, asp.net, winforms and WPF. It has a double meaning as either raising (as per the design guidelines) or handling (as per people's use of it). The examples in the previous post show that without . Furthermore, the asp.net language use OnXxx to autowire events to event handlers, just like html events.

The confusion is enough that I choose to split the pattern in two methods with clear intent: HandleXEvent to handle an event, RaiseXEvent to raise an event. And even by doing so, I still adhere to the design guidelines issued by Microsoft. If you find this more confusing than OnXxx, I'm just lost for words.

Making the case against OnXxx

[Updated the code sample for the raising event method. See my response to the comments that were made.]

Some people, like Jeremy, really don't like events. I have to admit having a nearly-fanatic interest in good event patterns. One of such patterns I've seen used and misused continuously is the OnXxx pattern. Let's have a quick look at what the MSDN gods have to say about this.

You raise the event by calling the protected OnEventName method in the class that defined the event, or in a derived class. The OnEventName method raises the event by invoking the delegates, passing in any event-specific data. The delegate methods for the event can perform actions for the event or process the event-specific data.

Note:
The protected OnEventName method also allows derived classes to override the event without attaching a delegate to it. A derived class must always call the OnEventName method of the base class to ensure that registered delegates receive the event.

When you want to handle events raised in another class, you add delegate methods to the event.

So far so good. Let's open reflector and check how well is this pattern implemented. First candidate (selected through my advanced AI randomisation algorythm called click until you find a class with an OnXxx patern), FileSystemWatcher.

protected void OnChanged(FileSystemEventArgs e)

{

    FileSystemEventHandler onChangedHandler = this.onChangedHandler;

    if (onChangedHandler != null)

    {

        if ((this.SynchronizingObject != null) && this.SynchronizingObject.InvokeRequired)

        {

            this.SynchronizingObject.BeginInvoke(onChangedHandler, new object[] { this, e });

        }

        else

        {

            onChangedHandler(this, e);

        }

    }

}

So far so good. Let's stay within mscorlib (just in case the pattern was team specific), and have a look at DictionaryBase.

protected virtual void OnClear()

{

}

Oh. Where's the event call? Let's see what the method is described as doing.

Performs additional custom processes before clearing the contents of the DictionaryBase instance.

Wait a second, I thought we were supposed to use OnXxx for raising events, not to change stuff. Ok, let's move on to the ado.net team, and have a look at DataSet, and for the same price I give you not one but two methods.

protected internal void RaisePropertyChanging(string name)

{

    this.OnPropertyChanging(new PropertyChangedEventArgs(name));

}

protected virtual void OnPropertyChanging(PropertyChangedEventArgs pcevent)

{

    if (this.onPropertyChangingDelegate != null)

    {

        this.onPropertyChangingDelegate(this, pcevent);

    }

}

Alright... Now I'm getting quite confused. I can call RaiseXxx(name) which in turns call the proper OnXxx pattern that calls the event. This is now getting quite messy. Let's see what the guys in the asp.net team do with the DataSourceControl.

protected virtual void RaiseDataSourceChangedEvent(EventArgs e)

{

    this.OnDataSourceChangedInternal(e);

    this.OnDataSourceChanged(e);

}

Note that both OnXxx are now private methods... At least in DataSet you have two ways to do the same thing, one legal and one not legal (again, according to the msdn documentation). Not convinced yet? Ok, let's see what the Winforms guy have been doing and have a look at Control. I'll point to two examples.

[EditorBrowsable(EditorBrowsableState.Advanced)]

protected virtual void OnNotifyMessage(Message m)

{

}

And example 2.

[EditorBrowsable(EditorBrowsableState.Advanced)]

protected void RaisePaintEvent(object key, PaintEventArgs e)

{

    PaintEventHandler handler = (PaintEventHandler)base.Events[EventPaint];

    if (handler != null)

    {

        handler(this, e);

    }

}

Note that the OnPaint event exists and does mostly the same thing. Isn't it great to have that much flexibility? Ok, last but not least, let's see what the latest greatest brings us with WPF's UIElement.

public void RaiseEvent(RoutedEventArgs e)

{

    if (e == null)

    {

        throw new ArgumentNullException("e");

    }

    e.ClearUserInitiated();

    this.RaiseEventImpl(e);

}

protected virtual void OnMouseLeave(MouseEventArgs e)

{

}

Can you make any sense of the OnXxx notation? No? Me neither, neither do my developers. So I hereby propose (again) to just get done with it already and *aknowledge* that OnXxx is an anti-pattern used either for raising or for handling events, is overused and misused, and should die a long and painful death. I propose the simpler and more semantically correct syntax:

public class DoingEventsProperly

{

    public DoingEventsProperly()

    {

        this.SomethingChanged += HandleSomethingChangedEvent;

    }

    public event EventHandler<PropertyChangedEventArgs> SomethingChanged = (src, ea) => { };

 

    protected virtual void RaiseSomethingChangedEvent(PropertyChangedEventArgs e) { SomethingChanged(this, e); }

 

    protected virtual void HandleSomethingChangedEvent(object src, PropertyChangedEventArgs ea) { }

}

What this class achieves is covering all the scenarios we just encountered.

  • The event handler is defaulted to an empty anonymous method, so it cannot be null, which means RaiseSomethingChangedEvent doesn't need to check for null.
  • The semantic of the RaiseXxxEvent method is simple: It raises the event. Want to cancel the event? Override RaiseXxxEvent.
  • The semantic of HandleXxxEvent is simple: It aint raising the event! Want to do some stuff in your class when the event is raised, override that method.

And it's also easy to explain: Call it Raise when you're Raising an event and call it Handle if you're handling an event. I think the semantic complexity is achievable.

I may go into the other patterns such as explicitly cancelable events for consumers and explicitly cancelable by contract for inheritance cancellation another day.

And remember: The best way to combat an anti-pattern is to stop using it.

Monday, 4 February 2008

alt.net - Some comments and ideas

[Updated: Toned down a few sentences as they were more emotional than necessary.]

I've been holding back from commenting as there's been a lot happening and I probably need a few more days before my mind is set, both on the technicalities we discussed, on the process, and on the ideas. For today I'll focus on the alt.net movement, and on the conference. I'l leave the technical stuff for later.

Communities, user groups and is the existing structure working for alt.net

There's been strong suggestions that user groups are enough to cover the scope of alt.net. The concepts behind alt.net have been up for discussion, but by their nature, they need a small kernel of focused people discussing what is doable, what the state of affairs are and how to convince people to take the alternative route of innovation. We need people to challenge, and for that they need to have a forum in which they can progress and advance ideas.

The wider communities existing today seems to me a perfect place to distill those ideas, but maybe they're not the right place for defining them. Doing that necessitate people knowing about the subject, the technologies and the commercial realities to break the all <insert your favourite software vendor> approach. Only from those reflections can it be distilled to user groups, in the more typical presentation style that is common to those groups.

The good

This conference had good less good sessions. The good sessions were the ones where people sat down and discussed in an open format each subject. Having Roy Osherove in a room discussing why mocks are not always a good idea and can lead to brittle tests, and question the constraints imposed on testing because of the first generation of mocking frameworks was fantastic. But what was fantastic was not having someone taking over the room to present his own agenda or switch the room into demonstration mode, where an individual does most of the talking. The spirit was very much a relaxed opened session where everyone contributed what they had to say.

The bad

The REST discussion was interesting, but dragged on longer than necessary. The discussion was very much focused on one presenter doing most of the talks, and I felt that by the time others had the opportunity to discuss their solutions, the room was tired, and people started leaving. To a certain extent I guess I can only blame myself for not having prepared material and moving the discussion more towards the points I was interested in, so I can't blame anyone, but it felt more like a presentation or an ask the expert session than the discussion that happened in other sessions.

Overall, I think the demonstrations that were done didn't add anything to the talk, as I do not believe most of the room saw the light of content type negotiation through yet another wiki demo. That said, I aplaud Alan for pushing this part of the HTTP spec, something that I've also been trying to get through for quite a few years. Other people had stuff to show and by then it was too late. Maybe those demonstrations should overall be discouraged to keep the focus on the discussion.

The ugly

As for the ugly, in the becoming a better developer, the discussion became quite wide on the challenges we face. I discussed, maybe too much, a recent case where one of my clients revoked my contract for a wide range of reasons. I highlighted the fact, during that session, that having a forum where developers can explain their worst experiences, share them with others, is probably a good idea to relief that feeling you get that you're the only one it happened to. Getting fired or being the scapegoat on a project happened to most contractors. Hence why the suggestion was made that maybe AA-like meetings for us guys to talk about the struggles we face in a safe haven would be good therapy.

The issue there is that maybe some people have over-inflated egos and refuse to talk about it, because it would tarnish their carefully crafted image. I assumed this session was a safe haven into which I could have those kind of discussions, without fearing consequences.

Only a few hours later  at the pub, we were discussing my inbox email filtering policy. I may blog about it in more details later on, but I filter email based on recipients, to/cc lists, if its a reply or not, and split those incoming emails in sub folders. The lowest priority I read when I have time at the end of the day, the medium is read when i have time (usually lunch), and only the very few emails getting straight to my inbox get read immediately and treated in a GTD way.

However, one of the person present during that session, I hope fuelled by the copious amount of beer that was consumed by all parties involved, saw fit to reply to me, after a couple of exchanges explaining that my email policy couldn't work, that my views on emails maybe were why I got fired. This is low. Furthermore, it made me wonder if that person had to resort to mentions of my previous failures because they ran out of arguments or because they were making a point. Maybe repeating the same thing three times is not an argument anyway. But more than that, this breaks the safe haven I talked about a few paragraphs earlier. Explaining my struggles with some clients should never come back to bite me back, especially not by an organizer that is supposed to help IT people deal with those issues.

I for one will know to avoid discussing those issues if I don't have the guarantee of a safe haven. I did express my complete dismay at his comments and that it was quite out of order, and got an apology for hurting my feelings. I accepted the apology even though my feelings in this matter are nearly as irrelevant as the comment that was made. Moving on.

Maybe the relevant point in all this is the reflection on why the situation got that bad. I think it may all come down to learning how to let go. Maybe as a contractor sometimes I should not push so hard when I see a project failing, and let it fail the way the manager wants it to fail. Maybe the constant push against decisions I deem bound to failure are not my place to take. Overall, when bad decisions are taken continuously, I should learn to quit and either get on with it, or more likely break my contract and find a client that wants to listen to what I have to say.

The question still pending is, what is the right forum to discuss failures? I find that contractors are especially frisky when talking about their mistakes and their failures, maybe by fear for their public image, or maybe because they've had the situation I just encountered and it hit them back. Who knows. It shouldn't be this complicated when we're all in the same boat. And personality conflicts are not going to help us much.

Conclusion

I'll focus on the technical discussions that happened as I try to remember them this week. There's been very good points raised that each should have their own entries, and the first will probably be about REST and my open implementation of UriTemplate for .net 2. I've learnt from others and their views, and have questioned my own views. I wish the conference would've spanned two days.

I'd like to thank the people that came, the organizers for their hard work (always nice to see Z and Ian, and I'm going to follow up on my promise to come to the london .net user group.) Thank to Conchango and Redgate (special mention to Michelle for always making sure I had a beer, for better or worse, and to Ben for such a lovely evening on Friday, and hope he recovered from that hangover). It's been a great experience.

Technorati Tags: ,,

Saturday, 2 February 2008

alt.net Conference day 1

My hotmail is back apparently... we'll never know what happened. At the alt.net conference this morning... Early start after a very late evening. There are damn smart people in here, very uplifting.

Here's the sessions I'm going to attend:

  • REST / SOAP / MVC and what it all means for services
  • Mocking, is it a good idea? (you know it's one of my pet peeves)
  • How to become a better developer and spread the alt.net ideas
  • DSL and fluent interfaces...

They're the bits I proposed in each of the topic-based subjects that are being grouped together...

It's my opinion that we should've had probably less topics proposed, and the decision on what stays and what doesn't should've been taken by the people that are here rather than pre-organized. It makes people passively vote for sessions with less self-organization. But maybe British people are just less proactive and expansive than our American counterparts.

Technorati Tags: ,,

Friday, 1 February 2008

Apparently I'm a spammer - Hotmail closes my account!

[Update: Hotmail reactivated the account within 24 hours. I do like a bit of drama...]

My hotmail account has been suspended... If you've tried to reach me on seb@serialseb.com from this morning, I'm in the hands of some sort of automatic processing that believes I'm a spammer... My account has been closed!

Considering the only emails I send are to my family, my work and the alt.net community, and that's at most 20 emails a day, you start wondering what the heck is going on!

I'll keep you posted. If anyone is working at hotmail, a bit of help would be appreciated!

Oh well, I'll have some road stories for the alt.net conference in a few hours. For the Londoners see you there!