IExtendable while (this.IsAlive) self => self.UpdateAll()

10Apr/130

Isg.EntityFramework 0.6.0 Released

Breaking Changes

New Features

 

Isg.EntityFramework.Interceptors.Auditable

If you have a class that implements IAuditable the AuditableChangeInterceptor will use IPrincipal and IClock to assign audit fields. If you are inserting a new record, CreateUser and UpdateUser will be set to IPrincipal.Identity.Name, and CreateDate and UpdateDate will be set to IClock.Now. If you are updating an existing record, only the Update fields will be modified.

    public interface IAuditable
    {
        DateTime CreateDate { get; set; }
        string CreateUser { get; set; }

        DateTime UpdateDate { get; set; }
        string UpdateUser { get; set; }
    }
16Mar/130

Onion Architecture: An Opinionated Approach, Part 1

The Purpose of Architecture

I believe that the value of explicitly identifying and conforming to an architectural pattern in your applications is two-fold.

  1. It defines the number of boundaries between layers and how they communicate.
  2. Future maintainers can leverage what they’ve learned about one vertical slice to understand the rest of the application.

In most cases I don’t think developers bother to identify their application architecture, and consequently their application doesn’t have one. Or rather, it has many. Each new operation is put together in a slightly different way from all the others. Nothing learned about one area of the system can be used to understand other areas of the system. Nothing in the existing implementations direct you on how to add or modify new or existing features.

What a mess!

Onion Architecture

Full disclosure: I don’t know many architectural patterns. However, I’ve spent the last 5 years of my career groping toward an architecture that was hazy in my mind. The first explicit description I encountered of this pattern that I encountered was in a lecture I attended by Uncle Bob at SCNA 2011. Later I found some other resources.

In The Onion Architecture Jefferey Palermo describes a method of structuring an application such that the work of the application is separated from the infrastructure and loose coupling provides flexibility.

There are two important rules about this architecture. I personally thinking of them as the Dependency Direction Principle and the Dependency Depth Principle.

Palermo writes:

The fundamental rule is that all code can depend on layers more central, but code cannot depend on layers further out from the core.  In other words, all coupling is toward the center.

This principle is about the direction of dependencies. A given application may have a greater or fewer number of layers in its “onion,” but the outer layers should depend on the layers underneath, and the inner layers should have no dependencies on the outer layers.

In Clean Architecture, Uncle Bob calls this The Dependency Rule

The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circle. In particular, the name of something declared in an outer circle must not be mentioned by the code in the an inner circle. That includes, functions, classes. variables, or any other named software entity.

By the same token, data formats used in an outer circle should not be used by an inner circle, especially if those formats are generate by a framework in an outer circle. We don’t want anything in an outer circle to impact the inner circles.

Neither of the above-linked posts calls out what I think is another important rule about dependencies. Here, I’m speaking for myself.

The Dependency Depth Principle: Application layers must depend only on the contracts exposed by the layer immediately beneath them.

By controlling dependency depth, the seams between your application layers become well-defined and easily testable. More importantly, changes to the mechanics or api of one layer do not necessitate changes to the surrounding layers.

An Example

Let’s say I have a domain service that performs searching for musical performances. This service accepts a request like this:

   1:      public class QueryPerformanceRequest
   2:      {
   3:          public int[] PerformanceIds { get; set; }
   4:          public string[] Artists { get; set; }
   5:          public string[] Venues { get; set; }
   6:          public bool? Upcoming { get; set; }
   7:   
   8:          public int? Page { get; set; }
   9:          public int? PageSize { get; set; }
  10:      }

 

and returns this:

   1:      public class QueryResponse<T>
   2:      {
   3:          public T[] Results { get; set; }
   4:   
   5:          public int Page { get; set; }
   6:   
   7:          public int PageSize { get; set; }
   8:   
   9:          public int TotalRecords { get; set; }
  10:      }

QueryPerformanceRequest is a parameter object with which the client can indicate which data is being searched for by filling out properties. Some underlying layer is responsible for executing the query against the data store.

My web application application has this controller action:

   1:          public ActionResult Search(string term)
   2:          {
   3:              using (var command = _performanceCommands.Query())
   4:              {
   5:                  var request = _builder
   6:                      .Create<QueryPerformanceRequest>()
   7:                      .From(term)
   8:                      ;
   9:                  var results = command.Execute(request);
  10:   
  11:                  var model = _builder
  12:                      .Create<PerformanceSearchResultsViewModel>()
  13:                      .From(results);
  14:   
  15:                  return View(model);
  16:              }       
  17:          }

What’s happening?

Line 3: Constructs the domain service used to perform the search.

