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

Tuesday, April 28, 2009

A Fluent NHibernate Tablename convention helper

So, one of my after hours duties is being a contributor/developer on the Fluent NHibernate project. This past week or so, I've been in the process of converting my day job company's production system to Fluent (from standard hbm mappings). In the process, I've created a couple of helper methods to assist me in standardizing table names, Primary Key names, and Foreign key names. 

First, we start with the basic pluralizer:



   1:  public static string GetPluralOfText(string text)

   2:          {

   3:              string pluralString = text;

   4:              string lastCharacter = pluralString.Substring(pluralString.Length - 1).ToLower();

   5:   

   6:              // y's become ies (such as Category to Categories)

   7:              if (string.Equals(lastCharacter, "y", StringComparison.InvariantCultureIgnoreCase))

   8:              {

   9:                  pluralString = pluralString.Remove(pluralString.Length - 1);

  10:                  pluralString += "ie";

  11:              }

  12:              // ch's become ches (such as Pirch to Pirches)

  13:              if (string.Equals(pluralString.Substring(pluralString.Length - 2), "ch", StringComparison.InvariantCultureIgnoreCase))

  14:              { pluralString += "e"; }

  15:   

  16:              switch (lastCharacter)

  17:              {

  18:                  case "s":

  19:                      return pluralString + "es";

  20:                  default:

  21:                      return pluralString + "s";

  22:              }

  23:          }


I also added a method for stripping out some of the class name suffixes that are prevalent in the project:



   1:  public static string GetTextWithoutObjectOrientedConventions(string text)

   2:          {

   3:              string newText = text;

   4:              if (newText.Contains("Base") && string.Equals(newText.Substring(newText.Length - 4), "base", StringComparison.InvariantCultureIgnoreCase))

   5:              { newText = newText.Replace(newText.Substring(newText.Length - 4), string.Empty); }

   6:   

   7:              return newText;

   8:          }




And finally, my methods that tie it all together:



   1:  public static string GetTablename<TClass>()

   2:          {

   3:              return GetTablename(typeof (TClass));

   4:          }

   5:   

   6:          public static string GetTablename(Type tClass)

   7:          {

   8:              string tableName = tClass.Name;

   9:              tableName = GetTextWithoutObjectOrientedConventions(tableName);

  10:              tableName = GetPluralOfText(tableName);

  11:   

  12:              return tableName;

  13:          }


So far, it's worked out pretty well. All of my FNH conventions utilize these methods regularly.  Anyhow, hope this post helps someone else out there :)

Monday, April 27, 2009

Presenting A New Acronym for Failure...

This contractor that I've mentioned before in passing, is really good at doing things the most absurdly ridiculous way possible. If there's an easy and a hard way to do something, he'll invent a new way that does both, backwards.

By now, everyone's familiar with AJAX (Asynchronous Javascript and XML), and if you're not, this blog may not be for you.

The application that was delivered to my company had a very peculiar feature. If you're familiar with .NET's AJAX 2.0 framework, then you're probably familiar with the Tab control. It's a very simple AJAX control, nothing fancy. Now, if you're also familiar with the ASP.NET webform's model of postbacks for controls to maintain viewstate, then you're familiar with all of the ingredients to the recipe here. 

A rational, sane man, might develop a webpage using an AJAX Tab control. A rational, sane man, might develop another page using a series of tabs that take postbacks and pass some information along in viewstate. Our developmestruction hero took the road less travelled, and picked both.

That's right. He's using the AJAX Tab control, except, when you swap tabs, about half a second to a second after the tab swaps, the whole page posts back, and you end up on a different .aspx page. My co-worker Robert and I couldn't believe it. I sat there, stupefied at what was before me. I announced that this man had created Asynchronous Synchronous Javascript and XML.

To which, Robert turned to me and loudly proclaimed:
ASSJAX! 
(ASynchronous Synchronous Javascript and Xml). 

There's no escaping it. This term has become standard use in our office now. So thank you, anonymous contractor. You may have developed an indecipherable, bug ridden, amateur, spaghetti code system of evil that we'll have to maintain for God knows how long; but at least you gave us the greatest gift of all. ASSJAX.

Wednesday, April 22, 2009

Powered by the internet!

Just received some very important news!

HELLO:
Good Day,This is to officially inform you that Your email address has just won an ATM CARD worth 6.8 Million Dollars in the satellite software email lottery conducted by OCEANIC BANK E-MAIL PROMO INTERNATIONAL, In which e-mail addresses are picked randomly by software powered by the Internet., Please Contact Mr.mark Kelvin with this email (oceanicplc@8u8.com)

Tell +2347060481461.
VEREFICATION FORM
1 Your Full Name:
2 Your Delivery Address:
3 Your Age:
4 Your Occupation:
5 Your direct Phone Number:
6 Country
:
Regards,Mr David Mark
SENATE PRESIDENT


---

Indeed, Mr. David Mark. I shall be forwarding you the verefication information you requested, only it'll be for this guy I used to work with, who's name rhymes with Chris Wells.

Tuesday, April 14, 2009

