Brisbane Alt.Net Beers I

Brisbane CentralTonight was the first Brisbane Alt.Net Beers. I am sitting at Central station killing time before the Cleveland train arrives to take me away from the madness. The diggy billboard informs me that they can get me on the front page of Google guaranteed! Sweet.

The evening turned out nothing like the UK Alt.Net Beers, which are characterised by a fixed time limit and a single topic. Tonight was a group of nerds, ranging from mild to intense, drinking beer and discussing the failures and successes of their professional lives. For some it was enlightening, for some it was cathartic and I hope it was enjoyable for everyone. I think it is a good sign that Brisbane Alt.Net is alive and well. Lets do it again some time.


Web Application Architectures

I continue to be interested in the architecture of the plain, standard, web application. Each of the web application frameworks defines an architecture for the plain web application. Think of Rails and Django (MVC + Active Record), or sharp architecture and Codebetter.Canvas (Asp.net MVC + NHibernate + DDD). This is a starting point from which more advanced and specialised web applications can grow.

Damian Maclennan, or as these guys might say (2:50) 'some guy',  presented a simple framework for web applications at Sydney Alt.Net. Damian's example mixes Asp.Net MVC, Fluent NHibernate and Structure Map. 

The Good Parts

My favourite part is the way that NHibernate is configured with the IoC container. The author inherits from the Structure Map Registry class and creates a registry called NHibernateRegistry

internal class NHibernateRegistry : Registry
    {
        public NHibernateRegistry()
        {
            ForRequestedType<ISessionFactory>()
                .CacheBy(InstanceScope.Singleton)
                .TheDefault.Is.ConstructedBy(() => new NHibernateSessionFactory().GetSessionFactory());

            ForRequestedType<ISession>()
                .CacheBy(InstanceScope.Hybrid)
                .TheDefault.Is.ConstructedBy(x => x.GetInstance<ISessionFactory>().OpenSession());
        }
    }

I think this is a neat way to group IoC registrations. The NHibernateRegistry registers NHibernateSessionFactory as a singleton, which is important because NHibernate requires that the session factory is at application scope. The scope for ISession is InstanceScope.Hybrid which means that the scope of an ISession is one HTTP request, exactly what is required for normal NHibernate usage. 

The Missing Parts

It is usually desirable to begin a transaction for each ISession and close the transaction prior to the ISession being closed. If the example is extended to include database writes it will fail without transactions. NHProf recommends that transactions be used even for read-only sessions.

Security can be a challenge in Asp.Net MVC. I would like to see how Damian prefers to secure controllers. 

The Repository<T> class currently only supports querying by Id. If a more complicated query is required where should it go? The two popular options are: specialised repositories (PostRepository : IRepository<Post>) with query methods and query objects where each query is encapsulated in an object. 

Fluent NHibernate is nice but I wonder why auto mapping was not used. It would work nicely for the domain in the example. 

Jerry's Final Thoughts

It's good to see the production of this kind of useful guidance. Someone new to the technologies could easily use Damian's example as a starting point for a well designed Asp.Net MVC application. It is certainly a much more helpful starting point than the Visual Studio template. 

Until next time, take care of yourselves and each other.


Code Camp SA

University of South AustraliaI spent the weekend in Adelaide for Code Camp SA. Code Camp SA is Adelaide's version of Code Camp Oz in Wagga Wagga, which I also attended and spoke at.

The event was well organised with excellent facilities and catering. Saturday night there was a social dinner at a local pizza restaurant for the tried and true nerd / pizza combination.

I gave my presentation, 8 Reasons Why ASP.NET MVC is better than Webforms on the first day before lunch. To keep things interesting I was followed by Tatham Oddie keeping things balanced with 8 Reasons Why Webforms is better than MVC. His argument was based around the difficulty of creating composite UIs with MVC, which is a valid criticism. 

Here is the ASP.NET MVC example code from my talk, including a nifty bulk geocoder for google maps.


Many-to-Many NHibernate HQL Queries

The only book on NHibernate, NHibernate In Action, conveniently fails to demonstrate how to perform a query that requires a many-to-many join. Suppose you are implementing a security system, where each user has access to a set of doors and each door is accessible by a set of user. There is a many-to-many relationship between User and Door. Here is how you could query for all the doors that a user has access to:

    session.CreateQuery("from Door door left join fetch door.Users user where user.Username = :username")
        .SetString("username", username);

The 'fetch' keyword causes an outer join between Door and User, transparently utilizing the connecting table.


