Blog Stats
  • Posts - 62
  • Articles - 1
  • Comments - 26
  • Trackbacks - 64

 

Monday, January 08, 2007

No Mo Here

No blogs are getting posted here...update feeds to http://blogs.chayachronicles.com/sonofnun/Rss.aspx or swing by the site at http://blogs.chayachronicles.com/sonofnun/Default.aspx. See you there :) MIKE

Wednesday, October 04, 2006

Moving Day - Feeds, Update Thineselves (both of you)

We've moved

New blog found here at http://blogs.chayachronicles.com/sonofnun/Default.aspx

RSS is here at http://blogs.chayachronicles.com/sonofnun/Rss.aspx

Thanks to GWB for parking me here for a spell :) MIKE

Saturday, September 30, 2006

When Design Decisions Aren't

I've been working exclusively alone on a project for a while and have as much liberty as any developer could hope for. I'm a blessed man. Nonetheless, I have tried to kind of "pretend" like I am working in a team environment that has regimented deadlines. This is mostly due to integrity and partly due to prevention for laziness...how easy is it to constantly be researching solutions without implementing them?

There was a necessary period of growth in skill sets that had to occur and while I certainly haven't 'arrived' at some point the rubber has to hit the road and instead of striking out to google for an answer first, there must be some confidence on the toolkit that has been developed. A car has to at least be moving before turning the wheels even in the right direction will make any difference.

So design decisions whether regarding overall architectural structure or about simple object creation aren't strictly design decisions, but are really business decisions. Maintainability is almost at the top of my list for development ; partly because it's just fun to meet the challenge, but also because I work alone and I could be buried with feature requests if I am not careful to write robust, scalable code. Still, this goal has a way of stalling design decisions if you're not careful.

Realigning my thinking into Test Driven Development has largely stumped this phenomenon. Most importantly because TDD isn't about the tests, but meeting requirements in a iterative, thoughtful way.

An example of this came up for deciding how I am going to query my DB using NHibernate as my OR/M. Now, I am using an IRepository for controlling access to the NHibernate implementation of data access and this brings along a whole sweet suite (excuse me) of tools that are a snap to use. I need to create Query Objects to get the data I need in my domain, but do I really want to wrap so much that NHibernate already does for you? For example, do I need to wrap every ICriteria implementation with my own custom implementation to avoid the dependency on NHIbernate's API?How far does one take isolating a domain from specific implementation of these tools?

There seem to be at least three options:

  • Have more specific IRepository<T> implementations that expose methods like "GetCustomerByNameAndGender(string name, Gender gender)", perhaps in CustomerRepository:IRepository<Customer>
  • Create an Object Query language as I go that accepts calls maybe with fluid interface calls like .Where(PropertyName name) and so on
  • Respect the Single Reponsibility Principle and use NHibernate's API within the Domain, but only within query objects.

The first option really just moves the complexity into different area. Maintaining a million little methods really misses out on the joys of Object Oriented thinking where you can treat tasks as things and have adaptable code. The second option is tempting at first, but this is where the business man in me has to speak up and question the wisdom in this route. Do I really want to write a parallel Object Query language just for the sake of independence from an external tool's API? I think this is called "not created here" (or something like that) syndrome, right?

So, after weighing my options, I very simply refactored my implementations of IQuery<T> to use the rich NHIbernate API and my Domain Entities use these objects that fill a collection of ICriteria objects, IProjection types and so on. MY IRepository<T> accepts any object of type IQuery<T> and returns the results I need. If I ever need to switch to a different OR/M provider I'll have to write implementations of IQuery<T> that speak that ORM's language. Really, if I am making that kind of change to an application, this level of adaption seems acceptable.

One tool that can keep these changes from affecting my service layer is some kind of Dependency Injection container that gets the appropriate instance for me at runtime. So instead of instantiating IQuery<T> implementations directly from, say, a higher service layer, I can invoke Castle or Structure Map or whatever to get the instance that I configured. These kinds of tools are perfect for these situations.

OK ...back to coding.

Friday, September 29, 2006

Isolating NHibernate Logging

I am sure everyone else has already figured this out but thought I'd jot it down here.

I wanted to isolate all messages being sent from NHibernate to its own logging file. NHibernate has lots to say during its operations and often the messages it delivers are the only way of tracking down some obsure error since sometimes the exception messages in NHibernate are...well, wanting. After poking around the forums and trying out a few methods, here is how I finally split my NHibernate logs from the rest of my application logs.

