Showing posts with label Development. Show all posts
Showing posts with label Development. Show all posts

Tuesday, July 3, 2007

Cursed Enums

When you're writing code using an object model, everyone likes to point out the obvious benefit of developing using enumerations.  The problem is that the database probably has certain values that represent the values of your enums.  How to convert between the values and the names?

public QuoteStatusType QuoteStatus
{
    get
    {
        return (QuoteStatusType)Enum.ToObject(typeof(QuoteStatusType),int.Parse(CurrentRow["QuoteStatus"].ToString()));
    }
    set
    {
        CurrentRow["QuoteStatus"] = (int)Enum.Parse(typeof(QuoteStatusType),value.ToString());
    }
}

Thanks C# Station

Wednesday, June 27, 2007

Who Writes the Program Here, Anyway?

 The diagram to the left represents a very simple quote.  Each quote contains multiple lines of business, lines of imagebusiness contain products.  Easy enough.  If the quote header is in a state which renders it read-only, however, none of its children should be editable either.

Faced with the challenge of making this work yesterday, I am ashamed to say I almost gave up.  This object model is easy to understand and manipulate, but when mapping to a database the object model begins to crumble.  This was exacerbated by some very early design decisions in our back-end library.  Our design revolved heavily around run-time modifications.  If a vested party asked for a new field on a screen, we wanted the ability to add the field at run-time.  We used business objects to implement business rules.  These objects represent tables and inherit from a single source.  At runtime we can change the BO for a selected table using reflection.

This approach uses the tenets of object oriented programming in working with and representing tables of information.  It does not allow for modeling of objects as represented in the figure above.  Everything was peachy until I got stuck between large releases.  The release version of the configuration file would continue to get out of sync with the development version.  I switched the model a bit, and now runtime changes can be saved...but they must be compiled into the main executable.  I lost my ability for runtime modification, but I still didn't have to design 80+ individual screens at design time.  I can drag fields around at runtime and save my changes.

Back to my problem from yesterday.  In order to determine the state of a quote header at the product level, I would have to find two queries in the configuration file, execute them, and then use the results to determine if the quote was editable.  What a pain.  Worse, if someone unwittingly changed the configuration, this subtle piece of code would stop working. I almost threw my hands up in desperation.  Perhaps I would make it impossible to drill into a quote that was read-only.

Then I started to realize some things.  I'm the coder, not the library of functions.  Runtime design is high maintenance for the reasons I just mentioned-there are very few compile time sanity checks.  Why not use application resources to associate business functions with stored procedure names and descriptions, and then create a stored procedure executor?  Then I could have the compile time checking I need, and the flexibility I crave!  I did it, it works, and it works well.  More importantly though...I realized that version three of our library needs to be designed around a real object mode, not a "sort of" object model.  The very reason I didn't like my own library is the very reason I don't like other libraries: lack of flexibility.  Finally, in order to make my new vision work...I'm going to need to change my coding habits.  I've been breaking the rule of designing to interfaces instead of classes.  Now I've got a bunch of display classes that only work with SetTableBO instead of something more flexible like iSetBindable.

Wednesday, May 30, 2007

RSS Keeps Getting Better

I have to admit, when RSS came out I wasn’t really very impressed.  Sure, at dinner parties I would jump on the bandwagon and proclaim the merits of RSS without actually believing.  When RSS feeds started showing up major websites, I perked up and paid a little more attention.  In FireFox, I actually started using RSS for news feeds.  That was really great because I no longer had to actually visit a site to see that there wasn’t anything there worth reading.

 

DevTeach taught me how much I don’t know.  The problem is, how can I keep up on all this information?  The next time I go to a conference, I’d really like to know a lot more going into the conference.  It was really very intimidating to be referred to as “Fly Catcher”.  In order to maximize my ability to learn new items, I decided to grab RSS feeds from all the presenters at the conference, as well as other development feeds.  That worked great, I got about thirty feeds to work with.  Using FireFox I started running into another problem.  How could I get a list of only the updated items, or perhaps only view items by category.

 

Enter: RSS Bandit.  RSS Bandit is an open source RSS aggregator that, for the most part, does a great job of check feeds and presenting new entries in an easily useable list.  Rolling down a single list of entries makes it much easier to find that one piece of information that I couldn’t find before.

Thursday, May 17, 2007

Develpment Blues

When Eric hired Carl to teach me .Net and help develop a framework, neither Carl nor myself had any idea what we were in for. Carl aptly suggested using business objects, and he pointed out that the binding object was a great place to start. We continued on our merry ways, until we realized that designing screens at design time might be a bad practice in our environment. At first we discussed dynamic screen design, but then decided against it as the layout would be difficult to get right each time.

As it turns out, we ended up using this exact paradigm. We also included our database select strings, and information about how data should be presented and validated. This allowed us to change any facet of an application at run time. No recompilation worries there.

Things aren't so simple now. Changes to the database get requested between code releases, and these changes can get incorporated into one configuration, but not another. This has caused me to question the wisdom of the approach that Carl and I took. This week at DevTeach has offered me an opportunity to once again question our approach. How better might I do things? There are some things I would do differently. I might migrate to pluggable, dynamically loaded objects to represent rows in a table. Validation would move into these objects and out of the config file. These objects should also be nested to reflect a schema.

At the end of the day, though, it still makes no sense to design each screen individually. Our design metaphor is still valid. The only problem is how to integrate changes to the live configuration (I can change a lot of screens without touching any code!) into the next development release. I designed a tool for combining configuration versions. It still needs some work, but it does its job. Carl had the knowledge, and I lacked the knowledge...which made it possible for me to ask why we would build each screen, bind each control, and fill each label.

The next iteration should have strong typing. Why? Because strong typing makes more robust code. We need intermediate objects to represent individual items, before they are aggregated into tables. That's where validation belongs. That's where schema should be represented. The bindingsource shouldn't update and validate, it should ask its constituent objects to do that.

The best part of all? The atomic elements become fields. At the record level, objects aggregate fields. Let's let the fields tell us how they should be represented. When I'm done tearing everything out of the configuration and placing it in intermediate objects, who knows...maybe the configuration will become manageable again!