<feed xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
    <title>On the Ledge</title>
    <link rel="self" type="application/xml" href="http://geekswithblogs.net/ontheledge/Atom.aspx" />
    <subtitle type="html">The general evolution (and occasional regression) of a .NET developer</subtitle>
    <id>http://geekswithblogs.net/ontheledge/Default.aspx</id>
    <author>
        <name>ledge</name>
        <uri>http://geekswithblogs.net/ontheledge/Default.aspx</uri>
    </author>
    <generator uri="http://subtextproject.com" version="Subtext Version 0.0.0.0">Subtext</generator>
    <updated>2009-10-08T13:38:23Z</updated>
    <entry>
        <title>Monster Projects</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/ontheledge/archive/2009/10/08/monster-projects.aspx" />
        <id>http://geekswithblogs.net/ontheledge/archive/2009/10/08/monster-projects.aspx</id>
        <published>2009-10-08T13:32:49-05:00:00</published>
        <updated>2009-10-08T13:38:23Z</updated>
        <content type="html">Since I wrote a post, previously, about side projects that I'm working on, I should probably mention: &lt;a href="http://www.askadndmonster.com/"&gt;Ask a DnD Monster&lt;/a&gt;. The site has been one of my more profitable side projects to date, earning $1.03 so far.&lt;img src="http://geekswithblogs.net/ontheledge/aggbug/135370.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/ontheledge/comments/135370.aspx</wfw:comment>
        <slash:comments>2</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/ontheledge/comments/commentRss/135370.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/ontheledge/services/trackbacks/135370.aspx</trackback:ping>
    </entry>
    <entry>
        <title>I'm the MVP of MVC</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/ontheledge/archive/2009/10/06/im-the-mvp-of-mvc.aspx" />
        <id>http://geekswithblogs.net/ontheledge/archive/2009/10/06/im-the-mvp-of-mvc.aspx</id>
        <published>2009-10-06T11:46:19-05:00:00</published>
        <updated>2009-10-06T11:46:19Z</updated>
        <content type="html">&lt;p&gt;There's a post title that'll screw with Google results.&lt;/p&gt;