The Configuration

For simplicity, say I want just two log text files produced, system.log and nhibernatelog.log. Look over the log4net configuration and Ignore the Console and AspNetTraceAppenders below:

  <log4net>

    <appender name="Console" type="log4net.Appender.ConsoleAppender">

      <layout type="log4net.Layout.PatternLayout">

        <!-- Pattern to output the caller's file name and line number -->

        <conversionPattern value="%5level [%thread] (%file:%line) - %message%newline"/>

      </layout>

    </appender>

    <appender name="AspNetTraceAppender" type="log4net.Appender.AspNetTraceAppender">

      <layout type="log4net.Layout.PatternLayout">

        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>

      </layout>

    </appender>

    <appender name="NHibernateAppender" type="log4net.Appender.RollingFileAppender">

      <file value="../../../log/nhibernatelog.log"/>

      <appendToFile value="true"/>

      <maximumFileSize value="1000KB"/>

      <maxSizeRollBackups value="2"/>

      <layout type="log4net.Layout.PatternLayout">

        <conversionPattern value="%date %level %thread %logger - %message%newline"/>

      </layout>

    </appender>

    <appender name="SystemAppender" type="log4net.Appender.RollingFileAppender">

      <file value="../../../log/system.log"/>

      <appendToFile value="true"/>

      <maximumFileSize value="1000KB"/>

      <maxSizeRollBackups value="2"/>

      <layout type="log4net.Layout.PatternLayout">

        <conversionPattern value="%date %level %thread %logger - %message%newline"/>

      </layout>

    </appender>

 

    <root>

      <level value="ALL"/>

      <appender-ref ref="AspNetTraceAppender"/>

      <appender-ref ref="Console"/>

    </root>

 

    <logger name="NHibernate">

      <level value="ERROR" />

      <appender-ref ref="NHibernateAppender"/>

    </logger>

    <logger name="NHibernate.Loader.Loader">

      <level value="INFO" />

      <appender-ref ref="NHibernateAppender"/>

    </logger>

    <logger name="System">

      <level value="ALL" />

      <appender-ref ref="SystemAppender"/>

    </logger>

 

  </log4net>

The primary points of interest are:

  • I do not have my SystemAppender or my NHibernateAppender inside the <root /> element. Doing so resulted in duplicate entries
  • The 'name' attribute on the <logger/> element is important. Take note.

Start 'er up

To get things wired up when the application starts, add this to your global.asax in the Application_Start section:

            log4net.Config.XmlConfigurator.Configure();

Logging to 'system.log'

To get a reference to my 'system' logger, i just have to use the following:

        static ILog logger = LogManager.GetLogger("System");

Notice that I am referencing the logger by its name ("System") in the <logger/> section above. Then to write out to the file, just this:

            logger.Debug("Writing Debug Message");

Logging to 'nhibernate.log'

The important thing to understand about controlling logging for NHibernate is that it writes using the following call:

LogManager.GetLogger( Type or string )

Check out this forum post for an explanation of the implications. I snagged the 'logger' setup from this post.

What this means is that the <logger/> element in the configuration will need to have its 'name' set to 'NHibernate' since that is how it is called...any other name NHibernate just won't recognize and logging won't happen.

Note, too , that the configuration above is only logging the SQL (NHibernate.Loader.Loader) sent to the DB and error messages. This helps sift out the rif-raf that I am not real interested in usually.

Once these have been all set up I was successfully logging to the right file. Here are the posts that helped me:

Sunday, September 24, 2006

NHibernate Class Mapping With Generic Parameters

I needed to implement a component that uses generic parameters. Documentation is sketchy on NHibernate so thot I'd jot it here. I *stole* an IRange implementation from someone and needed to use it for a date range within a class.

    <component name="DateTimeRange" class="Cei.eMerge.Common.Range`1[System.DateTime], Cei.eMerge.Common" access="field.camelcase-underscore" >

      <property name="Start" access="field.camelcase">

        <column name="StartDate" not-null="true" />

      </property>

      <property name="End" access="field.camelcase">

        <column name="EndDate" not-null="true"/>

      </property>

    </component>

