Clean Architecture vs. Startups

Disclaimer: I do not work for a startup. I have never worked for a startup. I am not interested in working for a startup.

Uncle Bob recently wrote an interesting post called “The Startup Trap” which prompted Greg Young at codebetter.com to respond with “Startups and TDD”.

The heart of their disagreement can be captured in two quick quotes:

As time passes your estimates will grow. You’ll find it harder and harder to add new features. You will find more and more bugs accumulating. You’ll start to parse the bugs into critical and acceptable (as if any bug is acceptable!) You’ll create modules that are so fragile you won’t trust yourself, or anyone else, to modify them; so you’ll work around them. You’ll build a festering pile of code that, with every passing week, requires more and more effort just to keep running. Forward progress will slow and falter. It may even reverse as each release becomes buggier and buggier, and less and less stable. Catastrophes will become more and more common as errors, that should never have happened, create corruptions and damage that take huge traunches of time to repair.

–Uncle Bob

What really mattered was that after our nine months of beautiful architecture and coding work we were making approximately 10k/month more than what our stupid production prototype made for all of its shortcomings.

We would have been better off making 30 new production prototypes of different strategies and “throwing shit at the wall” to see what worked than spending any time beyond a bit of stabilization of the first. How many new business opportunities would we have found?

— Greg Young (emphasis in original)

I disgree with the advice that Mr. Young seems to be giving. My initial comment on his post was:

I agree that you shouldn’t have spent a bunch of time building a new application alongside your prototype. You did the right thing in shoring it up and fixing the worst pain points. I personally do not believe in building a green-field app when you already have a working brown-field one.

I’m curious, is your prototype app still in use? Did it survive?

I can understand why Mr. Young’s attitude may be tempting for some developers to embrace, but how would we feel if we heard a comment like this from a used-car salesman? Would you want to do business with a salesman that would sell you a car that was held together with duct-tape and baling wire and then spend his time looking for other business opportunities while you’re stuck using his pile of shit?

Let me ask the question another way. Is working for a startup an excuse to churn out crap software and move on to the next big idea before the company that just paid you starts to notice that festering pile of rot you just created for them?

I’m not personally accusing Mr. Young of having this attitude, but it does seem to capture the attitude I’ve heard expressed by some developers in the startup world.

Update: Uncle Bob’s follow-up.

Refactoring: Replace DataModel with ViewModel

I have an application in which the UI is strongly bound to the data models.  I tried to make some modifications to the NHibernate mappings to better model the database and enable better querying. Since the UI was directly bound to the data models this meant that it have to follow navigation properties from one data model to another to get all the information it needed. Since the UI is no longer connected to the database, the app started generating data access exceptions all over the place. This is the reason that binding data models to the UI is not a good idea, and that data models should not properly be considered to be “domain” objects.

Consider the following simple WindowsForms application:

   1:      public partial class frmOwnerVisits : Form
   2:      {
   3:          public frmOwnerVisits()
   4:          {
   5:              InitializeComponent();
   6:  
   7:              this.Repository = new NHibernateRepository();
   8:          }
   9:  
  10:          private NHibernateRepository Repository { get; set; }
  11:  
  12:          private void btnLoadOwners_Click(object sender, EventArgs e)
  13:          {
  14:              // data is bound directly to the UI
  15:              var owners = this.Repository.All<Owner>();
  16:              this.cmbOwners.DataSource = owners;
  17:          }
  18:  
  19:          private void btnSavePets_Click(object sender, EventArgs e)
  20:          {
  21:              var owner = this.cmbOwners.SelectedItem as Owner;
  22:              foreach(var pet in owner.Pets)
  23:              {
  24:                  this.Repository.Save(pet);
  25:              }
  26:          }
  27:  
  28:          private void cmbOwners_SelectedIndexChanged(object sender, EventArgs e)
  29:          {
  30:              var owner = this.cmbOwners.SelectedItem as Owner;
  31:  
  32:              // Problem area: we're disconnected from the database at this point
  33:              // and we may not have pulled back all the visits for each pet.
  34:              var numberOfVisits = owner.Pets.SelectMany(p => p.Visits).Count();
  35:              this.lblNumberOfVisits.Text = numberOfVisits.ToString("D");
  36:          }
  37:  
  38:      }

