Friday, May 21, 2004

An interesting discussion was started at the SQL Server Users Group last night.  Basically, the question was whether it was ok to add 26 (!) Text/Image fields to a table.  And if not, what a viable resolution would be.  Now, I've had the opportunity to address a similar issue before and will withhold my solution for the time being from this blog entry so as not to bias the result.

Well, first of all, it seemed like the mandate to include these 26 fields (an arbitrary amount?) came from management which is a glaring red flag to me.  Very rarely (if ever?) does management actually understand database architecture and design and even more rarely how to tune and optimize a database for the applications that use it.  Ok, so management has asked for the ability to store tons of additional (categorized?) information and be able to retrieve it...that's what we need to know, not how they think it should be implemented - that's the responsibility of a knowledgable and creative DBA (more on that another time).

Now the real question: How should the data be stored so that it can be retrieved when needed?  It should be painfully obvious that putting the 26 columns in the table is wrong.  Wrong for a lot of reasons, architecturally and logically.  Some suggestions were:

1.  Create a related table with a foreign key and a single Text field (and possibly other metadata).  When you need the information you join that child table in and return it.

2.  Move the data (if it's file-based) off to a file server with a link in the database back to the actual physical file.

The group (I was a mere observer and didn't venture an opinion) ultimately came to the conclusion that it depends.  It depends on

  • the kind of data being stored (binary, text/comments, files, etc)
  • the amount of information stored (can you use a (N)VARCHAR instead?)
  • does the information need to be queried? (thus possibly requiring Full Text Search capabilities)
  • how is the information to be retrieved? (SQL? FTP? etc)

Anyway, what is your opinion? How would you recommend approaching this problem? 

Friday, May 21, 2004 6:23:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, May 19, 2004

I am reminded by a blog by Brad Abrams of a topic I meant to blog about a few weeks ago but forgot.  A while back I downloaded the free Microsoft tool FxCop.  This was back in the original versions and it was a bit cumbersome to work with.  Now, however, the new version (1.3) is much better!

FxCop performs an introspective analysis of your code, comparing rules that you select against your code and offering suggestions and recommendations.  These rules provide guidance for naming conventions, object design standards and practices, and common performance suggestions.  Additionally, the rule model is extensible - you can create your own sets of rules to apply to your code that help enforce individual or team standards and practices.

If you've not had the opportunity to use FxCop, take the time to do so!  In all honesty, I was a bit disconcerted when I first ran it on my code.  It's analysis is quite thorough and I was quite amazed at all the things (both small and great) that it caught in my code.  I try, now, to make it a habit to always run FxCop against my assemblies and am working on incorporating it into my daily builds of my code.

John Robbins has an excellent introduction into FxCop that you should read, whether you are new to FxCop or old hat.  Kudos to Microsoft for publishing such a great tool.

Wednesday, May 19, 2004 2:53:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Monday, May 17, 2004

Eric Gunnerson brings up an interesting point on which I'd like to elaborate regarding virtual methods.  It has long been a tenet of mine in the realm of object design that the programmer should be in full control of his components and their usage.  The developer of a component knows (or should know) intimately the inner workings of his components.  When an object is designed, the methods thereon should provide the consumer (another developer) with a direction and a usage.  Classes should readily make apparent their intended usage - if it's not really a possibility, then better documentation should be made available.  This helps avoid problems wherein another developer uses the class in an unsupported manner.

I am a strong believer that methods should not be virtual (overridable for the not-so-strong-right-pinkied folk out there).  When a method is marked as virtual it shouts out to the deriver that it was the developers intentions to support scenarios in which the method is overridden.  As EricGu points out, marking everything as virtual to handle the fringe case of 'just in case the developer wants to extend the functionality' is poor design and very non-intuitive.

I take it a step further in all of my design.  I believe that a class should be marked as sealed by default.  By doing so, the developers intentions are clear: You cannot override this class, it will simply not be tolerated!  I make it a practice, in fact, to mark all classes that I create 'internal sealed' to enforce this pattern.  Only in situations in which I am intentionally designing a class to be overridden do I remove the sealed class (e.g. when there is at least one virtual function).  Only when the class is intended to be used externally to my component to I mark them as public.  To help enforce this practice, I've taken the time to edit each of the VS.NET templates if anyone would like them.

This practice has saved me hours of headache and has enforced a logical design and structure to my components.

Thoughts? Comments?

Monday, May 17, 2004 12:43:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Saturday, May 15, 2004

Recently, a client of mine had a need for me to write (largely rewrite) an application for them.  Without getting specific or too detailed, the gist of the matter was that they had an application written and (semi-)working on Windows 95 that they NEEDED to migrate to Windows 2000/XP.  Unfortunately, they couldn't exactly take their existing investment and run it on Win2k due to some weird incompatibilities.

It came down to them needing to rewrite it entirely.  The client (with some guidance and directly from yours truly) opted to go with a .NET solution.  A hiccup was that the application relied very heavily on a third-party suite of tools that provides scientific analysis of images.  This suite was written entirely in C++ and is an MFC application.  Well, I'm not an expert in C++ and despite my experience in C++ it would take me a long time to write a full-blown app in C++, a lot longer than to, say, code the same app in C# or VB.  Well, the route I've decided to take (and one that I feel will provide the best experience going forward) is to design and code a translation layer between what would be considered a '.NET' interface to the backend MFC.

To accomplish this, I created a C++.NET dll that natively talks MFC and exposes the objects out to a .NET/managed client.  This was not a cake walk as it was fraught with gotchas.  These are a few of the caveats that I ran into:

  1. Memory management.  I had to manually control object lifetime of the MFC components.  I did this by designing an object hierarchy wherein each object implemented IDisposable.  Additionally, I supported the Finalize method by creating object destructors.
  2. Documentation.  The documentation for the suite of tools was horrendous.  The example code snippets were riddled with errors and inconsistencies.  The documentation was flat-out wrong in some cases.  Possible exceptions were not documented and identified.  This was one of the biggest hurdles to overcome.  Unfortunately, I really didn't have much of a choice with regards to their documentation - I had to use it.  I could find NOTHING online about this tool and we were stuck using it - no if's, and's or but's about it.
  3. Object interfaces.  The objects against which I was coding had very convoluted and relied on a lot of programmer knowledge of the inner-workings of the objects.  It was expected that to call method B() you already called A().  This particular design wouldn't be so bad except that the documentation never stated that you should have called A() in the first place.
  4. Lack of good customer support.  Emails were not responded to in a timely manner and were often not helpful.  Calls resulted in 'you're already in the queue' answers.
  5. Time Constraits.  The customer needs the app yesterday.

Well, the above list is by no stretch comprehensive, but gives a flavor of what I was up against.  Anyway, push come to shove, I was able to complete my .NET API version of the MFC components which, if I do say so myself, is much more useable and more understandable than the original objects.

This is what I did:

I created a base object (let's call it ObjectBase (names have been changed to protect the innocent)).  ObjectBase implements the IDisposable interface and manages the object's lifetime.  When the .NET object is created, a pointer to the object is acquired in ObjectBase and is then held until the .NET object is destroyed at which point the pointer is deleted.  Each ObjectBase-derived class can and may hold other non-.NET objects in memory.  The Dispose() method in ObjectBase makes a call to a virtual function called releaseUnmanagedMemory() that may be overridden in the derived class.

public __gc __abstract class ObjectBase : public IDisposable
{
   public:
      ObjectBase(void);
      ~ObjectBase(void);
      void Dispose(void);

      __property String* get_Name(void);
      __property void set_Name(String* value);

   protected:
      virtual void releaseUnmanagedMemory(void);

   private:
      mfcObj* _obj;
      bool _dispose;
      void dispose(bool disposing);

   protected public:
      ObjectBase(mfcObj* obj);
      __inline mfcObj* obj() { return _obj; }
}

That's not the whole object, but gives an idea of the direction I was going.  There's a protected public ctor as well that allows the .NET object to be created within my dll given the object pointer.  When I had finished the entire design it turned out that it was very elegant.

I tried to make my objects as self-documentating as I could while retaining all of the capabilities of the underlying third-party components at the same time making the classes have a .NET feel to them.  This required cleaning up object and variable names as well as creating several additional class types that weren't defined in the original API.

If anyone's interested I could probably post my actual implementation with some descriptions and comments.

Saturday, May 15, 2004 5:01:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Tuesday, May 11, 2004

Wow! What a success!

Tonight we had the as the .NET User Group meeting the Visual Basic 2004 World Tour.  The meeting was fantastic.  We had Jay Schmelzer and Joe Binder, both Program Managers on the Visual Basic .NET team, come and present to us.  I was amazed at the turn out.  We usually get 40 or so people to the user group meetings each month, which is good, but tonight we had 95!  This totally surprised me especially because we had 86 people registered online.  Usually, you'd expect 60 or so when 80 register, but we actually ended up with MORE than had registered - AWESOME!  This was even more stunning since we had 6 people that had registered 10 days ago.  Apparently we did some very effective last minute recruiting!  It would be fantastic if we had this turnout each month - but we're going to be working on that.

I missed the very beginning remarks that Joe had as I was working on logistics, but his presentation focused on the Tablet and Office which was very cool.  The majority of the evening was spent listening to Jay.  Jay had a very easy, funny presentation style that I think everyone appreciated.  Jay targeted productivity enhancements that have been made in VS Whidbey.  It is so exciting to see all of the enhancements and capabilities put into the next version of Visual Studio - kudos to the VS and VB groups!  In fact, some of the new features seem very tempting and alluring, almost making me want to use VB on a daily basis - a kind of returning to my roots.  I think I might use VB.NET quite a bit more once the 2005 version rolls around.

Afterwards, Jay, Joe, Aaron Skonnard, and several other guys from the group went to Cafe Rio for some dinner and to shoot the breeze...it was a great ending to a great day!

Tuesday, May 11, 2004 4:55:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback

Ok, this is a really simple post, but I didn't want to forget about it.  For years (since VB 5.0) I have loved to create reusable visual components, namely controls.  This passion has not gone by the wayside with .NET, but time has dwindled.  I find myself focusing on many other aspects of software development and haven't found the time to devote to control development.

Anyway, it's a pity this isn't easier, but have you ever wanted to create a control that has a fixed border (either a solid line or embossed)?  Well, various controls such as the PictureBox, Label, and TextBox offer a BorderStyle property for that purpose.  If, however you create your own control (one that derives from UserControl) you won't have a BorderStyle property and adding one of your own quickly turns nightmarish (not to mention tedious) unless you have a bit of knowledge about the Windows API.  Windows accomplishes this task by associating styles will visual and non visual characteristics of the control.

It wouldn't be .NETish to use PInvoke to set styles on a window (e.g. a control) via SetWindowLong() so we'll look into pursuing a different route.  The .NET team, it seems, has ridden up on a white horse and anticipated this need.  From within our control we can control the styles used when our control is created by the .NET subsystem via the CreateParams property.

Simply override this property, supplying your own styles and you've got your very own border style.

private const int WS_BORDER = 0x00800000;

protected override CreateParams CreateParams {
   get {
      CreateParams p = base.CreateParams;
      p.Style |= WS_BORDER;
      return p;
   }
}

There are many other styles to choose from as well, this one simply provides a solid border.  If you want to change the style after the control has been created, then you'll have to implement some different steps.  Have fun!

Tuesday, May 11, 2004 8:02:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, May 09, 2004

You know what I love above all other things? Resetting a domain! I mean, what can be more satisfying and energizing than watching one of your beloved hard drives crash and then taking the time to rebuild from scratch?  Such has been my lot these last several days.

On Thursday, May 6th, 2004, my domain controller's hard drive went out.  Fortunately it didn't go out hard, I could still reboot (periodically, and EXTREMELY slowly about 1.5 - 2.0 hrs per reboot).  Unfortunately, the crash occurred while I was backing up my data.  This is the second drive to go out on me in about a year.  Well, I've been in the process of rebuilding my Windows domain and Exchange server over the last few days - it wouldn't have taken so long but that we had company over for BBQs and such.

It wouldn't be so bad (missing email and stuff) except that I had to also rebuild a member server.  I couldn't simply change it's domain membership to the new domain because it is also a Certificate Server.  This member server also is my SQL Server, and IIS server, and File Server, et al.  Yes, being a very small, one-man shop has its pitfalls.

The good news is that I pretty much have the domain back up and operational...just a few thing lacking: a few databases, a few websites, and my source code control system.  That shouldn't take but a few more minutes tomorrow and I'll be cooking again.  A benefit of redoing everything is that I can revisit the initial configuration and more firmly cement into my feeble memory all the nuances to setting up DNS and DHCP as well as taking SQL Server databases and reconciling object ownership with new owners.  Not to mention file and folder ACLs.

Ah, the joy!  I just love computers!

Sunday, May 09, 2004 8:29:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, May 05, 2004

This sure is an exciting time!  Next week on Tuesday, May 11th, we have the Visual Basic World Tour 2004 coming to pay us a visit.  We'll the the opportunity to interact with members of the VB team and see many of the up and coming new features in the Whidbey Visual Studio product.

The VB Roadshow (as it's also known) will be hosting our .NET User Group at Northface University.  If you'd like to come, participate (of course it's FREE), eat pizza, and have a great time register online and don't forget to invite your friends!

Join us at the Salt Lake City .NET User Group Site as well.

The VB World Tour starts at 6:00 PM and runs until 8:30 to 9:00 PM.

2825 E. Cottonwood Pkwy, 3rd Floor
Salt Lake City, Utah

The office building's doors close (and lock) at 6:00 PM so be early to get in.  See you there!

Wednesday, May 05, 2004 8:59:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, May 04, 2004

Andrew Binstock, a columnist at SD Times, makes some very valid and interesting points concerning the software methodology known as Extreme Programming (XP) in his article 'Not So Extreme Programming'.  As one that has (in limited fashion) used Extreme Programming in the past I have been privvy to some of the benefits as well as some downfalls of the technique.  There are some definite key tenets of Extreme Programming of which I am a fan.

For example, I am a proponent of the 'Stand up Meetings' in which developers gather at the beginning of each day to set in order their tasks and resolve any foreseen roadblocks.  It's a great opportunity to make sure all of your ducks are in a row and everyone is ready to proceed with the days activities.  I am a big fan of test-driven development (TDD); I feel, however, that oftentimes developers will get too bogged down in writing tests so much that actual productivity is sacrificed.  I also am a fan of the story design technique in which a task or an activity is designed and the key actors and players are identified though I think the implementation should be different (not 3x5 cards).

I feel, however, that its disadvantages outweigh its advantages.  To begin with, in the XP way of things, applications are designed bottom-up which makes it very difficult to reach your intended destination with a solid packaging; it's a bit like building a skyscraper starting with lots of little bricks without a solid, preenvisioned foundation.  This lack of scope and real design can be detrimental to the end product.  XP projects seem to be especially geared towards smaller products; large applications are often too complex.

Refactoring, as a practice and a principle is paramount to programming and good software design - a tenet not overlooked by XP.  It seems, however, that it promotes refactoring ad nauseum.  Constant refactoring can be detrimental to the success of an application as developers are often dealing with minutiae that frankly are not that important or can be optimized later or in different ways.

Andrew to me hits his point home when he says the following:

The foundation of XP, in my view, is part of the problem: It is a radical embrace of an approach that goes from the particular to the universal. It is the purest form of bottom-up development: You never design more than what is immediately needed, you write the least amount of code that will fulfill your next test, and you design the test to provide the least amount of incremental change. After you’ve written lots of tests (frequently thousands), you clean up your code by using one of 72 refactorings—which are specifically analyzed techniques for cleaning code without changing its functionality.

The fundamental problem with this approach is that software today is complex and large, so it cannot be designed properly by using the least-increment approach and hoping that a sound product will eventuate through the organic accretion of lots of small design decisions (followed up by code cleaning).

Large, complex projects have to be designed top-down and the code must be developed to that design—regardless of its complexity.

Now, after having said all of this, I don't purport to be an XP expert by any stretch of the imagination.  Our embracing of the XP methodology was scattered at best and we picked and chose that which we saw as relevant to our team and our environment - much of it worked for us, though not everything did.  I'd welcome your comments and insights.

Tuesday, May 04, 2004 1:58:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback