A place to discuss Development techniques, .NET, XNA, NHibernate or anything else that tickles your fancy

Thursday, March 26, 2009

Fluent Method Chaining

So, something worth noting is the concept of Method Chaining. What I mean here, is the ability to call a method on an object, have that method return us an object, which we then use to perform actions on, which returns us an object which we then use to perform actions on, which return...oh you get the idea.

In general, I find this method exceptionally useful if you're creating a suite of objects that operate together to set up a configuration. A good example of this might be from the Fluent NHibernate mapping API. First, lets check out how to do a subclass mapping without using fluent chaining:



   1:  DiscriminatorPart<string, Document> subClassDiscriminator = DiscriminateSubClassesOnColumn<string>("DiscriminatorValue");

   2:  SubClassPart<string, Document, Manager> subClassPart = null;

   3:  DiscriminatorPart<string, Document> discriminatorPart = subClassDiscriminator.SubClass<Manager>("DocumentManager", x => {subClassPart=x;} );

   4:  ManyToManyPart<Document> manyToManyPart = subClassPart.HasManyToMany(x => x.Documents);

   5:  manyToManyPart.AsMap("indexColumn");

   6:  manyToManyPart.Inverse();

   7:  manyToManyPart.Cascade.AllDeleteOrphan();

   8:  manyToManyPart.LazyLoad();

   9:  manyToManyPart.WithForeignKeyConstraintName("FK_Managers_Documents");



Not too bad in all actuality. We've all written code like the one above. But what if there was a different way to get the same thing? Lets look at the same functional code, but this time with Fluent NHibernate's chaining:


   1:  DiscriminateSubClassesOnColumn<string>("DiscriminatorValue")

   2:                  .SubClass<DocumentManager>("DocumentManager", mgr =>

   3:  {

   4:  mgr.HasManyToMany(x => x.Documents)

   5:    .AsMap("indexColumn")

   6:        .Inverse()

   7:        .Cascade.AllDeleteOrphan()

   8:        .LazyLoad()

   9:        .WithForeignKeyConstraintName("FK_Managers_Documents");

  10:     });


Let me explain the basics of what's going on here:
1: We're calling a method on our class, which returns to us a DiscriminatorPart object.
2: That DiscriminatorPart has a SubClass() method on it, which returns to us the same DiscriminatorPart that was created on line 1
4: The subclass DocumentManager is being mapped in the lambda. This is chained to call a HasManyToMany method on the DocumentManager, returning us a ManyToManyPart
5: The ManyToManyPart has a Map() method called, setting up the collection type, and returning us itself as a ManyToManyPart
6: The ManyToManyPart has an Inverse() method on it which sets a flag telling the mapping to write an inverse="true" attribute, and then returns us itself as a ManyToManyPart
7: The ManyToManyPart has a Cascade() attribute set on it which creates a CollectionCascadeExpression on the ManyToManyPart. The chain from the CollectionCascadeExpression sets an attribute for the type of cascade, in this case, AllDeleteOrphan. The AllDeleteOrphan returns us the original ManyToManyPart object that Cascade was called on
8-9: Other attributes are set via chained methods returning the ManyToManyPart

What's the difference? Hopefully it's obvious. But I'll list out the main points I can see:
- Less verbose code. Simply put, the largest benefit is that you have to write less. There's less repetition on the screen regarding accessing the same object over and over
- Reads better. Because there's less code on the screen, it's easier to focus on just the parts that convey meaning, and read intent. When debugging or reviewing code, gathering intent is most likely the highest investment you have in the code.
- More meaningful interface. We are able to specify what is allowed to be done at what point, and control the flow of access. In effect, we can guide the subscriber to our API down the "happy path".

Regarding that last point, I would highly recommend the return types to fluently chainable methods to be exclusively interfaces. This allows you to cut down on the noise and dead end paths that might appear when you return an implemented class. Even Fluent NHibernate is guilty of violating this on many occasions, so don't feel too bad if you're tossing around concretes.