The problem area for us at this point is in cmbOwners_SelectedIndexChanged. We want “Pet.Visits” on the data model because it enables easier querying, but having the properties there implies that they are navigable. We won’t know that we have a problem accessing the information at compile-time which results in harder-to-find and diagnose run-time exceptions.

   1:      private IEnumerable<Owner> GetOwnersWhoHaveNotBeenHereInAYear()
   2:      {
   3:          // Without fully expressed relationships, queries such as this would be much harder.
   4:          var results = this.Repository.All<Owner>()
   5:              .Where(row => row.Pets.Any(pet => pet.Visits
   6:                   .All(visit => visit.Date < DateTime.Now.AddYears(1))))
   7:              .ToList()
   8:              ;
   9:  
  10:          return results;
  11:      }

This is a simplified example. An ideal solution would be to create a complete ViewModel that represents the entire form. Let’s pretend that the example if much more complex and involves multiple cooperation user controls and tons of nasty event-driven mess. Let’s further pretend that we’ve decided that replacing Owner with OwnerViewModel would be a manageable chunk of work. How would we be sure we got everything that the UI depends on?

Steps

  1. Extract all methods that retrieve or persist data into an external helper class.
  2. Write Tests against those methods if you haven’t already.
  3. Create Empty ViewModels for each input and output to your Data Operations
  4. Create and test converter classes to translate between DataModels and ViewModels
  5. Replace inputs and outputs of your external helper class with ViewModels.
  6. If you’re working in a statically typed language, use the compiler errors to help you identify which properties and relationships are actually being used by the View.
  7. Fill in the properties and relationships used by the View on your ViewModels.
  8. Regression test the UI to try to find side-effects not covered by existing tests.
  9. Review and Refactor

 

1. Extract methods that retrieve or persist data into an external helper class.

If possible, write integration tests against the UI before making any changes at all.

The data access operations associated with Owner are “Get Owners”, “Save Pets”, and “Determine the number of visits for the owner.”

I extracted those methods into an OwnerController class that encapsulates the data operations.

   1:      public class OwnerController
   2:      {
   3:          public IEnumerable<Owner> GetOwners()
   4:          {
   5:              using (var repository = new NHibernateRepository())
   6:              {
   7:                  var owners = repository.All<Owner>().ToList();
   8:                  return owners;
   9:              }
  10:          }
  11:  
  12:          public int GetNumberOfVisits(Owner owner)
  13:          {
  14:              using (var repository = new NHibernateRepository())
  15:              {
  16:                  var numberOfVisits = repository
  17:                      .All<Visit>()
  18:                      .Count(visit => visit.Pet.Owner.OwnerId == owner.OwnerId)
  19:                      ;
  20:  
  21:                  return numberOfVisits;
  22:              }
  23:          }
  24:  
  25:          public void SavePets(IEnumerable<Pet> pets)
  26:          {
  27:              using (var repository = new NHibernateRepository())
  28:              {
  29:                  foreach (var pet in pets)
  30:                  {
  31:                      repository.SaveOrUpdate(pet);
  32:                  }
  33:              }
  34:          }
  35:  
  36:      }

Then I replaced the direct data access calls in my Form with calls into the OwnerController.

   1:      public partial class frmOwnerVisits : Form
   2:      {
   3:          public frmOwnerVisits()
   4:          {
   5:              InitializeComponent();
   6:  
   7:              this.Controller = new OwnerController();
   8:          }
   9:  
  10:          protected OwnerController Controller { get; set; }
  11:  
  12:          private void btnLoadOwners_Click(object sender, EventArgs e)
  13:          {
  14:              // data is bound directly to the UI
  15:              var owners = this.Controller.GetOwners();
  16:              this.cmbOwners.DataSource = owners;
  17:          }
  18:  
  19:          private void btnSavePets_Click(object sender, EventArgs e)
  20:          {
  21:              var owner = this.cmbOwners.SelectedItem as Owner;
  22:              this.Controller.SavePets(owner.Pets);
  23:          }
  24:  
  25:          private void cmbOwners_SelectedIndexChanged(object sender, EventArgs e)
  26:          {
  27:              var owner = this.cmbOwners.SelectedItem as Owner;
  28:  
  29:              // Problem area: we're disconnected from the database at this point
  30:              // and we may not have pulled back all the visits for each pet.
  31:              var numberOfVisits = this.Controller.GetNumberOfVisits(owner);
  32:              this.lblNumberOfVisits.Text = numberOfVisits.ToString("D");
  33:          }
  34:  
  35:      }

 

