Procedural vs. Structural Code
In working with my development team, one of the things I've been working on is to figure out how to get them to be more object oriented. I've written about this topic before and I continue to evolve my expression of this idea to other developers that I work with.
To me, beyond the simple textbook definition of object oriented programming, at the level of construction, what it really boils down to is expressing logic structurally as opposed to procedurally. That is the very basis of what I've been trying to communicate and trying to understand how to impart that on other developers.
As a basic example, let's consider a user management API that has three operations for add, update, and delete. Suppose I want to send a sequence of actions to this API. We see this type of pattern of interaction all the time. Assume we have a repository class:
public class UserRespitory
{
public void Add(User user)
{
Console.Out.WriteLine("Added!");
}
public void Delete(User user)
{
Console.Out.WriteLine("Deleted!");
}
public void Update(User user)
{
Console.Out.WriteLine("Updated!");
}
}
I've left the implementation of the actions intentionally simple. Now assume that we have an operation and a user class like so:
public class Operation
{
private readonly string _type;
private readonly User _user;
public Operation(string type, User user)
{
_type = type;
_user = user;
}
public string Type
{
get { return _type; }
}
public User User
{
get { return _user; }
}
}
public class User
{
private string _username;
public User(string username)
{
_username = username;
}
}
Consider a use case where we must build an API to support bulk operations. The typical implementation pattern that I will encounter will look more or less like this:
private static void Main(string[] args)
{
List<Operation> inputs = new List<Operation>
{
new Operation("Add", new User("Charles")),
new Operation("Update", new User("Steve")),
new Operation("Delete", new User("John"))
};
UserRespitory repository = new UserRespitory();
foreach (Operation operation in inputs)
{
switch (operation.Type)
{
case "Add":
repository.Add(operation.User);
break;
case "Update":
repository.Update(operation.User);
break;
case "Delete":
repository.Delete(operation.User);
break;
default:
throw new InvalidOperationException();
}
}
}
This is pretty much textbook procedural code and, as a consultant, this is pretty much the code I expect to see (and have seen countless times) on projects. Of course, this is a pretty harmless case; in measuring the cyclomatic complexity and maintainability index of this code using Visual Studio's built-in analysis tools, I get values of 7 and 67 for each respectively.
Cyclomatic complexity is a good tool because it gives us a quantitative metric of code quality that is indifferent to "style" or any qualitative prejudices that individual developers might have -- it's a pretty good starting point for determining where to focus your time in terms of code reviews and refactoring. With that said, a value of 7 is certainly not bad (the NIST guidelines recommend a limit of 10 for methods), however, I think we've all encountered this before: if-else's nested under switch's nested under if-else's nested under for-loops and so on. When I see this pattern, I usually encounter it in the 20-30 range (and I've seen it in the 100+ range, sadly (an extract from a 1078 line method with cyclomatic complexity of 136 in production code -- I couldn't zoom out far enough to capture the whole thing)) for cyclomatic complexity simply because the developer doesn't know when to stop the madness.
Well, let me correct that last statement: when a developer starts down this path and once they've gone deep enough, there is simply no way that they can recover from the madness without structurally refactoring the code; the switch-case traps you into a cycle of cancerous code unless you can find a different way of representing the same logic in a more modular, orthogonal manner. To me, this is really the heart of understanding object oriented programming. How we achieve this -- in this case -- is quite simple, really. For starters, we make the operation abstract:
public abstract class Operation
{
private readonly User _user;
public Operation(User user)
{
_user = user;
}
public User User
{
get { return _user; }
}
public abstract void Execute(UserRepository repository);
}
We also add an abstract method called Execute which every inheriting class must implement -- it's here that we've captured the essence of the switch-case in a much more structural, object-oriented manner. Instead of a switch statement, we build the same logic structurally into the code by using three classes:
public class DeleteOperation : Operation
{
public DeleteOperation(User user) : base(user) {}
public override void Execute(UserRepository repository)
{
repository.Delete();
}
}
public class AddOperation : Operation
{
public AddOperation(User user) : base(user) {}
public override void Execute(UserRepository repository)
{
repository.Add();
}
}
public class UpdateOperation : Operation
{
public UpdateOperation(User user) : base(user) {}
public override void Execute(UserRepository repository)
{
repository.Update();
}
}
The abstract method now gives us a way of specifying a different action for each "case" by creating another class. Now our main code can be updated:
private static void Main(string[] args)
{
// Structural representation of the logic
List<Operation> inputs = new List<Operation>
{
new AddOperation(new User("Charles")),
new UpdateOperation(new User("Steve")),
new DeleteOperation(new User("John"))
};
UserRepository repository = new UserRepository();
inputs.ForEach(i => i.Execute(repository));
}
What is our end result?
The change in the code itself was very minor; we performed a slight-of-hand and simply moved the three logical branches in the switch into three separate classes instead with each class inherently representing one of the switch cases. In doing so, however, the cyclomatic complexity for the main program halved to 3 and the the maintainability index increased 6 points, even with such a barebones change.
The overall maintainability index of the entire solution increased 6 points. Our cyclomatic complexity for the solution did increase, but that's because we've added three new classes which adds to the sum.
There are several other advantages that are easy to extend from this point:
- It's easier to add new operations. Instead of adding another case, we simply add another operation class and inherit from the abstract base class. The logic for that particular operation -- for example, business logic or setup before the operation is invoked -- can be encapsulated in the new class instead of in the case.
- It's easier to add more logic around the operations. Because we've removed the invocation from the switch, we can avoid a giant if with deeply nested code as the logic around the operations change. With a class for each operation, we can add operation specific logic to the class instead. If we need to add common logic, we can use the base class.
- It's easier to read. I think the code is easier to read simply because the level of nesting is now greatly reduced. McConnell writes in Code Completed, 2nd Edition:
"The smaller part of the job of programming is writing a program so that the computer can read it; the larger part is writing it so that other humans can read it." (McConnell, 733)
- It's less prone to user error. By removing the switch and getting away from a string comparison, we've made the solution more resilient to input errors.
Overall, it's a very minor change in the structure of the code (check it out, even the LoC is the same), but even in this most basic of scenarios, it yields clear objective and subjective improvements. While this is a very basic example of a very specific case, the underlying idea here -- structural representation of logic and flow -- is the real essence of object oriented programming. The intentionally simplistic example is meant to (hopefully) help surface this concept, but the general idea of refactoring to structural representations is applicable to many different use cases, scenarios, and coding patterns.
Code samples: SampleProcedural.zip and SampleStructuralCode.zip
Browser MapReduce + Charting
Having dabbled in Mongo a bit, I was curious if there was an analog for MapReduce style functionality in browser JavaScript.
I found a small script as a starting point, but made some minor modifications to support array inputs:
// mapper should return an array of [{key:'somekey', value:'somevalue'}]
// reducer should return a single {key:'somekey', value:'somevalue'}
function mapReduce(i, mapper, reducer, property) {
var intermediate = [];
var output = [];
if(i && i.constructor == Array)
{
for(var x = 0; x < i.length; x++)
{
var value = i[x][property];
var key = property;
intermediate = intermediate.concat(mapper(key, value));
}
}
else
{
for (var key in i)
{
var value = i[key];
intermediate = intermediate.concat(mapper(key, value));
}
}
var groups = groupBy(intermediate);
for (var key in groups)
{
var values = groups[key];
output.push(reducer(key, values));
}
return output;
}
// list should be [{key:k, value:v}, ....] where key may be repeated.
// returns [{key, [v1, v2, v3...]}, ...] where key is *not* repeated.
function groupBy(list) {
var ret = {};
for (var i = 0; i < list.length; i++) {
var key = list[i].key;
var value = list[i].value;
if (!ret[key]) {
ret[key] = [];
}
ret[key].push(value);
}
return ret;
}
I then plugged in my custom map/reduce functions:
// Random data set -- could come from anywhere.
var data = [
{Country: "US", Type:"B", ProductCode: "001"},
{Country: "US", Type:"B", ProductCode: "001.A"},
{Country: "US", Type:"Z", ProductCode: "001.B"},
{Country: "UK", Type:"A", ProductCode: "002"},
{Country: "US", Type:"Z", ProductCode: "003"},
{Country: "FR", Type:"B", ProductCode: "003.A"},
{Country: "DE", Type:"B", ProductCode: "003.C"},
{Country: "DE", Type:"T", ProductCode: "004"},
{Country: "UK", Type:"R", ProductCode: "004.R"},
{Country: "UK", Type:"B", ProductCode: "005"}
];
// Custom mapper
function _map(key, value)
{
var result = [];
result.push({key:value, value:1});
return result;
}
// Custom reducer
function _reduce(key, values)
{
var sum = 0;
for(var i = 0; i < values.length; i++)
{
sum += values[i];
}
return {key: key, value: sum};
}
Now can I call it like so:
// Basic "group by - count" var out = mapReduce(data, _map, _reduce, "Country");
This yields the following result:
[{"key":"US","value":4},
{"key":"UK","value":3},
{"key":"FR","value":1},
{"key":"DE","value":2}]
Pretty nifty! And this data can then be fed into flot for charting purposes.
Sample (with flot example) is attached: MapReduce.zip
Externalizing Build Configuration
While PowerShell is great, I still do a lot of my build automation using plain old batch scripts when it comes to managing my SharePoint development workflow. Because I do my development outside of my SharePoint environment (develop on my host OS but SharePoint is in my guest OS), it requires some nifty batch scripts to keep the flow tight as no plugins or tools support this development model (dunno why...).
One of the challenges is making it easy to externalize environmental configuration information on a developer-by-developer basis.
In the past, I've relied on having team members create environment variables, but I decided to try out an external configuration file.
It worked out great
The following script reads a file and sets four variables:
@ECHO OFF ECHO ______________________________________________ ECHO Setting up build environment... ECHO ______________________________________________ For /F "tokens=1-4* delims=;" %%A IN (..\build-configuration.txt) DO ( SET SERVER=%%A SET LOGIN=%%B SET PASSWORD=%%C SET APPPOOL=%%D ) ECHO SERVER = %SERVER% ECHO LOGIN = %LOGIN% ECHO PASSWORD = %PASSWORD% ECHO APPPOOL = %APPPOOL%
And the file looks like this:
vm1;administrator;P@ssw0rd;SharePoint - DM App Pool
Now I can use the variables like so:
ECHO ______________________________________________ ECHO Copy to remote server... ECHO ______________________________________________ IF NOT EXIST \\%SERVER%\_ic\ctmo\ GOTO END DEL \\%SERVER%\_ic\ctmo\binaries /q /s XCOPY ..\..\pkgs\*.* \\%SERVER%\_ic\ctmo /Y /I /S
It even works when calling to psexec:
ECHO ______________________________________________ ECHO Start psexec... ECHO ______________________________________________ ::// Deploys the binaries only (doesn't reinstall .wsp). ..\..\tools\sysinternals\psexec.exe \\%SERVER% -u %LOGIN% -p %PASSWORD% -e -d -w C:\_ic\ctmo\binaries cmd /c \\%SERVER%\_ic\ctmo\binaries\gac-install.bat
The best part is that each developer only has to create the text file and all of the environment specific information (like the target SharePoint server) are configured in one tiny file, allowing the automation scripts to be ready for any developer.
SharePoint 2010 Service Applications Thoughts
I can't say that I can add much more to the tutorials and articles already out there on the Net on this topic, but I'd like to point to the definitive example of how to implement one: http://msdn.microsoft.com/en-us/library/gg193964.aspx
David Taylor's blog also has a good 10 part walkthrough with a bit more explanation; however, I would caution that the example he provides is broken as heck and was part of the problem that it took me a good part of 3-4 days to get something so simple to work right.
One bit of knowledge that I'd like to impart is that you will -- more than likely, 99.99% guaranteed -- run into errors with WCF. In these cases, the errors will:
- Not show up in any level of detail in the SharePoint logs
- Not show up at all in the system event logs
- Not show up in the IIS logs with any level of detail
You'll want to use SvcConfigEditor to enable tracing and of course, SvcTraceViewer to view your logs. Part of my problem was that I had an error in the configuration file for the service and part of the problem was that I had an error in the VirtualPath of the service in my service application. I was only able to track these two down through the usage of the aforementioned WCF utilities so keep them handy!
Chaining jQuery AJAX Calls (w/o Plugins)
Here's the scenario: you need to make a series of AJAX calls to process a list of objects and each call is dependent on the results from the previous call. How can we structure this elegantly in jQuery without having to write massive chains or script callbacks?
An example would be using an AJAX based API to create a hierarchy of nested folders. Perhaps the user enters a string like "/path1/path2/path3" and multiple calls are needed to create "/path1", then /path1/path2," then "/path1/path2/path3".
My friend John Peterson brought up jQuery deferred to me today and it clicked and my life is better for it.
Here's an example:
var parts = ["path1","path2","path3"]; // Output from string.split()
var chain = $.Deferred(); // Create the root of the chain.
var promise; // Placeholder for the promise
// Build the chain
for(var i = 0; i < parts.length; i++)
{
if(i == 0) promise = chain;
// Pipe the response to the "next" function
promise = promise.pipe(function(response)
{
var part = this.shift(); // Get the current part
var root = "";
if(response)
{
root = response.newPath;
}
return $.ajax // MUST call return here.
({
type: "GET",
url: "filemanager/create/" + root + part,
context: this
});
})
}
promise.done(function(response){
// This handles the response from the final AJAX call
});
chain.resolveWith(parts); // Execute the chain
The general idea is that we start with a chain and "pipe" the output from each step to the next. When I execute the chain, I pass in the array as the argument on line 35.
This is necessary because referring to part[i] inside the function declared on line 11 will always yield "part3" . To work around this, we pass in the whole array of parts as the context to the chain. It becomes the "this" reference and we simply shift() a value off of the array to get the "current" item.
To pass the array to the next function in the chain, we simply set the context of the AJAX call to the "this" reference. Now, in the next handler in the chain, the "response" is the output of the previous AJAX call and the "this" reference is the "current" item in the array.
Of course, the final call -- if you want to handle it -- can be added to the chain using done() instead of pipe().
It's a brilliant way of chaining multiple jQuery AJAX calls in a much more coherent manner!
The Beauty of Mongo
MongoDB is sexy. Sexy as hell.
This isn't the first or the best intro to Mongo+.NET, but I hope this one can show you how it finally solves the object-relational disconnect with an easy to follow example.
Let's start with the model:
#region prologue
// Charles Chen
#endregion
using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace MongoAssessmentsTest
{
public class Assessment
{
private DateTime _created;
private string _description;
[BsonId]
private ObjectId _id;
private List<ContentItem> _items;
private DateTime _lastUpdated;
private string _ownerId;
private List<string> _tags;
private string _title;
public ObjectId Id
{
get { return _id; }
set { _id = value; }
}
public string OwnerId
{
get { return _ownerId; }
set { _ownerId = value; }
}
public string Title
{
get { return _title; }
set { _title = value; }
}
public string Description
{
get { return _description; }
set { _description = value; }
}
public List<string> Tags
{
get { return _tags; }
set { _tags = value; }
}
public DateTime Created
{
get { return _created; }
set { _created = value; }
}
public DateTime LastUpdated
{
get { return _lastUpdated; }
set { _lastUpdated = value; }
}
public List<ContentItem> Items
{
get { return _items; }
set { _items = value; }
}
}
public class ContentItem
{
private List<Question> _questions;
private string _text;
public string Text
{
get { return _text; }
set { _text = value; }
}
public List<Question> Questions
{
get { return _questions; }
set { _questions = value; }
}
}
[BsonKnownTypes(typeof(CheckboxQuestion), typeof(RadioQuestion), typeof(SelectQuestion), typeof(FreeTextQuestion))]
public class Question
{
private int _order;
private int _points;
private string _text;
public string Text
{
get { return _text; }
set { _text = value; }
}
public int Order
{
get { return _order; }
set { _order = value; }
}
public int Points
{
get { return _points; }
set { _points = value; }
}
}
public class CheckboxQuestion : Question
{
private List<string> _answers;
private List<string> _choices;
public List<string> Choices
{
get { return _choices; }
set { _choices = value; }
}
public List<string> Answers
{
get { return _answers; }
set { _answers = value; }
}
}
public class SelectQuestion : Question
{
private string _answer;
private List<string> _choices;
public List<string> Choices
{
get { return _choices; }
set { _choices = value; }
}
public string Answer
{
get { return _answer; }
set { _answer = value; }
}
}
public class RadioQuestion : SelectQuestion { }
public class FreeTextQuestion : Question
{
private List<string> _acceptableAnswers;
private string _isAnswerCaseSensitive;
public string IsAnswerCaseSensitive
{
get { return _isAnswerCaseSensitive; }
set { _isAnswerCaseSensitive = value; }
}
public List<string> AcceptableAnswers
{
get { return _acceptableAnswers; }
set { _acceptableAnswers = value; }
}
}
}
The beauty of it is the absolute simplicity of working with this model. Aside from a few attributes, there's not much thought that needs to be given to collections and inheritance hierarchies (though there are additional attributes and classes that can be used to control how these are stored if so desired). I love it because this approach keeps your domain models clean.
How do we interact with this model?
#region prologue
// Charles Chen
#endregion
using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
namespace MongoAssessmentsTest
{
internal class Program
{
private static void Main(string[] args)
{
Program program = new Program();
program.Run();
}
private void Run()
{
MongoServer server = MongoServer.Create(); // Uses default connection options to localhost
MongoDatabase database = server.GetDatabase("assessments_db");
if (!database.CollectionExists("assessments"))
{
CommandResult result = database.CreateCollection("assessments");
if (!result.Ok)
{
Console.Out.WriteLine(result.ErrorMessage);
return;
}
}
MongoCollection<Assessment> assessments = database.GetCollection<Assessment>("assessments");
if (assessments.FindOne(Query.EQ("Title", "Sample 1")) == null)
{
// Insert an assessment.
Assessment a = new Assessment
{
Created = DateTime.Now,
Description = "A sample assessment",
Title = "Sample 1",
Items = new List<ContentItem>
{
new ContentItem
{
Questions = new List<Question>
{
new SelectQuestion
{
Text = "Who was the first president of the United States?",
Answer = "George Washington",
Choices = new List<string>
{
"George Washington",
"Abraham Lincoln",
"John Adams"
}
},
new CheckboxQuestion
{
Text = "Which of these is NOT a former US President?",
Answers = new List<string>
{
"Benjamin Franklin",
"Hillary Clinton"
},
Choices = new List<string>
{
"Benjamin Franklin",
"Bill Clinton",
"Hillary Clinton",
"Andrew Jackson",
"James Garfield"
}
}
}
}
}
};
assessments.Insert(a);
}
// Get it as BSON - great for writing straight to a web page
BsonDocument a1 = assessments.FindOneAs<BsonDocument>(Query.EQ("Title", "Sample 1"));
Console.Out.WriteLine(a1);
// Get it as an object - great if you want to work with it on the server.
Assessment a2 = assessments.FindOneAs<Assessment>(Query.EQ("Title", "Sample 1"));
Console.Out.WriteLine(a2.Title);
}
}
}
Brilliantly simple. Just fire up mongod.exe and you're ready to rock and roll. Download the example from here: MongoAssessmentsTest.zip
Thoughts on MongoDB
I just recently posted a short write up on Fluent NHibernate vs. Code First in Enterprise Library 4.1.
I'm starting up a new pet project (or rather re-starting it after a 3 year hiatus) so I've been trying to figure out the underlying technologies that I want to build on (as I mentioned, I've been in the SharePoint space for so long now, that I haven't been up-to-date on the latest developments in DB storage). To be honest, I wasn't really satisfied with the experience of either FNH or EF4.1, especially as I started to work with my model more and more.
What I realized is that the object-relational disconnect is still there. I'm starting to think that no amount of lipstick will make that pig presentable. It doesn't make a whole lot of sense and is an impediment to productivity in today's application-layer-oriented environment (if that makes any sense...); I really, really, really want to stop building database applications and focus my time and energy on the application layer.
Enter MongoDB. I think this (and the similarly JavaScript-friendly, document-oriented, seemingly less performant CouchDB) are what I've been yearning for in the data storage space. First, I love JavaScript; it's my favorite language (despite whatever flaws it has) for its flexibility and dynamic nature. So the fact that Mongo's interface language is JavaScript and that it's data storage format is a form of JSON is really appealing to me. Second, the document-oriented nature of the storage model -- combined with the JSON storage format -- really goes a long way in terms of solving the object-relational disconnect because, well, the relational part is gone. You have objects and embedded objects and they map perfectly to JSON objects which in turn map fairly easily into .NET CLR objects.
Of course, one neat thing about the nature of working with JSON from UI to the database is that in some cases, the application layer can be relegated to a relatively dumb pass-through (seems like it's still needed as one area of weakness for Mongo is authentication and authorization). Get your objects in JSON, bind to them in the browser using KO, modify them, and send them back! It's a beautiful paradigm that could only be better with an out-of-the-box REST interface like CouchDB.
I'm just digging in, but I'm starting to think that I'm never going to look back at relational databases outside of client work and possibly as a supplementary data store for reporting purposes. It only takes a few moments to get started with Mongo so give it a shot!
FluentNHibernate vs. Code First in EF 4.1
First, having been in the SharePoint space exclusively for so long now, I have to admit: it's been a while since I've had to deal with non-SharePoint data access. I don't know if I miss it or not
I've become really comfortable with my little SharePoint ORM approach thingy that generates models and such from content types (before you say SPMetal, this was developed for 2007 and I think still works better than SPMetal).
In the past, I've mostly avoided Entity Framework (EF), preferring LINQ-to-SQL due to EF1's shortcomings such as being less performant, creating more obtuse queries, my general disdain for the entity designer, the overly complex API, the lack of POCO support, etc. I've also spent some time with NHibernate and FluentNHibernate and found it more pleasant to work with as an ORM solution.
Only recently have I discovered the "code first" approach released with EF4.1 which makes it much more appealing in the same way that FNH made NH more appealing by doing away with hbm.xml files for mapping your entities. So I decided to take it for a spin and see how it measures up to NH+FNH.
If you're interested in much more in depth (and partisan) debate on the merits of one or the other, there's plenty to go around. I won't get into that
I'm just concerned with the basics for now and I anticipate this being a series of blog posts as I test the merits -- and demerits -- of each.
For this first post, the basics are:
- Create a simple console application that manages contacts
- The application should auto-generate and auto-provision the schema
- Basic queries should just work and not generate "dumb" SQL (i.e. counts should use COUNT in SQL, basic paging should be SQL based).
First up: Entity Framework.
So let's jump right into the code:
using System;
using System.Data.Entity;
using System.Linq;
namespace EFTest
{
public class Program
{
private static void Main(string[] args)
{
Database.SetInitializer<ContactContext>(
new DropCreateDatabaseAlways<ContactContext>());
using (ContactContext context = new ContactContext())
{
// Basic add
Contact chuck = new Contact {FirstName = "Charles", LastName = "Chen"};
Contact sandra = new Contact {FirstName = "Sandra", LastName = "Chen"};
Contact charlotte = new Contact {FirstName = "Charlotte", LastName = "Chen"};
Contact judy = new Contact {FirstName = "Judy", LastName = "Chen"};
context.Contacts.Add(chuck);
context.Contacts.Add(sandra);
context.Contacts.Add(charlotte);
context.Contacts.Add(judy);
context.SaveChanges();
// Basic paged read
var query = from c in context.Contacts
select c;
var results = query.OrderBy(c => c.FirstName).Skip(2).Take(2);
foreach(Contact c in results)
{
Console.Out.WriteLine(c);
}
// Basic count
int total = context.Contacts.Count();
Console.Out.WriteLine(total);
}
}
}
public class Contact
{
public int ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString()
{
return string.Format("{0} {1}", FirstName, LastName);
}
}
public class ContactContext : DbContext
{
public DbSet<Contact> Contacts { get; set; }
}
}
I like that it's fairly compact and straightforward. The development experience was a bit challenging, though. First, EF doesn't like it when you try to use the schema with an existing database. It insists that you let it provision the database. Okay, fine (though there are workarounds). It's often thrown around in these debates that one of the benefits of EF is that it's "out-of-the-box" but in reality, at least with the code first bits, it's anything but. You have to download EF4.1 first and install it just like you would with NH+FNH (though certainly, that may change in the future).
The walkthrough on the ADO.NET team blog is also broken. To get DbContext, you need to add a reference to EntityFramework.dll, not System.Data.Entity as posted in the blog. Overall, I found the code to be more compact and easier to work with. The one downside is the that one has to consistently update the class inheriting from DbContext as new entities are added.
Second up: NH+FNH:
Now lets take a look at code that does the same thing in NH:
using System;
using System.Collections.Generic;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
namespace FNHTest
{
internal class Program
{
private static void Main(string[] args)
{
ISessionFactory sessionFactory = CreateSessionFactory();
using (ISession session = sessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
// Basic add
Contact chuck = new Contact {FirstName = "Charles", LastName = "Chen"};
Contact sandra = new Contact {FirstName = "Sandra", LastName = "Chen"};
Contact judy = new Contact {FirstName = "Judy", LastName = "Chen"};
Contact charlotte = new Contact {FirstName = "Charlotte", LastName = "Chen"};
session.SaveOrUpdate(chuck);
session.SaveOrUpdate(sandra);
session.SaveOrUpdate(judy);
session.SaveOrUpdate(charlotte);
transaction.Commit();
// Basic paged read
IList<Contact> results = session.QueryOver<Contact>()
.OrderBy(c => c.FirstName).Asc.Skip(2).Take(2).List();
foreach (Contact c in results)
{
Console.Out.WriteLine(c);
}
// Check the count
int total = session.QueryOver<Contact>().RowCount();
Console.Out.WriteLine(total);
}
}
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2008.ConnectionString("Data Source=CHARLES-E6410;Initial Catalog=FNHTest;Integrated Security=SSPI;Application Name='FNHTest'")
)
.Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Program>()))
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
}
private static void BuildSchema(Configuration config)
{
SchemaExport schema = new SchemaExport(config);
schema.Drop(false, true); // Drops the tables only.
schema.Create(false, true);
}
}
public class Contact
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public override string ToString()
{
return string.Format("{0} {1}", FirstName, LastName);
}
}
}
It's slightly more verbose, but not terribly so. One note is that unlike the case with the ContactContext in EF, you won't need to continually update a "registry" with new entity types.
For this basic scenario, it's hard to say I prefer one over the other, but I'd have to give the edge to EF so far simply for the intangibles (read: Microsoft supported - in other words, it'll be easier from a convincing-your-team-to-not-roll-your-own standpoint).
Comparing the SQL
Of course, the next step is to compare the SQL generated from each of these.
Let's take a look at each query:
/*EF*/
SELECT TOP (2)
[Extent1].[ContactId] AS [ContactId],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName]
FROM (
SELECT
[Extent1].[ContactId] AS [ContactId],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
row_number() OVER (ORDER BY [Extent1].[FirstName] ASC) AS [row_number]
FROM [dbo].[Contacts] AS [Extent1]
) AS [Extent1]
WHERE [Extent1].[row_number] > 2
ORDER BY [Extent1].[FirstName] ASC
/*NH*/
exec sp_executesql
N'SELECT TOP (@p0)
Id0_0_,
FirstName0_0_,
LastName0_0_
FROM
(
SELECT
this_.Id as Id0_0_,
this_.FirstName as FirstName0_0_,
this_.LastName as LastName0_0_,
ROW_NUMBER() OVER(ORDER BY this_.FirstName) as __hibernate_sort_row
FROM
[Contact] this_
) as query
WHERE
query.__hibernate_sort_row > @p1 ORDER BY query.__hibernate_sort_row',N'@p0 int,@p1 int',@p0=2,@p1=2
You can see that for the first, paged read, EF uses a straight SQL statement whereas NH uses a parameterized dynamic SQL statement. For this small dataset, there is no discernible difference in performance, but I would gather that for larger datasets, we'd see a performance boost with NH.
For the second query to count, we see that again, there is a small difference in how the two go about generating queries:
/*EF*/ SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT COUNT(1) AS [A1] FROM [dbo].[Contacts] AS [Extent1] ) AS [GroupBy1] /*FNH*/ SELECT count(*) as y0_ FROM [Contact] this_
As far as I can tell, for this basic scenario where there is no additional filtering on columns, there should be no practical performance difference between the two (though obviously, EF generates an extra nested select statement, the real world performance impact is negligible).
Next up: I want to do some more tests with more complex queries and figure out how each of these frameworks handles dealing with schema changes. Seems like a wash for these basic scenarios and one of personal preference.
HTML5 on the Desktop — Finally!
As tidbits start to come out about Windows 8, it appears that we'll see a significant shift in the Windows UI in the next version. In itself, there's a whole lot of significance as it's a paradigm shift in terms of UI design. But from a technology perspective, I find it more interesting.
Related to this issue is the question of how new-style applications will be written. Microsoft said that they will be HTML5 plus JavaScript, but again this precludes the possibility of migrating existing applications to the new interface. I'm told by insiders that HTML5 and JavaScript won't be the only option, and that existing applications (native, Silverlight, and WPF) will be migratable in some way, but specifics are still lacking at this time.
For a while now, I've been advocating against technologies like Flash and Silverlight for the web.
My stance has always been that aside from a few use cases (streaming media, 3D-graphics, complex animations, games), there are very few use cases that call for Flash or Silverlight.
WPF on the other hand, is a much more interesting and useful piece of technology, but even with WPF, I find that the development cycle is still slow and there are some idiosyncrasies with HTML that are hard to overcome for me (case in point is WPF Grid layout and HTML table layout).
Maybe because I come from a web background and because I've been writing web applications and building web interfaces since I was a teenager, I've always been able to build richer, more compelling, more interesting user interfaces in HTML -- faster -- than I've ever been able to do with WinForms or WPF.
So this is good news to me. Time to get cracking on those HTML5 books!
A jQuery Scrollbar Replacement
Click here to see the demo page.
I was looking around recently for a jQuery based scrollbar replacement and spent quite some time trying out a few different libraries that I found in a blog post.
I was left quite disappointed as none of the scripts I tried (jScrollPane, ScrollBarPaper, and malihu's custom content scroller) seemed to work well with my use case. In particular, none of them seemed to work well with content that was set to 100% height.
Malihu's was promising, but as far as coding goes, it wasn't written to be a proper plugin and needed a lot of cleanup.
So after wasting half a day trying out various scrollbar scripts, I ended up rolling my own. Here are the specs:
- Works with fixed or fluid height containers
- Uses default jQuery UI slider as a scrollbar
- Does not attempt to mimic full scroll bar behavior (I don't want it to be full height, don't need the up/down arrows)
- Responds to mousewheel scrolling
- Easing animation when position changed with a mouse click
- Small - just 72 lines of code including comments and blank lines
A sample screenshot:
Markup wise, the script only requires that you create a structure like so:
<div id="my-id">
<!--// The scrollable class is required //-->
<div class="scrollable">
<!--// Content goes here //-->
</div>
</div>
Then you can initialize the scrollbars like so:
$(function(){
/*
Settings and defaults:
scrollbarHeight: "300px", // the height of the scrollbar
scrollbarSize: "6px", // the size of the scrollbar
positionX: "5px", // the distance from the right of the container
positionY: "15px", // the distance from the top of the container
easing: "easeOutQuart", // the named easing effect from jQuery UI
pace: 20 // affects the mousewheel increment
*/
$("#myIdWhatever, #anotherId").prettyScroll();
$("#yetAnother").prettyScroll({"scrollbarHeight": "400px"});
});
One CSS definition must be added:
/*--- Your container must have an inner DIV with the class "scrollable" ---*/
.scrollable {
width: 100%;
height: 100%;
overflow: hidden;
}
Two basic CSS overrides can optionally be added to make it more scroll bar like (feel free to toy around with this to get your scrollbar to look however you like):
/*--- Override jQuery styles so that there's no color in the slider track ---*/
.scroll-bar .ui-widget-header { background: #fff !important;}
/*--- Override jQuery styles so that the handle is taller ---*/
.scroll-bar .ui-slider-handle {
width: 1.1em !important;
height: 2em !important;
}
Since it uses the default jQuery slider widget, you can just use whatever CSS you would normally use to customize the slider here.
You can download the script and demo here: prettyScroll.zip
Update (6/13/2011): I noticed that this page actually gets a lot of hits in my Google Analytics so I figured it was worth updating with some new script: prettyScroll.20110613.zip
It has some new code that shows how to scroll to an object that's clicked in the scroll pane. Consider the following markup:
<div id="content3">
<div class="scrollable">
<p>Here is some stuff that's before.</p>
<p>Another sentence.</p>
<a id="toggler" href="">toggle</a>
<p class="after" style="display:none">Lorem ipsum dolor sit amet...</p>
<!-- shortened for brevity -->
</div>
</div>
When the link "toggle" is clicked, I want to scroll to the link. I've cut off the content, but assume that it generates a large body of text that requires scrolling once visible. You can cause it to scroll to the element by triggering a custom event:
$("#toggler").click(function(e){
e.preventDefault();
var $this = $(this);
$this.siblings(".after").toggle();
$this.parents(".scrollable").trigger("scrollTo", [$this]);
});