Line 5: I like to use a fluent api for object conversion. I’ll speak more about this later. In this case, we’re just converting the incoming string into the QueryPerformanceRequest object. The converter manages the seam between the Application Services layer (MVC Controller) and the Domain Services layer (the command).

Line 9: This is the line that performs the query.

Line 11: Now that we have results from the query, let’s get them ready for presentation by converting them into a ViewModel.

Line 15: Returns the page with the required data.

Things to notice:

The domain services layer provides a contract in the form of a command to execute the query, a parameter object to describe the query, and the query results. It’s probably that somewhere inside the command database connections are being created, domain models are being searched for, and the results are being transformed back into the response. The controller layer does not directly depend on any of that logic.

Further, the controller has it’s own api independent from that of the domain services layer. Pass me a string and I’ll hand you a ViewModel. None of the details of the domain services layer leak into the View.

Each layer depends only on the layers underneath, and only on the layer directly underneath. No abstraction from an underlying layer crosses more than one seam.

If I change my controller api, the query contracts do not have to change. If I add behavior to my query contracts, the controller gets that behavior without modifications to the existing code. If I change the implementation of the query command, the controller does not have to change. Each layer is protected from changes in the other layers by layer-specific contracts and explicit management of the seams between layers.

About this series

I’m going to be writing a series of posts in which I build a simple application from the ground up. I want to express the Onion Architecture as well as my favorite implementation patterns. I think it will be a good exercise for me to explicitly identify the reasons for many of the things I do in my daily work.

I will host the application on github so you’ll be able to review the full source code as I work.

In my next post in this series, I’ll explain the demo project and start describing the innermost layer of the onion: The domain model.

11Mar/131

Adherence to Architecture vs. YAGNI

I had an interesting discussion with my co-workers this morning about architecture.

Some background

We’re putting together a sample web application to demo the default architecture we expect from applications. The idea is that applications should either be written to use the default architecture, or they should be migrating in that direction. As we have new ideas about how things should be done, we can fork the demo application and try our new idea out. Then we can brownbag our new work to the team and share idea. If the team likes it, the pull request will be accepted into the demo project.

Onion Architecture

I was asked to start the demo application work. I am a proponent of the Onion Architecture which clearly discriminates responsibilities among layers and enforces the rule that dependencies only point inward, and only at the layer inside the current layer. In other words, dependency depth for any class should be 0 or 1.

The Problem

In Draw Abstractions From Concretes I wrote:

Waiting until you have an actual need for the abstraction proves that the additional complexity you’re adding is actually necessary and that the abstraction you’re creating is the correct one.

I’m basically just invoking YAGNI with a special focus on how you know “when you need it.” The problem is that in the demo application I’m creating contracts and services for each layer of the application even though the application itself doesn’t have enough functionality (yet) to demonstrate the need for those layers.

Our team is split.

One side believes that YAGNI precludes us from creating an Application Services layer when the Domain Services are sufficient to solve the immediate problem. The specific issue is that Application Services have their own contracts for inputs and outputs that look much like the contracts used by the Domain Services layer. Why not just expose the Domain Services directly? This just creates more complexity than is necessary to solve the problem and makes the code harder to understand.

The other side (me included) believes that choosing an architecture and sticking to it overrides YAGNI. It’s better to have an defined architecture applied consistently even in cases where it’s not strictly necessary from a purely functional perspective. The purpose of having an Application Services layer apart from the Domain Services layer is that it allows them to change independently over time. It’s immaterial that in the beginning much of the behavior is basically pass-through. Anyone who is going to work on the code base will have to learn what Onion architecture is (or whatever architectural pattern is chosen for the application) and the additional complexity will make sense.

What are your thoughts?

Filed under: Design, Practices 1 Comment
11Mar/130

Draw Abstractions from Concretes

It’s often tempting to draw a more abstract solution to the problem you’re currently facing. It seems wrong to handled the the local concrete case when you know you’re going to be doing something very similar soon. Why not build a more abstract solution now and reuse it later?

There’s a principle in software called YAGNI. “You Aren’t Going to Need It.” The ideas behind YAGNI are that you shouldn’t introduce complexity into code until you’ve proven you need it. Waiting until you have an actual need for the abstraction proves that the additional complexity you’re adding is actually necessary and that the abstraction you’re creating is the correct one.

That last point bears repeating.

Wait until you have at least 2 or even 3 similar code paths before creating the abstract solution. Otherwise, you may mistake which code needs to be abstracted and end up with an abstraction that is ill-suited to the actual problems you’re trying to solve.

Filed under: Design, Practices, TDD No Comments
7Mar/130

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.

6Mar/130

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.

2Feb/130

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

 

Tagged as: , , No Comments
25Jan/130

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.

Tagged as: No Comments
6Dec/121

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.

2Nov/120

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