Wednesday, April 16, 2008

Email Decision

Greetings

I love IMAP. Its great.. I can use the webclient when I'm away, and any other client when I'm at home. Everything stays in sync. No hassel. With POP, each client is only aware of the messages it created. If one downloads a message without saving a copy on the server, then the other doesn't get it. Its a pain.

IMAP good.

Here's my setup: I have a hosted mail server for AllardWorks.com. I've been using Spam Arrest for years to filter out the spam. (Incidentally, SPAM ARREST is the best spam product I've ever seen). SPAM ARREST downloads the messages from allardworks.com and does its thing. I used to use the SPAM ARREST web page and use Outlook Express as my at-home client. They both connect to SPAM ARRESTS servers rather than the allardworks servers.

Here's the problem with Spam Arrest: The spam arrest web client is minimal at best. It really hasn't improved much in the years I've been using it. Its really simplistic and ugly. Seriously guys, update the CSS once in a while! I jest. But really! No, I'm kidding. Or am I?

GMAIL, on the other hand, is a lot nicer. I don't think it looks great, but its a lot more functional. The label feature is neat. (Its the equivalent of putting the same message in multiple folders). Several months ago I changed to the GMAIL client. GMAIL -> SPAM ARREST -> ALLARDWORKS.COM. That's a roundabout way of getting there, but it works well.

Here's the problem with GMail: My gmail address is HamletCode@gmail.com. When I send a message from GMAIL, I don't want anyone to know it. I want the message to appear as FROM JAY@ALLARDWORKS.COM. But, there's no way to do that. You can set the reply to address, and the from address, but underneath it all, it still sends a hamletcode header. Its received as "from hamletcode@gmail.com on behalf of jay@allardworks.com". That might be backards, but either way, its not what I want. People keep asking me what hamletcode is when, really, that's just my account name. I've been using jay@allardorks.com for probably 12 years. I'm not interested in changing it.

I put up with that for a few months, then decided against it. Last night, I moved all of my messages from GMAIL back to SPAMARREST via OUTLOOK EXPRESS. Spam Arrest offers 1 gig of storage, which should last a while. Gmail offers 6 gigs.

Points
- The SPAM ARREST web mail interface is crappy, but the spam service is unmatched.
- SPAM ARREST offers only a gig of disk space. I suggested a feature to allow users to buy more space. We'll see if that happens when the time comes. (I'm now of the mindset that I'd like my email stored on a server, not just locally)
- GMAIL has a better interface, but I wouldn't call it top-notch.
- GMAIL is very generous with its drive space allotments.
- GMAIL messes everything up by revealing that the message is coming from a gmail address.
- YAHOO MAIL has the best interface I've seen, but they don't offer IMAP (I haven't seen many interface though)
- I put in a feature request to ask SPAM ARREST to offer increased disk space
- I put in a feature request to ask SPAM ARREST to show how much space is in use
- Hotmail is a pain... I couldn't get into it with my existing windows live ID. It kept throwing exceptions. It looks like a pretty serious bug, which surprises me. It would be nice to actually see it to determine if it helps me at all.

In the interest of full disclosure, I must fully disclose that my track record with Spam Arrest hasn't been perfect. One time I asked them how to delete a contact (or something like that). They directed me to the "delete contact" button. That was embarassing, though anyone who knows me would probably find it suprising that I couldn't find it on my own. Last night I asked them if they had plans to offer IMAP. They said "yes, we already do". That was embarassing too. I don't fully blame myself, though. I'm computer saavy. Clearly its not working the way I'm accustomed to, though I'm not spending enough time researching stuff. Also, the search engine (or the content) leaves a lot to be desired.

Example 1: Search for DISK, then QUOTA on spam arrest. It doesn't come up with anything. Then search for SPACE, and you finally find what I was looking for: The disk limit.

Example 2: Search for IMAP. The three results are:
1 - Multiple Protected Mailboxes - accessing other mailboxes outside of spam arrest
2 - What is a pop server? - If you open that, it gives you some IMAP information, but if the name of the article is POP, why would I open it if I'm looking for IMAP?
3 - Options page - does that answer my question? I didn't ask about options, I asked about IMAP.

Search #2 is what prompted me to ask them if/when they were going to going to offer IMAP, so I don't feel guilty about it. I searched. The results were dissapointing.

One may ask why I don't just use my own mail server rather than jump through all these hoops
- First of all, I'm not really an email administrator. I've had to fight through some issues for other clients of the server, but its not my cup of tea. I learned a lot, but that doesn't make me qualified.
- I have space restrictions. Its not very generous, either. I don't want to waste space when other services offer more space for free or for fee. (I pay for spam arrest).
- I'm responsible for backing up the mail server, which I don't do. None of the clients (other domains, same server) use the server to persist their messages; they download them and delete them from the server. I make no claims for redundancy, etc. Since I want redundancy for my own email, I clearly can't count on my own server.

Then, you may ask why not host allardworks.com elsewhere where responsible people can take care of all the details for me?
Mainly, I don't want to incur the cost of the non-jay users. I have a few friends and family at allardworks.com. To relocate, I'd have to pick a plan that allows for multiple mailboxes, which I'm not prepared to do. Nor am I willing to tell them that they can't use AllardWorks.com anymore. I spoke to TUFFMAIL.COM, which has potential if the spam arrest approach doesn't work. They assured me that even if I leave allardworks.com right where it is and use them just for storage/web client, TUFFMAIL will never show up in the headers. Also, there's a 30 day free trial, so I can check it out first. (The disk limits aren't generous, though, which is why I'm not going to do it until I need to.)

Fun, right?

Tuesday, April 1, 2008

Static variables and singletons

I planned on putting this online Saturday night, but I got lazy. The laziness lasted longer than expected, but at long last, here we go.

This is just a paste of a word document. If you want a copy of the doc, let me know and I'll email it to you.

Next task: Figure out how to more effectively use blogger to post this sort of thing.



Jay’s Current Stance on Singletons and Static Variables
3/29/2008

"I hate being quoted" - Jay Allard



Overview
Singletons are really convenient. I’ve used them for many things over the years. As I’ve evolved, I’ve changed my stance on them several times. The changes range from minor tweaks to “why in god’s name did I ever think that was a good idea?”

This rant describes where I currently stand with singletons, static variables, and how I came to my current opinion.

Mixing Static and Instance State
Just a quick blurb based on some object I’ve seen. An object should not, in most circumstances, have any static data.

I ran into a situation on a side project a while back. I had to add new functionality to an existing object. I created unit tests for the object to define the new functionality.

In each test, I instantiated the object and tested whatever I wanted to test. The tests were working apparently randomly, but not really. Sometimes things passed, sometimes they failed.

It turns out that even though I was instantiating the object, it was driven by a lot of static data. So, instantiating a new instance gave you a new instance, but everything driving the object was static. Once the first instance was created, the static data was populated, so the subsequent tests didn’t behave as expected. Instantiating the object didn’t actually do anything. The instance was just exposing static data.

If you instantiate an object, you should get a fresh new object. If that object loads a bunch of stuff and you only want to load it once, then use another pattern. Either use a singleton so that it’s clear that it’s shared data. Or, don’t bother giving it a constructor at all. Make it a static object.

I only advise the creation of a static object, or singleton, as a better alternative to an insignificant instance. The better solution follows.

What is a Singleton?
A singleton is an instance of an object that is shared in the app domain. Rather than recreating the same type of object multiple times, just create it once, and allow everyone to use it.

Lets use a new cache object as an example. We’re going to ignore the fact that there are plenty of caches available, and build our own.

Cache cache = new Cache();
cache.Add("test", new object());
cache.Add("test 2", new object());

Now, you can retrieve things from the cache by key.

string hello = cache["test"];
string world = cache["test 2"];

Simple, right? Realistically, though, you only want to create the cache once then make it globally available. If you converted the cache object to a singleton, in its simplest form you would get:

Cache.GetCache().Add("test 3", new object());
Cache.GetCache().Add("test 4", new object());

You could alternatively change GetCache() to be a property name. Technically, that would work, but I disapprove. The method approach is, logistically, more accurate. You’re telling the object to do something. (It can be argued either way, but I’ll always use a method)

You may also see that we can achieve the same thing by exposing a public static variable. That’s smarts. Statics are the basis of the singletons, and a lot of times that may be the way you go, though I won’t.

By the time you get to the end of this document, you’ll learn that I no longer do singletons as described above. I do it with a slight design driven variation. But, the concepts are the same, so lets work through it.

Candidates for a Singleton
No State
A singleton is basically a server object. It can’t maintain state between calls because its getting hit by multiple threads at once, all with their own agenda.

Pay pay = new Pay();
pay.Hours = 3;
pay.PayPerHours = 375.00;
decimal myMoney = pay.Pay;

The Pay object cannot be a singleton. Multiple threads would overwrite the properties. By the time you got to “pay.Pay”, the state is completely unpredictable.

If you converted Pay to be method driven, you could then make a singleton of it.

int myMoney = pay.CalculatePay(3, 375.00);

Thread Safety
Thread safety becomes very important. If your object supports read and writes, then you have to manage the threads to make sure they don’t step all over each other.
For example, suppose the object checks a cache for a value. If the value is there, it returns it. Otherwise, it does a db lookup, populates the cache, then returns it. What if that happens twice simultaneously? Does the object end up on the cache twice?
Creating a Singleton
A singleton is an instance of an object assigned to a static variable.

Initialization
Option 1 – Inline Initialization – Jay’s Preference

In most cases, this is how I go about it.

public class Cache
{
private static Cache _cache = new Cache();

That will get compiled into to the constructor anyway, so its not much different from #1. I just like the syntax better.

In option #1, you saw that I added some initialization statements. How would you do that here?

public class Cache
{
private static Cache _cache = CreateCache();
private static Cache CreateCache()
{
Cache cache = new Cache();
cache.GetCache().Add("test 7", new object());
cache.GetCache().Add("test 8", new object());
return cache;
}

Note: This is only prudent when the object doesn’t have anything else to do. It’s just a cache; it doesn’t have any other functionality. That should usually be the case, but if you have a helper class with lots of stuff in it, then you may inadvertently create the cache when you do something irrelevant.

The static constructor is thread safe, so you don’t have to worry about thread management. It will only get hit once.
Option 2 - Static constructor
For some reason, I used to like using the static constructor. For some reason, I don’t like it anymore.

static Cache()
{
_cache = new Cache();
}

This gives you the opportunity to do some initialization right after you create it.

_cache = new Cache();
_cache.Add("test 5", new object());
_cache.Add("test 6", new object());

When an object has a static constructor, a flag is checked each time the object is hit to make sure that it has already been called. Regardless of how we do this, something is going to have to be checked on each visit anyway, so don’t get hung up on that.

Repeat Note: This is only prudent when the object doesn’t have anything else to do. It’s just a cache; it doesn’t have any other functionality. That should usually be the case, but if you have a helper class with lots of stuff in it, then you may inadvertently create the cache when you do something irrelevant.

The static constructor is thread safe, so you don’t have to worry about thread management. It will only get hit once.
Option 3 – Lazy Load
Back when I was a boy, this was my preferred approach. I did it this way to make sure that it only got created as needed, not when the class was used for any other reason. Since objects should only do one thing, that shouldn’t be a concern, so I don’t do this anymore. But, here you go.

private static object _singletonLock = new object();
public static Cache GetCache()
{
if (_cache != null)
{
return _cache;
}
lock (_singletonLock)
{
if (_cache != null)
{
return _cache;
}
_cache = new Cache();
return _cache;
}
}
Since this is a method, we’re responsible for the thread safety.
First, check to see if _cache already exists. If so, return it.
If not, lock the next chunk of code. We want to make sure only one thread hits this at any given time.

Check _cache again. It may have been created, by another thread, since the last time we checked. If it exists, then return it. Otherwise, create it then return it.

This Lock/Check/Lock approach doesn’t work in java. I read a bunch of stuff a few years ago. It was a hot topic, and it was proven that regardless of how logical the code is, it didn’t compile as you’d expect, so it wouldn’t work.

I only know it works in .Net based on experience. I should compile it and look at the IL to make sure its doing what I think its doing. It would be a great exercise. But, thus far, I have no reason to suspect that its not working.

A lesser approach is to lock the entire method. I don’t like that at all, though, because it only needs to be locked once, yet you’re locking it every time. Crazy, right?

Constructors
Once you’ve created an instance of your singleton object and assigned it to a static variable, are you done?

Possible Answers:
A: No
B: No

The correct answer is B: No. You are not done; at least, not if you want to enforce the SINGLE INSTANCE ONLY part of the singleton.

public class Cache
{
private static Cache _cache = CreateCache();
private static Cache GetCache()
{
return _cache;
}

Now, you can quite easily use the singleton.

Cache.GetCache().Add("Test 9", new object());
Cache.GetCache().Add("Test 10", new object());

Smashing. But, what’s to stop you from doing this?

Cache myLocalCache = new Cache();
myLocalCache.Add("Test 11", new object());
myLocalCache.Add("Test 12", new object());

Nothing is stopping you. By the definition of Singleton, you should stop it. You stop it by adding a private constructor. The private constructor will prevent any other object from instantiating cache


Final Product
public class Cache
{
private static Cache _cache = CreateCache();
public static Cache GetCache()
{
return _cache;
}
private static Cache CreateCache()
{
return new Cache();
}
private Cache()
{
}
public void Add(string key, object value)
{
//do someting
}
public object this[string key]
{
get
{
// do lookup
return null;
}
}
}

Now we’re sitting pretty. The only way anyone can use your cache object is by calling Cache.GetCache(). In order for this to work properly, your implementation must be thread safe. Your methods may get hit multiple times simultaneously.

That’s All Great, But Don’t Do It!
Did I just waste 5 pages? No, its all valid information. And I’m being over dramatic when I say “don’t do it”. That’s your choice go for it.

None of my business
I’ve come to the determination that it should be up to the application to decide what is a singleton and what is not. Who am I to say that there should be one and exactly one Cache object? Maybe the application would like to create 5 cache objects for different things. (Please keep in mind that this cache object is an ambiguous example. The question applies to anything that you want to make a singleton.)

If you come to the conclusion that you, as an object developer, have specific reasons to make sure that there is only one instance in any app domain, then it is your prerogative to make it a singleton yourself. What are some examples?
Maybe your object opens up a specific TCP port and listens on it. You can’t do that more than once. (Though, if the port was a parameter, then you could).
The Windows Workflow engine can only be started once per app domain. Somethine like that is a good candidate. (For the record, I don’t think WF should be a singleton for the reasons described in this section. But, it could be.)
I’m out of examples, but just 2 bullets is a waste of bullets. A list needs at least 3 bullets to be respectable.

I’m sure there are plenty of other examples, but in my experience, I’ve used singletons for convenience rather than necessity. I wanted my application to share one cache in an easily accessible way.

It comes down to this: Build objects. Let the consumer of the objects decide what they want to do with them. Its none of your business.

Testing
TDD is one of the primary forces that drove me to stop doing singletons.
In practicality, if you decided that you wanted something to be a singleton, then for most purposes its fine as a singleton. But, when you add testing to the equation, it becomes more problematic.

For example: As I develop my cache object, I’m going to write a ton of unit tests. Each of those tests should be stand alone (ie: not victim of anything that happened before it; won’t influence anything that happens after it?) How do you do that with a singleton?

For example, the test may be to add three items to the cache, then make sure the cache has three items.

The next test may be to make sure the cache initializes to empty. If the cache exposes a Clear() or Remove() method, then you can do it. If it doesn’t, then you’re stuck. The singleton instance is already populated. Test #2 will fail.

That’s only one minor example. We can invent plenty more.
Evolution Step 1: Default Singleton and Instantiate a Class

The previous conclusions were formed over time. Along the way, I took an incremental step towards supporting them. This worked out well since we already had existing singletons, but I wouldn’t do it for anything new.

One of the key parts of the singleton is the private constructor. The private constructor prevents anyone from instantiating the object. It remains entirely in your control, not the consumer’s.

Step 1 of the evolution was to eliminate that contructor, and change the getter to GetDefaultInstance.

public class Cache
{
private static Cache _cache = CreateCache();
public static Cache GetDefaultInstance()
{
return _cache;
}
private static Cache CreateCache()
{
return new Cache();
}
//private Cache()
//{
//}
public void Add(string key, object value)
{
//do someting
}
public object this[string key]
{
get
{
// do lookup
return null;
}
}
}

Now, you can either use the default instance (the singleton), or create your own. Technically, though, this is no longer a singleton. A problem with this approach is that the singleton is created even if you never use it. This could be a good place to use the Lazy Loading approach

Evolution Step 2: Have your application do it.
You have created a cache object and made it available to your applications. Its up to your application how to use it. If your application decides that there should be one and only one instance of the cache object for the entire application, then it can manage it.

public static class ApplicationCache
{
private static Cache _cache = new Cache();
public static Cache GetCache()
{
return _cache;
}
}

Now you can use ApplicationCache.GetCache() to get to your single instance of the cache object. (Of course, that doesn’t stop anyone from creating their own Cache if they’d like to).

If you have a few things like that, you could have one static class to expose them all to your application.
Conclusion
Going forward, I don’t see myself creating any objects that are automatically singletons. If I need a singleton, it will be at the application level.

The singleton is a very basic pattern that’s probably not worth 9 pages of information. But I did it anyway. I hope you find it useful.

Monday, March 10, 2008

MAC and no cheese

For some unexplainable reason, I was wondering how I would go about manually changing the MAC address of my wireless network card. I was just curious if it could be done incase I ever happened to go to a hotel that charges $13/day/laptop, and I didn't want to spend $26/day in addition to the hundreds of dollars already being spent.

My research revealed that you could theoretically signup for the internet service with one laptop, then change the macaddress on the second laptop so that the hosting service doesn't know the difference. The one problem that I might someday theoretically run into is that perhaps the hypothetical service always issues the same IP address to the laptop with the recognized mac address. That would mean that while both computers could both connect to isp, only one can do it at a time. That would be ok, right? Better than $26/day, should the situation ever arise.

If this were to ever come up, I would search google for a means of changing the mac address when the NIC properties doesn't allow for it. Maybe I'd find a program called MACSHIFT to help out. We may never know.

I believe the moral of the story is: pack a router.

Tuesday, March 4, 2008

Added TV SHOW and REVIEW COMMENTS

As part of the continuing effort to keep Chris satisified with the forward progress of the site, I have added two new features:

TV Show Season
Actually, this isn't really a feature. Its just a new type of product that you can review. Its intended for an entire season of a show. The immediate example is THE SARAH CONNOR CHORNICLES. As far as individual episodes: That's a whole other thing that I haven't started yet.

Comments
Yet another feature that was on the old site and is now, at last, on the new site. I actually attempted to do this a couple times before. I wanted to use an ajax dialog control, but I couldn't get the ajax toolkit to work in VS2008, and I wasn't in the mood to fight with it. I think its clashing with an old version that the GAC util won't let me delete. Another fight for another day. In the meantime, I tossed in a plain-old textbox on the page. It only shows up if you're logged in.

Unlike the review page, the comment box doesn't care if your session times out while you type your comments. It tracks who you are in viewstate so that it can always get to your id. The review page has a pretty major bug... if your session times out, the review won't save. I made it a habit to copy it before clicking save. I'll get to it.

Enjoy

Sunday, February 24, 2008

ASP.NET - Client Side List Box

We needed to create a dropdown list that would allows us to reorder items on the list. Piece o' cake, right? We created a composite web control with a drop down list and 3 client side buttons. A bunch of javascript managed adding the items and sorting the list. No big deal.

The interesting part didn't happen until post back. Asp:ListBox doesn't recognize things that are added from the client, only from the server. I thought it would work because you can do that type of things with, for example, a textbox. The different is that a textbox is an input control and a listbox is just a select control.

I created a new composite control called ClientListBox. I have know idea if I did it correctly, but it works. (I have minimal web control experience. I'm more about all of the other tiers. The composite control contains a listbox and a hidden field. As you add items to the list, the text and values are saved to the hidden field. On post back, it wipes out the list times, then creates new ones based on the contents of the hidden field.

The hidden fields stores the values as:
value\ttext\n

The IDs of the listbox and hidden fields are set dynamically based on the id of the composite control. So, if the control id is TEST, then the listbox is TEST_LB, and the hidden is TEST_HIDDEN.

Its intended use is client side script, so it gives you a known method name to retrieve the object.

If the control name is TEST, then in javascript, you can call getTEST() to obtain a reference to the object. You can then all methods like Add(text, value), etc. Conceivably, there would be MoveUp and MoveDown methods too, but we didn't bring it that far.

ie: alert(getTEST().getCount());

getTest() is created on the server side.

function getTEST() { return new ClientSideListbox(hiddenId, listboxId); }


Is that the proper way to write a webcontrol? I have no idea. But its clean and it works.

DvdFriend - Added the RECENT RELEASES section

For a site that would like to sell some DVDs, there certainly has been a lack of price listings.

In all 87 versions of the site that I've built to date, I've always struggled with determining what information to show where. Movies are coming out on DVD... should I list the date? The average rating? The Image? How many should I show? Should it be a number or by date range?

I refused to engage my self in those debates this time. Its showing 50 releases ranging from TODAY + 21 days, to whenever it runs out of movies. They're listed on the right side of the main page. this will eventually evolve into a more detailed page. I'd like to add a mouse-over dialog to it (like netflix does). I can easily do that, but as always, making it pretty will be the difficult part.

A key thing I did tackle is determining which titles to show. There may be a ton of movies in there, but not all of them are interesting enough to put on the front page. So, its only showing DVDs of movies that someone on the site has reviewed. Additionaly, there's a mechanism in there to flag movies that I want to show up. I haven't added the page functionality yet, but the back end is ready to go.

Later, the date headings will become hyperlinks that will show all of the releases for that day, without any filters. At the rate I'm going though, I'll spend 4 minutes doing it in 3 months.

Saturday, February 9, 2008

DvdFriend - User Review Page

In the other blog, Chris requested a page that shows all of the reviews he has written. I estimated it would take 14 seconds. It took 50 minutes to build and deploy.

Example: http://www.dvdfriend.us/UserReviews.aspx?un=DVDFriend

1 - Create a page Called UserReviews.aspx. It uses the normal site master page. Loaded this page into the browser passing it ?un=DvdFriend. The page loaded without any content.

2 - Created a stored procedure called DFGetUserBlogs(@userName). There's an existing view, DFvwBlogEntries, that already has all of the information I need. The stored procedure queries some fields for that where UserName=@userName

3 - Expose the query as a method in one of the business objects. There's an existing class called BlogFactory that has lots of similar methods. I created the new method:


public static DataTable GetUserBlogs(string userName)
{
const string STORED_PROCEDURE = "DFGetUserBlogs";
return AWDatabase.GetReadonly().ExecuteDataSet(STORED_PROCEDURE, userName).Tables[0];
}

4 - Added an object data source to the new page. Pointed it to the new method. Added a query string parameter for un.

5 - Added a datagrid to the page. Wired it up to the object data source. Loaded the page.. it's good!

6 - Tweaked the grid. Shut off AUTO GENERATE COLUMNS, then added the fields in the order I wanted. Formatted the date field.

7 - Added the SortExpression for each of the columns.

8 - Added a server-side H1 to the page. Assigned its value from the UserName property, which returns the value of Request.Querystring["un"];

9 - Changed Default.aspx and P.aspx: converted the USERNAME display fields to hyperlinks for the new page.

10 - Tested

11 - Deployed

Using out-of-the-box asp.net controls, and a little custom code, I was able to create this page pretty quick, but there's a lot more that can be done.

The page is a dump of everything the user has. Currently, DVFriend is the worse-case-scenario, wich isn't so bad. Once the list reaches a certain unknown size, it will be time to add paging.

Adding paging is easy enough; just have to enable it in the grid. However, the problem is that even if you're only showing one page of data, it would still query for all of the rows. I wouldn't be able to sleep if I did that (other than as, maybe, a transitional step).

I had a problem with the sort description. I set the Rating column to Rating,ProductName. I thought that would work, but it didn't. It always sorted by rating ASC. DESC wouldn't work, so I took off product name for now. The sorts will have to be revisited.

Other TO DOs
- I'd also like to add a summary grid and some filters on the top. IE: Pick a particular rating, and or date range; and/or reviews only. The summary would show how many ratings and reviews the user has, how long they have been active, etc.

- Show a list of other users on the right side so you can browser all reviews from all users. As long as the active user list is short, that will work... i can drop it in quick. Once the site conquers the world and the list is bigger, it won't hold.

- Put the grid in an asp.net update panel. I would've done this to begin with if I thought of it at the time.

So, the asp.net controls are pretty powerful; quick and easy. I'm not a huge fan of the final result, though. Its super quick and easy, but each SORT operation is a post back. I'd rather use the querystring so that you can bookmark the page and get back to it in the same state you left it. As is, you can bookmark it, but it will go to its original state.

Prior to asp.net, I created a ton of reports in JTS that needed this functionality. It was all done by adding attributes to the html tags, and javascript would create the new url and request it. In the end, I ended up with one generic ASP page and a bunch of XLSTs and data sources. To sort, you'd add a SORT="" attribute to the corresponding TH. There'd be some notation for asc, desc, etc (I forget the details). That worked out pretty well.

Pet Peeve 277: Ordinals vs key name

Pet Peeve #277

select FirstName, LastName, ShoeSize from MyFavoriteTable

... get a reader ...

while (reader.Read()) {
Console.WriteLine("First Name: " + (string)reader["firstname"]);
}

Per my previous post, I prefer (string)reader["firstname"] over reader["firstname"].ToString(). But it doesn't stop there. Oh no. There's more. I don't like that approach at all. I'd much rather see reader.GetString(FIRST_NAME) but more on that later.


Notice that the select statement queries for FirstName, but we're looking for "firstname" in our reader. The reader is going to do a case-sensitive search for "firstname". When that fails, it will do a case-insensitive search. Why search twice? In fact, why search at all? Just tell it the index number.

string firstName = reader.GetString(0);
string lastName = reader.GetString(1);
Int32 shoeSize = reader.GetInt32(2);

That's more efficient. Its going right to where it needs to go. But, 0, 1 and 2 aren't very readable, are they? Gosh no.

I use constants.

const int FIRST_NAME = 0;
const int LAST_NAME = 1;
const int SHOE_SIZE = 2;

get reader... create while loop, etc

string firstName = reader.GetString(FIRST_NAME);
string lastName = reader.GetString(LAST_NAME);
Int32 shoeSize = reader.GetInt32(SHOE_SIZE);

Of course, for this to work the fields need to be in a known predictable order, which in my experience is usually the case. Maybe it wouldn't fit if you have multiple existing procedures that return similar fields in different orders all going through the same method, but what are the odds of that? I've always been able to define the order.

Reader has another method called GetOrdinal() that you can use to look up the ordinals up front. So, if you really don't know the ordinal, you can do this:

int firstNameOrdinal = reader.GetOrdinal("FirstName");
int lastNameOrdinal = reader.GetOrdinal("LastName");
while (reader.Read()) {
string firstName = reader.GetString(firstNameOrdinal);
string firstName = reader.GetString(lastNameOrdinal);
...
}

That way, you only do the lookups once rather than at every iteration of the loop.

If you know they'll never change, then maybe you assign them to statics. I used to have a pattern to cover that scenario, but I quickly learned to dislike it because of the comingling of static/non-statics. Basically, when it got to the reader, it would check the value of one of the static ordinals. If it was -1, it would assign all of the statics. From there on, it wouldn't have to do it again. I don't like it.

The GetOrdinal follows the same steps as reader["fieldName"]. First it does a case-insensitive search, then a case sensitive search if necessary. So, if you don't have the ordinal, then hopefully you at least have the proper column name.

My position is clear: know the ordinals upfront and use them.

In order to do that effectively, you have to rely on the column order. If you do "select *", that's not reliable or portable. Always explicitly specify your select wether you're hitting a table or view directly, or when a proc does it for you.

Reader Source Code

I took a look at the reader source code to compare reader["string"] to reader.GetString(0). The by-ordinal approach doesn't immediately return the value... it does a little legwork first. By-string does the same legwork, plus the additional work of looking up the ordinal to get it started.

Pet Peeve 318: (string) vs ToString()

I'm trying to make it a point to blog entries on a regular basis. I've been told its a good idea, and I like good ideas, but at this time of the day, I don't have much to talk about.

So, I'm going to fall back to Jay Pet Peeve #318 (I just made that up, but I'll start keeping track.)

Let me be upfront about Pet Peeve #318: It is superceded by Pet Peeve #277. If you have to do a lookup by string, then its covered by #277. However, I feel you should do the lookups by ordinal, which is covered by the next post.


ToString()

select FirstName, ShoeSize from SomeStupidTableThatDoesntActuallyExist

The name is a varchar, and the shoesize is an integer.

You write some code to execute the query, and you end up with a data reader. Then you start looping through the reader.

while (reader.Read()) {
Console.WriteLine("First Name: " + reader["firstname"].ToString());
Console.WriteLine("Shoe Size: " + reader["shoesize"].ToString());
}

An alternative for first name is:
Console.WriteLine("First Name: " + (string)reader["firstname"]);

The first approach is technically sound, though I prefer the second simply for semantics. ToString() is used to provide the string representation of an object. When your object is already a string, you're essentially saying "convert my string to a string". Whereas, the 2nd approach says "here's my string". You wouldn't do "hello".ToString(), would you?

Does it matter? No. Its a pet peeve. I tried to be upfront about that. Pardon me if I wasn't clear.

As for the "shoesize", that's a different story. That's an integer, but you want to display it as a string, so ToString() doesn't offend my delicate sensibilities in that case.

NOTE: I don't like "firstname" and "lastname" in the reader calls either... that's covered in the next post.

Wednesday, February 6, 2008

More string silliness

Lets convert that previous example into a C# 3.0 extension method.

It would be cool if we could add static extension methods instead.
IE: string.IsNullOrTrimmedEmpty();
rather than
x == null || x.IsTrimmedEmpty()

Test Class




using MbUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YaddaYadda
{
class Program
{
public static bool IsNullOrTrimmedEmpty(string s)
{
return s == null || s.IsTrimmedEmpty();
}
static void Main(string[] args)
{
Assert.IsTrue(IsNullOrTrimmedEmpty(null));
Assert.IsTrue(IsNullOrTrimmedEmpty(""));
Assert.IsTrue(IsNullOrTrimmedEmpty(" "));
Assert.IsFalse(IsNullOrTrimmedEmpty(" a "));
Assert.IsFalse(IsNullOrTrimmedEmpty("a "));
Assert.IsFalse(IsNullOrTrimmedEmpty(" a"));
Assert.IsFalse(IsNullOrTrimmedEmpty("a"));
Console.ReadLine();
}
}
}


The class with the extension method



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YaddaYadda
{
public static class StringExtensions
{
public static bool IsTrimmedEmpty(this string s)
{
return s.Trim().Length == 0;
}

}
}

String silliness

Yesterday at work, Carlos and I had a silly converstation about the best way to check if a trimmed string is NULL or EMPTY.

I usually do this:

if (string.IsNullOrEmpty(x) x.Trim().Length == 0)


Carlos liked this better because its prettier:

if (x == null || x.Trim().Length == 0)

Of course, I took offense to that because I find my version to be quite attractive as well. So, instead of settling on which one is prettier, we broke it down into basic operations to see which one would be (theoretically) quicker.

In most cases, x will be a valid string.

string x = "123";
if (string.IsNullOrEmpty(x) || x.Trim().Length == 0)

1 - Check for null
2 - Check for empty (.Length == 0)
3 - Trim the string
4 - Check the length
Under normal circumstances, there are 4 things to do


string x = "123";
if (x == null || x.Trim().Length == 0)

1 - Check for null
2 - Trim
3 - Check the length
Under normal circumstances, there are 3 things to do.

So, the second choice is the better one, and we will use that going forward.

Out of curiosity, I took a look at the string source code to see how it was doing some things.


if (x.Trim().Length == 0)
or
if (x.Trim() == string.Empty)


.Length has been my means of choice. Its just a property value as opposed to a comparison. The string source code does it the same way.


System.String.IsNullOrEmpty()
if (value != null) { return value.Length == 0;} return true;

I think we've made a lot of progress towards solving some insignificant problems. Super.

Sunday, February 3, 2008

Code Camp 2008 recap

Code Camp 2008 is an excellent programming event sponsored by a variety of companies (including the one one I work for) in South Floida. Its a day of 72 classes at 70 minues each. This year's agenda is here:

http://codecamp08.fladotnet.com/agenda.aspx

Its a great event. Its completely free, and you can get exposure to a lot of stuff.

7:30 -8:00 - Registration
This was chaotic. There several copies of sign in sheets spewed about. You had to find a page with your name on it, and sign. Presumbably someone later consolidated the lists. After that, we were given the goody package. The goody packages was assembled on demand rather than prepackaged, so the line was pretty backed up.

8:00 - 8:30 - Keynote
There were 600 people crammed into a cafeteria that felt as if it were only intended for 1/2 that number. I fell asleep for 10 minutes and didn't fall over.

At 8:15, there was a very brief welcome, and code camp officially began.

8:30 - 9:40
I went to "Essential of the Architect and Architecture". I didn't have any expectations for this, because that's how I roll, but if I came up with some, I would've been way off. Ron Jacobs from Microsoft was the presenter. He's a pretty significant character in the great northwest, so it was good to get his view of things.

He described the roll of an architect by breaking it down in to three major components and comparing them to the roles of real people such as Christopher Columbus (explorer) and OJ Simpson's layer (advocate). It was interesting. I have several take aways from that session.

There were 2 other sessions at the time that would've been intresting: Dynamic Data Fields and Tools

9:15 - 11:00
I've already mastered the "Science of Great UI" as clearly demonstrated by the multitude of 3 color sites that I have assembled. Its real simple: Use a table for layout, then make everything look ad boring as possible within the cells of the table. Clearly I don't need a class.

I went to the Web Service Software Factory Modeling Edition. The software factories are basically code generators. It gets you started, you fill in the blanks. The modeling edition is more than that because you can work with the designer and regenerate from the model as you need to. I'm going to have to become more familiar with this.

Stan Schultes was the presenter
http://www.vbnetexpert.com/

11:10 - 12:20
From C# to F# in 60 minutes
This was a good introduction to F#. The gist of it was this: "We can't make light got any faster". Computer power has stopped doubleing every 18 months, so we have to make better us of multicores, etc. F# is a functional, scripting, and OOP language all rolled into one. Its great for list based stuff, and it makes it very easy to fire off stuff asychronously. It was nostalgic to watch it in action because most of the commands were issued from a command line. Good stuff.

http://cs.jaxdug.com/blogs/eugene_chuvyrov/
I just went to the presenters Blog, and the top entry is "VB.NET Must Die". I love it.


12:20 to 1:20 - Lunch
Once again, 600+ people crammed into the cafeteria. There were rumors of pizza going througout the crowd. I wasn't keen on the idea of waiting in another line and trying to find somewhere to sit, so Carlos, Steve and I went to Chilis instead.

1:20 - 2:30
High Speed Development in Visual Studio with Code Rush and refactor.
This was great. I installed CodeRush a few weeks ago, but haven't really used it. I didn't take the time to learn it. It turns out that there's a TRAINING window for inflight training. I'm going to turn that on, then most likely buy it when the trial expires.
http://www.devexpress.com/Products/NET/IDETools/CodeRush/

2:40 - 3:50
For Love or More Money, Developing Your IT Career
I initially thought this was a poor choice, but it worked out. I figured that by "Developing your IT Career", it would cover how to grow as an IT professional. There was some of that, but mostly it was "how to interview for another job". It was presented by http://www.sherstaff.com/, a company I haven't worked with before. (I've only changed jobs twice, so I don't get around a lot.) Despite my initial trepidation, I did get some pointers out of it. (IE: Keep a technical blog).

I've always had trouble with the interview process. There's a lot of etiquette. There are things you should and shouldn't say, should and shouldn't do. I have a very hard time accepting that. I like putting my forks AND spoons on the same side of the plate. I don't care where the wine glass is or the accessibility of my cloth napkin. Just give me food. I'm the same way with the interviews which, amittedly, isn't good. I want to get a job based on my experience with technology and people, and I would prefer to do that without rehearsing lines in front of the mirror. Thankfully, I don't interview often.

4:00 - 5:10
"Orcas for Architects" - I think its time to update the presentation name.
This was a 70 minute crash course in all things VS 2008 and beyond. I got a kick out of it. Most was stuff I'm already familiar with, but there were some gold nuggets in there such as ParallelFX. This reminded me of the "can't make light go any faster" comment earlier in the day. ParallelFX offers some new contructs that will automatically perform certain operations in parallel. It will use the other cores on your CPU to finish things faster.

The first set of example was mostly linear: on a dual core, it was twice as fast. On a quad core, it was 4 times as fast. The second one was graphic based. A quad core was 53% faster.

I told a couple guys about this later that night, and messed it up. I thought it was called PLINQ, but it looks like PLINQ is just part of it.

I'm looking forward to that one.

5:10
Wrapup. We once again assembled in the fire-hazard cafeteria. There were some nice raffle items, and closing comments from several of the sponsors. Some of the sponsors put together an after party, but I was unable to attend due to other plans.

It was a great day. I can't say I learned a lot of detail about anything in particular, but I got a lot of exposure to a lot of cool things, which is important.

Most of my takeaways came from the first Architecture session and the "For Love or Money" session.

Hamlet Code

"Hamlet Code" is a piece of foolishness that I came up while trying to find a new XBOX Live ID. My original ID was "DvdFriend", and ode to my website, but after a while I realized it was a lame handle.

I tried a variety of different code related user names, but they were all taken. A thought process that I don't recall came up with "to code or not to code", which is too big, so I rounded it down to "Hamlet Code". I only hope that my recollection of 9th grade literature is accurate.

So anyway. I have another blog at http://jayallard.blogspot.com/. I occasionaly add some foolishness there, and every once in a while I toss in some technical stuff. Quite honestly, its a disaster. However, I call the blog "Jay's Rants", so I'm being upfront about the kind of attention I apply to it. I just go in, type whatever I want to type, then hit save. More than one person has commented on typos and grammatical whoopsies.

This new blog is strictly for technical foolishness. If you want to read about how our community flooded, or the affect of the 1986 Transformers animated movie on my relationship with my nephew, or how I feed my dogs, then go to the other one. If you want to read about code related stuff, then read this one. In the end, there's something for everyone (or, at least for me).