Want to follow this site? Here's the RSS feed.

Coders and Professional Programmers

Saturday, August 18, 2007

I have to say it: there is a severe lack of skill in the technology world today, even among senior-level developers.  Perhaps I just have too high of standards, but when I see a person working in technology, I kind of expect them to have the requisite skill set for the job.  It always amazes me when I see a developer, even a senior-level developer, who doesn't know the basics of their own system (i.e. an ASP.NET developer who doesn't understand CSS positioning or a .NET developer who doesn't understand the framework design guidelines).  They may have degrees and have years of experience, but they have no actual skill.  It's always concerned me a bit that people have so little skill, but I wasn't able to put the problem into words until recent.  Well, that's not completely true.  An old friend of mine put it into words years ago, but it wasn't until this week that I was reminded of my own story.

Last week I was in a bookstore looking at a few design patterns books and a "1960s NASA engineer" type of guy in a white shirt and tie came up next to me, dressed in extremely casual blue jeans and a black shirt, looking at similar books.  I noticed he picked up a rather lame design patterns book, so I took it upon myself to hand him the GoF book saying "This one is the classic".  He thanked me and started to flip through it.  A minute later I realized that I couldn't resist asking: "So, what exactly are you looking for?"  He mentioned he was looking for a book demonstrating a state machine.  I grabbed another book, flipped the pages a bit and handed it to him saying "page 486".  His response was "Wow, thanks... so, where did you go to school?"  I have to admit that I've gotten many questions in bookstores, but I've never been asked that one FIRST.  The way he asked the question wasn't so much out of sincere curiosity, but more out of arrogance.  It felt like wanted to compare his degrees to my own.  I simply replied "School?  What?  You're looking at it...", pointing to the wall of computer books.  He immediately shut up and stepped away.  I'm not sure if that qualified me as a leper or if I just castrated the man's sense of academic accomplishment, but, regardless, that conversation was over.  However, a few moments later I found a book I was looking for and said "AHA! This will make them think!"  The same man curiously asked "What do you mean?"  I explained that I was looking for a book to recommend to developers to help then get a clue about software architecture.  The man gave the look of familiar with my situation and said something I haven't thought about in years: "Oh yeah... I know exactly what you mean.  Some people just don't get the difference between a coder and a professional."  At that point I had my flash back to a time of my life almost 6 years earlier... back when I was a coder.  It was a lifetime ago and I had all but repressed until recently.

The year was 2001 and I was a PHP programmer, Linux hacker and Math major at Kansas State University.  My idea of programming was looking at the PHP documentation, reading the PHP documentation comments and copy/pasting until my application was built.  I figured I knew what I was doing because I had already been in the field for 5 years; I was only now going back to school after a 3 year academic hiatus.  I would mix PHP, HTML, JavaScript, and tiny bits of CSS all in the same page in an absolutely unreadable pile of slop, "but it worked".  A friend of mine from high school, who by this time was a Microsoft employee, looked at what I was doing and mentioned to me in his usual blunt style: "Dude, that's not programming, that's slop coding.  You don't even have a data access layer, do you?"  Completely ignorant of the first clue of what he was talking about I said "Well, sure I do, PHP has a connector to mySQL.  I'm not accessing mySQL directly; I'm using the PHP API."  Thinking back on it I think he wanted to punch me in the face from that painfully ignorant comment."  Truth be told, I was not a professional programmer even though I had 5 years of crazy JavaScript development, 2 years of Ajax development, 2 years of ASP development, 2 years of SQL Server development, and 1 year of PHP development under my belt; I was only a coder.

After that, I spent a tremendous amount of time going back to the books and learning more about technology.  In high school I had some of the lowest grades in my classes because I spent my nights reading video game programming,  graphics programming, C/C++ programming, computer history, networking theory, Novell NetWare, and web development books.  In college, the pattern was being repeated in a the same familiar way.  I spend a ton of time studying all kinds of new technologies, one of which being XHTML/CSS design, all to the destruction of my meaningless academic career.  After finally breaking free from the tight bondage of academia I went to work for a few places as a PHP developer.  After one of two complete waste-of-time contractor positions I finally realized that it was time to cross over to .NET.  So, I spend an incredible amount of time studying .NET concepts, ASP.NET, the Framework, and C# technologies.  After a month I took and passed the 70-315 (ASP.NET) exam and the 70-229 SQL Design exam a week later.  From there I went to study the 70-320 (.NET components) and 70-228 material (SQL Administration).  Around that same time I realized that Mozilla finally released a product that didn't suck.  Not only did this product not suck, it was by far and away the most revolutionary piece of technology since the Internet itself: Mozilla Firefox 1.0.  With that I also started studying web standards much more deeply.  Being former Linux hacker, I wasn’t and still am not brained washed by the Microsoft extremist cult, so I've always been open to having the best technology regardless of vendor.