Note the `[genericTypeParameter] syntax. Here's how we map it. Be sure you have a default constructor! The exceptions thrown by NOT having a default constructor are riddles at best.

Tuesday, September 19, 2006

NHibernate Parameters and Escaping Special Characters in HQL

I am sure I everyone else knows this by now, but I wanted to jot a note. When you are passing strings to an HQL query, it's best practice to assign those strings to a parameter (named or positional) and let HQL escape the special characters for you. So it would look like this when searching by a Name and Distinction tag on an Entity:

            StringBuilder queryString = new StringBuilder();

 

            queryString.Append("from Entity e where e.Name= :name AND ");

            queryString.Append("e.DistinctionTag = :distinctionTag ");

 

            try

            {

                query.Match = Session.CreateQuery(queryString.ToString()).SetString("name",query.Name)

                                  .SetString("distinctionTag",query.DistinctionTag).UniqueResult() as IEntity;

            }

            catch (NonUniqueResultException)

            {

                query.Match = new NullEntity();

            }

            return query.Match;

The call to .SetString() is where we assign our parameters to our string values. This works for matching Custom Classes and even Custom Type Properties as well. Sweet.

Further Info

Thursday, September 14, 2006

Patterns, voicings, and rudiments

For the first 14 years of my professional life, I was a touring musician with a Master's in Music Performance in percussion. By the grace of God, I've been moved along into a fun profession of Software Development. For the most, I've been a lone ranger and have had to learn everything on my own, which is fine since I enjoy problem solving. As I've matured (ok..I am still in Beta :)) in my 'skills' - not the numbchuck kind - I've seen many parallels to music composition/arrangement and development. This isn't a new idea I know, but one struck me tonight.

I needed to add a new field to distinguish records on an object. Now, in the past I'd add the field int the Db and then have to think about ALL THE PLACES I HAVE TO ADD IT and any functionality to accomodate it. This simple requirement COULD break my whole dang domain if I had built spaghetti code. However, as I've built my domain, certain styles and patterns have emerged that let me ALMOST be mindless in solving problems like these. Since I had implemented solutions using certain software patterns, I could simply look into the domain and let IT tell me how to code. Kind of a pattern-of-patterns thing.

A parallel to this in jazz piano is voicings on a keyboard. Pianists like Bill Evans, McCoy Tyner (tho I shudder to put them in the same sentence), Red Garland and so on voiced chords in their unique way, but did so usually from a common way of thinking about how a chord SHOULD be voiced. Voicings, by the way, are the notes you select to play a type of chord...so McCoy might leave the third out to get a kind of earthy sound, but Evans might add upper partials to a chord to give more of a shimmer. The point is, IT'S THE SAME CHORD but they have a bag of tricks to drawn on so they don't have to freak out everytime a new chord comes along.

Patterns in software are like that I think and actually make the process of development more fun. Not because you can use fancy terms .. they are just ways to solve problems. But in the end, I feel like I have expressed something in a way I WANTED to express it, as opposed to throwing datasets all over the place and then feeling lucky that I just got the data back and forth to the user.

Wednesday, September 13, 2006

Builds that make my eyes bleed and the assemblies that cause them

Lately, my ASP.NET 2.0 app has been taking so long to build I have been going crazy. I came across this post at ScottGu's blog that had a possible cause for suddenly long build times. I have about 20 projects, but it's hardly a massive site.

I had some problems that I just kind of put up with a while ago where an older version of Iesi.Collections.dll would appear in my /bin folder of my web root and I have been running the NHibernate alpha 9that uses version 1.0.0.2 of Iesi.Collections). Anyways, it didn't occur to me that this was cuasing the problems ScottGu is discussing in his blog. But I couldn't track down WHO was bringing in the wrong assembly. Finally, I remembered that some code was using Ayende's NHibernate.Generics ... AHA! This was built against the older Iesi collections assembly so that was the culprit.

So since I am moving to the new NHibernate that supports generics anyways, I yanked all the references and code out that use the NHibernate.Generics library and my build times got back to normal and my sanity has slowly begun to be restored...

Tuesday, September 12, 2006

Validation With Bows and Arrows or With Battle Axes and Swords?

One of the things that requires a realignment in thinking when moving away from RAD development tools as a means of solving business problems into a Domain Driven approach is where to put validation and how to provide meaningful messages back to the user when something goes wrong.

It seems to me that a good indicator of an anemic strategy for validating data is lots of work being done with validation controls and checks at the presentation (view) level. That doesn't mean that careful validation and thoughtful strategies at this layer are useless, but rather we shouldn't DEPEND on this layer to guard our datastore from bad data. Personally, I love using Peter Blum's Validation Controls for my web pages because he has taken great pains to create a rich set of controls that do one thing VERY well...validate at the client-side. Still, before I implemented a rich validation scheme across my layers in my app, I was spending TOO MUCH time with these controls to do work that belonged in the Domain Layer.

A neat approach to validating entities in the Domain layer can be found on JP Boodhoos site where he has a thorough explanation of a kind of reactive validation scheme. It's simple and easy to implement as well as flixible, should you want to apply different rules on the same entities.

After being careful in validating data and implementing strategies in the 'lower layers' I discovered that I had to do very little to guard my user's input from garbage data. All of a sudden, I didn't have to have a ton of validation controls checking conditional comparisons or making sure data was complete before posting because the thoughtfulness that was applied to the domain layer bubbled up to how I designed my User Interface strategy.

So for me, when I find myself having to accomodate complex rules in the User Interface, I need to take a step back and see if there is some insight in the Domain Layer that i haven't gotten yet...for example,

  • Is there YAGNI lurking in my design that might simplify things vertically across the layers?
  • Did I let my own business specs creep in, or are my requirements actually coming from the stakeholders?
  • Am I building my User Interface TOO SOON? Maybe I need to understand my domain better if I am adding and deleting controls like crazy.
  • Am I relying on textboxes with elaborate javascript do things that CODE should do in the layer beneath?
  • These are good questions to ask when i am sticking a million validation controls on my page.

    I kind of think of clientside validation like the guys with the bows and arrows on top of the wall around the city when the Orcs are marching in with their bad typing skills. They can take out quite a few of the bad guys, but really the heart of the protection is going to take place by the fellas in the Domain layer with their swords and magic wands. The women in my database are relying more on the guy with the battle axe than the guy with the slingshot.

Monday, September 11, 2006

I'm sure I don't get it about the ObjectDataSource control

I guess I'm confused about the ObjectDataSource control. the SqlDataSource control is a non-issue for me since I'll *never* build an app that puts a view dependency on my database schema, but I see alot about the ObjectDataSource control in the Nhibernate forum.

It's been a while since I actually wrangled with the ObjectDataSource control since I didn't see what advantage trying to get it to wireup to my model this extra control would bring to the table. What is so different about simply binding to a Repeater control? Two-way binding I suppose is the answer, but typically I communicate with a service layer on top of my domain entities since I rather protect my domain entities from upper layers, so by the time i get done wiring up the CRUD events in these new ASP.NET 2.0 controls, did I save time from simply iterating over a repeater and passing the values to the appropriate service for processing?

I'd love to see know what I'm missing since so many developers seem to be spending time extending these controls that, at least from what i can tell, expose an app's Domain layer to bad practices and creates rigid dependencies between the view and it's data source.

What you tink sensei?

Saturday, September 09, 2006

Visitor Pattern For DataBinding ListControls with Model View Presenter

Implementing the Model-View-Presenter has been fun. I appreciate it's tendency to enforce discipline in keeping any business decisions out of the View layer. I was always bewildered when I would read that the business logic should be separated from the 'code-behind' source and then see millions of DataSet examples where that was tons of business logic embedded in Web Pages.

However, trying to separate the presentation logic away and keep the client as dumb as possible presents (forgive the pun) some new challenges. Keeping the presenter interacting with only the interfaces of both the IView and IFacade (or IService or whatever...IModel) is straightforward so long as basic property setters and getters on the view are the requirements. But when you get into nested collections within collections AND want to keep the client dumb, then it is time to reach into the patterns hat for a solution.

Specifically, I wasn't sure how to have the Presenter authoritative for logic decisions while still keeping the DataBind() calls in place on my DataSource controls (like a Repeater). My first reaction is to create a kind of 'placeholder' property for the DataItem and have that iteratively set during binding for processing in the Presenter layer. For example, perhaps a different list in a dropdown list needs to appear BASED ON WHAT THE DATA ITEM IS. I want my presenter to inject the correct list, but how to do that during binding?

A refactoring has emerged that I'll call Replace Placeholder Property With Visitor. The Visitor pattern is well-suited to exactly this kind of databinding dilemma. No doubt, some will think it's heavyhanded, but I have found it elegant and keeps responsibilities between the view and presenter where they belong.

To start, say we have Person we want to edit that has a collection of Addresses. We want to bind a Repeater control on a collection of Labels so that for each label, we have a blank Address form. Within each address form, we have a drop down list of StreetTypes (Rd, St, Ln, etc). So it looks like this.

To use the Visitor pattern to inject the list of StreetTypes into the DropDown list, we'll abstract away the contracts and have the actors only deal with those. First, the ISaveAddressViewItem interface This will live in the Presentation project so the Presenter will interact with any implementation of it. Before creating that let's have it inherit from a more generic interface (explain later):

    public interface IViewRepeaterItem

    {

    }

Ok, now let's create the contract that has the property names we expect.

    public interface ISaveAddressViewItem:IViewRepeaterItem

    {

        string Label { get;}

        string SuiteApartment { get;set;}

        string PostalCode { get;set;}

        string StreetField1Value { get;set;}

        string StreetField1StreetType { get;set;}

        string StreetField2Value { get;set;}

        string StreetField3Value { get;set;}

 

        IList<StreetTypes> StreetTypes { set;}

 

 

    }

Next, let's create a custom RepeaterItem that will implement this interface. We'll put this in its own project where we create our other custom controls (NOT App_Code!):

    public class SaveAddressViewRepeaterItem : RepeaterItem, ISaveAddressViewItem,IViewRepeaterItem

    {

        public SaveAddressViewRepeaterItem(int itemIndex, ListItemType itemType) : base(itemIndex, itemType)

        {

        }

 

        public string Label

        {

            get { return ControlUtil.FindFirstControlById<System.Web.UI.WebControls.Label>(this, "Label").Text; }

        }

 

        public string SuiteApartment

        {

            get { return ControlUtil.FindFirstControlById<TextBox>(this, "SuiteApartment").Text; }

            set { ControlUtil.FindFirstControlById<TextBox>(this, "SuiteApartment").Text = value; }

        }

 

        public string PostalCode

        {

            get { return ControlUtil.FindFirstControlById<TextBox>(this, "PostalCode").Text; }

            set { ControlUtil.FindFirstControlById<TextBox>(this, "PostalCode").Text = value; }

        }

 

        public string StreetField1Value

        {

            get {return ControlUtil.FindFirstControlById<TextBox>(this,"StreetField1Value").Text; }

            set {ControlUtil.FindFirstControlById<TextBox>(this,"StreetField1Value").Text = value; }

        }

 

        public string StreetField1StreetType

        {

            get { return ControlUtil.FindFirstControlById<DropDownList>(this, "StreetField1StreetTypes").SelectedValue; }

            set {

                ControlUtil.FindFirstControlById<DropDownList>(this, "StreetField1StreetTypes").SelectedValue = value;}

        }

 

        public string StreetField2Value

        {

            get { return ControlUtil.FindFirstControlById<TextBox>(this, "StreetField2Value").Text; }

            set { ControlUtil.FindFirstControlById<TextBox>(this, "StreetField2Value").Text = value; }

        }

 

        public string StreetField3Value

        {

            get { return ControlUtil.FindFirstControlById<TextBox>(this, "StreetField3Value").Text; }

            set { ControlUtil.FindFirstControlById<TextBox>(this, "StreetField3Value").Text = value; }

        }

 

        public IList<StreetTypes> StreetTypes

        {

            set

            {

                DropDownList list = ControlUtil.FindFirstControlById<DropDownList>(this, "StreetField1StreetTypes");

                if (list != null)

                    list.DataSource = value;

            }

        }

 

 

    }

Before we look at the Repeater that will consume this, let's look at the contract for the Presenter that the ISaveAddressViewItem's parent will interact with during databinding

    public interface IPresenterVisitor

    {

        void PostVisit(IViewRepeaterItem item);

        void SetItemVisit(IViewRepeaterItem item);

        void LoadItemVisit(IViewRepeaterItem item);

    }

Now let's look at the Repeater control (also in the Class project, not in the Web folder) we create to bring the IViewRepeaterItem and IPresenterVisitor together. We need to tell this somewhat generic repeater control what kind of custom RepeaterItem to instantiate in order to get our implementation, so quick and dirty I add a ItemType property that I can declare in the aspx form. We also need to tell the Repeater control who the Presenter is that implements IPresenterVisitor. Finally, we need to override certain events to wireup our conversation between the View and Presenter during binding. This is where the visitor pattern shines.

    public class