Database Gateway

by Rob 29. March 2010 11:14

A buddy of mine asked for a copy of the database access strategy on my current project. We're not talking about repositories or data access layers or anything like that. We're talking about all the way down to where the call is actually made to the real database. So I give you...

DatabaseGateway.cs
IQuery.cs
or get both as code in DatabaseGateway.zip

I'm not going to walk you through the code here. You can do that at your own leisure if you want to. The interesting part of the gateway to me is its use. Most of the time, you'll find something like this in our code: _db.ExecuteQuery(Query.For(prepare, map)). "prepare" and "map" being delegates declared locally. In other places you'll see something like _db.ExecuteQuery(new MySelectSOHeaderQuery(salesOrderNumber)) where "MySelectSOHeaderQuery" is a private nested class that implements IQuery (or IResultQuery<SalesOrderHeaderDTO> in this case).

The main thing I wanted when I created this was to simplify data access down to the fact that we want to execute queries against the database. Since that's the way we say it, that's the way the code should read. Therefore, when you're reading our data access, you see (if you look at it just right) the statement, "database, execute this query".

If you look at the code, you'll notice there are three different types of queries: queries that just do things, queries that return things, and queries that should be audited. No matter the type, they're still just queries. That's why in the database gateway the three overloads are named the same - because we're still just executing a query against a database and that's the way the code should read.

Keep in mind the vast majority of our data access is done with nhibernate. There are a few left-over queries against our own database that still use this gateway (left over from before we started using NH). Most of the gateway's use comes from our interaction with other systems. You see, we still value connection string sharing as an acceptable SOA strategy ("we" doesn't include a few of "us" so please be easy).

Feel free to comment with any questions or thoughts about it. Enjoy!

What I like About ASP.NET MVC

by Rob 16. March 2010 10:42

I've been asked a lot lately about why one would choose MVC over Web Forms. I'm not so sure about when one should, but I know my default choice is always going to be MVC.

Here are a couple of reasons why

Closer to the metal

With the lack of server controls and postback model, I find myself writing more raw HTML. I like that. Some people won't and that's fine by me. I do.

I meet too many developers who have no idea what the server controls they use actually end up as in the browser. That blows. Some don't even realize the server controls are not real HTML elements. Some don't notice the difference between server and client. I can't remember how many times a developer has asked me if they can call C# from HTML or if they can call javascript from the codebehind. I know the answer to both is "yes" in a round about funky way, but you know what I mean.

Forcing developers closer to the metal is forcing developers to realize what is actually happening. That has to be a good thing.

Forces a more user friendly design

You know how in web forms you can build an entire workflow in a single page using the postbacks? You know, selected index change event on a dropdown, lookup buttons, sorts, filters, wizard controls, tab controls, etc. All these things causing postbacks and firing events and the URL never changing. It's all happening in place due to the magic of web forms and viewstate.

Well, I find that doing anything like that in MVC is hard. And I love that! The result for me is that I end up rethinking my view. I find my putting myself in the shoes of the end user and concentrating more on how to allow them to accomplish the goal as simply as humanly possible. If I really do need richness or dynamic data to accomplish the task, I'm going to do it in an AJAXy way because that's easier than posting back and forth. For the end user, that's a very good thing!

In a nutshell, I tend to focus more on accomplishing goals and less on editing data when I build with MVC.

All the other goodness

Google MVC vs. Web Forms and you'll find a ton of other opinions. I agree with just about every reason you find that favors MVC :). They're all good and whatnot, but the above two are my favorites.

Branching Strategy

by Rob 24. November 2009 14:35

Check out http://stackoverflow.com/questions/16142/what-do-branch-tag-and-trunk-really-mean for some good discussion about branching strategy.

This is in reply to a question about our branching strategy on my current project at work.

  • Main - similar to "trunk". Contains the latest and greatest code and is always ready to deploy to production.
  • Dev - similar to "branches". Any feature that will take more than one check-in to finish should be done in a branch. This is to facilitate the most important part of main – always ready to deploy. And of course, we check-in frequently as a good practice so branching is pretty important.
  • Prod - similar to "tags". Contains the code that is currently in production. If it's a web app, you only really need one branch in here unless you think you might actually roll back to a previous version. This branch is useful when you need to immediately fix a bug in production but aren't quite ready for main to be deployed. Just because main can technically be deployed, doesn't mean the business is ready for it. The reason you see so many versions in our prod folder is pure laziness. It needs to be cleaned up big time.

And for the other two questions:

When you branch, you need to remember to check in the code you just branched. The icon mentioned is TFS's way of telling you that you haven't checked in the branched code yet.

We get the version number from the version of our core library. Many projects will use a shared settings file or something to ensure all the libraries within a solution have the exact same version - much cooler than the way we do it :)

Hope that helps!

Paul's Final Iteration

by Rob 11. October 2009 17:16

I was poking around in my data the other day doing a bit of housekeeping and ran across the recoding of Paul Clements' final presentation to devloop before leaving the company. I hated to see it hidden away on my HDD so I decided to chop it up and post it for all to enjoy!

Wise words from a wise man: Paul's Final Iteration

Enjoy!

Arrays Lists and some IEnumerable Philosophy