How to tell when to use Fluent Method Chaining? The end result should be a much more elegant way in which to interact with your model. If you don't immediately notice the improvement, or it feels like you're having to do more work than you used to when interacting with dependant operations on your class, then go back and re-evaluate your usage of this technique. Perhaps you're using too large of an interface as the return type. Perhaps you're forcing chaining in situations where it doesn't make much logical sense to.

Not every situation needs this approach. With enough experience, you'll quickly find which scenario's work best and which are better left to traditional declarations.

Tuesday, March 10, 2009

NHibernate and Snapshot Isolation

Isolation levels make a large difference in how scalable your application is. Pick the wrong one, and your users will experience the kind of pain you see on The Daily WTF. But, if you're running into concurrency issues (row locks), or other scalability problems, it may be worth your time to take a look at the Snapshot isolation.

Typically, with NHibernate, you have four isolation strategies to choose from:

  • ReadUncommitted - The one you really want to stay away from unless you're 100% you know what you're doing. You can end up with cascaded failures on transactions. That in and of itself should steer you away.

  • ReadCommitted - The default isolation level used by NHibernate, and recommended for use in NHibernate In Action, and other such qualified sources

  • RepeatableRead - Really, you should get the majority of the benefits of this from using caching and versioning

  • Serializable - The flip side to ReadUncommitted, except this encounters scalability issues

However, NHibernate will use any isolation level supported by the database (and to that extent, ADO.NET). Which gives us "Snapshot" (recently introduced to MsSql2005+)


Lets talk briefly about the Snapshot isolation model (ref: MSDN Article):


When writing to rows, snapshot isolation actually copies the rows from the table, into the TempDB (or another comparable system if not using MsSql), performs the necessary modifications, assigning those rows to transaction ID's, then commits the snapshot rows back when it's done. While the first transaction is performing operations on the rows, it will not cause a read lock. So a ReadCommitted isolation level can actually read the rows the way they were before the snapshot isolation transaction began.

If you attempt to write to rows as a second transaction that are in a first transaction who's isolation level is set to snapshot, then the second transaction will attempt to write to the same row our isolation transaction is attempting to write to, it will raise an error and roll back the snapshot transaction.

This mode can be a major benefit, giving you some of the concurrency benefits of ReadUncommitted, while still maintaining the data integrity of a more Serializable approach.

First, you must enable snapshots on your database. For MsSql:

ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON

ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON

Then you set the default isolation level in the NHibernate Configuration section. Add the following config element:


<property name="connection.isolation">Snapshot</property>

You can alternatively change the isolation level inline when a transaction first begins:



   1:  ISession session = NewSession();

   2:  session.BeginTransaction(IsolationLevel.Snapshot);

This recently (along with other tweaks) helped us solve a concurrency issue in a large application. Is it a fixall? No, absolutely not. As always, you should be pragmatic in your approach to improving performance.

Thursday, March 5, 2009

AT&T was pretty close to the truth

In 1993 AT&T ran a couple ads explaining what you could do in the future (of course, AT&T would bring it to you).

They were pretty spot on, but to be fair, the technology trend was already heading down those paths. They of course, had the insight, because they were in the "know" due to R&D.

All in all, when you think about it, it's pretty amazing where we are from where we came in as little as 15 years. Science and technology are progressing at a rate unheard of in the history of the world. We're curing diseases faster than they can be discovered. We're increasing the average life expectancy at a rate of 40% of the time it takes to do it (thus, if you were born today, theoretically, your ALE by the time you're intended to die at age 75, will have gone up another 40% by the time you get to D-Day, assuming the same trend continues).

Of course, we were lied to. We were told we'd be making a better world. And in some respects, we have. We need more funding towards enforcing net neutrality, Stem Cell research, and exploration (space and ocean). That's our future.

The internet's wonder is it's neutral platform, what happens when everyone on earth is able to communicate at the speed of light without worry of being jailed as a result of something they've said or seen online.