2. Write tests against the OwnerController if you haven’t already.

I suggest you always write your tests before creating the new class. As written above, the OwnerController doesn’t really allow for Unit Testing since NHibernate requires a connection to a database. NHibernate supports Sqlite for in-memory database testing and Entity Framework supports Sql Server CE. At some point I’d like to be able to stub in an In-Memory repository to the OwnerController so that I have no external dependencies for my tests, but that may be out of scope for the current operation.

3. Create Empty ViewModels for each input and output to your Data Operations

At this point, there are only 3 data models used by the OwnerController: Owner, Pet, and Visit. I have an idea about Visit so I’m not going to model it yet. I will create empty ViewModels for Owner and Pet though.

   1:      public class OwnerViewModel
   2:      {
   3:  
   4:      }
   5:  
   6:      public class PetViewModel
   7:      {
   8:  
   9:      }

4. Create and test converter classes to translate between DataModels and ViewModels

The OwnerController is going to be altered to return ViewModels instead of DataModels. However, the details of converting DataModels to ViewModels and back should really be dealt with separately. Whether you use a tool like AutoMapper or some custom mapper or converter interface for your transforms, you’ll need tests. These tests will be anemic at first since we don’t have any properties on our ViewModels yet. We’ll fill them in more as we go.

5. Replace inputs and outputs of your external helper class with ViewModels.

Depending on DataModels makes the UI brittle. This coupling needs to be completely broken. Nothing but parameter objects or view models should be exposed outside of your helper class. Data models should not leak into the UI for any reason.

In our case, the OwnerController will use the converters to create and expose viewmodels through it’s interface. The OwnerController now looks like this:

   1:      public class OwnerController
   2:      {
   3:          private readonly IBuilder _builder;
   4:  
   5:          public OwnerController(IBuilder builder)
   6:          {
   7:              _builder = builder;
   8:          }
   9:  
  10:          public IEnumerable<OwnerViewModel> GetOwners()
  11:          {
  12:              using (var repository = new NHibernateRepository())
  13:              {
  14:                  var owners = repository.All<Owner>().ToList();
  15:                  var viewModels = _builder
  16:                      .CreateEnumerable<OwnerViewModel>()
  17:                      .FromEnumerable(owners)
  18:                      ;
  19:                  return viewModels;
  20:              }
  21:          }
  22:  
  23:          public int GetNumberOfVisits(OwnerViewModel owner)
  24:          {
  25:              using (var repository = new NHibernateRepository())
  26:              {
  27:                  var numberOfVisits = repository
  28:                      .All<Visit>()
  29:                      .Count(visit => visit.Pet.Owner.OwnerId == owner.OwnerId)
  30:                      ;
  31:  
  32:                  return numberOfVisits;
  33:              }
  34:          }
  35:  
  36:          public void SavePets(IEnumerable<PetViewModel> petViewModels)
  37:          {
  38:              using (var repository = new NHibernateRepository())
  39:              {
  40:                  var petIds = petViewModels.Select(vm => vm.PetId).ToList();
  41:  
  42:                  var pets = repository.All<Pet>()
  43:                      .Where(pet => petIds.Contains(pet.PetId))
  44:                      .ToDictionary(pet => pet.PetId.Value)
  45:                      ;
  46:  
  47:                  var existingPets = petViewModels.Where(vm => vm.PetId.HasValue);
  48:                  var newPets = petViewModels.Where(vm => !vm.PetId.HasValue);
  49:  
  50:                  foreach(var petViewModel in newPets)
  51:                  {
  52:                      InsertPet(petViewModel, repository);
  53:                  }
  54:  
  55:                  foreach (var petViewModel in existingPets)
  56:                  {
  57:                      var pet = pets[petViewModel.PetId.Value];
  58:                      UpdatePet(pet, petViewModel, repository);
  59:                  }
  60:              }
  61:          }
  62:  
  63:          private static void UpdatePet(Pet pet, PetViewModel petViewModel, NHibernateRepository repository)
  64:          {
  65:              pet.Name = petViewModel.Name;
  66:              pet.Type = petViewModel.Type;
  67:              pet.Breed = petViewModel.Breed;
  68:              pet.BirthDate = petViewModel.BirthDate;
  69:  
  70:              repository.SaveOrUpdate(pet);
  71:          }
  72:  
  73:          private void InsertPet(PetViewModel petViewModel, NHibernateRepository repository)
  74:          {
  75:              var pet = _builder.Create<Pet>().From(petViewModel);
  76:              repository.SaveOrUpdate(pet);
  77:          }
  78:      }