by Rob 16. September 2009 21:36

So I had an "architecture moment" today at work. I was refactoring some code with Jay Smith and while modifying a few classes, we changed a few data types from List<T> to T[] (from generic lists to plain old arrays) at my request. I'll get to why in a moment. Just let it be noted first that doing this caused two things: first it caused a significant amount of work at merge time for one of my teammates, and then it caused a philosophy discussion about why we should or should not bother with plain arrays instead of their big brother List class. And then the conversation veered in the direction of using IEnumerable<T> as return types and the dangers therein.

Inflicted Pain

When we made all the changes, I thought we were doing all the grunt work for everyone else on the team. I hate when what I do causes a significant amount of work for someone else; especially when the change isn't "needed" but is more of a philosophy type change. It turned out that one of the classes heavily affected by our changes was being worked on heavily by someone else. Thus the heavy merge problems for him. Completely my bad.

Array vs List

I have a very strong belief that all code should be self documenting. Therefore, to me, if I make the data type of a property List<whatever>, I feel that is telling other developers that this is a property expecting to be modified (adding and removing things). An array, however, says to the world that here is the final un-modifiable list as it was at object creation. A side result of this belief is that I pretty much never return a List from a method call since there are very few contexts where that makes sense.

Well, there usually is a reason to use List as a data type or return type. Not a good reason, but a reason... I usually see this as a convenience because those lists do get modified by adding dummy objects (like the first item in a dropdown that says "Please Select One") before data binding.

There was one other point mentioned too - performance. Yes, I know, I know. A List is bigger than an array and calling ToList on an IEnumerable is slower than calling ToArray, but not by much. And when I say "not by much", I mean seriously, seriously small amounts. I actually did a bit of testing to be sure and this is the result I got, so this part of the argument isn't worth ever mentioning again.

ToList speed (10,000 calls): 2,089 ms
ToArray speed (10,000 calls): 1,986 ms

ToList size: 16,448 bytes
ToArray size: 16,024 bytes

Total guids created: 20,002,000

The code that generated this result is at the bottom of the post.

IEnumerable Gotcha

When I mentioned that I never return List<T> from a method and always choose T[], it was asked why I don't just return IEnumerable<T> instead of an array.

Do you happen to remember the phrase deferred execution? It basically means that any variable of type IEnumerable<T> might be a list of stuff and it might just be an execution plan that will return a list of stuff as the list is enumerated.

The gotcha in that last statement is that the execution plan will run every time the list is enumerated. Did you notice the last line of the above test result? I did that on purpose to show again that an IEnumerable<T> will execute over and over. This is why even though the size of the list of guids is 1000, the GetNewGuid() method was called over 20 million times during the test!

So, you certainly can be careful when returning IEnumerable by calling ToArray() or ToList() to force the execution plan and return a finalized list. The problem for my little brain is that I constantly forget to do that! I'll run the application or the unit test, see whacky things happen or poor performance, and then go back and fix things properly. Or at least I used to when I was on the kick where every list was an IEnumerable no matter what. Now by default I use an array and only return IEnumerable when deferred execution is my intention (remember all code is self documenting).

Enough already!

Ya, ya... that's enough rambling. I really do hate long winded blog posts! Here's the code I mentioned earlier that generated that result. Happy coding!

internal class Program
{
   private static int _numGuids;

   private static void Main()
   {
      IEnumerable<Guid> guids = Enumerable
         .Range(0, 1000)
         .Select(x => GetNewGuid());

      MeasureSpeed(guids);
      MeasureSize(guids);

      Console.WriteLine("Total guids created: {0:n0}", _numGuids);
   }

   private static void MeasureSpeed(IEnumerable<Guid> guids)
   {
      const int iterations = 10000;

      var stopwatch = new Stopwatch();
      stopwatch.Start();
      for (int i = 0; i < iterations; i++) guids.ToList();
      stopwatch.Stop();
      Console.WriteLine("ToList speed ({0:n0} calls): {1:n0} ms", iterations, stopwatch.ElapsedMilliseconds);

      stopwatch.Reset();
      stopwatch.Start();
      for (int i = 0; i < iterations; i++) guids.ToArray();
      stopwatch.Stop();
      Console.WriteLine("ToArray speed ({0:n0} calls): {1:n0} ms", iterations, stopwatch.ElapsedMilliseconds);

      Console.WriteLine();
   }

   private static void MeasureSize(IEnumerable<Guid> guids)
   {
      var startingMemory = GC.GetTotalMemory(true);

      var list = guids.ToList();
      var memoryAfterList = GC.GetTotalMemory(true);
      Console.WriteLine("ToList size: {0:n0} bytes", memoryAfterList - startingMemory);

      var array = guids.ToArray();
      var memoryAfterArray = GC.GetTotalMemory(true);
      Console.WriteLine("ToArray size: {0:n0} bytes", memoryAfterArray - memoryAfterList);

      Console.WriteLine();
   }

   private static Guid GetNewGuid()
   {
      _numGuids++;
      return Guid.NewGuid();
   }
}

Powered by BlogEngine.NET 1.5.0.7
Theme: Slightly modified version of Standard (by Mads Kristensen)

Page List