&lt;p&gt;My fortune cookie from Panda reads: Avoid unchallenging occupations - they waste your talents.  This is followed by what appears to be a little ad for Panda Express and Panda Inn (I guess those are the occupations that wouldn't waste my talents).  Overall, I agree with the cookie, but I could use a little less challenge for a while.&lt;/p&gt;
&lt;p&gt;I haven't posted in a bit largely because of the challenge.  Writing your own MVC framework from scratch is not something normal people should be doing.  Today, I'll be meeting with my boss to get some guidance from the master on a few choke points in my development (i.e. points at which I started to choke myself while developing), so maybe I'll be able to get this project behind me, shortly.&lt;/p&gt;
&lt;p&gt;Developing framework code is a really different animal than developing business process code.  I think it is, anyway.  It's one thing to design and build a better bookshelf; it's another thing altogether to design and build a better hammer suited for building bookshelves.  It's a level of abstraction I'm not used to working with and, although I appreciate the wise sage who wrote my fortune cookie, it's been a real source of stress.&lt;/p&gt;
&lt;p&gt;So, for all my developer brothers and sisters who are currently in the depths of a project that feels somewhat too big, and every step forward takes such an amount of effort that staying where you're at actually sounds pretty good - I'm with you.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/ontheledge/aggbug/135330.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/ontheledge/comments/135330.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/ontheledge/comments/commentRss/135330.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/ontheledge/services/trackbacks/135330.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Code Standards Can Kill You</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/ontheledge/archive/2009/09/28/code-standards-can-kill-you.aspx" />
        <id>http://geekswithblogs.net/ontheledge/archive/2009/09/28/code-standards-can-kill-you.aspx</id>
        <published>2009-09-28T14:20:05-05:00:00</published>
        <updated>2009-09-28T14:26:45Z</updated>
        <content type="html">&lt;p&gt;First of all, the folks I used to work with will be glad to know that &lt;a href="http://www.pandaexpress.com/"&gt;Panda Express&lt;/a&gt; is selling their Orange Chicken sauce at their restaurants.  Unfortunately, it does not come in 2 liter bottles or six packs.&lt;/p&gt;
&lt;p&gt;On topic, the posts I've made here lately have gotten me thinking about the idea behind standards and/or best practices.  I noticed a refrain in many of my posts, although it was unintentional - the idea that a given situation dictates the best solution as opposed to taking a pre-determined solution and applying it to the situation.  While I think most sane people would agree this is generally a good way to go about development (and perhaps a lot of things in life in general), there are some ramifications for ideas like code standards that may be a challenge to work through.&lt;/p&gt;
&lt;p&gt;Code standards and practices have some key advantages.  They enforce code quality (or at least, the standard's definition of code quality).  They provide a pre-existing level of familiarity when people come to a new area of the codebase.  It is often relatively easy to automate the testing and generation of code according to particular standards.&lt;/p&gt;
&lt;p&gt;The problem, though, is that dictating firm standards (and especially specific practices, tools, or techniques that a developer must use or avoid) forces a one-size-fits-all solution that might not be the best solution for what you're trying to accomplish.  In fact, it's possible that your standard, which is great 90% of the time, is a crippling hack the other 10%.  In that 10% of the time, isn't it best for the company and your software not to use your standard?&lt;/p&gt;
&lt;p&gt;In other words, I believe a standard should never be created or enforced for the sake of having a standard.&lt;/p&gt;
&lt;p&gt;Standard coding practices are not inherently good.  You can have bad standards.  You can have pointless standards.  You can have standards that are good some of the time, and not so good otherwise.  Standard coding practices are only useful insofar as they provide and protect certain values.  They don't have value all by themselves.  They have pragmatic, not inherent, value.&lt;/p&gt;
&lt;p&gt;If those values are better provided and protected by defying a standard or having no standard at all, then that's exactly what you should do, and it boggles my mind how many blogs I read or stories I hear where someone is just convinced that slavish devotion to a standard, practice, design pattern - whatever - is something that should never be compromised, as if there's something inherently unethical or dangerous about that.&lt;/p&gt;
&lt;p&gt;A solution to a problem needs to be evaluated on its own merits, and the objection, "But that's not our standard," is not a valid objection on its own.  You have to remind yourself what that standard is buying you in this situation, and then see if the alternative also provides that for you or provides something that is worth the trade-off.  This is always a valid discussion to have.  To rule out solutions -purely- on the basis that they are non-standard is the last refuge of not having to think or make educated, calculated decisions about what's best.  Anybody can parrot a document or an article - very few people can think critically about code and how to solve problems with it.&lt;/p&gt;
&lt;p&gt;There are some common objections I've read or heard about deviating from standard practices, and I'd like to address them, briefly.&lt;/p&gt;
&lt;p&gt;"We'll have all different kinds of code and methodologies in our solution."&lt;/p&gt;
&lt;p&gt;I have yet to see the project where this is never the case.  If you have a common codebase with two people working on it, you're going to have different kinds of code and methodologies; I don't care how much you try to legislate it.  In fact, this often happens with just one person.  Trying to fight this is something like trying to get communism to work.&lt;/p&gt;
&lt;p&gt;The other side of this objection is the assumption that having different kinds of code and methodologies in the same codebase is inherently bad, and I'm not sure that's the case, anymore than having different kinds of tools in your toolbox is inherently bad.  To be honest, a codebase that is completely monolithic in its code structures probably lacks any kind of innovation and has many circumstances where the code used is not the best for the situation - like trying to hammer all your nails in with screwdrivers.  It can be done, but it's also stupid.  No standards document is going to make using screwdrivers to hammer nails anything but stupid if you could just as easily have obtained and used a hammer.&lt;/p&gt;
&lt;p&gt;"Our people aren't going to understand different styles of code / more advanced methodologies."&lt;/p&gt;
&lt;p&gt;It amazes me how much a company is willing to suck in the name of accommodating their employees' level of aptitude.  While that may sound harsh, and while I admire companies trying to retain their employees in a bad economy, it's never a viable excuse to say, "Methodology X would be a lot better, but the people we've got will never be able to understand that."&lt;/p&gt;
&lt;p&gt;Really?&lt;/p&gt;
&lt;p&gt;So, one has to ask what the actual problem is.  Is it that your employees are literally not mentally capable of learning new ways to do things?  Is it that they're capable, but they're unwilling?  In either case, I'd have to ask why you're so committed to holding on to people who are either incapable of becoming more skilled or refuse to do so.  If your employees can get to a level of dealing with different styles of coding and they are willing to do so, then this objection falls.&lt;/p&gt;
&lt;p&gt;Developer teams always have different levels of ability in them, and the way to most effectively direct a team like this is not to bring everyone down to the lowest common denominator, nor is it even to create a midpoint.  The way to effectively direct a team is to give people responsibilities commensurate with their skill levels and have a plan in place to increase their skills and give them different kinds of tasks if that is their desire.&lt;/p&gt;
&lt;p&gt;Some people may be perfectly happy doing little bug fixes.  Fine.  Use them for fixing little bugs.  But if you orchestrate your standards for application development based on your lowest level of competence, well, guess what kind of product you're going to produce.&lt;/p&gt;
&lt;p&gt;Once again, I find that this objection has more to do with laziness than anything else.  Companies do not exist to pay salaries; they exist to make money.  If you doubt this, find the report that your company distributes to shareholders and see how much attention is given to profit and loss versus how well you're doing at increasing the number of employees.  If a new methodology seems too complex for most of your crew to work with, then put a plan together to get them to a level of understanding.  If that's impossible, then you may find that you need to reorganize or perhaps even eliminate some people.&lt;/p&gt;
&lt;p&gt;I'm not saying just to boot people out the door who can't hack it.  As a former trainer, I believe in bending over backwards and exhibiting all the patience you can muster with someone who's willing to learn and work hard.  But what I am saying is that you've bought an express ticket to Stupidville if the primary value of your standards is that they protect the least skilled of your workers from ever being confused.&lt;/p&gt;
&lt;p&gt;"What's the point of having a standard if we allow people to deviate from it?"&lt;/p&gt;
&lt;p&gt;This is actually an excellent point.  What -is- the point of having a standard way to do something if it turns out that the best solution, at least part of the time, is to do something different?  But the assumed answer here is that the practice should promptly change in favor of the standard.  I would argue that the best answer is the other way around.&lt;/p&gt;
&lt;p&gt;If you find that your standard isn't the best solution, you should change it to the best solution.  Otherwise, you should get in touch with those other people going to Stupidville so you can get a group discount.&lt;/p&gt;
&lt;p&gt;What is probably more common, however, is that you discover that your standard is pretty good in many situations, but there's one or more where it isn't, and the question is whether or not you should allow exceptions in the name of implementing a better solution.&lt;/p&gt;
&lt;p&gt;The first thing I have to say is that it's worth considering that standardizing that practice isn't a good idea.  If there are multiple ways of doing it, and some of them are the best in one situation and others are the best in another, that sounds like a prime candidate for not standardizing, or at least offering a defined list of acceptable options.  If your standard is hurting you, why have it?&lt;/p&gt;
&lt;p&gt;If, for whatever reason, that's not an option (maybe you have a standardized practice for establishing standards and are stuck in a space-time continuum paradox), then we go back to the original point - what is the standard getting you in this situation?  What is the deviation getting you?  Which one is worth more?  If what the deviation gets you is worth more than what the standard gets you, on what planet does it make sense to enforce the standard?&lt;/p&gt;
&lt;p&gt;Experientially and logically, it seems to be that there are very few one-size-fits-all solutions in development.  Naming conventions and the like are probably harmless enough and provide some value, but you are heading into dangerous waters when you being to mandate practices or forbid the use of others.&lt;/p&gt;
&lt;p&gt;Every situation is going to have different parameters, and every solution should be weighed on the basis of whether or not it provides the most value in that situation.  And if some upstart developer challenges the standard by producing actual reasons why her solution is a better choice for solving her problem, you'd better come to the table with something better than, "Well, it's not our standard."&lt;/p&gt;&lt;img src="http://geekswithblogs.net/ontheledge/aggbug/135143.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/ontheledge/comments/135143.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/ontheledge/comments/commentRss/135143.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/ontheledge/services/trackbacks/135143.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Custom User Settings and the Cache</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/ontheledge/archive/2009/09/25/custom-user-settings-and-the-cache.aspx" />
        <id>http://geekswithblogs.net/ontheledge/archive/2009/09/25/custom-user-settings-and-the-cache.aspx</id>
        <published>2009-09-25T10:51:57-05:00:00</published>
        <updated>2009-09-25T11:01:17Z</updated>
        <content type="html">&lt;p&gt;We get Flumphs from several, different providers.  Each provider has various settings that the system uses for them - particular URL routes, specific timeouts, etc.  In the old Proxy, anything that absolutely had to be client-specific was stored in a configuration file.  The timeout limit was universal.  Here's the kicker - the only thing in the Flumph that gets sent to us that clues us into the provider is the structure of the XML.  Since our Flumph providers delight in sending their own formats, we can't count on a specific identifier for the provider being in the XML - or any identifier at all, in some cases.&lt;/p&gt;
&lt;p&gt;So, we need a way that can identify the provider and retrieve their specific, custom settings without hitting the database several times a second to pull information that rarely changes.  Here's what I did:&lt;/p&gt;
&lt;p&gt;First, I made a class called ConfigurationSettings which has the following kinds of fields: constants that define the keys we'll use for the database lookup and the cache, constants that represent defaults in case the values can't be found, and collections (mostly string, string Dictionaries) to hold the settings in different groups.  This class will hold all our settings for all our providers.&lt;/p&gt;
&lt;p&gt;Some examples:&lt;/p&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;public const string&lt;/font&gt; TimeOutsKey = &lt;font color="#800000"&gt;"TimeOuts"&lt;/font&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;public const int&lt;/font&gt; DefaultTimeOut = 18;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt; &lt;font color="#008080"&gt;IDictionary&lt;/font&gt;&amp;lt;&lt;font color="#0000ff"&gt;string, string&lt;/font&gt;&amp;gt; TimeOuts;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;In those examples, you see how we specified the key for looking up TimeOut settings, a default timeout for universal use (in other words, we can't find this provider's timeout in our TimeOuts collection, so we'll use this one), and a collection of all our providers' timeouts.  I used timeouts for the examples because that's what precipitated this need, but we do the same thing to store a provider's domains, restrictions, XML format info, and application settings in general.&lt;/p&gt;
&lt;p&gt;The XML format info is done a bit differently - it's a collection of SourceXmlSetting objects - a class I wrote that stores things like RootNodeName, SourceNodeName, and some other stuff.  But aside from that twist, it works pretty much the same way.&lt;/p&gt;
&lt;p&gt;We then have a number of static methods.&lt;/p&gt;
&lt;p&gt;GetConfigurationSettings() is a private static method that hits the database and populates our collections.  This is very straightforward.  The configuration settings are in one table, the XML format info is in another table.  This method just hits both tables, iterates through them, and adds an item to the appropriate collection.&lt;/p&gt;
&lt;p&gt;For example, the ConfigurationSettings table has three fields: Type, Key, and Value.  "Type" refers to our categories of information, like "TimeOuts."  This is where the constant fields are helpful in making sure we use the same types in both the database and cache retrieval.  "Key" and "Value" are pretty straightforward.  So, you might have a record in this table that looks like: "TimeOuts", "LS15U", 30.  The first is the type, the second is the key (which is the provider name/code), and the third is the value, which is 30 seconds in this case.&lt;/p&gt;
&lt;p&gt;As our code iterates through this table with a datareader, a switch/case statement on the "Type" field tells us which dictionary to put the key-value pair into.  Once this is done, a very similar thing happens with the XmlRequests table, except, once again, several fields of information are involved, so this is stored in a custom collection of a custom class to hold the data.&lt;/p&gt;
&lt;p&gt;Note that this method is private.  Calling code cannot directly cause ConfigurationSettings to populate.  We do, however, have a public static method called LoadConfigurationSettingsIntoCache which our calling code does use when our populated ConfigurationSettings are no longer found in the cache.&lt;/p&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;public static void&lt;/font&gt; LoadConfigurationSettingsIntoCache() &lt;br /&gt;{ &lt;br /&gt;  &lt;font color="#008080"&gt;ConfigurationSettings&lt;/font&gt; configurationSettings = GetConfigurationSettings(); &lt;br /&gt;  &lt;font color="#008080"&gt;HttpRuntime&lt;/font&gt;.Cache.Insert(CacheKey, configurationSettings, &lt;font color="#0000ff"&gt;null&lt;/font&gt;, &lt;font color="#008080"&gt;DateTime&lt;/font&gt;.Now.AddHours(1), &lt;font color="#008080"&gt;TimeSpan&lt;/font&gt;.Zero); &lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;As you can see, we cache this data for an hour.  The data doesn't change nearly that frequently, but when you plan caching, you also have to plan how long you want changes to take.  This way, if we have to change someone's timeout, the longest we wait is an hour.  Ideally, we would probably cache these settings longer and provide some other mechanism to flush the cache if we change the info in the database.  We have not done that, yet.&lt;/p&gt;
&lt;p&gt;We also have a handful of static methods used to get commonly accessed settings, like GetTimeOut, GetRequestRoot, and so on.&lt;/p&gt;
&lt;p&gt;When our proxy receives a request, the first thing it does is look for the ConfigurationSettings in the cache.  If it's there, great.  If not, it calls the LoadConfigurationSettingsIntoCache() method, which puts it there.  Any exception causes an XML response to be sent back to the provider that the system is currently offline for maintenance.&lt;/p&gt;
&lt;p&gt;With that collection of settings in the Cache, retrieval of client-specific settings is a breeze.  We can either use one of our little helper static methods to quickly pull out commonly-used data, and we can just access the ConfigurationSettings' collections directly for all other operations:&lt;/p&gt;
&lt;pre&gt;_timeOut = &lt;font color="#008080"&gt;ConfigurationSettings&lt;/font&gt;.GetTimeOut(_source, _configurationSettings.TimeOuts);&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;foreach&lt;/font&gt; (&lt;font color="#008080"&gt;SourceXmlSetting&lt;/font&gt; setting &lt;font color="#0000ff"&gt;in&lt;/font&gt; _configurationSettings.XmlSettings)&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;for example.&lt;/p&gt;
&lt;p&gt;Once again, it all comes down to what kind of data you've got, how regularly it changes, and the costs and benefits of how you handle persisting and retrieving that data.  For us, this data rarely changes, and our high volume of requests is just begging to make this information available without a database hit.  Also, this particular solution means we can add more settings or change them without recompiling or redeploying anything - not even a config file.&lt;/p&gt;
&lt;p&gt;There are two, main improvements I would like to make:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Reloading into the cache every hour is still too often, I feel.  These settings change once in a blue moon &lt;em&gt;except &lt;/em&gt;for the flag that marks our system down for maintenance, which still only changes once or twice a month.  I'd like to have the data cached longer and code a specific XML request we could send to the Proxy that would cause it to flush and reload the cache. &lt;/li&gt;
    &lt;li&gt;We can add new settings without changing code.  We can't add new types of settings.  If we wanted to store, say, a provider's maximum allowable volume, we'd have to make a few alterations to the ConfigurationSettings class.  I'd like to abstract those collections further - maybe implementing a common base class - so that ConfigurationSettings could just deal intelligently with a generic "collection of collections."  Then, if we wanted to add new kinds of configuration settings, we could just create a new collection that inherited from that base class, load it up, and add it to ConfigurationSettings without actually changing the ConfigurationSettings class. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But, if wishes were horses, you could make baseballs for the rest of your life.  Our current setup works great for our current needs, and one of the cool things about where I work is that we set time specifically for refactoring old code, so I might get my wish at some point.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/ontheledge/aggbug/135094.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/ontheledge/comments/135094.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/ontheledge/comments/commentRss/135094.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/ontheledge/services/trackbacks/135094.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Asynchronicity, Too</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/ontheledge/archive/2009/09/24/asynchronicity-too.aspx" />
        <id>http://geekswithblogs.net/ontheledge/archive/2009/09/24/asynchronicity-too.aspx</id>
        <published>2009-09-24T13:18:13-05:00:00</published>
        <updated>2009-09-24T13:28:41Z</updated>
        <content type="html">&lt;p&gt;You guys have heard the song "&lt;a href="http://www.sing365.com/music/lyric.nsf/Synchronicity-II-lyrics-Sting-Police/257016E614A5B65548256874003687DB"&gt;Synchronicity 2&lt;/a&gt;," right?  Am I the only person who thinks &lt;a href="http://www.sting.com/"&gt;Sting&lt;/a&gt; did that song for his own amusement?  Cackling in his lush, vaguely European voice at the fans scrambling to figure out the deeper meaning between a harried husband going through his day and the Loch Ness Monster getting his killing on.  I can just see him laughing atop his enormous piles of money as people make connections with Carl Jung and nod their heads sagely at the unique, but highly apt, metaphor.  Ah, Sting, is there anything you won't do?&lt;/p&gt;
&lt;p&gt;Anyway, part of what I had to do to enhance the Proxy's performance is make the logging asynchronous.  In other words, we wanted the application to log something to the database, but not wait until that operation was complete before moving on.  One way to do this is by having the logging process run in its own thread.  The main application (in the main thread) hits the logging method, and it spins a new thread to run that code in while continuing on down the main thread.  When that spawned thread completes is of no consequence to the application.  So, if you can run it in its own process, this can speed up your application, because it isn't waiting around for stuff that it really doesn't need in order to finish.&lt;/p&gt;
&lt;p&gt;After a few trials, we decided only to do this with logging the request and the response to the database.  The gains from making the log file logging asynchronous were both insignificant and inconsistent.&lt;/p&gt;
&lt;p&gt;This is the first time I actually got into multi-threading.  I can't say I liked it very much, at first, but once I got to know my way around a bit, I can see that, in some applications, it can be an invaluable performance tool.&lt;/p&gt;
&lt;p&gt;Some of you may already be thinking about things like &lt;a href="http://shiman.wordpress.com/2008/09/10/c-net-delegates-asynchronous-invocation-begininvoke-method/"&gt;BeginInvoke&lt;/a&gt;, but here's the thing I came to learn: virtually everything the .NET Framework provides for asynchronous threading involves using the &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx"&gt;ThreadPool&lt;/a&gt; under the hood.&lt;/p&gt;
&lt;p&gt;The ThreadPool is a managed collection of threads which, in theory, allows the server to manage threads more efficiently.  So, a method like BeginInvoke works because it can receive notifications from the ThreadPool and hit callback functions, etc.&lt;/p&gt;
&lt;p&gt;The problem is that the ThreadPool has a maximum number, and we wanted theoretically unlimited growth.  If we're getting several Flumphs a second and the database operations aren't keeping pace, you'll run into a large number of threads very quickly, at least for a time.  So, it looked like simply spawning another Thread without any fancy-schmancy asynchronicity baked into it was the way to go.&lt;/p&gt;
&lt;p&gt;It's important to note, if you didn't already know, that threads by default will run parallel with the main thread.  So you don't have to do anything special to make them asynchronous.  It's just that the asynchronous stuff the Framework provides gives you a lot of flexible options, and probably has performance benefits, although I don't know that for a fact.&lt;/p&gt;
&lt;p&gt;The syntax for creating a new thread and executing it is pretty simple.  First, code your method that you want to do something just like you usually would.&lt;/p&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;public static void&lt;/font&gt; DoStuff() &lt;br /&gt;{ &lt;br /&gt;  &lt;font color="#008080"&gt;Console&lt;/font&gt;.Write(&lt;font color="#800000"&gt;"Throw open ya house!"&lt;/font&gt;);&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Then, in your code, you create your thread and pass it your method.&lt;/p&gt;
&lt;pre&gt;&lt;font color="#008080"&gt;Thread&lt;/font&gt; myNewThread = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#008080"&gt;Thread&lt;/font&gt;(DoStuff); &lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Technically, what you're doing is creating a delegate (an object in your program that represents a method) and passing that to the new thread.  The line above is just a shorthand way of doing it.  You could still actually type out the code to create a delegate for the DoStuff method and pass it to thread.  In fact, you can even create your delegate right there in the thread constructor, complete with the code that it represents.&lt;/p&gt;
&lt;p&gt;Also, I used a static method, but it doesn't have to be static.  You could just as easily pass in myObject.SomeMethod.&lt;/p&gt;
&lt;p&gt;When you want your new thread to kick off, it's as simple as:&lt;/p&gt;
&lt;pre&gt;myNewThread.Start();&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Whatever delegate has been passed to your thread, you will execute that code in its own, separate thread parallel to the execution of the rest of your main code, which will continue chugging merrily along its way.  There are ways to wait for the new thread to finish, and I'll cover that when I get to our use of threads for processing responses.&lt;/p&gt;
&lt;p&gt;Simple, eh?&lt;/p&gt;
&lt;p&gt;Well, there might be a complication.  When you look at that line of code that creates a new thread, do you notice anything about the method we pass to it?  More specifically, do you notice the &lt;em&gt;absence&lt;/em&gt; of anything?  Parenthesis, right?  No big deal in this case, but it's a plenty big deal if you want to pass parameters.&lt;/p&gt;
&lt;p&gt;To cope with this, I created classes that had settable fields.  These classes also had the method that would be executed by the thread, and this method would simply access the class properties for its data.&lt;/p&gt;
&lt;p&gt;For instance, I created a ResponseLogThread class.  It has three, private fields:&lt;/p&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;private readonly string&lt;/font&gt; _header; &lt;br /&gt;&lt;font color="#0000ff"&gt;private readonly string&lt;/font&gt; _body; &lt;br /&gt;&lt;font color="#0000ff"&gt;private readonly&lt;/font&gt; &lt;font color="#008080"&gt;Guid&lt;/font&gt; _requestId;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;These fields are set in the constructor:&lt;/p&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt; ResponseLogThread(&lt;font color="#008080"&gt;Guid&lt;/font&gt; requestId, &lt;font color="#0000ff"&gt;string&lt;/font&gt; header, &lt;font color="#0000ff"&gt;string&lt;/font&gt; body) &lt;br /&gt;{ &lt;br /&gt;  _header = header; &lt;br /&gt;  _body = body; &lt;br /&gt;  _requestId = requestId; &lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;And then I have a method that is the code I want the thread to run:&lt;/p&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;public void&lt;/font&gt; ExecuteLogResponse() &lt;br /&gt;{ &lt;br /&gt;  ... writes info to database ...&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Note that the method receives no parameters, but it doesn't need to.  The code just uses the values in _header, _body, and _requestId for its arguments.&lt;/p&gt;
&lt;p&gt;Back in my main code, when I'm ready to create and execute my thread.  I first create an instance of ResponseLogThread that holds the values I want to "pass in," and then I create my new thread, passing it the ExecuteLogResponse method, like so:&lt;/p&gt;
&lt;pre&gt;&lt;font color="#008080"&gt;ResponseLogThread&lt;/font&gt; responseLogThread = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#008080"&gt;ResponseLogThread&lt;/font&gt;(_requestId, response.Header, response.BodyStr);&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#008080"&gt;Thread&lt;/font&gt; responseLogExecutionThread = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#008080"&gt;Thread&lt;/font&gt;(responseLogThread.ExecuteLogResponse);&lt;/pre&gt;
&lt;pre&gt;responseLogExecutionThread.Start();&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;(You can see my proclivity for verbose names - and, no, BodyStr is not my invention.  It would probably be more like StringThatContainsTheBodyTextOfTheResponse or some other stupidity if I'd done it.)&lt;/p&gt;
&lt;p&gt;The first line creates my object and sets its fields; the thread executes its method that refers to those properties.  It works great.&lt;/p&gt;
&lt;p&gt;There are probably better ways to architect this solution, but this way works great, so suck it.&lt;/p&gt;
&lt;p&gt;No, just kidding.  I'd love to hear other ways or more elegant ways that people do this.  Like I said, I'm new to it.  But it is also true that this does work great and it did buy us some nice performance gains.  If you have "side operations" in your code, you might consider doing something like this to run them in their own thread and see if it buys you some speed, too.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/ontheledge/aggbug/135076.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/ontheledge/comments/135076.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/ontheledge/comments/commentRss/135076.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/ontheledge/services/trackbacks/135076.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Logging with log4net</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/ontheledge/archive/2009/09/23/logging-with-log4net.aspx" />
        <id>http://geekswithblogs.net/ontheledge/archive/2009/09/23/logging-with-log4net.aspx</id>
        <published>2009-09-23T10:42:35-05:00:00</published>
        <updated>2009-09-23T10:45:17Z</updated>
        <content type="html">&lt;p&gt;&lt;a href="http://logging.apache.org/log4net/index.html"&gt;log4net&lt;/a&gt; is a great little logging library.  There seem to be some mixed results out there as to whether or not it outperforms the &lt;a href="http://msdn.microsoft.com/en-us/library/dd139916.aspx"&gt;Enterprise Library's Logging Application Block&lt;/a&gt;, although it appears to me the general findings are that log4net is faster.  For me, I guess it would come down to how badly I wanted integration with the rest of the Enterprise Library.  If that's not a priority, log4net can be a lightweight, fast way to get logging going in your application.&lt;/p&gt;
&lt;p&gt;Once you've got the library in your project, you can configure your loggers in web.config.  For example:&lt;/p&gt;
&lt;pre&gt;&amp;lt;log4net&amp;gt; &lt;br /&gt;  &amp;lt;logger name="Activity"&amp;gt; &lt;br /&gt;    &amp;lt;level value="ALL"/&amp;gt; &lt;br /&gt;    &amp;lt;appender-ref ref="Activity_FileAppender"/&amp;gt; &lt;br /&gt;  &amp;lt;/logger&amp;gt; &lt;br /&gt;  &amp;lt;logger name="Errors"&amp;gt; &lt;br /&gt;    &amp;lt;level value="ALL"/&amp;gt; &lt;br /&gt;    &amp;lt;appender-ref ref="Error_FileAppender"/&amp;gt; &lt;br /&gt;  &amp;lt;/logger&amp;gt; &lt;br /&gt;  &amp;lt;logger name="ElapsedTime"&amp;gt; &lt;br /&gt;    &amp;lt;level value="ALL"/&amp;gt; &lt;br /&gt;    &amp;lt;appender-ref ref="ElapsedTime_FileAppender"/&amp;gt; &lt;br /&gt;  &amp;lt;/logger&amp;gt; &lt;br /&gt;  &amp;lt;logger name="TimeOut"&amp;gt; &lt;br /&gt;    &amp;lt;level value="ALL"/&amp;gt; &lt;br /&gt;    &amp;lt;appender-ref ref="TimeOut_SmtpAppender"/&amp;gt; &lt;br /&gt;  &amp;lt;/logger&amp;gt; &lt;br /&gt;&lt;br /&gt;&amp;lt;appender name="Activity_FileAppender" type="log4net.Appender.RollingFileAppender"&amp;gt; &lt;br /&gt;  &amp;lt;file value="c:\Logs\Proxy_Activity.log" /&amp;gt; &lt;br /&gt;  &amp;lt;appendToFile value="true" /&amp;gt; &lt;br /&gt;  &amp;lt;rollingStyle value="Composite" /&amp;gt; &lt;br /&gt;  &amp;lt;datePattern value="yyyyMMdd" /&amp;gt; &lt;br /&gt;  &amp;lt;maxSizeRollBackups value="10" /&amp;gt; &lt;br /&gt;  &amp;lt;maximumFileSize value="10MB" /&amp;gt; &lt;br /&gt;  &amp;lt;layout type="log4net.Layout.PatternLayout"&amp;gt; &lt;br /&gt;    &amp;lt;conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" /&amp;gt; &lt;br /&gt;  &amp;lt;/layout&amp;gt; &lt;br /&gt;&amp;lt;/appender&amp;gt; &lt;br /&gt;&lt;br /&gt;... other appender configs ...&lt;br /&gt;&lt;br /&gt;&amp;lt;/log4net&amp;gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;(I'm not going to do the color coding on all that)&lt;/p&gt;
&lt;p&gt;So, you can get fairly fine-grained in your log4net configurations.  Emails, databases, etc. for your log events are configured also using an &amp;lt;appender&amp;gt;, just with some different nodes set.&lt;/p&gt;
&lt;p&gt;In code, you simply instantiate a logger using the name you chose in your config, then use that to log messages.  I chose to create static instances in my classes so I could just re-use them:&lt;/p&gt;
&lt;p&gt;&lt;font color="#0000ff"&gt;protected static readonly&lt;/font&gt; &lt;font color="#008080"&gt;ILog&lt;/font&gt; ActivityLog = &lt;font color="#008080"&gt;LogManager&lt;/font&gt;.GetLogger(&lt;font color="#800000"&gt;"Activity"&lt;/font&gt;); &lt;br /&gt;
&lt;font color="#0000ff"&gt;protected static readonly&lt;/font&gt; &lt;font color="#008080"&gt;ILog&lt;/font&gt; ErrorLog = &lt;font color="#008080"&gt;LogManager&lt;/font&gt;.GetLogger(&lt;font color="#800000"&gt;"Errors"&lt;/font&gt;);&lt;/p&gt;
&lt;p&gt;And so on.  Both ILog and LogManager are part of log4net's API.&lt;/p&gt;
&lt;p&gt;Once those are available, you can use them in your code according to the format string you put in your web.config for that logger.  You use different logging methods to assign different severity levels:&lt;/p&gt;
&lt;p&gt;ActivityLog.Info(&lt;font color="#008080"&gt;String&lt;/font&gt;.Format(&lt;font color="#800000"&gt;"Response sent for {0}: {1}"&lt;/font&gt;, _requestId, response.BodyStr));&lt;/p&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;ErrorLog.Fatal(&lt;font color="#008080"&gt;String&lt;/font&gt;.Concat(&lt;font color="#800000"&gt;"EXCEPTION: "&lt;/font&gt;, response), exception);&lt;/p&gt;
&lt;p&gt;With this very simple setup, it was easy to insert logging statements into different areas of the Proxy's processing.  Since the Proxy was only a few classes and mostly procedural in operation, using Aspect-Oriented Programming to tie logging to methods and such wasn't the best way to go for this specific situation, although it probably is for most.&lt;/p&gt;
&lt;p&gt;Regardless of how you actually call your logging functionality, you already have a quick setup and a nice decoupling of your log "publishers" from your logging calls, allowing you freedom to change where your log messages end up and add several "publishers" to the same logging call.  For example, our system timeouts are not only logged, but also emailed to an email box specifically set up to track timeout issues.&lt;/p&gt;
&lt;p&gt;By doing this, we log the following points:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;When a request comes in. &lt;/li&gt;
    &lt;li&gt;When preprocessing of that request begins. &lt;/li&gt;
    &lt;li&gt;When that request is forwarded to the system. &lt;/li&gt;
    &lt;li&gt;When a response is received from the system. &lt;/li&gt;
    &lt;li&gt;When the response is forwarded to the requestor. &lt;/li&gt;
    &lt;li&gt;The time differences between each point. &lt;/li&gt;
    &lt;li&gt;Any time an exception is thrown. &lt;/li&gt;
    &lt;li&gt;Any time a timeout occurs. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once the setup was done, logging when and what we wanted was a piece of cake.  In fact, I could describe a good chunk of our release of the Proxy as, "Looks like it's running great!  Wait a minute.  Are you logging X?  Go back and add logging to X."  This happened at least ten times while we were deploying, and I was able to do it because it was so easy to modify the logging in such a short amount of time.&lt;/p&gt;
&lt;p&gt;However, we still had a need for speed.  In my next post, I'll talk about how we used threads to make our logging to the database asynchronous.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/ontheledge/aggbug/135041.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/ontheledge/comments/135041.aspx</wfw:comment>
        <slash:comments>1</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/ontheledge/comments/commentRss/135041.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/ontheledge/services/trackbacks/135041.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Proxy Problems</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/ontheledge/archive/2009/09/22/proxy-problems.aspx" />
        <id>http://geekswithblogs.net/ontheledge/archive/2009/09/22/proxy-problems.aspx</id>
        <published>2009-09-22T09:51:17-05:00:00</published>
        <updated>2009-09-22T09:55:38Z</updated>
        <content type="html">&lt;p&gt;My first actual project with regard to our systems was to write a new Proxy.  I'm going to have to be a little ambiguous, once again, because I don't want to give away any proprietary or quasi-proprietary information.&lt;/p&gt;
&lt;p&gt;One of our major systems serves as a sort of brokerage for &lt;a href="http://www.somethingawful.com/d/dungeons-and-dragons/fiend-folio-1.php?page=7"&gt;Flumphs&lt;/a&gt; (I'm going to compensate for being ambiguous by being completely ridiculous about it).  Flumph providers constantly feed our system with information about new Flumphs.  Flumph-consumers have given us their criteria they use to buy and sell Flumphs, so our system facilitates the automated sale/purchase of Flumphs to different consumers.&lt;/p&gt;
&lt;p&gt;So, a Flumph provider sends information about one into our system.  Our system does some routine checks.  Is this a valid Flumph?  Do we already have this Flumph in our system?  Then, we begin to examine the rules we have for different clients.  What additional information can we get from third parties about this Flumph?  Does anyone want a Flumph like this?  If not, should we buy the Flumph ourselves in order to sell it, later?  After all these questions have been answered, automatically, the system responds to the Flumph provider with a buy, a rejection with a reason, or a notice that we're not buying because the system is down for maintenance (usually during a release).&lt;/p&gt;
&lt;p&gt;This process is happening at the rate of several Flumphs per second, and the majority of providers want their response in 18 seconds or less.  The typical response comes in around one second.&lt;/p&gt;
&lt;p&gt;We had started to run into an anomaly where this operation was timing out in blocks.  The time outs seemed to have nothing to do with volume.  In fact, the provider with the smallest volume was the first to exhibit the behavior.  Different hypotheses were tested, but no one thing seemed to hold the explanation.  We assumed that it must be a few, different factors working together as opposed to one, big issue.&lt;/p&gt;
&lt;p&gt;My piece of the puzzle was to rewrite the Proxy.  The Proxy sits between our system and Flumph providers.  Its sole mission in life is to receive HTTP requests (these are incoming XML data) and forward them to the system, then send the response (also XML data) back to them.  It seems simple, right?  Well, until you realize that not every client uses the same XML format, nor do they wish to receive the same XML format.&lt;/p&gt;
&lt;p&gt;My mission was to make the Proxy leaner and faster, not only by tightening the code and processes, but also by making as much asynchronous as I could, including logging.  I also needed to add the following, new functionality:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;The old Proxy used &lt;a href="http://logging.apache.org/log4net/index.html"&gt;log4net &lt;/a&gt;to write the request info and the response info to a database.  I had to add logging events to track the time between when the request was received and when the request was forwarded as well as the time between a response was received and the response was forwarded.  I also had to log any timeouts or exceptions and display them with different severities in log files. &lt;/li&gt;
    &lt;li&gt;The timeout cap was the same for all clients.  I had to make the timeout settable for each client. &lt;/li&gt;
    &lt;li&gt;If a timeout occurred, I had to send an XML rejection response to the client as opposed to the system actually timing out and throwing that exception.  This way, the client's system can just keep on chugging without having to process a timeout. &lt;/li&gt;
    &lt;li&gt;Cache various client and system settings that would be refreshed every hour. &lt;/li&gt;
    &lt;li&gt;Implement a templating system to allow different XML formats to be sent to different clients. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In doing this project, I learned a lot.  It was my first time really working with threads and the performance benefits they can bring to a system if you do them right.  I learned a lot about IIS configuration and multiple processors.  I learned a lot about the guts of an HTTP request and response.  These were all new worlds to me, not just because I hadn't really delved into those areas, but because the problem domain wasn't a business problem, per se, but a framework problem.  My classes and objects all revolved around HTTP operations as opposed to business operations.&lt;/p&gt;
&lt;p&gt;It was a level of abstraction I wasn't used to working with, but I learned a lot and released a really good Proxy.  In the posts to come, I'll spin out how I handled the different things outlined above and what I learned that I could carry with me to other projects.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/ontheledge/aggbug/135008.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/ontheledge/comments/135008.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/ontheledge/comments/commentRss/135008.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/ontheledge/services/trackbacks/135008.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Culture Club</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/ontheledge/archive/2009/09/21/culture-club.aspx" />
        <id>http://geekswithblogs.net/ontheledge/archive/2009/09/21/culture-club.aspx</id>
        <published>2009-09-21T13:16:17-05:00:00</published>
        <updated>2009-09-21T13:19:14Z</updated>
        <content type="html">&lt;p&gt;The first bug I was asked to fix, here, was a bug in the Q Framework.&lt;/p&gt;
&lt;p&gt;Our websites use a little pop-up, calendar datepicker (I believe it's the &lt;a href="http://docs.jquery.com/UI/Datepicker"&gt;jQuery datepicker&lt;/a&gt;, but I'd have to check).  The problem we were experiencing is when we added a UK client.  As most of you know, the UK displays dates in DD-MM-YYYY format as opposed to the US MM-DD-YYYY format.&lt;/p&gt;
&lt;p&gt;This trivial detail actually has a wide range of implications.  First of all, any US-oriented datepicker is going to have a conniption if you pass it a date like 24-06-2007.  In our case, it rendered the control inoperable.  The page worked fine - you just couldn't change the date.&lt;/p&gt;
&lt;p&gt;The other side of the problem was on the data side.  It's one thing for 24-06-2007 to throw an error; it's a completely different thing for 06-07-2007 to select data from June 7 when what you really wanted was July 6, especially in a report.&lt;/p&gt;
&lt;p&gt;In our application, we get the country of the organization the login belongs to - so our app knows our UK client is in the UK.  The hack solution for this is to find our code that deals with date formatting on our pages and reports (which is mostly in one spot - a few rogues out there) and slide in an if statement.  If this is our UK client, use this format, otherwise leave it in US format.  That solution does fix the problem in a very fast timeframe, and the code is so simple that even junior-level developers can understand and modify it.&lt;/p&gt;
&lt;p&gt;The problem is that I'm setting myself up for a death spiral.  As we move into other countries and cultures, I'm going to be adding more and more conditions and more and more hard-coded formats to that logic.  That's assuming we even remember to do it when we add a new client from a new country.&lt;/p&gt;
&lt;p&gt;The first thing was to check and make sure that the thread's Culture property was being set.  When the user logs in, we should be finding their country/culture information from persistence (it's the database in this case) and setting the thread's Culture to it.  Something along the lines of:&lt;/p&gt;
&lt;p&gt;&lt;font color="#008080"&gt;Thread&lt;/font&gt;.CurrentThread.CurrentCulture = &lt;font color="#008080"&gt;CultureInfo&lt;/font&gt;.CreateSpecificCulture(organization.Culture);&lt;/p&gt;
&lt;p&gt;So, it doesn't matter where you're logging in from, what our culture is, or what yours is, we set the thread's culture to match yours.  This should take care of many default formatting issues, including dates.&lt;/p&gt;
&lt;p&gt;This was already being done, so after poking around, I found our reporting datepickers and fields were using a date format hard-coded to DD-MM-YYYY.  It's easy enough to change this.&lt;/p&gt;
&lt;p&gt;pickedDate.ToString(&lt;font color="#800000"&gt;"d"&lt;/font&gt;, &lt;font color="#008080"&gt;Thread&lt;/font&gt;.CurrentThread.CurrentCulture)&lt;/p&gt;
&lt;p&gt;Maybe not the most impressive coding in the world, but I was the first developer to make a change to the Q Framework other than the author, and that's pretty cool.  Also, this little bug fix turned out to be little because the existing codebase took the Single Responsibility Principle quite seriously.&lt;/p&gt;
&lt;p&gt;Ok, I actually did have to change code in two places and not one place, so Plato's ideal might not have been hit yet, but still.  Coding a fix in two places that fixes about 20 other applications is still pretty nice.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/ontheledge/aggbug/134950.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/ontheledge/comments/134950.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/ontheledge/comments/commentRss/134950.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/ontheledge/services/trackbacks/134950.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Pathfinder and the Zombie Apocalypse</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/ontheledge/archive/2009/09/18/pathfinder-and-the-zombie-apocalypse.aspx" />
        <id>http://geekswithblogs.net/ontheledge/archive/2009/09/18/pathfinder-and-the-zombie-apocalypse.aspx</id>
        <published>2009-09-18T13:09:39-05:00:00</published>
        <updated>2009-09-18T13:14:20Z</updated>
        <content type="html">&lt;p&gt;I tend to always have side projects going on.  I think many developers are like this, either because we want to learn new things or have the opportunity to work on things that directly interest us or to make a little extra cash.&lt;/p&gt;
&lt;p&gt;Two of my side projects are the Pathfinder Project and Zombie Apocalypse.&lt;/p&gt;
&lt;h3&gt;Pathfinder Project&lt;/h3&gt;
&lt;p&gt;There are two kinds of companies in the world: the ones that listen to what consumers want and give it to them, and the ones that shove what they want to give you down your thoat and spend tons of money making you think you have no real alternatives.  &lt;a href="http://paizo.com/"&gt;Paizo Publishing&lt;/a&gt; is an example of the first type and, as such, are not as big and successful as &lt;a href="http://www.wizards.com/"&gt;their second type counterpart&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I'm a DnD nerd from way back, so I was excited about Paizo putting out &lt;a href="http://paizo.com/pathfinderRPG"&gt;Pathfinder&lt;/a&gt;, which is an evolution and streamlining of the DnD 3.5 system.  The game just released last month.&lt;/p&gt;
&lt;p&gt;Frustrated with the frequent database and performance woes of a &lt;a href="http://www.dndonlinegames.com/"&gt;DnD onling gaming site that I enjoy&lt;/a&gt;, I decided to create a site for online Pathfinder games that would not just perform faster and have less database worries, but would provide additional features and ways of doing things that would make running online games easier as opposed to DnDOG's approach of basically taking forum software and adding some things to make them more useful for running online games.&lt;/p&gt;
&lt;p&gt;This project is fun for a number of reasons.  The first reason is that it's an exercise in DDD (Domain Driven Design) using a domain that I'm very familiar with, so I'm free to explore different methodologies that interest me without having to spend a ton of time modeling an unfamiliar business.  It uses &lt;a href="http://fluentnhibernate.org/"&gt;Fluent NHibernate&lt;/a&gt; for the O/RM (using the AutoMapping features), &lt;a href="http://www.gallio.org/"&gt;Gallio / MbUnit&lt;/a&gt; for tests, and the &lt;a href="http://www.asp.net/mvc/"&gt;ASP.NET MVC Framework&lt;/a&gt; for the... well... the MVC framework.&lt;/p&gt;
&lt;h3&gt;Zombie Apocalypse&lt;/h3&gt;
&lt;p&gt;A few weeks ago, I came down with a really bad cold and, under the influence of heavy drugs, I began to write a browser-based zombie survival roleplaying game - sort of an improved version of &lt;a href="http://www.urbandead.com/"&gt;Urban Dead&lt;/a&gt;.  I was surprised at how easy this turned out to be, and even more surprised at response from gaming forums when I began to pitch the idea.&lt;/p&gt;
&lt;p&gt;The hardest part is the actual rules and mechanics, not the coding.  It's hard to come up with a fairly balanced system that will hold people's interest.  For instance, if you cap a character's development, what will keep them interested in playing?  But if you have no caps, then veteran players will become essentially unstoppable juggernauts.  How do you balance between a zombie and a human who will have fundamentally different ways of fighting?&lt;/p&gt;
&lt;p&gt;Anyway, the URL I bought is &lt;a href="http://www.zathagame.com/"&gt;http://www.zathagame.com/&lt;/a&gt;, and its release is evidently eagerly awaited by many Internet gaming nerds.&lt;/p&gt;
&lt;p&gt;It uses the same rig as the Pathfinder Project, except the domain turned out to be surprisingly simple, so I use &lt;a href="http://msdn.microsoft.com/en-us/library/bb425822.aspx"&gt;LINQ to SQL&lt;/a&gt; for persistance.  I realize Microsoft isn't going to develop that technology further, but what it already does is quite sufficient for this particular project, and I doubt I'll be calling up Microsoft to support it, since calling Microsoft support ranks just under "Slide down razor blade into bucket of iodine" on my list of "Things to Do to Shorten my Time in Purgatory."  Besides, if it's good enough for the &lt;a href="http://www.nerddinner.com/"&gt;NerdDinner&lt;/a&gt; folks, it's good enough for me.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/ontheledge/aggbug/134916.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/ontheledge/comments/134916.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/ontheledge/comments/commentRss/134916.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/ontheledge/services/trackbacks/134916.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Creating Attributes</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/ontheledge/archive/2009/09/16/creating-attributes.aspx" />
        <id>http://geekswithblogs.net/ontheledge/archive/2009/09/16/creating-attributes.aspx</id>
        <published>2009-09-16T09:26:14-05:00:00</published>
        <updated>2009-09-16T09:53:46Z</updated>
        <content type="html">&lt;p&gt;EDIT: Lesson learned.  Don't copy and paste code from Visual Studio into this blog.&lt;/p&gt;
&lt;p&gt;This was something I did not know how to do until I started working here, and since learning it, I've been finding uses for it all over the place, both in my work projects and in my own projects.&lt;/p&gt;
&lt;p&gt;In previous posts, I talked about how we often use attributes to store metadata as opposed to getting those values from a database or an XML/config file of some kind.  Metadata is something that comes up in virtually every .NET application.  If you have a connection string, you've got metadata - information about how your code is supposed to work and/or information it needs to do its job.  Depending on what your metadata is being used for and how often it changes, attributes can be a handy way to store and use that metadata.&lt;/p&gt;
&lt;p&gt;To create your own attribute, you first create a class that inherits from System.Attribute.  You also include some metadata as to how your attribute can be used.&lt;/p&gt;
&lt;p&gt;For example, the class definition for the ControllerRegistration attribute looks like this:&lt;/p&gt;
&lt;p&gt;[&lt;font color="#008080"&gt;AttributeUsage&lt;/font&gt;( &lt;font color="#008080"&gt;AttributeTargets&lt;/font&gt;.Class, AllowMultiple=&lt;font color="#0000ff"&gt;true&lt;/font&gt;, Inherited=&lt;font color="#0000ff"&gt;false&lt;/font&gt; )] &lt;br /&gt;
&lt;font color="#0000ff"&gt;public class&lt;/font&gt; &lt;font color="#008080"&gt;ControllerRegistration&lt;/font&gt; : &lt;font color="#008080"&gt;Attribute&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;So, we have the class ControllerRegistration inheriting from Attribute.  We then put metadata on this class in the form of the AttributeUsage attribute (metadata, in this case, is information about how our code is supposed to work).  You set AttributeTargets to specify what things this attribute can be set on - classes, properties, methods, etc.  AllowMultiple describes whether or not this attribute can appear more than once on the same item with different values, and Inherited describes whether or not this attribute and its values get passed to classes that derive from a class where you're using that attribute.&lt;/p&gt;
&lt;p&gt;At this point, you can do virtually anything you would normally do in a class.  Most commonly, you pass values into a constructor and/or set properties.  If I were writing the code for the AttributeUsage attribute, for example, I would make a constructor that accepted a value of AttributeTargets, and I would define the properties AllowMultiple and Inherited (there's more that can be set in that attribute, but I'm just sticking with the code you see, above).&lt;/p&gt;
&lt;p&gt;In our ControllerRegistration attribute, we have a constructor that accepts a string value that represents the route that controller listens for, and it gets set to an internal variable.  We've also defined multiple properties in the ControllerRegistration class that can be set in the attribute.  Just to keep things simple, our constructor looks like this:&lt;/p&gt;
&lt;p&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt; ControllerRegistration(&lt;font color="#0000ff"&gt;string&lt;/font&gt; route) &lt;br /&gt;
{ &lt;br /&gt;
  _Route = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#008080"&gt;RoutePattern&lt;/font&gt;(route); &lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;So, when a class uses the ControllerRegistration attribute, it looks like this:&lt;/p&gt;
&lt;font size="2"&gt;
&lt;p&gt;[&lt;font color="#008080"&gt;ControllerRegistration&lt;/font&gt;(&lt;font color="#800000"&gt;"/I/Am/Many/Levels/Deep/{id}/"&lt;/font&gt;)]&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;That string is passed into the constructor, and we use it to build a RoutePattern.  Obviously, you can do whatever the heck you want in your constructor.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;We've also written some properties for that attribute which you just write like normal properties - no special metadata or anything - and you set them in your attribute the same way you see AllowMultiple = true set in the AttributeUsage attribute, above.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;Ok, so now you've got your custom attribute, and you've used it in a few classes.  How do you get that information back out and use it in your code?&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;Assemblies, classes, methods, properties - anything that could have a custom attribute in it has a GetCustomAttributes() method that returns an array of custom attributes attached to whatever you used the method on.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;For example, if I wanted to get the ControllerRegistration off a particular class, I might do something like this:&lt;/font&gt;&lt;/p&gt;
&lt;font size="2"&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;
&lt;p&gt;&lt;font color="#000000"&gt;&lt;font color="#0000ff"&gt;object &lt;/font&gt;[] attributes = type.GetCustomAttributes(&lt;font color="#0000ff"&gt;typeof&lt;/font&gt;(&lt;font color="#008080"&gt;ControllerRegistration&lt;/font&gt;), &lt;font color="#0000ff"&gt;false&lt;/font&gt;);&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#808080" size="2"&gt;Where "type" is the type of the class I was getting the attribute from.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#808080" size="2"&gt;Now, I have an array of matches for the ControllerRegistration attribute (it could possibly have multiples).  I can do whatever I need to do, now, such as loop through the array, cast each item as a ControllerRegistration, and access its properties and pull the info out, or pass the attribute into the constructor of another object, or whatever I'm going to do.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#808080" size="2"&gt;As I mentioned in other posts, what we usually do is, when the application starts up, we get those attributes and populate Descriptor objects that hold the values of those attributes so we don't have to do that reflection as part of the normal application use, but you certainly don't have to do that, and for smaller operations, we just go ahead and pull the attribute values during normal usage.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#808080" size="2"&gt;Just think of custom attributes as a data store for information about your class, property, or method.  It could be security information - like a security level or an approved role.  It could be mapping information to a database, URL, or other resources.  It could be a type of some kind.  You can get a ton of mileage out of these guys; the only thing you have to watch is managing your reflection so you don't bog your processing down doing a ton of it with every operation.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#808080" size="2"&gt;But if done properly, it can be a very easy way to associate unique data with your classes.&lt;/font&gt;&lt;/p&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;img src="http://geekswithblogs.net/ontheledge/aggbug/134844.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/ontheledge/comments/134844.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/ontheledge/comments/commentRss/134844.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/ontheledge/services/trackbacks/134844.aspx</trackback:ping>
    </entry>
</feed>