At this same time I realized that I really, really wanted to be a professional programmer and not a coder in any way.  So, I said goodbye to Visual Studio and took back my EditPlus to do all my .NET work.  I was not about to rely on Intellisense to do my work for me and already knew the danger of learning a new technology by error messages.  For the next year I deliberately did all my development without color syntax and without Intellisense.  I've never had any respect for "drag-n-drop" property developers, so I never used the designers anyhow, but now I wasn't even going to let Intellisense help me either.  If I needed to do something, guess what, I had to actually read the manual.  There would be no copy/paste slop coding and no hitting the forums every single time I hit the slightest bump.  If I had a problem, I would think about it and solve it using that technology, not simply a hack to throw some hack together.  I had enough years of wasting my time doing that.  Yes, at first, this got me into trouble, but I was determined to be a professional programmer at any cost and not a coder at all.  I wanted to internalize the systems as I had internalized driving my car.  After the initial slowdown (and the initial "being let go" from a project), I became much faster than all the other developers from the forced memorization of much of the documentation.  Whereas others had to look up how to use the Sqlconnection, SqlCommand, SqlDataAdapter, and DataSet combination, I was typing them out as if I were writing a sentence.  Around the same time I spent much time studying LLBLGen Pro, unit testing, object-oriented design (not to be confused with the entry-level concept of object-oriented programming I learned 10 years ago in C++), N-tier architecture, Modern JavaScript, and a year after that I took a block of time to study web services, MSMQ, COM+, service interop, and other communication mechanisms (most of which were later rolled up into WCF) all to the point of either complete or partial internalization.  In 2005 I was finally able to say that I am a professional programmer, not simply a coder.

As you can see from my story I know what it’s like to be a coder and I know the temptation to remain as a coder.  You think “your way” works and therefore you shouldn’t change it.  In fact, you probably hate other technologies, because their way isn’t "your way".  I can understand that too, but really it’s just a misunderstanding of that other technology.  My first ASP.NET application (a photo gallery) had absolutely no declarative code and was written with 100% Response.Write statements (I often tell people "make sure your first project in any technology is NOT a production one"; this is why).  I didn’t have the first clue what I was doing and, being a longtime classic web developer, I could not get that “magical” ASP.NET postback through my head.  Building that same application today would consist of an elegant ASP.NET custom control and two or three web forms.  I also understand what it’s like to say “...but this is how I do it in this other technology”, when in a reality that’s a completely meaningless statement.  Each technology has its own paradigms, naming schemes, guidelines, concepts, and languages.  Just because you are a Java rock star, doesn’t mean you will be able to do anything in .NET for at least 6 months.  The same goes for VB rock stars and PHP rock stars (as odd as it sounds, in my experience PHP developers have the hardest time learning .NET where as VB developers excel rather quickly-- this goes to show how hard it can be to un-link and old technology from your mind). I also know what it’s like to ask yourself “how can I do this?”  That’s what a coder asks where as a professional asks “How has this been built before in this technology; what is my precedence?”  In case you didn’t know, software development has been around for decades.  If you are running around trying to come up with a way to do something, you may be wasting your time as it’s probably been done before, the debates have probably already happened, people have probably already learned from their mistakes; you just have to accept what they've done for you, within limits, of course (i.e. C++ design patterns transfer to C#, but obviously not OOP style as .NET doesn’t allow multiple implementation inheritance).