Note that the implementation of line 23 drove us to add OwnerId to the OwnerViewModel.

The implementation of Update drove us to add Name, Type, Breed, and BirthDate to PetViewModel.

6. If you’re working in a statically typed language, use the compiler errors to help you identify which properties and relationships are actually being used by the View.

At this point, the OwnerController is starting to look okay. The OwnerVisits form doesn’t compile anymore mainly because it’s still using Owner, Pets, and Visits to display and edit its data. If we modify the form so that it interacts with OwnerViewModel and PetViewModel instead of Owner and Pet, we’ll get even more compiler errors. OwnerViewModel needs a reference to a Pets collection of type PetViewModel.

The compiler may not find everything. You’ll have to do a bit of manual regression to make sure you found everything. When you do find problems, be sure to document the problems in unit tests. This last is especially important in dynamic languages where you don’t get compiler hints.

7. Fill in the properties and relationships used by the View on your ViewModels.

The OwnerViewModel and PetViewModel now look like this:

   1:      public class OwnerViewModel
   2:      {
   3:          public int? OwnerId { get; set; }
   4:  
   5:          // snipped for brevity
   6:  
   7:          public IList<PetViewModel> Pets { get; set; }
   8:      }
   9: 
  10:      public class PetViewModel
  11:      {
  12:          public int? PetId { get; set; }
  13:  
  14:          public string Name { get; set; }
  15:  
  16:          public string Type { get; set; }
  17:  
  18:          public string Breed { get; set; }
  19:  
  20:          public DateTime? BirthDate { get; set; }
  21:      }

 

8. Regression test the UI to try to find side-effects not covered by existing tests.

In DataBinding scenarios—in both web and desktop applications—data binding is often done via magic strings. This can result in run-time errors not visible at compile time that are hard to test in an automated fashion. In manually regressing the UI behavior you should be able to detect run-time binding errors and add any properties necessary to make the UI work correctly again.

9. Review and Refactor

One thing I noticed while refactoring this code is that numberOfVisits is being calculated against the database every time the selected owner is changed in the combo box. This is inefficient. I’d like to add NumberOfVisits to the PetViewModel and write a function on the OwnerViewModel to aggregate visits per pet for display purposes. This will allow us to calculate the value in-memory and remove a function from the OwnerController. The calculation to determine the number of visits can be done as part of the conversion from DataModel to ViewModel.

Now the ViewModels look like this:

   1:      public class OwnerViewModel
   2:      {
   3:          public int? OwnerId { get; set; }
   4:  
   5:          // snipped for brevity
   6:  
   7:          public IList<PetViewModel> Pets { get; set; }
   8:  
   9:          public int GetNumberOfVisits()
  10:          {
  11:              if (Pets == null)
  12:                  return 0;
  13:  
  14:              var result =Pets.Sum(pet => pet.NumberOfVisits);
  15:              return result;
  16:          }
  17:      }
  18:  
  19:      public class PetViewModel
  20:      {
  21:          public int? PetId { get; set; }
  22:  
  23:          public string Name { get; set; }
  24:  
  25:          public string Type { get; set; }
  26:  
  27:          public string Breed { get; set; }
  28:  
  29:          public DateTime? BirthDate { get; set; }
  30:  
  31:          public int NumberOfVisits { get; set; }
  32:      }

