Thursday, January 20, 2005

Words that should be in the dictionary pretty soon.

splab ('splab)
adj. splab·ber; splab·best

1slang
   a: of or related to a high degree of excellence
   b: very good, fashionable
synonyms:  cool, excellent, fashionable
example: The app was definitely splab.

 

whap ('hwäp, 'wäp)
v. whapped; whap·ping

1: to assemble
2: to create, specifically in the realm of software
3: alt: whap-out: to complete
synonyms: code, develop, write
exampleWe whapped-out that app.

These new words can be combined to form from pretty elaborate sentences that will undoubtedly enhance the developer's vocabulary:

Let's whap a splab app, chap.

Thursday, January 20, 2005 6:03:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Wednesday, January 19, 2005

[Fixed spelling error 02-15-2005]

I whole heartedly agree with Jeff Atwood's post.  Therein, while quoting Rico Mariani, he talks about a developer's tendency to use OOP features that are not needed nor warranted.  Oftimes while refactoring code (mine and others'), the authors utilized language constructs (such as delegates, virtual methods, elaborate object hierarchies, etc) when the code could be simplified and made much more maintainable.

The quote that stuck in my mind more particularly was “As developers, I think we also tend to be far too optimistic in assessing the generality of our own solutions, and thus we end up building elaborate OOP frameworks around things that may not justify that level of complexity.”  How true it is!  Almost every developer I know has this tendency.  The vast majority of the time, however, the simpler, more direct approach is the best one.  “Don't spend a lot time planning for grandiose, unknown future scenarios.  Good software can evolve into what it will ultimately become.”

Amen.

Wednesday, January 19, 2005 11:59:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback

One of the many things of late that has kept me from being as active on my blog as I would like to be is the looming pressure of a deadline.  We're building momentum towards releasing our application and there are quite a few loose ends that need addressing.  One of these is just about knocked out of the park - and it's one of the more difficult utility applications.

Prior to starting to work on it, I had never developed and IDE and as such, have had to delve into many obscure areas of .NET and application design that most developers shun and usually don't go.

Our application that we're writing is web-based.  It utilizes templated html in the form of controls (.ascx as well as server controls).  These User Controls (the .ascx variety) are designed to be edited and tweaked by end users (non-programmers/developers) and without the assistance of a tool such as Visual Studio.  We have, therefore, decided to create an IDE tailored towards targetting these users.

Without going into the details of the design of the application, we concluded that the best environment for the non-technical users to work would be a tool of our own creation that masked much of the complexity of .ascx controls (that is, directive tags and control tags) while providing full control fidelity and power.  A control within the .ascx might resemble <asp:literal id=litHeaderCaption ... /> but that would be too ugly (and perhaps intimidating) to display to an end user.  Instead we wanted to display [HEADERCAPTION] that acted as a cohesive unit within the editor.  That is, when a user positioned the insertion point within the tag (via keyboard or mouse), the entire tag would become selected and a set of properties would appear allowing it to be customized similar to how Visual Studio might work.  These controls would also be draggable from a toolbox (a la Visual Studio) onto the editor.

This discussion isn't focused on the richtext color syntax highlighting, the parsing of text to yield the [...] tags, nor the dragging of tools, though each of those is cool and might warrant a complete discussion (let me know if you're interested).  Instead, herein I'm going to talk about another aspect of the application that I thought was pretty incredible.

When dealing with a text string that contains a tag [HEADERCAPTION] how do you assign values to properties for an object that doesn't exist?  When the user selects the 'control' I need to render in a PropertyGrid control the public properties and their values.  Well initially, the control instance doesn't exist at all, that is, nothing is really hosting a control instance - you simply have a string.  Therefore, I had to, upon parsing out the controls, resolve which tags would be represented in the text, parse out the properties present in the <asp:... /> tag and somehow get these values into an instance of the control.  Well, this is a completely separate application from the actual product that performs the rendering of the controls in the web-world.  I need to define a class for each child constituent of my parent user control.

I decided pretty early on that I did not want to create a suite of classes representing each and every control type.  Sure this would have been a snap, and the object hierarchy is extremely straightforward, but I didn't want to have to deal with the maintenance.  After quite a bit of thought on this I decided it would not be the right approach.  If so, the code would have resulted in being a lot less maintainable and much more difficult to work with.  Instead, I decided to have every control type dynamically defined.

The first step in this was that to create a set of properties and their definitions so I could reuse them later in other class instances.  I decided to use the GoF's flyweight pattern so that I would have one set of base objects that were reusable with the mutable data in each property instance.  My code resembled the following:

[Flags()]
internal enum PropertyMode : int {
   Read       = 0x0001,
   Write      = 0x0002,
   ReadWrite  = 0x0003,
}

internal interface IToolPropertyDefn {
   Type            DataType { get; set; }
   PropertyMode    Mode { get; set; }
   string          Name { get; set; }
   string          PrivateName { get; set; }
   string          Description { get; set; }
   object          DefaultValue { get; set; }
   bool            IsMetaProperty { get; set; }
}

Then I had another class called ToolPropertyDefns that wrapped a Hashtable containing instances of ToolPropertyDefnImpl which represents instances of each of the properties in question.  The ToolPropertyDefns class can be indexed into by control type to retrieve the set of properties that pertains to the control type in question.  A snippet resembles:

internal sealed class ToolPropertyDefns {
   private static Hashtable _defns = new Hashtable();

   private ToolPropertyDefns() { }

   static ToolPropertyDefns() {
      // initialize the controls here...
      ToolPropertyDefnImpl[] defn = new ToolPropertyDefnImpl[] {
         new ToolPropertyDefnImpl(typeof(string), PropertyMode.ReadWrite, “Visible“, “_visible“,
            “Determines whether the control is visible or hidden.“, true, false);
      }
      _defns.Add(Tools.HeaderCaption, defn);

   }

   internal static IToolPropertyDefn[] GetDefn(Tools id) {
      return _defns[id] as IToolPropertyDefn[];
   }

   private sealed class ToolPropertyDefnImpl : IToolPropertyDefn {
      // define implementation here
   }
}

Once I had this class that managed the properties associated with each control type it was time to dynamically generate instances of the controls at runtime...which will be the topc for Part II of the discussion.

Wednesday, January 19, 2005 11:35:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, January 16, 2005

Back in the beginning of November I installed a CAPTCHA control to help mitigate all of the spam comments that were filtering into my blog.  These were a nuisance back then, but not yet an epidemic.  Shortly after I had installed the control I ran into some problems - namely the fact that the text was very difficult to read.  After a little battling with it I eventually removed it.  The spam had temporarily ceased anyway...until recently.

About daily now I get about 2-5 spam comment posts (either relating to poker or drugs).  Therefore, I decided to go out an search again for a CAPTCHA control that I could just drop onto a .Text blog.  It turns out that Miguel Jimenez had made some updates to his control not three days after I initially added it.  I wish I had followed up sooner and most (if not all) of these would have been avoided.  The control looks fantastic and it's a pleasure to have it on my site.

Thanks, Miguel for your great work!

Sunday, January 16, 2005 1:21:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback

At long last (and I've been wanting to do this for some time now), I've added a calendar control to my home page for the blog.  I really like the look and feel of it.  I had done some searching in months past for the control and honestly never found any that I really liked and I almost resorted to creating my own.

However, yesterday I came across a few blog posts: one on Scott Willeke's site, and the second (which is really a modification to Scott Willeke's) by Alex Gorbatchev.  I am extremely pleased with the ease of deployment.  I had some styles that competed with the Alex's styles, but that was no big deal as he packaged his styles inline in the .ascx file.

I think they both did a fantastic job on the control and thank them heartily for their contributions to the .Text world.

Sunday, January 16, 2005 11:54:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, January 15, 2005

The .NET Framework is immense...it's plain huge; and it's getting bigger.  Once I feel that I sorta have a grasp on it I discover new classes and functionality.  Now this may be common knowledge, but I wasn't aware of it until recently.

A few days ago I stumbled upon a class in the System.Diagnostics namespace called ConditionalAttribute.  This attribute, when applied to a method, provides the compiler with the opportunity to selectively ignore calls to the method, depending on whether a given condition (a preprocessor constant) is met.  Note that the presence or absence of the constant doesn't determine in any way whether the method in question gets compiled - it always does (unless otherwise overridden with #if..#endif block, for example), but rather controls whether calls to the method get compiled.

For example:

[Conditional(”DEBUG”)]
public void DoSomething() {
   Console.WriteLine(”DoSomething() called...”);
}

public static void Main() {
   Console.WriteLine(“Before DoSomething() call“);
   DoSomething();
   Console.WriteLine(“After DoSomething() call“);
}

Given the previous example, in a Debug build (in which the DEBUG constant is defined by Visual Studio), the output will include all three lines, whereas in a Release build (in which the DEBUG constant is not defined), only two lines will be spit to the console.

This sure makes code look a lot cleaner than say:

public static void Main() {
   Console.WriteLine(“Before DoSomething() call“);
#if ( DEBUG )
   DoSomething();
#endif
   Console.WriteLine(“After DoSomething() call“);
}

I have some utility classes that exist in an external library (.dll) that provide some logging and tracing functionality for testing and debugging purposes; they log method entry/exit, parameters, variables, expressions, you name it.  Well, it's a pain to have calls to these logging methods always wrapped in #if..#endif blocks to conditionally compile them into a Debug vs a Release build, especially when calls might appear multiple times within a block of code.

The ConditionalAttribute class has come to the rescue.  I can now have a method that resembles the following code in my Logger.dll:

[Conditional(”LOG_ALL”)]
[Conditional(”LOG_EXPRESSION”)]
public void WriteExpression(...) {
   // ... perform the logging
}

If either LOG_ALL or LOG_EXPRESSION is defined within my calling assembly, the call to WriteExpression() gets compiled into the IL.  If neither of the two constants are defined, it's as though the call doesn't even exist.  This is pretty powerful and definitely cleans up the client code quite a bit, and makes it much more maintainable.  I really wish I had known about this sooner.

Saturday, January 15, 2005 5:29:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Thursday, January 13, 2005

Well, tonight was a pretty cool night.  We had a really good .NET user group meeting.  We tried a slightly different format from what we've historically done, having two presentations rather that the traditional one.

Jason Walker, a good friend of mine and a member of the user group leadership gave a presentation concerning performance and optimization.  He decided to focus of tools and practices that tend to yield high performance and maintainable applications (should their advice be heeded) such as FxCop, Process Explorer, CLR Profiler, and more.  Though I have used each of these tools quite a bit, it was nice to see them in action once again and glean from Jason's experience.  I think that many members of the user group benefitted greatly from the presentation.

I was the second speaker tonight and decided to focus my talk on Generics in the .NET Framework 2.0.  All in all it was a pretty good presentation and was well received.

I felt that we had a very successful meeting tonight.  I continue to look forward to more in the coming months!

Thursday, January 13, 2005 5:24:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, January 10, 2005

Well, I guess 2005 isn't already without its surprises.  Today we were welcomed with what appeared to be a very prolonged contraction - lasting upwards of 2 1/2 - 3 hrs.  Lisa called the doctor and we went to the hospital.  After a bit of diagnosis, it was determined that they would need to operate and her appendix would need to be removed.  Luckily, Lisa had her wits about her enough to call in the first place.

It turned out that she did indeed have appendicitis; it was literally on the verge of bursting.  That would have been very bad - especially since she's more than 25 weeks into the pregnancy with baby #4.  The doctors were saying that if she hadn't had her appendix removed it undoubtedly would have caused her to enter a premature labor and miscarry.

We are very blessed that she is ok and currently recovering.  We hope to have her home from the hospital tomorrow or Wednesday at the latest.

Monday, January 10, 2005 5:04:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Thursday, January 06, 2005

What with my 'nerd fest' on Dec 31st, I've been dying to know just how nerdy I really am.  It turns out that I'm just a part-nerd, though I am proud to say that it took lots of hard work to reach that distinguished level.

I am nerdier than 74% of all people. Are you nerdier? Click here to find out!
Thursday, January 06, 2005 12:27:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, January 04, 2005

Well, I knew this day would be here, sooner rather than later.  Microsoft has come out with a PC version of Settlers of Catan, the award winning and thrilling game by Klaus Teuber.  In all honesty, when I found out about MS's endeavors in this area a few months ago I had some moments of depression and despair because I (along with a few friends) have been working pretty hard on a version of the game for about 10 months in our spare time (that is, 1 night a week) and have made great in-roads to its completion.

Well, when I found out today that it had already been released, I had to give it a try, so I downloaded it.  Upon playing it for a while to test it out I can honestly say I was pleased.  Pleased that the one we've been working on is far superior.  It is both graphically superior as well as much more engaging.  I find that the MS version drags (a lot) especially in the Trade dialogs - there's no tension or aggravation or banter - aspects of the real board game that we've worked hard to bringing into the game.  That said, however, there are some things that I think they did well and others not so well.

The Trade window, while slow and tedious, is difficult to get used to...I had to read it over and over and over again before I would initiate a trade because I was never really sure what I was giving and what I was getting.  There is no feedback on the window, so you have no idea what the other players are doing.  Even then I'd miss out on a trade while making sure I knew what I was giving up because of a built in timer that seems to expire automatically without any warning.

I like how the player list appears on the right side - it consolidates the information nicely and is quickly readable.

When hit by a robber the dialog is not intuitive at all...I ended up getting rid of cards I didn't want to drop and I could never recover in the game.

With respect to our spin-off (which isn't quite the same game, but very close in some respects), I'll keep everyone posted on our progress and make the bits downloadable once completed.  Thanks, Microsoft, for not overdoing it and making my despair and discouragement moot points. :-)

Tuesday, January 04, 2005 8:42:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [21]  |  Trackback
 Saturday, January 01, 2005

12-0!  Utah finished a spectacular year winning the Fiesta Bowl against Pittsburgh who was obviously outmatched.  Utah beat them 35-7, but I feel the score wasn't very indicative of how much Utah dominated.  They sacked the Pittsburg quarterback for a record 9 times.  This was especially sweet, not so much for the convincing win (which might propel them in the rankings to 2 or 3 when all is said and done), but because I went to the University of Utah for several years and have strong ties there.

Go Utes! We will miss you Urban!

I love football!

 

Saturday, January 01, 2005 3:21:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, December 31, 2004

New Year's Eve was a good time!  We had over several friends over for what my brother affectionately called a 'Nerd-fest'.  In fact it was more of a Lord of the Rings marathon.  Ever since these movies came out we've been wanting to watch them back-to-back-to-back, but time and energy have never been on our side.

Yesterday, however, we got together at about 12:30 PM and started in on the extended versions.  It was a blast, though I can honestly say that I've NEVER sat and seen that much TV in a day, much less in a week.  Had we not taken a break that lasted for about 10 minutes, I think we would have finished the movies at 12:00 AM on the dot.

Despite today's complete lack of exercise, we had a good time with friends and I plan on never ever doing that again - it's just too much TV - even though they are the my favorite movies of all time.

Friday, December 31, 2004 5:47:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback