19 March 2010

Keyboard Layouts

As you may know, type-writers originally had more or less alphabetic key ordering. Typing was a mechanical process -- essentially pressing a key caused block letter to smack the paper, printing that letter. It was soon discovered that certain very common letter combinations (e.g. ST) would physically cause the machine to jam.

The QWERTY keyboard layout was devised by Christopher Sholes to minimize jamming. The commercial success of his typewriter in 1898, featuring the QWERTY layout, led many manufacturers to adopt it. Over time, it became the standard layout for keyboards, and it has changed only slightly since then. By and by computers came along, and the QWERTY layout has come to include some things specifically for the computer -- function keys, arrow keys, etc.

So a professor named Dvorak decides to investigate efficient text entry methods. After a bit of research on hand physiology and letter / diagraph frequencies, he came up with a keyboard layout specifically designed to minimize finger travel. It was patented in 1936 and is commonly known as the Dvorak keyboard. The layout, being an ANSI standard, is available but hidden away on most modern operating systems. The layout, once learned, promises faster data entry and reduced risk of CTS / RSI over the QWERTY layout. Of particular note is that 70% of English words can be typed using just the ten keys on the home row of the Dvorak keyboard.

However, the Dvorak keyboard never saw widespread acceptance. There are many cited reasons for this. Of particular note was the fact that workers would need retraining, and new equipment would have to be purchased (before the computer age). On top of that, you might recall that the 30s was a particularly bad time for the world economy. Even today, few studies on QWERTY vs. Dvorak exist, therefore it is difficult to empirically justify a switch from the established standard.

Part of the purpose of this entry was to explore the Dvorak keyboard, and in fact I wrote all of the above with a Dvorak-based layout, before editing. (I can see why people are reticent to switch... it is very frustrating to relearn to type!) However, I can't help but wonder if, after the training obstacle is overcome, if it won't be better, easier, less strain, maybe even faster. Perhaps I'll give it a try.

Regardless of what I do, I doubt that Dvorak will ever become the standard, even if it was one day empirically found to be superior. Learning to type is no small task (something you take for granted until you have to relearn it). The established labor pool has a QWERTY mindset. Heck even the staggered rows that modern keyboards have are owed to the "ancient" typewriter. It had to stagger them so that all the keys could mechanically connect to every corresponding letter block. Typing is such a fundamental function of computer use today, and QWERTY is so entrenched, that probably the only thing that will change it is to make the keyboard obsolete as a data entry method.

02 December 2009

Avoid Javascript if you can!

If you're developing a rich web control, then -- no two ways about it -- you are stuck using JavaScript. If you're developing a business web app, avoid JavaScript at (nearly) all costs.

Now before you assume that I'm an ignorant wretch who's never really used JavaScript, let me tell you this. I've done a bit of client-side in my time. Including: A Mac OS X widget written with no JS framework, a jQuery plugin for filtering search results (written for and included in jqGrid since 3.5), and lots of custom code for various projects using jQuery or Prototype.

This is what clinched it for me: When I was doing a refactor of a particular piece of my main work project, I decided to fully embrace jQuery and use its UI components, themes, plugins, etc. The long and the short of it is that I will never do this again.

I mean, it's cool that you can create a snazzy jQuery UI widget with a div and a line of javascript, but making that work with your server-side language requires javascript glue. Even with jQuery making things easier, I had to write an inane amount of JS code to glue everything together (check or toggle css classes, setup and handle events like clicking, make ajax requests). My application was a tad complicated, and this was not helped by the fact that I now had to debug both client and server code (and the server code being the much easier part). Sometimes it's fun to make your own glue, but it's a massive expense just to have a pretty client-side control.

The take-away from this is that as an app developer (not a control developer) it's best to avoid using client-side code (Javascript) when possible. I can get around this in ASP .NET for the most part by using pre-made AJAX server controls from the Ajax Control Toolkit, or by using normal server-side controls in UpdatePanels. UpdatePanels potentially add a good bit of overhead, but for internal projects (which is most of what I do) having slightly better performance is not nearly worth the time it takes to make high performance glue.

Well, that's my perspective anyway. ;)

Microsoft showers students with software

First I found out about DreamSpark. As long as you are enrolled in a participating college or high school and have an email address ending in .edu, you can download the following full versions of MS software (and Product Keys if they are needed) completely free:
  • Visual Studio 2008 Pro
  • Visual Studio 2005 Pro
  • Expression Studio 3
  • SQL Server 2008 Developer
  • Windows 2008 R2
  • Windows 2008
  • Windows 2003 R2
  • Robotics Developer Studio (Standard I assume?)
  • Other free software (Visual Web Dev Express, SQL Express, etc.)
No media is available. Most of these are for both 32 and 64 bit systems. 2008 R2 is only for 64 bit. (EDIT: The next bit is only if you try to install it on a Mac.) Burning the 2008 R2 IMG file requires special software beyond a standard ISO burner. On my first go, I got the 1. 2. prompt. I found this blog, which explain the why and how to fix it. It's a lengthy process, but I muddled through.