So, if you find yourself in a place where most of your development is done doing things “your way” or the way “you have always done it” or if you ever ask “how can I do this”, maybe it’s time to break down and take some time out of your life to convert from being a coder to a professional.  It is definitely an investment, but with many great books out today (not all are so great), you could probably convert from being a coder to some level of professional programmer rather quickly (it took me a bit longer because I didn't have any role models to work under and I had no idea what the scope of the training was). There is an old computer science saying that goes something like this: "Anyone can write code that a computer can read, it takes a professional to write code a human can use."  We should all think about that and possibly post it on our walls.

To aide in the process of converting from a coder to a professional programmer, a few months ago I wrote up my requirements for a Senior-Level developer or Architect on my blog.  It should give you a shell outline for some of the technologies and topics you seriously need to have under your belt to be a professional.

(6 Comments)

Fast Visual Studio 2008 Beta 2 Downloads

Wednesday, August 8, 2007

WOW! I heard that these downloads were fast, but I had no idea they were this fast!  MSTorrent [theoretically] rules!

Hopefully this will actually work.  The first two times I've tried MSCD with Standard I got a "verified" download, but it was completely corrupted.  Then I downloaded and installed Web Developer Express from the web site and then downloaded and installed Standard from the web site to find out that they have completely incompatible versions of the .NET Framework 3.5.  No idea.

If you want to give it a try, head on over to the link below.

Related Links

Real World HttpModule Examples

Monday, August 6, 2007

Back when I first discovered HttpHandlers I remember being ecstatic that the control that I thought I lost when moving from PHP to ASP.NET was finally returned, but when I first discovered HttpModules I remember almost passing out at the level of power and control you get over the ASP.NET request pipeline.  Since then, I've used HttpHandlers, HttpHandlerFactories, and HttpModules in many projects, but I'm noticing that while many people have heard of them, many have no idea what you would ever use them for.  So, I would like to give a few examples.

The first example is really simple.  On my blog, I didn't ant anyone to alias my web site or access it in any other way than by going to www.netfxharmonics.com.  Since HttpModules allow you to plug into the ASP.NET request pipeline, I was able to quick write an HttpModule to do exactly what I wanted:

public class FixDomainHttpModule : IHttpModule
{
    public void Dispose( ) {
    }

    public void Init(HttpApplication context) {
        context.BeginRequest += delegate(Object sender, EventArgs ea) {
            HttpApplication ha = sender as HttpApplication;
            String absoluteUrl = ha.Context.Request.Url.ToString( ).ToLower( );
            if (ha != null) {
                if (MinimaConfiguration.ForceSpecifiedDomain) {
                    if (!absoluteUrl.StartsWith(MinimaConfiguration.Domain.ToLower( ))) {
                        context.Response.Redirect(MinimaConfiguration.Domain);
                    }
                }
            }
        };
    }
}

...with this web.config:

<httpModules>
  <add name="FixDomainHttpModule" type="Minima.Web.HttpExtensions.FixDomainHttpModule" />
</httpModules>

By doing this I don't need to put a check in each page or in my MasterPage.  Since HttpModules are for the entire application, even URLs accessing my images are forced to be done by www.netfxharmonics.com.

Another example is a simple authentication system for a system I was working on a while back.  The application allowed anyone logged into active directory to access it's resources, but only certain people logged into active directory would be authorized to the use application (i.e. anyone could access images and CSS, but only a few people could use the system).  Knowing that the .NET framework is the model for all .NET development, I looked at the machine's web.config to see how ASP.NET implemented its windows and form authentication.  As it turns out, it does so by HttpModules.  So, I figured that the best way to solve this problem was by creating an HttpModule, not by throwing a hack into each of my WebForms or my MasterPages.  Furthermore, since ASP.NET uses the web.config for its configuration, including authentication configuration, I wanted to allow configuration of my authentication module to be via the web.config.  The general way I wanted to configure my HttpModule would be by a custom configuration section like this:

<Jampad>
    <Security RegistrationPage="~/Pages/Register.aspx" />
</Jampad>

The code for the HttpModule was extremely simple and required only a few minutes to throw together.  If the page being accessed is a WebForm and is not the RegistrationPage set in web.config, then the system's Person table is checked to see if the user logged into the machine has an account in the application.  If not, then there is a redirect to the RegistrationPage.  Simple.  Imagine how insane that would have been if you wanted to test for security on each page.

public class JampadSecurityModule : IHttpModule
{
    public void Dispose( ) {
    }

    public void Init(HttpApplication context) {
        context.BeginRequest += delegate(Object sender, EventArgs ea) {
            HttpApplication ha = sender as HttpApplication;

            if (ha != null) {
                CheckSecurity(context);
            }
        };
    }

    private void CheckSecurity(HttpApplication context) {
        SecurityConfigSection cs = (SecurityConfigSection)ConfigurationManager.GetSection("Jampad/Security");

        if (String.IsNullOrEmpty(cs.Security.RegistrationPage)) {
            throw new SecurityException("Security RegistrationPage is required.");
        }

        if (cs == null) {
            return;
        }

        if (!context.Request.Url.AbsoluteUri.Contains(cs.Security.RegistrationPage) &&
            context.Request.Url.AbsoluteUri.EndsWith(".aspx")
            ) {
            PersonCollection pc = new PersonCollection( );
            pc.GetMulti(new PredicateExpression(PersonFields.NTLogin==ActiveDirectoryFacade.NTUserName));

            if(pc.Count < 1){
                context.Response.Redirect(cs.Security.RegistrationPage);
            }
        }
    }
}

Again, plugging this into the web.config makes everything automatically happen:

<httpModules>
    <add name="JampadSecurityModule " type="Jampad.Security.JampadSecurityModule" />
</httpModules>

Recently I had to reuse my implementation in an environment that would not allow me to use LLBLGen Pro, so I had to rewrite the above 2 lines of LLBLGen Pro code into a series of Strongly-Typed DataSet tricks.  This implementation also had a LoginPage and an AccessDeniedPage in the custom configuration section, but other than that it was the same idea.  You could actually take the idea further by checking if the person is currently authenticated and if they aren't do a check on the Person table.  If they have access to the application, then PersonLastLoginTime column to the current time.  You could do many things with this implementation that would be rather crazy to do in a WebForm or MasterPage.

Another example of an HttpModule would be my custom access control system I built into my blog.  I'm not going to paste the code here as it's just the same idea as the other examples, but I will explain the concept.  Basically I created a series of tables in my blog's SQL Server database that held information on access control.  In the Access table I put columns such as AccessDirection (allow, deny), AccessType (IP Address, UserAgent, HTTP Referral), AccessText, AccessMessage, and AccessRedirect.  My HTTPModule would filter every ASP.NET request through this table to figure out what to do with it.  For example, I could block an IP address by creating a table record for 'deny', 'IP Address', '10.2.1.9', 'Your access has been denied.', NULL.  Immediately upon inserting the row, that IP address is blocked.  I could also block certain UserAgents (actually this was the original point of this HttpModule--bots these days have little respect for the robots.txt file).  I could also block requests that were from a different web site.  This would allow me to stop people from leaching images off my web site for use on their own.  With a simple HttpModule I was able to do all this in about an hour.  By the way, one record I was tempted to create was the following: 'deny', 'UserAgent', 'MSIE', NULL, 'http://www.getfirefox.com/'.  But I didn't :)

Now when would you use an HttpModule versus an HttpHandler?  Well, just think about what the difference is.  An HttpHandler handles a specific address pattern for a specific set of HTTP verbs, while every request in an application goes through an HttpModule.  So, if you wanted to have an image creator at /ImageCreator.imgx, then you need to register .imgx to IIS and then register your image creation HttpHandler in your web.config to handle that address (in case you forgot, web browsers care about the Content-Type, not the file extension.  In this example, your HttpHandler would set the Content-Type as 'image/png' or whatever your image type is.  That's how a web browser will know what to do with a file.  It has nothing to do with the file extensions; that's just for IIS.)  On the other hand, if you wanted to block all traffic from a specific web site, then you would create an HttpModule, becayse HttpModules handle all traffic on an application.  So, if you just remember this fundamental difference in purpose between the two, then shouldn't have my problems in the future.

Integrity in Life via Cartoons

Saturday, August 4, 2007

Anyone who knows me knows that I do not waver on my integrity.  If there is an option between doing something properly and getting something done quickly, then I'm going to do it properly.  PERIOD.  There will be no discussions.  I've left three gigs for not wavering on my integrity and I'm very grateful for it as each time, by the grace of God, my pay has been increased (I did the math and I think I should keep this pattern up!)  Most of my principles are Biblical principles that I would very literally and very gladly give my life for, but some of them are principles in the technical world.  It's important to note that having integrity means that you are one whole, complete, singular person with no divisions; you are an integral unit.  You cannot have integrity if you have one belief system at home and a completely different one at work.  I don't mean simply "religious" beliefs, but I mean moral, ethical, and general beliefs and philosophies of your entire life.

www.reverendfun.com

One of my role models in this area is Al Weiss, the president of worldwide operations for Walk Disney Parks and Resorts, who reports directly to Michael Eisner.  A few months ago I attended the "Rebuilding Integrity in the Workplace" conference in Kansas City, Kansas hosted by the Integrity Resource Center, where Weiss spoke on "Guiding Principles for Faith and Work".  It was one of the most powerful and jolting conferences I've ever attended.  This is a man who told Michael Eisner that he would NOT attend his meetings when his son has a baseball game.  By listening to him, you could just hear a screaming reminder that meekness (consciously controlled strength) is the opposite of weakness (being a sissy).  Granted sometimes it feels like the cartoon on the right, but it's always worth it!  Christians, remember when you were spiritually resurrected?  You were given a Christ's backbone; don't let it go to waste.  That thing held the sins of the world and didn't break.  Non-Christians... intrigued?

One principle that I live by is a simple principle of what some call "taking pride in your work".  It's really just called "doing it right", but whatever you call it the result is the same: no one can in good conscious put you to shame for what you've done.  Now, many people like to apply this in their personal life, but completely forget to apply it professionally.  For example, some programmers may be very good about applying the 10 commandments and parables to their live, but will blatantly on something like the W3C standards or .NET Framework Design Guidelines.  It may not seem like a big deal to that person, but each of these things are very similar in that they each flow from the person's integrity.  If you start to be sloppy at work or tolerate sloppiness, you will inevitably start to be sloppy or start to tolerate sloppiness at home or at church.  This is very analogous to stealing.  If you start to steal office supplies, you are demonstrating your abilities to steal, which could eventually lead to the stealing of greater things (not that there are "lesser" or "greater" things-- we don't get to choose the value of what we steal as it's always still stealing).  One example of good work is the ESV Bible website.  This website houses one of the best English translations of the original Greek, Hebrew, and Aramaic that the Bible was written in while at the same time making my Firefox HTML validator give a perfect rating.  The webmaster of the ESV Bible website, Stephen Smith, is a model of integrity when it comes to this area.  Having this level of integrity allows him, to continue to expose the ESV Bible in even more ways without having to go back and worry about something not being right; he just did it right to begin with.  Flowing from his integrity is the ability to access the full ESV Bible text via the website, a web service, a GET service, or even directly via e-mail.  His respect for the web and therefore the users of the web prompted him to also release a Firefox search plug-in for the ESV Bible.  Furthermore, since he isn't skipping steps or taking shortcuts, he can publish information about the internals of the website or other website components without the fear of shame.  If you are following the rules and living by integrity even in the seemingly areas of life you will have no shame.

www.reverendfun.com

In the .NET community having integrity at work may mean that you are holding fast to the to the Framework Design Guidelines, to which I have a very high allegiance.  Krzysztof Cwalina and Brad Abrams's book is by far and away the most important book that any .NET developer can own.  When I get a new job at a company, I make sure to mention this book in the interview as it's always a job requirement for me, because this book is the absolute LAW.  There are no need for opinions and no reason to make decisions, we just need to look to the law and see what it says.  Methods are CamelCased, Streams are to be disposed, and classes are to never be prefixed with a "C".  Simple.  Some people think that you can waiver on something like this or bring our own "opinions" to it but, we do not come to the law to judge the law, but, rather, we come to the law to be judged by the law.  It would be incredibly difficult to overstate that principle.  The other day I saw some code that came across my desktop and, obviously, my honor and integrity forced me to throw it away as it violated a virtually innumerable amount of rules.  Looking at this horribly impossible to read code felt very much like the cartoon on the left (that truly is such a perfect picture of it!)

Of course, being a scientific person who bases my life on evidence, proof (no, they aren't the same thing) as well as oral and paper defenses backed by research, I defended my position by a working code example and gave various examples of what would happen when someone violates the rules.  I also explained that the .NET Framework has more people working on it than probably the biggest open-source project in the world and yet it looks like it was written by a small team, thanks to the Framework Design Guidelines, without which the entire framework would look like a series of agitated quantum particle swinging from a double pendulum (i.e. it would look very chaotic!)  Of course, while everyone present agrees that each of my arguments were valid and were said to be "very good" and "very helpful", they were completely dismissed.  There are people in this world who actually believe that ignoring fundamental principles and rules is OK if it means a deadline can be met or if it agrees with how projects have always been built.  It's as if the norm implies normal, which it doesn't, or as if normal means right, which it also doesn't.  Being a bit naive, I used to think that everyone was taught as a child "just because something works, that it doesn't mean it's right".  It used to be that when a parent caught their son or daughter in a lie that child would be told something along the lines of "it doesn't matter if it didn't hurt anyone, it's still wrong."  Alas, the pragmatic and utilitarianism model for success has spread like a virus in place of traditional values such as righteousness and integrity.

www.reverendfun.com

Thankfully, most everyone obeys the official Framework Design Guidelines and all respectable companies have them has requirements.  Yet, some people have absolutely no respect for the law, so, in interviews I make very sure that people understand what will be required of them in terms of the .NET coding rules.  Of course, those who have no experience with the official rules, don't have the Framework Design Guidelines book at their desk, or have no idea what FXCop will probably end up bring around a situation similar to the cartoon on the right.  Of course that image also represents what will happen when a company demands that you completely disregard the Framework Design Guidelines that all .NET developers are required to give their complete allegiance to.  These are situations were holding to your integrity in "little things" will help you hold to your integrity in "greater things".  It's very important to note that I'm not saying that you need to be uncompromising with everything that you want.  No, you're never going to get what you want.  I'm talking about foundational principles, not product or tool requests.  For example, though we have every right to vigorously fight for it, we have no right to cry about not getting the data access layer creator we want, but we must not waiver on the simple foundational concept that a solution will have a data access layer.  Font styles, colors, or sizes belong in the world of preference, not in the world of foundational principles; however, implementation of layout via CSS versus that of tables might be a foundational principle for someone.  When you compromise on a seemingly insignificant foundational architectural principle like this, you will you soon be compromising on greater things in your finances, in your church, or with your relationships.  Great or small, foundational principles are non-negotiable.  For almost 10 years now I've been trying to explain with my lips and with my life that there is no difference between personal and professional.  They each flow from the exact same core of a person.  No one can take the foundational principle from you no matter how hard they try.

All this should help explain to people the beginnings of my absolutely lack of respect for today's (2007) most widely used "web" browser, the perfect example of anti-integrity.  I just can't see how introducing a tool into the world's computers which lowers the value of our world's information infrastructure isn't an act of terrorism.  This is, without equal, the quintessential example of lack of integrity in all of the entire technology world.  Decisions were made for the "business" and not for the people.  Businesses ultimately never matter, but people will never cease to matter.  People with integrity never strive to seek what a business wants or what a business needs or seek to find "business reasons" for anything, but rather seek to live by their foundational principles that define who they are to increase the quality of the lives of people.  Often this means, that you must do an upgrade simply to aide in the satisfaction of someone's job or to assist in system usability.  For example, you never need a business reason to switch from MSDE to SQL Server 2005.  SQL Server 2005 will greatly lower the stress levels of people and will thereby increase the quality of their lives.  The same would go for moving to .NET 1.1 to .NET 2.0 or WSE 2.0/3.0 to WCF or VSS to Subversion.  Businesses are only abstract entities, while people are the creation of God and the intense focus of His loving gaze.  With regard to web browsers, it's very fortunately that when working with the aforementioned "web" browser, web developers quickly learn the lesson that they just can't develop applications in that thing at the early stages of development, but, in fact, really need to develop for web browsers (W3C browsers) like Firefox, Opera, and Safari first and then add support for the other one later.  If the people choosing release dates on that product had integrity, instead of releasing what amounts to spyware, they would have simply told their managers "No".  Alas, the results of the Acid2, the test of web browser integrity, test were almost identical for their latest release as the previous one and the product is bringing nothing but grief to developers and users all over the world.  That's the price of not having integrity in the world place.  Admittedly, the Firefox team isn't guiltless either, but their version 3.0 seems to be holding up quite well with the Acid2 test, with the other "web" browser showing no hope in sight.

www.reverendfun.com

There are so many other examples of integrity it's difficult to know where to start.  It could be with your finances, your language, your honesty, your influences, your bumper stickers, or actually anything else.  In the technology realm, showing your integrity would be obeying fundamental principles and following the official guidelines even if they break corporate "standards" or not going on corporate retreats if there is any chance that it will cause you to violate your personal integrity.  Imagine if you were building a tall building or a bridge, would you compromise for any reason?  No, doing that could leave people dead.  Integrity demands that your level of steadfastness in the small things match your steadfastness in the great.  You just can't be one person at home and another at work.  Having integrity means that you live the same principles in both places.  You cannot be one person on Sunday and another on Monday.  This includes full-time employees and contractors.  One manager actually told me to my face "You're a contractor, you have no integrity!"  Needless to say, I didn't last another week :)  You cannot put your work or anything else above your integrity.  Nothing matters that much.  Christians, above all, relax, get marinated in your Bible, live by the cartoon on the left and run the software of your lives on PHP 3.8 ("Indeed, I count everything as loss because of the surpassing worth of knowing Christ Jesus my Lord. For his sake I have suffered the loss of all things and count them as rubbish, in order that I may gain Christ" -- remember that no popular English Bible has ever translated the word "rubbish" in its full force!).  You will be fine, no one can touch you.  Also, don't beat yourself for even publicly messing up.  We all make mistakes, even big ones.  That's the entire point of forgiveness.  Non-Christians... again, intrigued?

Simplified Universal HttpHandlerFactory Technique

Saturday, August 4, 2007

A few months ago I wrote about the Universal HttpHandlerFactory Technique where you have one HttpHandlerFactory that all your ASP.NET processing goes through and then in that HttpHandlerFactory you then choose what HttpHandler is returned based upon what directory or file is accessed.  I still like this approach for certain scenarios, but my blog got to the point where I was managing 11 different HttpHandlers for about 25 different path and file patterns.  So, it was time to simplify.

What I came up with was basically my go to card for everything: put it in SQL Server.  From there I just checked the URL being accessed against the patterns in a database table and then looked up what HttpHandler to use for that particular request.  Then, of course, I cached the HttpHandler for future file access.

Here are my SQL Server tables (yes, I do all my design in T-SQL-- SQL GUI tricks are for kids):

create table dbo.HttpHandlerMatchType  (
HttpHandlerMatchTypeId int primary key identity not null,
HttpHandlerMatchTypeName varchar(200) not null
) 

insert HttpHandlerMatchType select 'Contains'
insert HttpHandlerMatchType select 'Starts With'
insert HttpHandlerMatchType select 'Ends With'
insert HttpHandlerMatchType select 'Default'

create table dbo.HttpHandler (
HttpHandlerId int primary key identity not null,
HttpHandlerMatchTypeId int foreign key references HttpHandlerMatchType(HttpHandlerMatchTypeId),
HttpHandlerName varchar(300),
HttpHandlerMatchText varchar(200)
) 

Here is the data in the HttpHandler table:

 HttpHandler Table

Looking at this image and the SQL Server code, you can see that I'm matching the URL in different ways.  Sometimes I want to use a certain HttpHandler if the URL simply contains the text in the HttpHandlerMatchText and other times I'll want to see if it the URL ends with it.  I included an option for "starts with" as well, which I may use in the future.  This will allow me to have better control of how paths and files are processed.  Also, notice that one is "base".  This is a special one that basically means that the following HttpHandler will be used (keep in mind we are in a class that inherits from the PageHandlerFactory class-- please see my original blog entry):

base.GetHandler(context, requestType, url, pathTranslated);

Now in my HttpHandlerFactory's GetHandler method I'm doing something like this (also note how LLBLGen Pro helps me simply my database access):

HttpHandlerCollection hc = new HttpHandlerCollection( );
hc.GetMulti(new PredicateExpression(HttpHandlerFields.HttpHandlerMatchTypeId != 4));

IHttpHandler hh = null;
foreach (HttpHandlerEntity h in hc) {
    hh = MatchHttpHandler(absoluteUrl, h.HttpHandlerName.ToLower( ), h.HttpHandlerMatchTypeId, h.HttpHandlerMatchText.ToLower( ));
    if (hh != null) {
        break;
    }
}

This is basically just going to look through all the HttpHandlers in the table which are not the "default" handler (which will be used when there is no match).  The MatchHttpHandler method basically just passes the buck to another method depending of whether I'm matching the URL based on Contains, StartsWith, or EndsWith.

private IHttpHandler MatchHttpHandler(String url, String name, Int32 typeId, String text) {
    IHttpHandler h = null;
    switch (typeId) {
        case 1:
            h = MatchContains(url, name, text);
            break;

        case 2:
            h = MatchStartsWith(url, name, text);
            break;

        case 3:
            h = MatchEndsWith(url, name, text);
            break;

        default:
            throw new ArgumentOutOfRangeException("Invalid HttpHandlerTypeId");
    }

    return h;
}

Here is an example of one of these methods; the others are similiar:

private IHttpHandler MatchContains(String url, String name, String text) {
    if (url.Contains(text)) {
        return GetHttpHandler(name);
    }
    return null;
}

As you can see, it's nothing fancy.  The last method in the chain is the GetHttpHandler, which is basically a factory method that converts text into an HttpHandler object:

private IHttpHandler GetHttpHandler(String text) {
    switch (text) {
        case "base":
            return new MinimaBaseHttpHandler( );

        case "defaulthttphandler":
            return new DefaultHttpHandler( );

        case "minimaapihttphandler":
            return new MinimaApiHttpHandler( );

        case "minimafeedhttphandler":
            return new MinimaFeedHttpHandler( );

        case "minimafileprocessorhttphandler":
            return new MinimaFileProcessorHttpHandler( );

        case "minimapingbackhttphandler":
            return new MinimaPingbackHttpHandler( );

        case "minimasitemaphttphandler":
            return new MinimaSiteMapHttpHandler( );

        case "minimatrackbackhttphandler":
            return new MinimaTrackBackHttpHandler( );

        case "minimaurlprocessinghttphandler":
            return new MinimaUrlProcessingHttpHandler( );

        case "projectsyntaxhighlighterhttphandler":
            return new ProjectSyntaxHighlighterHttpHandler( );

        case "xmlrpcapi":
            return new XmlRpcApi( );

        default:
            throw new ArgumentOutOfRangeException("Unknown HttpHandler in HttpHandlerMatchText");
    }
}

There is one thing in this that stands out:

case "base":
    return new MinimaBaseHttpHandler( );

If the "base" is simply a call to base.GetHandler, then why am I doing this?  Honestly, I just didn't want to pass around all the required parameters for that method call.  So, to make things a bit more elegant I created a blank HttpHandler called MinimaBaseHttpHandler that did absolutely nothing.  After the original iteration through the HttpHandlerCollection is finished, I then do the following (it's just a trick to the logic more consistent):

if (hh is MinimaBaseHttpHandler) {
    return base.GetHandler(context, requestType, url, pathTranslated);
}
else if(hh != null){
    if (!handlerCache.ContainsKey(absoluteUrl)) {
        handlerCache.Add(absoluteUrl, hh);
    }
    return hh;
}

One thing I would like to mention is something that that sample alludes to: I'm not constantly having everything run through this process, but I am caching the URL to HttpHandler mappings.  To accomplish this, I simply setup a simple cached dictionary to map URLs to their appropriate HttpHandlers:

static Dictionary<String, IHttpHandler> handlerCache = new Dictionary<String, IHttpHandler>( );

Before ANY of the above happens, I check to see if the URL to HttpHandler mapping exists and if it does, then return it:

if (handlerCache.ContainsKey(absoluteUrl)) {
    return handlerCache[absoluteUrl];
}

This way, URLs can be processed without having to touch the database (of course ASP.NET caching helps with performance as well).

Related Links

All my work in this area has been rolled-up into my Themelia ASP.NET Framework, which is freely available on CodePlex. See that for another example of this technique.

Creative Commons License
This work is licensed under a Creative Commons Attribution 2.5 License.

Built on Themelia Pro 2.0

Mini-icons are part of the Silk Icons set of icons at famfamfam.com