Many-to-Many Relationships With Fluent NHibernate Automapping

You can't. The trick is to fall back to fluent nhibernate mapping for many-to-many relationships. Also remember to map both sides. Here is an example:

        private static AutoPersistenceModel Automapping()
        {
            return AutoPersistenceModel.MapEntitiesFromAssemblyOf<Entity>()                
                .ForTypesThatDeriveFrom<User>(map => {                     
                    map.HasManyToMany(u => u.Communities).Cascade.All().WithTableName("CommunityMembers");                    
                })
                .ForTypesThatDeriveFrom<Community>(map=> map.HasManyToMany(c => c.Users)
                     .Cascade.All().Inverse().WithTableName("CommunityMembers"))
                .Where(t => t.Namespace == "Myproject.Domain");
        }

 


Resize and Save Images with .NET

In this post I will present a service class for resizing and saving an image. The service has one public method, ResizeAndSave() which accepts a stream, a filename and a directory to save the file to. It uses a simple algorithm to rescale the image to fit into a maximum rectangle and then performs the actual resize using System.Drawing, and returns the dimensions of the resized image.

    public class ImageService : IImageService
    {
        private readonly IFileSystem fileSystem;
        private const int LARGEST_WIDTH = 400;
        private const int LARGEST_HEIGHT = 500;

        public ImageService(IFileSystem fileSystem)
        {
            this.fileSystem = fileSystem;
        }

        public Rectangle ResizeAndSave(Stream input, string filename, string toDirectory)
        {
            using (Image image = Image.FromStream(input))
            {
                Rectangle scaledRectangle = (image.Width > LARGEST_WIDTH)
                    ? ScaleByWidth(image.Width, image.Height, LARGEST_WIDTH)
                    : new Rectangle(0, 0, image.Width, image.Height);
                
                if (scaledRectangle.Height > LARGEST_HEIGHT)
                {
                    scaledRectangle = ScaleByHeight(scaledRectangle.Width, scaledRectangle.Height, LARGEST_HEIGHT);
                }

                Bitmap newImage = new Bitmap(scaledRectangle.Width, scaledRectangle.Height, image.PixelFormat);
                Graphics toDrawOn = Graphics.FromImage(newImage);
                toDrawOn.CompositingQuality = CompositingQuality.HighQuality;
                toDrawOn.SmoothingMode = SmoothingMode.HighQuality;
                toDrawOn.InterpolationMode = InterpolationMode.HighQualityBicubic;
                toDrawOn.DrawImage(image, scaledRectangle);
                
                fileSystem.Write(ConvertImageToMemoryStream(newImage).ToArray(), toDirectory, filename);
                newImage.Dispose();
                toDrawOn.Dispose();
                return scaledRectangle;
            }
        }

        private static MemoryStream ConvertImageToMemoryStream(Image image)
        {
            var stream = new MemoryStream();
            image.Save(stream, image.RawFormat);
            return stream;
        }

        private static Rectangle ScaleByWidth(int originalWidth, int originalHeight, int newWidth)
        {
            float scalingFactor = (float)newWidth / (float)originalWidth;
            float newHeight = originalHeight * scalingFactor;
            return new Rectangle(0, 0, newWidth, (int)newHeight);
        }

        private static Rectangle ScaleByHeight(int originalWidth, int originalHeight, int newHeight)
        {
            float scalingFactor = (float)newHeight / (float)originalHeight;
            float newWidth = originalWidth * scalingFactor;
            return new Rectangle(0, 0, (int)newWidth, newHeight);
        }

    }

The actual file writing is delegated to the IFileSystem service, which is implemented like so:

    public class FileSystem : IFileSystem
    {
        public void Write(byte[] data, string directoryPath, string fileName)
        {
            if (!Directory.Exists(directoryPath)) Directory.CreateDirectory(directoryPath);
            File.WriteAllBytes(directoryPath + fileName, data);
        }
    }

 


ASP.NET MVC Gravatar Helpers

Gravatar is a service that provides globally unique avatars linked to email addresses. Imagine you could include a user's gravatar in a view simply by passing their email address to a helper:

<img src="<%= Url.Gravatar("user@domain.com") %>" />