Blackest Night...

There's a consultant that I've had to work with at my company, who's legitimately a nice guy, or tries to be. But regardless of that, he's a terrible coder. What he checks in is some of the most bug addled, overly complex, difficult to read and debug code I've ever seen.

I'll see if I can't get some permission from my employer to submit a couple of the "Golden nuggets" of his handy work, but for now, enjoy this brief glimpse at an enum I found of his for doing an item import. Honestly, I hope I never have to figure out how this works, but hey, at least it's commented for me...


   1:  Enum ItemField

   2:          Photo = 9999    'positive #'s are reserved for characteristics

   3:          Disgard = 0

   4:          LocalItemCode = -1    'negative #'s are reserved for Item table values

   5:          CompanyItemCode = -2

   6:          Name = -3

   7:          Description = -4

   8:          Vendor = -5

   9:          Bilingual = -6

  10:          Complete = -7

  11:  End Enum




Update: I have permission to post some of his code :) Prepare!

Saturday, April 4, 2009

The best laid names of mice and men

What's in a name? If you're a person, it's there to establish your uniqueness within the community you live. If your name is Frank, and your father's name is Frank, then there's usually a Jr., Third, Fourth, etc attached to the end of your name so the people in your household know how to call which one of you down to supper. If you went to school with someone who had the same first name as you, it was often common for people to use your last name, or some abbreviation of your name to tell you apart. Your name establishes you as an entity.

If you lived back in times not too far gone, say starting around 10th or 11th century AD, your last name (surname) would typically describe one of four things about you:
1.) What you and your family did for a living. The Coopers were barrel makers. The Wagners were wagon makers or blue fuzzy teleporting mutants.... 
2.) Who your father was. Johnson, Peters, Myers, "The Mailman", etc.
3.) Something about your locality. The Ashley's lived by ash trees (not set on fire, or maybe they were, I'm sure some Ashley's were cremated at some point).
4.) Nicknames. Reid's were the redheads, the Armstrongs had strong arms, and the Cox's had...um...

You can even trace your family line back hundreds, if not thousands of years based on nothing more than your name. The point is, names are important. They help define us, and what we do. 

The names of your variables, classes, and methods are no less important. In fact, they're probably more important, because they have no visual features in which to distinguish themselves by. They give context to your application. Well named objects help you define how your application works just like putting the correct words in the correct order helps someone read a book.

Naming is so important, that Steve McConnel dedicated 32 pages to just naming variables in chapter 11 of the foundational book "Code Complete", plus even more pages for naming methods and classes.

Back in 1999/98, Paul Haahr  (blog here), wrote a foundationally solid article regarding naming that I recommend checking out.

Example time. Which set of variable names are easier to understand:
numBckWLinFtTtl01, numBckWLinFtTtl02, numBckWLinFtTtl03
or
standardStoreBackWallLinealFeet, prototypeStoreBackWallLinealFeet, remodeledStoreBackWallLinealFeet

So what's wrong with the first set of variables? Other than it used to be in use in one of the legacy systems at my company.
  • Uses a form of Hungarian notation (putting type information, along with other prefixes) into variable names. The truth is, there's simply no need to do this anymore. With modern IDE's, all it takes is hovering over your variable to get a tooltip telling you what type it is. All it does is add more letters to the front, that developers have to train themselves to ignore, so they can get at the real info
  • The abbreviations. Cripes. If I had a nickle for every time I've touched a system that was bogged down by abbreviations, I'd be able to form a stimulus package of my own for the government. If you feel like your name is too long, and should be shortened, do not "fix" it by abbreviating. There are only two times when abbreviation is acceptable. When it's a common abbreviation (such as URL, RAM, email, etc.); or when your code size matters, such as in the case of Javascript. If your reason is the second one, let me introduce you to an automated technique called Minification.
  • Ttl. Another abbreviation. Total is unnecessary in this case. Use generic words like "count" and "total" sparingly, if at all. In the majority of cases, they're too generic to add value to their use, and if the rest of your application is written well, the reader will easily be able to infer that meta piece of information.
  • 01, 02, 03. One day, the people who append generic numeric suffixes to variable names, will be set on fire and become Ashleys. We could easily fill a book on why this is a bad practice; completely indecipherable intent, accidental confusion with integer constants (especially if one uses a variable name like that in an expression: numBckWLinFtTtl01+01), or difficulty of managing multiple variables that only differ by the number on the end. But most importantly, always program like the next guy who takes over your code may be a serial killer. Keep that in mind the next time you think this it's acceptable to have a dateLastUsed04 in the system.

Now, what about the second set of names? Well, those make more sense in the given system. I don't even have to tell you anything about how the system works, or what it does, for you to start to understand what those three variables do. That's really the point. I want to be able to look at a variable, method, or class name, and immediately understand the purpose and use of the object.

Before you create an object; spend a little bit of extra time and consideration to it's name. If you can't come up with a good name that describes the intent, then perhaps you should re-examine the purpose of your new entity. After all, if you can't explain what it's purpose is, how can you expect someone else to come along after you and figure it out?