The SelectedIndexChanged event is modified as follows:

   1:          private void cmbOwners_SelectedIndexChanged(object sender, EventArgs e)
   2:          {
   3:              var owner = this.cmbOwners.SelectedItem as OwnerViewModel;
   4:              var numberOfVisits = owner.GetNumberOfVisits();
   5:              this.lblNumberOfVisits.Text = numberOfVisits.ToString("D");
   6:          }

We now have a UI that is bound to ViewModels instead of DataModels. This decouples the UI from the database which prevents errors from occurring when attempting to access properties from related tables that haven’t been loaded. The UI can now change independently of the database. We can change the shape of the ViewModels without changing the shape of the underlying data, and vice versa. The steps to accomplish this decoupling were not particularly hard and have dramatically improved the reliability and flexibility of the code. We are one step closer to sitting our Form on top of a master ViewModel specifically designed for this UI.

The Command Pattern + Knockout: koCommandButton Knockout Binding

I wrote this binding handler to work correctly against a formal Command object, a dynamic object with static properties and functions, and a static object with ko.observable() properties.

I still need to figure out how to pass the viewModel to the canExecute() function when it is a ko.computed() function.

Thanks to rniemeyer. I found “Another Look at Custom Bindings for KnockoutJS” to be very useful in getting this working.

View this on JSFiddle

 

Recursive Mocks with Rhino Mocks and NSubstitute

I just learned that you could do this:

Update: 2013-01-25
Note that successive chained mocking calls to RhinoMocks fail. I now have a reason to prefer NSubstitute other than it’s beautifully simple API.

The Value of Features of ORM’s

At Redacted Associates, we’ve been having a discussion about whether we should use the Generic Repository pattern on top of NHibernate. We have a simple IRepository interface as follows:

For my part, I like don’t like to spend a lot of time worrying about the way my ORM interacts with the database. I prefer to spend my design-energy around how to architect the application such that interacting with the database is a minor implementation detail, almost an afterthought even.

At least one of my co-workers disagrees, and has given a really good argument for a specific case when using direct features in NHibernate saved some work. This discussion has spurred me to ask myself “what are the most important features of an ORM?” and “at what level of abstraction should we work with an ORM?” There’s no way to answer these questions without identifying your purpose in using the ORM to begin with. With that in mind, I decided to categorize the features we all look for in an ORM and compare them to our Generic Repository implementation.

ORM features basically fall into one of 3 categories:

  1. Queryability

    • Linq Provider

      In .NET, Linq remains the most discoverable way to query an ORM. NHibernate has the QueryOver api, but I find it to be hopelessly unreadable anything but the simplest query.

    • Specification pattern

      The easiest specification pattern in .NET relies on Linq. It’s a very nice way to allow api clients to construct their own queries without concerning themselves with database schema details. In an SOA architecture, it provides a flat contract to support complex query results. It minimizes the number of service methods because you don’t have to write GetCustomersByNameAndCityAndProduct.

    • Fully mapped relationships between objects.

      I depend on having a fully expressed query model to use for linq queries. Getting the right data to work with often involves a number of database relationships and it’s impossible to predict when some new object or property will be needed to satisfy a query. It’s easiest to ensure that the model fully expresses the database and that all fields and relationships are present in the model. The model should fully and accurately express the database schema.

    • Id navigation properties.

      Id navigation properties as a companion to the object relationship properties are really handy. They can reduce query-syntax clutter quite a bit. Employee.ManagerId is cleaner than Employee.Manager.Id. Some ORM’s will pull back the whole Manager to get the Id. I hate that.

    • Full support for all relationship types (one-to-one, one-to-many, many-to-many).

      These relationships are standard in relational db’s. Any Object-Relational Mapper should support them.

    • Lazy Loading
  2. Behavior

    • Cascade mappings.

      This is not personally a value to me, but I recognize that in some cases it’s useful.

    • Trigger-behavior.

      This sort of behavior is useful when you want the ORM to handle things like audit fields, soft deletes, or log table entries.

    • Sql-Efficiencies.

      Sometimes pulling back large datasets and mapping them to in-memory objects can be very expensive. If performance is a concern, it’s nice to be able to have the ORM optimize the operation. NHibernate’s “Merge” operation is a good example of this.

  3. Testability

    • In-memory testability
    • Mockable/Stubbable