Then I found out about The Ultimate Steal where you can get more software from MS on the CHEAP. As long as you have a .edu email address, you can download ISOs, get CD keys, and get shipped the actual media for the following:
  • Media for all of these costs an additional $13.00 per product
    • The media is NOT the full retail package
    • The media takes a long time to arrive (a month perhaps)

  • Windows 7 Pro Upgrade (32 or 64 bit) - $29.99
    • You do NOT get both 32 and 64 bit versions. So know what you need beforehand. 32-bit should work for any machine that can run Windows 7. 64-bit is better if you have the hardware for it.

  • Office 2007 Ultimate - $59.95
  • Visio 2007 Pro - $55.95
  • Non-English language packs for Office/Visio - $9.95 each (no media available)
The agreement reads that if they discover you are not an enrolled student, they can charge you the difference between what you paid and full price. Just a fair warning.

The download process is more annoying than at DreamSpark. There are 2 things you can download. One of them is a downloader for the ISO, and the other is for the setup files themselves, presumably for an in-place upgrade. I couldn't finish the latter to find out since I was running XP (and 32-bit to boot). Regardless, at least get the ISO and burn yourself a DVD to keep, just in case!

After you download the small .exe file, you have to run it to start the download of the actual product. The Digital River downloader caused a lot of problems on my machine. I got out of buffer errors and the entire machine became completely unstable, lost network connection, wouldn't start programs, etc. Then when I shut down, it blue screened. I believe this was due to AVG. After I turned the real-time scanner off, the problems seemed to stop. After that fiasco, I uninstalled AVG and put Windows Security Essentials in its place. Just to test, I redownloaded the entire thing post-WSE with no problems.

AVG has generally been solid for me, but I guess it just couldn't handle the strain of scanning my 12 M/s download. Thumbs down to AVG.

Anyway, hope this helps all you students out there.

17 November 2009

Business and Data Layers