All we need to do is to add some extension methods to UrlHelper to generate the url to the gravatar service:

    public static class UrlExtensions
    {
        public static string Gravatar(this UrlHelper url, string emailAddress)
        {
            var baseUrl = "http://www.gravatar.com/avatar/{0}";
            return String.Format(baseUrl, MD5Hash(emailAddress.ToLower()));
        }

        public static string Gravatar(this UrlHelper url, string emailAddress, int size)
        {
            var baseUrl = "http://www.gravatar.com/avatar/{0}?s={1}";
            return String.Format(baseUrl, MD5Hash(emailAddress.ToLower()), size);
        }

        private static string MD5Hash(string input)
        {
            StringBuilder hash = new StringBuilder();
            MD5CryptoServiceProvider md5provider = new MD5CryptoServiceProvider();
            byte[] bytes = md5provider.ComputeHash(new UTF8Encoding().GetBytes(input));

            for (int i = 0; i < bytes.Length; i++)
            {
                hash.Append(bytes[i].ToString("x2"));
            }
            return hash.ToString();
        }
    }

 The second overload of the Gravatar() method accepts a parameter called 'size' that is the desired size of the gravatar in pixels. The default is 80.

 


Fluent NHibernate with Automapping: Mapping Enums to Database String Fields

In general, I like to use enums for model properties that have a fixed set of values, and I like to persist those enums are strings. The advantage is that the values can be read without requiring a pointless mapping.

Because I am using Fluent NHibernate Automapping it was not straightforward to get this to work. The trick is to specifically instruct the automapping to map the enum property. Without this, the property is simply ignored. Here is my automapping configuration, the enum is the User.Role property (line 7):

private static AutoPersistenceModel Automapping()
{
    return AutoPersistenceModel.MapEntitiesFromAssemblyOf<Entity>()
        .ConventionDiscovery.Add<OneToManyConvention>()
        .ConventionDiscovery.Add<NotNullPropertyConvention>()
        .WithSetup(s =>  s.IsBaseType = type => type == typeof(Entity) )
        .ForTypesThatDeriveFrom<User>(map => map.Map(u => u.Role))
        .Where(t => t.Namespace == "MyNamespace.Domain");
}

The other interesting mapping here is line 6. It instructs the automapper that every domain class inherits from Entity.


The Trouble With Agile

Money GrabWhen a customer sponsors a software development project they want to know two things:

how much will the project cost and when will the project be finished.

The trouble with agile is that it cannot answer either of these questions with any degree of confidence. Put another way, the trouble with agile is that it exposes how difficult and costly estimation really is. The agile promise is that for the time and money the customer allows they will get the most value possible, but the magnitude of that value is not known in advance. Agile does not increase the customer's risk, but it increases their perception of risk.

Today I read cogentconsulting's Customer Brief. They talk about how agile should eliminate waste:

we don’t want anyone to spend too much time documenting details that turn out to be irrelevant, or writing down things that can be communicated more effectively by phone or face to face,

and how the customer must give up their fixed-price safety blanket:

you need to be comfortable with the concept that some things will turn out to be cheaper and easier than expected, and some things will turn out to be harder and more expensive than expected.

I was also intrigued by their careful handling of reported defects:

unfortunately, we don’t have an indisputable way of making that distinction [between a defect and a change], so instead we treat every change as simply that – a change.

In other words, the customer bears the risk of undiscovered, misinterpreted or incorrectly implemented requirements. Caveat emptor. That such a mature and respected company felt the need to write such a strongly worded disclaimer makes me think that I am not the only software provider dealing with this challenge. It reinforces the need to educate customers on their role in an agile environment.

I have found some hope reading about Kanban and lean. The refreshing change is that Kanban has removed all pretense of estimating project time and cost. It includes some vague forcasting but the customer is never given the impression that they can fix a feature/time/budget trinity. I like kanban because it is honest, however I doubt how well it will work for a commercial project.

kick it on DotNetKicks.com

Clarification post Brisbane ALT.NET Meeting

At the Brisbane ALT.NET meeting last night (which rocked and had code kata) we had a discussion about the Resharper guidance "Using directive is not required by the code and can be safely removed".

I was saying that I like to leave the System.Linq reference even if it is not being used. Heinrich demonstrated that if you type

from a in "astring"
select a;

resharper suggests adding the linq reference back in. But here is an example of linq code (collection extension method) for which resharper does not correctly detect the required reference:

var a = new string[] {"serfsdfas"}.Where(

In this case you have to know that the System.Linq using statement is required. That is why I like to leave it in even when it is not being used.

Prior to this I wrote the greatest and best blog post in the world, and accidently deleted it by hitting Backspace. I'll probably get over it one day. Probably not today.

 

ALT.NET