I composed the following table listing the features we are seeking from an ORM and how each tool fares against our needs.

NHibernate
Entity Framework
Generic Repository
Micro ORMs
Linq Provider
Not Fully Implemented Fully Implemented Depends on ORM No
Specification Pattern
Easy to implement against partially implemented Linq provider. Hard otherwise. Easy to implement. Depends on ORM No
Can Fully Map Relationships
Yes Yes Depends on ORM No
Id Navigation Properties
Not without extreme (and not very useful) hacks Yes Depends on ORM Yes
Full support for relationship types
One-to-one doesn’t work well. Results in N+1 queries on one side of the relationship * Haven’t tested this. Depends on ORM Sort of
Lazy Loading
Yes Yes Depends on ORM No
Cascade Mappings
Yes Yes Depends on ORM No
Trigger Behavior
Yes Yes Depends on ORM No
Sql Efficiences
Yes Yes Depends on ORM No
In-memory testability
Yes, provided you use SqlLite. Yes, provided you use SqlCompact edition—or you can interface your DbContext. Yes No
Mockable-Stubbable
Mostly. Some of the methods you use on ISession are in fact extension methods. .Query is an extension method which is problematic since that’s an obvious one I’d like to stub. Mostly. Methods such as .Include() are extension methods with no in-memory counterpart. If I really need to use .Include() I’ll write an integration test instead. Yes No
Notes
  • ISession.Query is an extension method. Not testable.
  • ISession.QueryOver is a difficult api for complex queries, especially those involving groups.
  • Automappings make map-by-configuration easier.
  • No (current) support for convention-based configuration.
  • No Merge operation.
  • Generic repository does not give you direct access to methods like ISession.Merge.
  • You have two ways of dealing with this:
    1. Use ISession (or DbContext) directly.
    2. You can inherit or adapt the IRepository interface to provide the other methods.
Fantastic for quick and dirty CRUD on single tables. Not so great otherwise.

 

Takeaways

My advice is to use Generic Repository except when you need to get close to the metal of your ORM for some fine-grained control over your data access.

IlMerge in TeamCity

I wanted to IlMerge an assembly in a TeamCity project. TeamCity has a Powershell build step that you can use to run your own arbitrary scripts. Here’s how I did it

TeamCity Configuration

image

Powershell Script

Isg.EntityFramework.ObservableProvider

The Problem

I’ve been struggling for awhile to figure out how to get Entity Framework to set and unset application roles in Sql Server when opening and before closing a connection. The problem is that ConnectionState does not provide a Closing state that fires before a connection is closed.

It was suggested to me to turn of connection pooling. Errrr, no. We want connection pooling for our applications. I also don’t want to have to manually open and close the connection every time I create a DbContext. That’s just messy and irritating.

The next obvious thing to do would be to create a DbConnectionDecorator to wrap the existing database connection and expose the Closing event. This proved to be very difficult because Entity Framework does not expose when and how it opens connections.

Grrrrrr.

The Solution

What’s that you say? I can implement my own EntityFramework Provider? There’s a provider wrapper toolkit I can plug into to do this? Awesome!

Oh wait—that looks really, really, REALLY complicated? You mean I can’t just decorate a single object? I have to decorate a whole family of objects?

Hmmmm.

Alright, tell you what I’ll do. I’ll implement the provider wrapper using the toolkit as best I can—but then I’m going to strip away everything I don’t actually need. Besides, if I just make the various data related events observable, it’s nothing to Trace the output. And Cacheing can easily be added as a IDbContext Decorator anyway. I don’t really get why that should be done at the Provider level.

Configuring Your Application to use the Provider

To use the new provider, first install the package. At application startup, you’ll need to register the provider and tell it which other provider you are wrapping. The registration process will set the ObservableConnectionFactory as the default connection factory used by EF unless you pass the optional setAsDefault:false.