What follows in this entry is a way that works well for me to architect a Business Logic Layer (BLL) and Data Access Layer (DAL) into my projects. This may not be the best way, so any constructive feedback is welcome. I love to learn new and more efficient ways of doing things. (Read: I'm lazy, and if I can make it easier on myself, I will.)

Naming

DAL

I tend to like to organize my DAL in a structure similar to the database itself. The namespace ends up being something like:

com.project.DAL.DbName.TableName.Entity.Select.All()

com.project.DAL is the namespace for the DAL project
DbName.TableName is a folder structure
Entity is a class
Select is a nested class
All is a static method
(compare the latter two parts to doing a static method called SelectAll under the Entity class)

If there are specialized procedures that don't map to specific tables, I might make a "Procedures" class under the database folder to encapsulate those.

BLL

The BLL class, I tend to name based on functionality rather than database organization. Something like:

com.project.BLL.CRM.Customer.Get.All()

Interfaces

DAL

The DAL only returns DataTables or DataSets. I don't even bother with typed data sets because of the added hassle of regenerating the XML files each time I make a change.

Returning DataTables has a number of advantages.

For one thing, it's an abstraction over the database. I could even take DataTables pulled from completely different servers, put them in the same DataSet, and use DataRelations to query them in memory to get exactly what I need.

For another thing, if no extra business logic is needed (perhaps the table is only for display, not for editing), then I can skip creation of C# objects at the business layer and bind the DataTable from the DAL directly to web controls. Out of the box, DataTables already support all the niceties of web controls like paging and sorting.

BLL

The business layer objects are Plain Old CLR (C# or VB .NET) Objects (POCOs). They look something like this:
    public class Customer : IInitable  // my interface to make an Init method
{
public int customer_id { get; set; }
public string name { get; set; }
public CustomerTypeEnum type { get; set; }
public DateTime since { get; set; }
public List<History> HistoryEntries { get; private set; }

// note absence of constructor... CLR makes a default constructor this way

#region IInitable Members
public void Init()
{
... // set the HistoryEntries with something like this.HistoryEntries = History.Get.ByCustId(this.customer_id);
}
#endregion

public static class Get // nested class to handle fetch operations
{
public static List<Customer> All()
{
DataTable customer_table = DAL.DbName.Customers.Select.All();
List<Customer> ret_val = Converter.Fill<Customer>(customer_table);
return ret_val;
}
}
}
By convention, I use the same field names from the database as my object property names. That makes converting the data from the database to a C# object easy with reflection. I use a method similar to what I blogged about a while back that does this for me. Something like this:
    public static void Fill(object obj, DataRow row)
{
// get object's writable properties into dictionary by name
...
// loop through each column of the datarow
...
// if the prop name is the same as the column name
// check/handle: null values, enum types, type conversion
// assign obj to property
}
When I need to convert a whole DataTable into a list of objects, I wrote another convenience method:
    public static List<T> Fill(DataTable Table) where T: IInitable, new()
{ // where part means that T implements IInitable interface as has a default constructor
List<T> ret_val = new List<T>();
foreach (DataRow row in Table.Rows)
{
T obj = new T();
Fill(obj, row);
obj.Init(); // IInitable defines this method in case the object needs initialization after filling.
ret_val.Add(obj);
}
return ret_val;
}
IInitable is just a one-method interface that I wrote that makes the C# BLL class implement an Init method that returns void. Because I have to use empty constructors for uniformity, this Init method allows me to still initialize parts that would normally be initialized in the constructor, but after the data is filled in.

The CUD part of CRUD operations, at the BLL layer can take in an object and then use that object's properties for parameters of the DAL method.

However, to be really lazy, I am considering making an overload method for my DAL operations so that the BLL can just pass in the object directly and the overload method will use reflection to pull the properties out of the object and pass them into the method with typed parameters. I can probably encapsulate this with a separate static converter method so that the overload will essentially be a one-line call to the converter method (and therefore not much coding overhead), which invokes the real method. Once I get around to trying this, I'll post something about it.

Not that into NHibernate

I heard great things about Java's Hibernate, so I checked out NHibernate (Hibernate for .NET). After researching it a bit, I believe it will take more time and hassle to maintain than the current way I map data to objects. Here are my reasons.

Maintenance - 3 Sets of things to maintain
  1. C# Objects
  2. XML Mappings (something extra to learn)
  3. Database relations
Maintaining the XML doesn't have to be tedious, since there are tools that can generate it for you from the database schema. But most of the projects I work on are constantly evolving, and data changes are frequent. Assuming I remember to do it, that's a lot of regenerating XML (the same reason I stayed away from typed datasets) in addition to changing C# objects and database structures.

There are also things like NHibernate Mapping Attributes and ActiveRecord. These allow you to forego XML at first (although they ultimately recommend making XML files). But instead of learning XML, you have to learn the appropriate Attribute tags (although admittedly much less pain than the XML, especially ActiveRecord). Fluent NHibernate actually seems like the least pain, but you have to learn and use Fluent's coding conventions (which don't seem out of line) in order to get it to work properly.

Database Independence

This is probably the thing that NHibernate has going for it most. If you use the query language and the criteria language to get all your results, then you really could be connecting to just about any database.

The main issue I have with this is that NHibernate queries != stored procedure calls. For small projects that you don't expect to grow, stored procedures could be an overkill (but so could NHibernate!), but for projects of any complexity store procedures are the way to go. Stored procedure calls have a couple of major advantages, not the least of which being the object-oriented principle of encapsulation (or information hiding if you prefer). If you have a DBA, they can completely rewrite a procedure (for efficiency, say) and your program never knows the difference, which is a Good Thing. The other major advantage is performance as database procedures can be pseudo-compiled, depending on db platform, to make them run faster.

You can use NHibernate to call stored procedures, but the XML just specifies the native stored procedure call syntax ("exec proc_name" in MS SQL and "call proc_name()" in MySQL, for instance) -- there's no real database abstraction advantage there. Worse, if you need to run a procedure that doesn't return a result set, then you just have to make a native query call.

Conclusions

While I had high hopes for using NHibernate to make data access easier, it doesn't seem to accomplish that goal for me. It's an extra thing to learn and maintain, and has a number of drawbacks. Next article (who knows when that will be), I will show the way I architect data access. It might be a laughable thing to some of you (as if anyone reads my blog), but it's the easiest way I've found so far, while still having a lot of flexibility.

10 November 2009

ObjectDataSource TypeName and Nested Classes

When trying to use an ObjectDataSource with an method from my data access layer, I kept getting this error:



The type specified in the TypeName property of ObjectDataSource 'myODS' could not be found.



Long story short, the object I was using was actually a nested class. Even though you write you code like this:

MyNamespace.MyClass.NestedClass.Action();

The actual fully qualified type name for an ObjectDataSource TypeName will be "MyNamespace.MyClass+NestedClass" with a SelectMethod of "Action". If you visit this MSDN page and look down to where it talks about delimiters, you will see that nested classes use a plus as a delimiter for some reason instead of the usual dot.

05 October 2009

Crystal Reports 2008 V1 and MySQL

I have had the worst time with Crystal and MySQL. I tried MySQL's ODBC 5.1 drivers, but for me it didn't show any tables or views, even though I had all CR 2008 updates applied. Then I tried MySQL's ODBC 3.51 drivers, which showed tables, but when I didn't select any database, it would not show all databases... it would just show Add Command as the only option. That's not very useful since I have multiple databases. I'd have to create a connection for each one.



I finally ended up finding this page, and using the JDBC drivers. They aren't perfect, and they are a pain to install (editing config files), but they seem to work better than ODBC. I suppose Crystal just hates MySQL... which is ironic since that's the database they embed in their server product!



Getting Crystal Server 2008 setup... now that's a whole different (and painful) ball of wax. If I had this to do over again, I think I would have evaluated Crystal alongside a solution from Logi first. From the hassle I've had just to get a Crystal Reports Server 2008 solution working (and still not successful so far), I can only imagine it being better with Logi.