The time is upon us, for a release and for a party to celebrate it.
Come and join all the UK OpenRasta users, it’s on the 12th of December and in Central London.
Go register on the eventbrite site now, quick!
This is not a leadership blog, please kindly piss off.
The time is upon us, for a release and for a party to celebrate it.
Come and join all the UK OpenRasta users, it’s on the 12th of December and in Central London.
Go register on the eventbrite site now, quick!
I realize I’ve never clarified what you can or cannot do with my slides and my talks. So here’s a clarification for anyone that wishes to inspire themselves from my work (aka derivative works) or reuse them.
I do not release my presentations, the videos or the content / slides under any kind of open-source license. Not even creative commons. Presentations take a while to build, structure and mature, and this cost me money. If you’re going to use them, you’re effectively using my work.
Now, I’m not anal about how you use the content, it’s written to benefit the community. However, ff you want to create a derivative work, or even re-present my presentations, I’m happy for you to do so provided the following conditions are met:
If you have any issue with any of that, don’t hesitate to send me an email we can chat about it.
We are expanding, how brilliant is that! If you want to have an open-space after the Cambridge StackOverflow dev-day, you now can!
I’m very pleased to announced that this weekend, for a day only, Greg Young will be delivering a workshop for the AltNetGroup, for free, in London, on Command-Query Separation.
3 tickets will be available daily at 2PM on the AltNetGroup site.
The registration for the post-StackOverflow conference in London is now open at http://altnetbeers-stackoverflow.eventbrite.com/
I’m sure it’s going to be an absolutely brilliant event, so register early as space will be limited.
Just a quick reminder for those not monitoring the www.gaygeekdinner.com site, our next event is this Friday, and you can register at http://london-gaygeekdinner.eventbrite.com/
It’d be great if you could do it by Wednesday so I can have an idea of numbers. :)
And there you go. When you can’t scale up, scale out! We’re creating a new kind of talks, one where communities will meet and cross the technological Styx.
The first one is on Ruby, RubyOnRails and IronRuby, the presenter is Shay Friedman, the place is MRM, the time is this friday, and the this is the link.
As you know, Roy is delivering the first of our AltNetWorkshops on Saturday the 26th of September. Most of the tickets are now gone, but you have the chance to enter a raffle for the last remaining ticket by sending me an email at seb@serialseb.com
As the ever excellent Udi Dahan is in town, it’s only natural that I organize an AltNetBeers. So get ready for another session on the 16th of September! You can register now on the ukdotnet site.
And because I’m equally excited about going back to Ireland as I am going back to Scotland, I’ll be doing a bunch of things there.
Dublin alt.net at 8pm in Seagrass http://www.seagrassdublin.com
An intro to OpenRasta
Dublin
Not confirmed yet but should be a talk on agility in Dublin
Galway
Speaking at a conference on agility, will post about it when I get more details.
Well, it’s been a while since I’ve been a up north, and with such a great community up there, it was only a matter of time before I got back. Frankly, I was just looking for an excuse, and the guys have given me a beautiful one!
So here’s the schedule.
Dundee – http://www.eventbrite.com/event/390722662/seb
With applying agile methodologies comes changes in many aspects of delivering software. And with any change will come a time when something fails. How to keep everyone calm? How to provide practical solutions to prevent people from reverting back to non-agile practices at the first roadblock? Through examples gathered from personal experience and the community, we’ll explore ways to prevent the boat from sinking at the first spilled glass of water.
Edinburgh - http://www.eventbrite.com/event/390708620/seb
Everybody seems to rediscover the MVC model, and new frameworks seem to appear all the time. Most of those hide the richness of the web. Come discover OpenRasta, a very opinionated framework that help you write MVC-style web applications and data services, using a unified API.
The scot alt.net guys have asked me to facilitate a session of AltNetBeers, which I’m really excited about. Will update with the details when I know where it’ll be organized.
See you there!
public interface IRepository<T> : INHibernateQueryable<T>
{
ITransaction BeginTransaction();
void Delete(T item);
T Get(object id);
void Save(T target);
void Update(T item);
}
public class NHibernateRepository<T> : IRepository<T>, IDisposable
{
readonly ISessionManager _sessionManager;
INHibernateQueryable<T> _queryable;
ISession _session;
public NHibernateRepository(ISessionManager sessionManager)
{
_sessionManager = sessionManager;
}
INHibernateQueryable<T> AsQueryable
{
get
{
if (_queryable == null)
_queryable = Session.Linq<T>();
return _queryable;
}
}
public Type ElementType
{
get { return AsQueryable.ElementType; }
}
public Expression Expression
{
get { return AsQueryable.Expression; }
}
public IQueryProvider Provider
{
get { return AsQueryable.Provider; }
}
public QueryOptions QueryOptions
{
get { return AsQueryable.QueryOptions; }
}
public ISession Session
{
get
{
if (_session == null)
_session = _sessionManager.OpenSession();
return _session;
}
}
public void Dispose()
{
if (_session != null)
_session.Dispose();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return AsQueryable.GetEnumerator();
}
public IQueryable<T> Expand(string path)
{
return AsQueryable.Expand(path);
}
public ITransaction BeginTransaction()
{
return Session.BeginTransaction();
}
public void Delete(T item)
{
Session.Delete(item);
}
public T Get(object id)
{
return Session.Get<T>(id);
}
public void Save(T target)
{
Session.SaveOrUpdate(target);
}
public void Update(T item)
{
Session.Update(item);
}
}
public static class CustomerQueries
{
public static IQueryable<Customer> ByName(
this IQueryable<Customer> repo,
string name)
{
return repo.Where(x => x.Name == name);
}
public static IQueryable<Customer> ByCity(
this IQueryable<Customer> repo,
string city)
{
return repo.Where(x => x.City == city);
}
}
public class MyPage
{
IRepository<Customer> _repository;
public MyPage(IRepository<Customer> repository)
{
_repository = repository;
}
public Customer UpdateCustomer()
{
return _repository
.ByCity("Aarhus")
.ByName("Sebastien")
.FirstOrDefault();
}
}
public class when_filtering_by_city
{
public void the_wong_city_is_not_selected()
{
var myTestData = new List<Customer>
{
new Customer { City = "Aarhus" },
new Customer { City = "London" }
};
var funPlaceToBe = myTestData
.AsQueryable()
.ByCity("Aarhus")
.FirstOrDefault();
Debug.Assert(funPlaceToBe.City == "London");
}
}
public class Customer
{
public string Name { get; set; }
public string City { get; set; }
}
Grab the binaries at http://www.ohloh.net/p/openrasta/download?package=OpenRasta+2.0&release=Beta+2 or the code at http://svn.caffeine-it.com/openrasta/branches/2.0.2000
The good chaps in Denmark have asked me to do a session on OpenRasta. You can imagine how excited I was, and I immediately said yes! You can go and register now for it.
Rick Strahl, C# MVP extraordinaire, has released a very cool app at codepaste.net. Go and check it out, it’s quite cool.
One of the things Rick is doing is publishing a POD API that uses xml and json. And he posted on an unrelated entry an implementation of POD using MVC. For reference, here’s his snippet.
AcceptVerbs(HttpVerbs.Post | HttpVerbs.Put)]
public ActionResult PostNewCodeSnippetObject()
{
StreamReader sr = new StreamReader(Request.InputStream);
string data = sr.ReadToEnd();
sr.Close();
Snippet inputSnippet = null;
if (Request.ContentType == "text/javascript" || Request.ContentType == "application/json")
{
JSONSerializer ser = new JSONSerializer(SupportedJsonParserTypes.WestWindJsonSerializer);
inputSnippet = ser.Deserialize(data, typeof(Snippet)) as Snippet;
}
else if (Request.ContentType == "text/xml")
{
inputSnippet = SerializationUtils.DeSerializeObject(data, typeof(Snippet)) as Snippet;
}
else
return ExceptionResult("Unsuppported data input format. Please provide input content-type as text/javascript, application/json or text/xml.");
busCodeSnippet codeSnippet = new busCodeSnippet();
codeSnippet.NewEntity();
DataUtils.CopyObjectData(inputSnippet, codeSnippet.Entity, "Id", BindingFlags.Public | BindingFlags.Instance);
if (!codeSnippet.Validate())
return this.ExceptionResult("Code snippet validation failed: " + codeSnippet.ValidationErrors.ToString());
if (!codeSnippet.Save())
return this.ExceptionResult("Couldn't save new code snippet: " + codeSnippet.ValidationErrors.ToString());
return ApiResult(codeSnippet.Entity);
}
Ouch. Lot of fluff if I may say so. Let’s see what the equivalent implementation would be using OpenRasta.
The configuration:
using (OpenRastaConfiguration.Manual)
{
ResourceSpace.Has.ResourcesOfType<Snippet>().AtUri("/snippets")
.HandledBy<SnippetHandler>()
.AsJsonDataContract().And.AsXmlDataContract();
}
The handler:
public OperationResult Post(Snippet newSnippet)
{
var codeSnippet = new busCodeSnippet();
codeSnippet.NewEntity();
DataUtils.CopyObjectData(inputSnippet, codeSnippet.Entity, "Id", BindingFlags.Public | BindingFlags.Instance);
if (!codeSnippet.Validate())
return new OperationResult.BadRequest("Code snippet validation failed", codeSnippet.ValidationErrors.ToString());
if (!codeSnippet.Save())
return new OperationResult.InternalServerError("Couldn't save new code snippet", codeSnippet.ValidationErrors.ToString());
return new OperationResult.OK(codeSnippet.Entity);
}
I much prefer the latter. Don’t you?
On a very positive note, I’ll be delivering Skillsmatter’s NHibernate course in Aarhus, Denmark, from the 26th to the 28th of August.
I’m also discussing with some guys to get an OpenRasta presentation there so you can hear what the fuss is all about.
And I’ll take the Saturday to visit Copenhagen, as it would be a shame not to. If some people are available Saturday we can meet for a beer and a chat.
First time in Denmark, I’m quite excited!
[Update: Nate was kind enough to link so we could enter a conversation]
Yesterday, I made a certain comment on a person’s decision to release something in open-source, and they made a certain comment, and I’m very disappointed…
I could’ve started this entry like this, without providing you quite enough information to enter the conversation yourself. This is the way Nate decided to go about it in his entry last night entitled Open Source is not a Zero-Sum Game.
Let’s see what happened.
Nate - [Announcing the release of Siesta]
Victor - @nkohari seen snooze http://tr.im/wamQ ? why the need for siesta?
Nate - @vkornov Hadn't seen it.
Victor - @nkohari you need to ask on twitter before coding your own ;)
Nate - @vkornov Eh, nothing wrong with different approaches to the same problem.
Me -@nkohari if it was a different approach or a different problem, maybe. If it does the same as other REST frameworks, it's a waste of time and resources.
Nate - @serialseb Then don't use it. Sorry to bother you.
Me - @nkohari that's not the question that was raised by Victor, but fair enough, i won't use it. Meh.
Nate - I'm really disappointed to see people complaining that I open-sourced part of my commercial product. Sorry, next time I won't try to help.
So now you have the background. I won’t go and bore everyone with the countless support messages Nate received telling him to ignore the whiners and naysayers, I’ll let you decide for yourself if this was worthy of such a long rant.
Leaving aside the non-conversational aspect of Nate’s entry and twitter messages, there’s a couple of points I think are worth discussing. As I intend on having a conversation about this stuff, comments are open, you can name me in your blog and leave links to your blogs in there, I’ll add them to this entry.
When you require infrastructure code, you should always ask yourself this question: Is it worth me building? This is the Not Invented Here syndrome, and unless your business model is to reinvent the wheel for IP protection reasons, it’s an expensive process, as not only do you spend your time building it, you’ll have to maintain it.
There are two reasons why you’d want to build something. First, there is no equivalent on the market that can solve your problem in the amount of time it’ll take you to build it yourself (or slightly more as, as seen before, you’ll have to add the maintenance cost). Secondly, if the existing solution is poor and there’s no easy or cheap way to make it better.
If you’re building stuff for any other reason than the two above, you’re generating waste, spending time building code that is not going to give you a competitive advantage or serve your product / user.
That’s the point I tried to make in my twitter conversation. If it’s a different problem or if the solution is innovative, then maybe there’s nothing wrong with a different approach. If it’s the same, with a new brand, then it is a lean:waste. And there, I agree with one of Nate’s sentences: rolling your own is not always waste (emphasis mine).
The second part of the conversation is about open-sourcing code. I think those are two different conversations to have, as one doesn’t usually have the same waste-eliminating concerns when dealing with open-source.
Open sourcing code is great. I love doing it, so do others. And a myriad of frameworks pop-up, thanks to open source. Just in the ReST space, you have Snooze, BistroMVC, Restful MVC, now Nate’s Siesta, and of course OpenRasta. I’m pretty sure you could achieve some of the same results with FubuMVC too.
The question is not if multiple projects are good, they foster innovation by providing new ways to think about a problem, and new best practices start to appear. I know I am taking in a lot of ideas from all of those frameworks for future versions of OpenRasta. Competition is good.
I do still believe in eliminating waste in open source though. Call me idealist, but I don’t see why everybody would reinvent the infrastructure stuff. Pipeline models, asp.net integration, all those frameworks share some core infrastructure aspects. Why do we all reinvent the same problem over and over? Because we’ve not been collaborating to ensure we have communication in place.
That’s why I told Chad Myers many times: It’s great to see another frameworks with really good ideas, it’s a shame we’re duplicating effort endlessly on parts that are not bringing much innovation or value.
But I suppose that’s the state of things. The bazaar model requires that we’ll all come up and only the solution with the most market leverage will survive. Yes, we’ll have 250 ReST frameworks in a year time. And in two years, only two or three will probably see any usage at all. In the meantime, we’ll have wasted hundreds of hours of developers time.
Maybe the innovation will be worth it, but I’m still unsure if we’ll ever reach even.
So there you go, here’s the core of the question. Fragmentation doesn’t always lead to innovation, collaboration and discussion can prevent people going in a direction where they don’t innovate but just recreate it their way because it’s only 5 or 6 hours. Allegedly, Nate’s solution is simple and small enough that he’s probably not affected by this.
I don’t however believe that ignorance is a good reason to discard frameworks like snooze (which, by the way, is the one that was mentioned in the conversation, and the work of the ever excellent Andrew Davey).
As a final word, I’d like to remind everyone that one of the constraints of ReST is hypermedia. If you design APIs without any links, and advertise how to build URIs, you’re not doing ReST, your doing something else. It doesn’t mean you’re doing something badly, just that you’re not actually doing ReST.
So, MVC 2 is innovating by having default values on parameters. I think there’s a lot of value in doing that, and as such OpenRasta has always supported those. Here’s an example.
public object Search([Optional, DefaultParameterValue("*")]string searchString)
{
return ...;
}
I’m glad the guys at Redmond saw the value in that. The do however use an attribute that wasn’t meant for optional parameter values. At least the way OpenRasta supports it, VB methods with optional parameters and default values work out of the box.
Just to let everyone know that we’ll be organizing the AltNetBeers on the evening after the StackOverflow London conference, on the 28th of October. The event will be up when we’ve arranged a location a bit later, but you can pre-register by commenting on this entry.
That way, the hangover won’t kill the early morning enthusiasm, and with enough notice those of you that want to do both can organize their travel plans more easily.
As my servers are all down to maintenance, I use this blog entry to repeat the announcement that was made on friday night at AltNetBeers 10 regarding the Altnernative Network Group.
We’re expanding the scope of AltNetBeer, and creating a proper structure behind it, the Alternative Network Group, together with some new areas in which we want to expand.
The Alternative Network continues with the tradition of the AltNetBeers, an environment in which all software professionals can get together and learn together. While its origins are in the alt.net movement, AltNetGroup is for everyone with a desire to become better at delivering software.
The history of AltNetBeers has shown that the topics people want to discuss are not technology-specific. We all share the same struggles and interests: from DDD to dealing with legacy code, from opiniated frameworks to agile methodologies, the topics we discussed and investigated over the last year are universal. It is the absolute and fundamental belief of this group that much is to be gained by not limiting ourselves to our vendor-driven sphere of influence.
The Alternative Network Group hopes to become the forum for those that want to enrich their understanding of software development and the practices that surround it. How? By putting at its core knowledge sharing and continuous improvement, by building on experience, and by creating a bridge between technical communities.
Beyond the regular AltNetBeers open-space flavoured event that is running monthly in London, we’ll be starting a couple of new initiatives.
This is just the beginning, I still have plenty of ideas, and the community has come up with plenty more. As such, this list is only my pledge for the next 6 months, and will be adapted and refactored as seen fit.
Some of you have expressed your interest in helping out financially however you could, and I’d like to thank you for that. I’m glad to announce that there will now be a structure for you to contribute back in the form of cash, used for organizing all those events. As we want to deliver all this to the community for free (or as low cost as possible), we’re setting up a levelled corporate sponsor program, that stays very simple.
Supporter Level, £50 a month, by chunks of three months. You can renew your membership whenever you want. This will get you a presentation in one of the event when we salute the people that make it all possible, your logo on the website, and a reserved seat a month to workshops and the AltNetBeers event. We may include an online presence for likeminded people to get in touch for work, so if you see value in that, let me know.
Partner Level, for those that contribute above and beyond. We can discuss individually what you can do, want and what you hope to get out of it.
A new website is coming up at www.altnetgroup.com and will contain all this information.
FAQ
When is it all starting?
September 09
Is this related to the Alt.net UK Society?
No, they are two different organizations with different objectives. We focus on bringing knowledge to developers beyond their platform through group learning experiences. The Alt.Net UK Society is the organizer of the alt.net conference. We hope to continue working together on .net events where appropriate, just like we did for the alt.net weekend.
Is there a membership for individuals?
No. Individuals are the people we work on providing with content. Asking them to pay a membership is not compatible with the kind of events we want to organize. We want to stay self-sufficient and as lightweight as possible.
I’ve given that talk quite a few times now, and always forget to give the full material. So here goes.
The slides can be downloaded at http://svn.caffeine-it.com/mug/agile-goes-bad/when-agile-goes-bad.pptx
A couple of references that I mention in my talk.
A couple of points I hammer constantly, so let me repeat them once again:
And to answer a question that was asked in Cork, where do you start when you have none of the agile practices, I’d do it in the following order:
[Update: Added example pages from aria]
For the answer, see the points below.
I was going to email the comments below to some people at Microsoft that have shown an interest in opening up a conversation, but after a comment I left on Hanselman’s blog, and Bertrand Le Roy, a PM at Microsoft, responded by saying “I really wish we could concentrate on the fantastic features in Microsoft Ajax 4 instead of discussing dogma.”, I think it’s in the public interest to highlight some of the incompatibilities the Microsoft’s proposed syntax for AJAX 4 is going to induce in your code. Not that it’s the first time either that a suggestion for MS Ajax takes liberties with standards. See my previous post from their original idea of xml scripts that were also breaking stuff last year.
So what is it that AJAX is providing in the visual studio beta 1? Here’s a partial example taken from Hanselman’s entry.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AdventureWorks AJAX</title>
</head>
<body xmlns:sys="javascript:Sys" xmlns:class="http://schemas.microsoft.com/aspnet/class">
<h1>Customer Directory</h1>
<table cellspacing="0">
<tbody id="customers-template" class="sys-template">
<tr sys:command="select" class:odd="{{ $index % 2 != 0 }}">
...
</tr>
</tbody>
</table>
</body>
</html>
Before we go any further, let’s clarify what the state of affairs is. The HTML family exists as follow:
That’s the serialization formats. Now all those formats end up in a DOM, an in-memory representation of the components of an html page
So this is where the fun begins. As everything is lowercase, this language could be HTML4.01, HTML5, XHTML5 or XHTML 1.x. In effect, HTML4 like HTML5 are case-insensitive, while any xml language is actually case sensitive.
The absence of an HTML4 doctype means this document cannot be a valid HTML4 document. It could be an html 5 element, or one of the XHTML languages. We’ll see why it’s important later, and it all comes down to the DOM.
So, let’s move on to the attributes used in the tbody element. How would a browser parse this element to build a DOM?
So now we start seeing where the problem lies. HTML languages *do not* support xml namespaces. At all. Ever. Not even HTML5. The DOM however supports namespaces in XML-based languages and in HTML5, but not in HTML4.
Ok so I mentioned that introducing xml namespaces in such a way broke a bunch of scenarios. Let’s review them.
Bertrand Le Roy highlighted that all was fine in xml, because surely xml supports xml namespaces. While this is true, XHTML does not allow using other xml namespaces within the XHTML specification. Here’s the relevant quote from http://www.w3.org/TR/xhtml1/#well-formed.
The XHTML namespace may be used with other XML namespaces as per [XMLNS], although such documents are not strictly conforming XHTML 1.0 documents as defined above. Work by W3C is addressing ways to specify conformance for documents involving multiple namespaces.
What this means is that a document may well be well-formed xml but not be conforming XHTML 1.0 if it uses xml namespaces. That is why validators will refuse XHTML+RDFa or XHTML+MATHML are different specifications with their own DTDs.
Character entities are breaking
As it happens, without a DTD for XHTML served as xml, Firefox and any other xml-enabled browser will ignore all the character entities everybody has been scattering for too long in their pages. Yes, that even includes the sacrosanct
The only way for those character entities to be recognized, including in scripts, is to include a DTD.
In this scenario, the format proposed by microsoft would be a compound XHTML language requiring its own DTD in order to validate at all, unless you agressively prevent people from using DTDs.
As I’ve highlighted before, the HTML serialization of HTML5 specifically ignores, and will not generate namespaced DOM elements, any element and attribute that is not part of either the mathml, svg or html namespaces. More than that, the xmlns attribute is ignored and allowed only for convenience.
What this means is very clear: if you’re doing an HTML5 document (as opposed to XHTML5), you cannot use namespaces.
DOM is broken in most scenarios
For those of us that use scripts, and I assume AJAX 4.0 is for scripters, this gets better. In the case where the document was served as HTML, be it that it was HTML 4.01, HTML5, XHTML5 or XHTML 1.x, the method you’d use is the getAttribute(“sys:command”).
In the case where you actually care about processing using Xhtml and serve to browsers that support this language, you’d have to use getAttributeNS(“javascript:Sys”,”command”);
For an example of the kind of trouble this provokes, see this code snippet: https://developer.mozilla.org/en/Code_snippets/getAttributeNS
So DOM is broken when using namespaces, as you now have to know in your script if you’re with a DOM that supports xml namespaces, if the page was served as an xml serialization or an html one.
Because of exactly the same reason, CSS selectors don’t work in scenarios where you’re served as xml and html, or across versions of HTML.
Let’s try to write a CSS selector for the element specified above. In the scenario where the document is parsed without xml namespaces, aka HTML5, HTML4.01 or XHTML 1.x served as text/html.
Sys\:command { background: red; }
The backslash, as per the CSS specification, is used to escape a character that would otherwise be recognised. Here, I style an opaque element name with the value of “Sys:command”
So what happens when you deal with xhtml?
Sys|command { background: red; }
The syntax is different because xml namespaces are expressed that way in CSS.
And if you think the CSS syntax is a problem, you’ll have to remind yourself that jQuery is using CSS selectors, and doesn’t support the xml namespace syntax. See the problem above.
Rather than write code myself, I’ll point you to two tests that were written when the debate on the aria extensions was all the rage. Note that the first one may be flawed because of firefox parsing the content as html. In either case, none of those scenarios have consistent results across browsers as it stands today.
I made the point, on Scott's blog, that entering the field of using xml namespaces in non-xml languages was a grave mistake that had major compatibility issues with xml languages. I was brushed off, on that blog and through twitter, with the argument that dogma was the root cause of my argument. I hope that this entry addresses this concern, and that we can start discussing a way forward that doesn’t break anyone attempting to use application/xhtml+xml as it was intended.
To recap why using xml namespaces for this scenario is a bad idea:
My point here is not that the whole concept is wrong, it is right in a few scenarios, and comes with a lot of baggage. If Microsoft intends to deliver those features to a wide audience, and knowing their track record at warning developers of the tradeoffs of not respecting standards (and to be fair, the track record of Microsoft developers not giving a f*ck about standards and eating whatever comes from the hosepipe), they should take a responsible approach and warn prominently of those incompatibilities.
So, how to move forward? Here’s a few ideas thrown against the wall, to see if it sticks:
And the nitpicker corner, for all the things I heard before, and that I may agree with, none of which changes the result of this analysis:
I keep on reading things like the following quote from wikipedia’s talk page on the ReST article (a poorly written page at that):
Decide on an unambiguous definition of REST. IMHO, Fielding lost and the engineers won. REST = XML over HTTP
Rather than point out the sheer stupidity of such a statement, let me tell you the story of the ice-cream maker.
Once upon a time, in the age of fairies and leprechauns, an ice-cream maker named Roy Fielding discovered a seed that people have been using in a remote land, called cacao. Keen on using that discovery, he mixed those seeds with sugar, milk, eggs, cream and sugar and got the inhabitants of his village to try it.
Everybody was excited about this new ice-cream. They all knew the ingredients of course, and some of them were using it, but the mixing of all of them in one ice-cream was somewhat a revelation for many. Villagers became very fond of that new ice-cream, and Roy decided to call it chocolate ice-cream. For a long time, many people in Roy’s village consumed chocolate ice-cream, and all was good in the world. That village was named Web and declared chocolate ice-cream it’s local speciality.
One day, a traveller from the village of Soap, that everybody was calling mister Sainsbury, came to the village of Web and saw how much people liked that chocolate ice-cream. You see, in the Soap village, the local dish was made of soap, and people didn’t like soap very much. He decided to bring back the idea in his own village.
Sainsbury tried to reproduce an ice-cream people would like, and put milk, eggs and sugar, but because he didn’t know about cacao, he decided to use vanilla POD instead. And he got his fellow villagers to try the ice-cream, and they all liked the ice-cream very much, all all was good in the world. And it was named chocolate ice-cream.
Mister Sainsbury knew that the rest of the country was still eating soap, and decided, as a good business man he was, that they should all enjoy his chocolate ice-cream. And as mister Sainsbury got so rich from selling soap before, he started promoting his new chocolate ice-cream in the whole country, and soon all were excited about eating chocolate ice-cream made of vanilla.
One day, an engineer from the village of Wikipedia came to Web and asked for the national desert, the chocolate ice-cream. The villagers happily provided him with a wonderful cocoa-based chocolate ice-cream. When the engineer started eating it, he started screaming:
Engineer - This is not chocolate ice-cream! It’s not even the right colour! Do you think I’m a fool?
Roy – This is chocolate ice-cream. It has cacao in it, as it always had.
Engineer – No no no! Chocolate ice-cream is made of vanilla! Everybody knows that!
Roy – No, it’s made of chocolate, if you put vanilla in it it’s vanilla ice-cream, because there’s no chocolate in it?
Engineer – You’re just an extremist, you’re trying to confuse us!
Roy – …
And that’s when the villagers of Web decided that it was time for them to travel the country, and explain to people the advantages of putting cacao in their chocolate ice-creams.
I’m a villager of Web, and my mission is to re-educate the masses: ReST is *not* made of POD (Plain Old Data). It has a clear definition. It is time to get the industry back on track.
Same as usual, please register, limited space, it’s in Soho, it’s at 6:30, it’s about being a developer and talking about it, and it’s sponsored by ThoughtWorks.
Une fois n’est pas coutume, cette entrée sera en Français.
Vous avez sans doute vu qu’ayende a donne une formation nHibernate à Londres. Vous pouvez maintenant assister à cette formation, en Français, et délivrée a Paris, par nul d’autre que moi-même. Que demande le peuple ! ;)
Si vous êtes intéresses, envoyez moi un email et je vous enverrai les détails.
I’m available for work from now, so if you’re looking for a freelance that can code, coach and teach, pop me an email.
Someone last week mentioned that Java was now getting static methods defined on interfaces. We’ve had that capacity, through extension methods, since C#3, and is one pattern I keep on reusing.
An interface, at core, is a contract of extensibility between me and other developers: Implement method Bla() and I promise you will be called whenever that stuff is needed. The problem with such an approach is that some functionality is repetitive and makes implementing the interface more complicated.
Let’s take the example of an interface that’s part of OpenRasta…
public interface IDependencyResolver
{
T Resolve<T>();
object Resolve(Type serviceType);
}
Because both generic and non-generic methods are needed by the consumer, your initial reaction is to impose the implementation burden on the person implementing the interface.
Using static methods, we can take all that work away, and provide overloads and added funcitonality on any implementation of an interface. And it’s as simple as doing the following.
public interface IDependencyResolver
{
object Resolve(Type serviceType);
}
public static class DependencyResolverExtensions
{
public static T Resolve<T>(this IDependencyResolver resolver)
{
return (T)resolver.Resolve(typeof(T));
}
}
I now do most of the work, and the people wanting to implement the interface only have one method to implement. And everyone is happier.
Earlier this week, I attended the Scotch on the rocks conference. The organizers had the brilliant idea to invite developers from other communities with Amnesty tickets, to come and see what was happening in the ColdFusion world.
I’m very grateful they did, as this event has been an eye opener for me. I arrived with preconceptions of script people afraid of real languages hacking together un-maintainable solutions. I should know, I’m still hosting one of those for one of my clients. But this picture is inaccurate, or at least incomplete.
One of the sessions I attended, presented by Peter Elst, highlighted the source of some of my earlier concerns: an assertion was made that a flex developer could easily pick up ColdFusion and deliver the whole backend, without developer intervention. Without a specific scenario in mind, this assertion makes every warning sign in my synapses go red. I do believe however that this is reflective of one part of the ColdFusion community.
On the other end of the scale, Mark Drew presented multiple MVC frameworks available for ColdFusion, and talked about many of the same subjects we talk about in the .net community, including convention over configuration. The excellent Peter Bell talked about software estimation, in which TDD practices, and even Lean approaches to software development were discussed. And there is a vibrant open source community, through the use of IDE tools integrated in Eclipse (CFEclipse), and even an open-source implementation of ColdFusion, called Railo, presented by the excellent Gert Franz (can’t find a blog to link to).
From my discussions with quite a few developers after the event, this impression is widespread. While there are quite a few terrible developers and code being produced, there’s another side of the community that works on best practices and use modern approaches to software development.
In a word, exactly the same configuration as what we have on the Microsoft side of things.
And indeed, I learnt much about the traditional ColdFusion development. Best practices have been described to me as a split in components, for which the signature is described in the html derivative we have all seen in the past, with the implementation being done in CFScript.
One particular thing a developer told me was that, once you add attributes to your java / c# code, it doesn’t look that much different from writing the same thing in html. And while I have a personal issue with the context switch involved, I can’t refute that there is ground to the argument.
What I’ll take away from the event is the confirmation of something I’ve given a lot of thoughts about for a while: good developers are good, whatever platform they adopt. It is now my absolute belief that it is time for communities to build bridges and share knowledge of their craft, with no regard for the actual framework they use. Good ideas are worth knowing about, wherever they come from.
I’ve invited a lot of people I met to the next AltNet beers, as they are exactly the reason for my dropping the dot from the name. I really hope they accept the reciprocal invitation and help us build bridges between communities.
Footnote
Here’s a video interview done at the end of the conference, after quite a few beers.
Paul says “The whole .NET space has gone fluent interface crazy”, and he is quite right. Everybody has their own fluent interfaces, and unless I’m missing the bigger picture, most of them seem to be about productivity over discoverability. The intent is clear, write more intent-revealing code in less time.
More often than not however, you multiply the entry points needed to be known by developers. Let’s take an example with the criteria API in nHibernate.
|
I’ve highlighted in red those entry points. Each of those method usually takes an instance of an interface. A static method is then used to create those objects. What’s the issue with that?
It all comes down to discoverability. One of the biggest issue I’ve always had with the criteria API is the low discoverability of those types. Take the ICriterion interface, for which the Expression class provides the simple criterions. The only way, once in a method, for me to know that where it expects ICriterion I could use Expression is by going to the documentation. This is for me a massive discoverability failure.
The second issue comes from the latest lambda-based APIs. Let’s have a bit of code from the original blog post from Dru that Paul was referring to.
I’ve not downloaded the code to have a play, but I assume that Define and During are actually properties on the base type. On a positive note, this does help with discoverability, at the cost of enforcing an inheritance hierarchy.
So why do I feel awkward with this syntax? The nesting of lambdas. The multiplication of p, x and other one-letter prefix make the code much less readable. The pen*s operator is not exactly my favourite addition to the C# compiler.
Here’s my checklist for what constitutes a nice usable fluent API. [nitpicker corner: OpenRasta doesn’t do it that way everywhere. You didn’t say the same thing six months ago].
There is a way to make a fluent API while respecting those points, but I believe the result would be better. So here’s Dru’s example rewritten using those guidelines.
using(Definition)
{
During.Web
.Server("WebServer")
.Has.IisSite("Apps")
.VirtualDirectory("dashboard")
.Verify()
.CreateIfItDoesntExist()
.And
.Server("SvrTopeka19")
.Has.Msmsq()
.PrivateQueueNamed("mt_subscriptions")
.CreateIfItDoesntExist()
.And
.CopyFrom(@".\code_drop\dashboard\**\*.*").To(@"\\webserver\apps\dashboard\");
}
The main difference here is the introduction of scoping operators. The Server method returns two properties, And which closes the current Server scope, and Had Has which open a new service-specific scope.
I find this kind of API much more readable, and they introduce less syntax noise (aka no lambda operators or blocks). There is also no need to introduce external points of references, be them be properties or static classes, except for the original entry point. Arguably, they’re harder to write, but I think the effort is worth the benefits.
Wow, who would’ve thought the first conference season would’ve been so intense! I had an absolute blast meeting people, presenting, chatting away and drinking nice beers with so many interesting people! WebDD, DDD Scotland and DDD Belfast have been a blast!
I also realize that I’ve delivered all the talks and workshops I announced in my last schedule, so time for an update, both on my talks and on the interesting conferences and events that are being organized.
There you go. May have more to announce if things happen, or may not, but it’s going to be a busy summer!
I just received an email from Computer People, telling me “we agreed that I would keep in touch and update you with any further opportunities and developments around SharePoint”. I’m pretty sure that’s factually inaccurate, as I have very little interest in SharePoint development and certainly wouldn’t agree on the phone to be contacted for marketing reasons. But fair enough, if it was to help me find new clients, I wouldn’t be that bothered. But no! It’s to try and sell me sharepoint seminars! For Christ’s bullocks’ sake!
So off to my sent items, in which I keep years and years of emails (roughly since 2001), and of course I find absolutely no mention of that Dan Freshwater that just sent me an email, so emails are out.
Leaves only their website, maybe I subscribed to that and forgot to check the “do not contact me for marketing purposes” option. Although I’m very anal about always making sure I check that box, on paper forms or online, mistake is human so I may have not seen it. Or maybe it wasn’t there. Who knows.
The email goes on to try and sell me a seminar for SharePoint. So off to the website to check Computer People’s privacy policy, and here’s what I found.
You can exercise the right at any time by contacting us at Legal Services, 71 Elstree Way, Borehamwood, Hertfordshire, WD6 1WD.
What, legal services doesn’t have computers? Designing an option in your profile was too hard? Or are you making this difficult on purpose? Seeing as you lost my trust at the very beginning by saying I asked to receive marketing information about SharePoint, I’ll go for the last option.
Email was sent asking to not ever receive marketing emails again. We shall see if it has an effect, and I’ll be sure to report.
As I was coding some new tests for the container integration part of OpenRasta (which, since beta 2 changes, has become much more complicated…), I discovered a feature I didn’t even realize was there.
I use abstract test classes so that each container that OpenRasta supports automatically gains any new tests that verify the behaviour of the container matches OR’s expectations. In an abstract test, the test class that contains the test is marked abstract, and you inherit from that class for each specific set of tests you can run. I’ve used that trick for a long time, and was one of the main reasons why I didn’t like MSTest much, as it seems the guys in Redmond didn’t support that scenario.
So here I was, coding away in an abstract class, and frenetically executing the test as I added code (something I remapped to Ctrl+T, T). Then it dawned on me that I was attempting to execute the abstract class. But surely, an abstract class can’t be instantiated I told myself.
And then I realized what was happening. TD.net was simply executing the concrete classes inheriting from my test class. Sweet.
PS: I have no idea if it’s the runner or nunit, and have no idea either if other runners will or won’t execute this scenario. It just works and that makes me happy :)
I’ve given that talk in quite a few places, and always promise to post the slides on my blog. But in fact, I was secretly waiting for the VistaSquad video to be released.
Thanks to Ian Smith, you can now see it all, complete with slides and excessive arm waving.
The next AltNetBeers is going to be on the 12th of May!
Drinks and food will be provided by our two sponsors, SkillsMatter and ThoughtWorks, big thanks to them for helping our community strive!
We’re moving venue for a while, and we’ll be organizing this one at the GlassHouse, on 55 Brewer Street.
So we can plan ahead, please register for the event at http://ukdotnet.ning.com/events/london-altnetbeers-8
Because of the progressive.net workshops happening and the June event happing earlier in the month (and me not preparing early enough), I’m postponing the April edition to the second week of May.
Will announce the details as soon as I get all the dates secured.
We’ve now had quite a few very successful events with the alt.net London beers. One thing that strikes me every single time in this event is how much people are interested in discussing the why and the how of our profession, and not so much the actual tools or platform we use.
Our little community has been talking about DDD, SOLID, legacy code and many other side conversations that have, in the end, had very little to do with .net, and everything to do with being a professional developer.
We’re about practices and continuous (and documented) improvement, and the attendants have made that event mostly technology agnostic. It’s something I always wanted to see happen and never had the need to push for. The name change reflects the reality of the nature of our group, rather than my personal will. Those just happen to be in sync at the moment.
So the event is now the AltNet London Beers, the event of the Alternative Network of software professionals. Let’s expand our horizon beyond what we’re comfortable with, and see if it sticks. If not I’ll put the dot back in.
On to the schedule:
And the good news is that we’re trying an enhanced format for the next edition. All will be revealed at the next event. See you there!
One of the most surprising thing for me has always been an impression by many LGBT geeks that they were alone, especially around the younger crowd out there. And indeed, the tech world is always very reserved about revealing what is a very personal thing.
A group of us have been thinking for a while that it’d be nice to organize a social event to meet fellow gay geeks, have a pizza and some booze to go with it. Thanks to Ben’s effort, we’re now all set for our first event.
It will all be happening on the 24th of April.
To get the details, go to http://www.gaygeekdinner.com
To register, simply send an email to attend@gaygeekdinner.com. Registration is anonymous for those that feel more comfortable keeping things that way.
Rules are fairly simple (and stolen from the GirlGeekDinner): it’s open to any LGBT, and straights are allowed as long as they’re invited by an LGBT (only one per person people :) )
Hope to see many of you there!
The WebDD community-driven conference registration is open, go ahead and book yourself for a day of fun and web technology!
You can have a look at the schedule at http://developerdeveloperdeveloper.com/webdd09/Schedule.aspx
This entry may be outdated. For the latest updates on openrasta, see www.openrasta.com.
I just had an idea to clean-up my resource definitions. I could’ve gone straight in the OpenRasta code and add just this small additional feature I really want, but OpenRasta is all about extensibility and composition, and I’m a few days away from the beta 1 release. So I thought I’d put to test the API from the outside, and tell you a story about how to define multiple views on a resource with the WebForms Codec. I may move this entry over to the documentation part of the project later on.
--
In OpenRasta, you need to define your resources individually. A resource in OpenRasta is simply a class you create that handlers will deal with. Each resource may have any number of URIs, and any numbers of codecs. A codec is a piece of code responsible for rendering a codec, and on this project I use the WebForms codec.
ResourceSpace.Has.ResourcesOfType<UserRegistration>()
.AtUri("/registration")
.HandledBy<UserHandler>()
.AndRendededByAspx("~/Views/User/New.aspx");
You can see here the registration for my UserRegistration resource. It defines where to find it, what handler is using it, and a page to render it.
Whenever a user has successfully registered, it’s quite usual to return them to a page welcoming them to the world of splendor that you’ll provide them, now that you have all their previous personal details. And it usually contains the exact same information that you collected previously. And that’s where it can become a bit hairy.
The initial (and in many scenario sane) reaction is to create a separate resource / handler / view couple to render our Thanks page. This is indeed accurate: the thing that I serve to the client is indeed a document with a “Thank you” message, complete with blink tags.
Another point of view, and the one I usually favour, is to consider those various elements as different views on the same resource. From a ReST point of view, each of those views will be a resource in its own right, but from a programming perspective OpenRasta will treat them as being the same entity to operate against.
So how do we solve the conundrum? The first piece of the puzzle is to use the capacity baked in the WebForms view engine to define multiple views. We can change the registration ever-so-slightly by using the generic notation for registering the view.
ResourceSpace.Has.ResourcesOfType<UserRegistration>()
.AtUri("/registration")
.HandledBy<UserHandler>()
.AndTranscodedBy<WebFormsCodec>(new
{
index = "~/Views/User/New.aspx",
thanks= "~/Views/User/Thanks.aspx"
});
The registration looks very similar. The AndRenderedByAspx method you saw earlier is a shorthand for the full notation using the AndTranscodedBy<T> which lets you plug-in many different codecs per-resource.
The anonymous type itself defines view names that will be passed to the WebForms codec. The question is, how do we get the framework to choose those views?
By default, that codec always uses a view named index (or default or get) for the default view to select. Another approach is to use uri path segments. If I typed the URI http://localhost/registration;thanks the thanks bit is called a path segment, and is always separated by a semi-column. If you go and try that now on your OpenRasta website, it won’t work (something about not enabling features don’t want). You need to go and enable it by adding a UriDecorator.
ResourceSpace.Has.UriDecorator<PathSegmentAsRendererUriDecorator>();
URI decorators in OpenRasta are modules that lets you manipulate uris before a request is processed. It’s used for integrating various features, such as file extensions, localized URIs, and whatever else you may think of. And the reason the PathSegmentAsRenderer is called the way it is is historical, and before this blog entry I never realized that it should really be updated to PathSegmentAsCodecParameter. Expect to see that change in the trunk over the weekend. (Codecs used to be called Renderers when I was working on the codebase that preceded OpenRasta).
So, all is good, we can now go to /registration;thanks and see the Thanks.aspx page rendering a resource. But what if you didn’t want to use path segments, and define two different URIs yourself?
.AtUri("/registration")
.AndAt("/registration/{emailAddress}/complete").Named("thanks")
.HandledBy<UserHandler>()
.AndTranscodedBy<WebFormsCodec>(new
{
index = "~/Views/User/New.aspx",
thanks= "~/Views/User/Thanks.aspx"
});
We’re going to need to leverage a few other features of the configuration API.
First is the support for named URIs. If one resource can have multiple name, that feature lets you give it a friendly name. It is mostly used to decorate a handler method to help select which overload of a method gets executed, but it can also serve our purpose here quite well.
We’re going to plug in the OpenRasta pipeline, and do the same thing the PathSegmentAsRendererUriDecorator type does: add a string that will be sent to the codec to help it choose. To do this, we’re going to implement a class implementing IPipelineContributor. You can find the code at the end, as an example.
This exposes a few specificities of OpenRasta. The first one is the pipeline model itself. Whenever you want to integrate deep within the framework, and modify the way things are processed, you need to tell OpenRasta which components you depend on in the execution pipeline. That’s what the ExecuteBefore and ExecuteAfter methods do. Out of the box, there’s 18 contributos to choose from. Each component does a tiny bit of the request processing, and enrich the data until it’s been turned back into a byte stream. The execution order is non-deterministic: OpenRasta will always honour your requests to be before or after someone else, but doesn’t guarantee anything beyond that.
Another aspect is the fact that pipeline contributors are the only components in the system to be singletons. They will be loaded one and never be discarded. That’s why they take a dependency on the ICommunicationContext god object. It’s the only ever Context object you’ll find in OpenRasta. Most of the interfaces in the system have flat methods with a well-known number of parameters. Just the minimum amount of information needed for a component to execute, everything else is handled by dependency injection.
Overall, when you’re an IPipelineContributor in OpenRasta, your’re like god, you run at the kernel of stuff. And because it’s a pipeline model, any of your actions *will* have consequences on everyone else. There’s many other less low-level extensibility points in OpenRasta, so when you can, use them!
The code
public class UriNameAsCodecParameter : IPipelineContributor
{
public void Initialize(IPipeline pipelineRunner)
{
pipelineRunner.ExecuteBefore<ResponseEntityWriter>(AddUriNameToCodecParameters);
}
public PipelineContinuation AddUriNameToCodecParameters(ICommunicationContext context)
{
if (context.PipelineData.SelectedResource.UriName != null)
{
var newCodecParameters = new List<string> { context.PipelineData.SelectedResource.UriName };
if (context.Request.CodecUriParameters != null)
newCodecParameters.AddRange(context.Request.CodecUriParameters);
context.Request.CodecUriParameters = newCodecParameters.ToArray();
}
return PipelineContinuation.Continue;
}
}
The registration (until I’ve revisited that part of the code, cause I sure don’t like it. It’s an outstanding task)
DependencyManager.GetService<ITypeRepository<IPipelineContributor>>().Types.Add(typeof(UriNameAsCodecParameter));