Consuming the Provider Events

ObservableConnection exposes several new events, including Opening, Opened, Failed, Closing, and Closed. However, to subscribe to those events directly requires that you cast the DbConnection exposed by EF to ObservableDbConnection, which strikes me as a little cumbersome (not to mention a violation of the LSP). My first use case demands that I handle the Opening and Closing events the same way for every DbConnection application-wide. To that end, ObservableDbConnection (and ObservableDbCommand) pushes its event messages onto a static class called Hub.

Guarantees

This code is brand-spanking new and it hasn’t had time to bake yet. I’m using it, but it’s entirely possible that there are unforeseen problems. Feel free to report issues to and/or contribute to the open-source project on BitBucket. Until then, know that it has been rigorously test and that it works on my machine.

works on my machine, starburst

Review: HTML5 Conference in Austin, TX

I didn’t realize this when I signed up, but the DevCon5 Html5 Summit was a conference within a conference. The larger conference was an ITEXPO. The ITEXPO conference was focused more on infrastructure than development—in fact as far as I could tell, HTML5 was the only developer-centric conference at the entire event. This did not turn out to be a good thing for me. I noticed maybe 20 or 25 developers for the HTMl5 portion of the event.

The Negative

The sessions themselves had a few problems. First, the focus was almost all on mobile and app development. I realize that the world is changing and that more and more people are developing for the mobile platforms, but there are an awful lot of us that are building applications for the business we are trying to support. It would be nice if someone would discuss benefits to the business of the new HTML5 goodies. There was a little of that in the sessions, but it wasn’t very meaty. Yes, it’s great that you can make images float across the page, but my business users don’t really care about that.

The second problem, which perhaps isn’t the speaker’s fault, is that no one was really super-excited about HTML5. Since the focus was on apps for the mobile platforms, most speakers spent time acknowledging that the write-one-run-anywhere promise of HTML5 isn’t a reality, and likely wont’ be for a long time (but it’s getting better!).

Another issue with some of the speakers is that they did not seem to know very much about HTML5. If I had to reverse-engineer their talk, I would say that there was something they wanted to learn about, they learned just enough about it to fill up an hour of speaking, and then stopped. They were unable to answer questions about possible uses for the bits they were covering beyond their demo. Several speakers also did not have working demos.

The Positive

The best part of the sessions is that I got a lot of tools and references to other sessions that might fill out some of what’s missing. Here are some of the things that were referenced:

There were a very few principles and practices discussed. They are:

  • Get familiar with messaging in javascript.
  • If you’re going to support mobile, develop for mobile first—then the desktop.
  • 1 class per js file.
    • I especially like this one because it implies that you should still be writing classes in javascript.

Presenters I’d Like to See Again

Instead of picking on the presenters I thought were less than spectacular, I thought it would be better to shout the names of those who were particularly good. These are people that I’d enjoy talking to about web development again.

  • Jonathon Morgan – His talk on HTML5 vs. Native apps was well-reasoned and balanced. His enthusiasm for development was refreshing.
  • Tom Shafron – He is the current CEO of Viewbiquity. His session was on machine-to-machine communication in javascript. It was in his talk that we got into javascript best practices and patterns.
  • Jesse Cravens – His session on node.js was substantive and interesting. Most of the libraries mentioned above came from his presentation.
Simple.Validation 0.6.1 Released

What’s new?

Testability has been kind of an issue for us with code that relies on the static Validator class. To improve the situation, I added IValidationEngine as an alternative. Validator is still fully backwards compatible

  • Addition of the IValidationEngine interface
  • The DefaultValidationEngine requires an instance of IValidatorProvider for its constructor
  • Validator.SetValidatorProvider() has been marked obsolete. You can still use it, but it will have the side-effect of over-setting Validator.ValidationEngine to a new instance of DefaultValidationEngine.
  • Added a NinjectModule to Simple.Validation.Ninject that configures the DefaultValidationEngine and DefaultValidatorProvider automatically.
Install-VSCommandPrompt Powershell Script updated

Previous Page · Next Page