Stem Cell research (and many other scientific advances that have been blue balled by government, specifically America's last administration) is the key to improving our physical well being.

Space and Ocean exploration is the answer to coping with an increasingly diminishing supply of natural resources.

It's an uncertain future. I, for one, have faith in humanity. Perhaps these dreams won't be realized in my lifetime, but if we can affect the change required to ensure that our children, and children's children have the bright future we were promised, I'll chalk that up into the win column.

Monday, March 2, 2009

Nifty little vector2 get angle function

If you're working with Vector2's in XNA, or any other platform really, some functions you'd think should be on a vector object in your given framework just aren't. With XNA, it was the ability to get an angle from a vector. So I made one. This returns the angle the Vector2 is currently at.


   1:   public static float GetAngle(Vector2 vector)

   2:          {

   3:              float x = vector.X;

   4:              float y = vector.Y;

   5:              float angle = 0f;

   6:   

   7:              //Gets Angle

   8:              if (Math.Abs(x) < Math.Pow(10, -6))

   9:              {

  10:                  if (Math.Abs(y) < Math.Pow(10, -6)) { angle = 0f; }

  11:                  else if (y > 0) { angle = 90f; }

  12:                  else if (y < 0) { angle = 270f; }

  13:              }

  14:              else if (x > 0)

  15:              {

  16:                  if (y >= 0) { angle = (float)(180 * Math.Atan(y / x) / Math.PI); }

  17:                  else if (y < 0) { angle = (float)(180 * Math.Atan(y / x) / Math.PI - (-1) * 360); }

  18:              }

  19:              else if (x < 0)

  20:              {

  21:                  if (y >= 0) { angle = (float)(180 - 180 * Math.Atan(-y / x) / Math.PI); }

  22:                  else if (y < 0) { angle = (float)(-180 - (-1) * 180 * Math.Atan(y / x) / Math.PI - (-1) * 360); }

  23:              }

  24:   

  25:              return angle;

  26:          }

Best Guess Theory

I've read many blogs in the last 10 or so years. I don't think I've ever read a single one of their first posts. This is one of those. Best Guess Theory stemmed out of the concepts discussed in an article from the New Yorker, and some comments from Robert Dusek, a good friend/co-worker about naming a blog something like "We're guessing at this" (he'll blog with me at some point here soon I'd expect).

Back to the New Yorker article. Basically, your nervous system doesn't actually send a complex "packet" of pain to your brain, serialized with all of the intricacies that you're feeling, how much pain, where, burning versus smashing versus cutting versus freezing. It sends a much simpler signal, with minimal amount of info, shooting to your cortex. Your brain essentially makes a best guess at what to tell you you're feeling based on the small amount of information it's given. Smooth rock. Wet pond. Sticky syrup. Warm blanket. Hot fire.

More importantly than that, it's estimated that 90% of your perception of the world around you, is actually based on your memory of how something *should* look, how something *should* feel. Only 10% is actually interpreted by your brain from the signals received from your nerves.If you put that in the context of children, it makes so much sense why the first few years of a child's life has such a large impact on how they interact with the world. Because after those holes are filled, and the memory of the cortex is relatively complete, they're working off of previous experiences more so than current. That's the way we're trained to develop. It takes a real push to change your development style from what you learned when you first started down this path. You've got to stay on the edge, keep pushing that 10% margin and feeding your brain new sensory signals reinforcing and correcting it's associations. When you encounter a problem, your first question when solving it is probably something like: "Have I solved this problem before?". If yes, then your inclination is to attempt to apply your prior solution to the problem at hand, in some capacity. You solidify mappings between a problem and the approach you use to solve that problem in your memory.

It's extremely important to keep a critical thought process during, and after your implementation of the solution. The only way to evolve your ability to solve problems, is to association better solutions to those problems. Obviously, this is what Design Patterns are for. It's even more important to attempt to apply those patterns to your problem so you have a meaningful link between the pattern and the problem in your head. Remember, it's all in your head .