www.codinghillbilly.com   kyle.baley.org  Subscribe / Contact
 
 
 
 
LATEST POSTS
Wednesday, December 12, 2007

Greetings brothers and sisters and solidarity to you. The revolution is off to a tremendous start. We have integrated continuously and Comrade Marc Davis has won a key early victory by excising the putrid web service that so fiendishly guarded our data access layer.

As for myself, I have just returned from a bloody battle with the enemy and have come away battered but triumphant. It was a great blow to the despots of uncohesiveness!

Our wily foes tried to gain the upper hand early by striking when our defenses were low. After opening a seemingly benign file, we were awash, AWASH I tell you!, in a veritable SEA OF ORANGE running along the right side.

I stared dumbfounded at the awesomeness of the task before me. "How can this be?" asks I, "this is no mere autogenerated class? This class was typed by hand. Clearly by the devil himself!" No matter, with a cry of "ONWARD!!! TO BE RELEASED FROM UNDER THE OPPRESSIVE THUMBS OF THE HIGHLY-COUPLED SWINE-PIGS!!" I leap headlong into the fray.

My battle begins and I become the Comment Warrior. It is a bold move because of the sheer numbers. <summary> tags that hold no relevance, <param> tags for non-existent parameters. No comment survives. Void methods have been tagged with <returns>Nothing</returns>, a move which stuns me at first but I quickly recover. After several skirmishes, I no longer notice the empty lines of History: in the <remarks> tags as I go about decapitating the methods in the name of maintainability.

Soon, I see an opening! Find & Replace can take a regular expression! After a brief two-day refresher of the syntax, the first phase is mine in one fell swoop of replacing the following expression with an empty string:

///.*\n

With that, the opposing army is almost 1000 less strong. But the enemy is quick and responds with waves upon waves upon waves of:

    catch
    {
        throw;
    }

along with their slightly bigger pawns:

    catch ( Exception ex )
    {
        throw ex;
    }

These blocks are thrown at me from *every single method*. Some even have finally calls that set object references to null. Clearly, this army's overlords were trained in the style of Crouching Tiger/Visual Basic from the late 20th century.

Luckily, they are easily picked up with the Blade of Alt-Enter from my ReSharper arsenal. But after untold hours, my fingers become weary. And my Mace of Shift-Ctrl-Alt-F fails me when it is unable to reformat the 6000+ soldiers remaining in this class. But I risk a glance to the right and allow myself a brief bout of euphoria as the orange gives way to the dull gray of victory.

By this time, the battle is all but won. I drive a final blow by deleting all regions (regular expressions: \t*\#region.*\n and \t*\#endregion.*\n) and with a flourish of Ctrl+Alt+O, all references are properly qualified for the final victory!

Resistance is NOT futile!

Kyle the Understated

Tuesday, December 11, 2007

Have started a new project at the current contract and I'm muy excited about it. It's a "legacy" .NET 1.1 app that was upgraded to 2.0 by running the wizard, then left alone. It has a web service created by an architect who appears to have worked with Jeremy Miller before. It returns datasets. Lots of them. There's a DataDude project created in some CTP version that can't be upgraded. There is no CI process.

I discovered most of this without cracking open the code. I have since done so and analogously speaking, it is clearly the result of the type of relationship we hillbillies are *very* familiar with.

I'm pretty pumped to dive into it, actually. The CI process is mostly done. The tests are running regularly (2.5% code coverage, woohoo!). Now it's time to start the grand-scale refactoring.

First, however, we need to go to the customer and tell him, "The architecture of this app is not unlike something akin to roadkill. It compiles only during the waxing phase of the moon and the fact that it runs at all has restored my faith in God. I know you've been using it relatively successfully for several months but we'll need several tens of thousands of dollars from you to refactor large portions of it. When we're done, there will be no discernible difference to the application from your perspective but we in the IT department will sure feel better about ourselves."

Now I've never been able to say "discernible" out loud convincingly and I'm sure as heck not going to imply that I believe in a higher power so obviously, this isn't going to work for me. Which leads me to a tactic I've become quite fond of: Guerrilla Refactoring

Guerrilla refactoring requires some unconventional tactics. Like in guerrilla warfare, I'll need to ambush the code often. Come at it from an angle it's not expecting. Do quick, focused skirmishes and get out again before anyone notices (except the code which will be grateful to be liberated from its bourgeois oppressors).

Subterfuge and guile will be my allies. "How long will it take to implement the 'sync' function? Four hours, minimum. Change the layout of the form? A good day of coding. You need the text changed on this label? I'd say....three full days. Not including writing tests to expose the bug."

I will bear the brunt of their skeptical, leering eyes for the sake of the common good. No longer will we toil under the totalitarian regime of logic-laden views and hand-rolled data access code. Their armies will *tremble* in fear in the face of my legion of Freedom Fighter Presenters! And the fascists will COWER as I slash at them with my Sword of NHibernate!! JOIN ME, brothers (and to a lesser extent, sisters), as we stamp out the Dictatorship of Duplication and drive a *hammer* through the very heart of hardcodedness!!1!!1!!!!

VIVA LA REVOLUCION!!!!

Kyle the Pacifist

Friday, November 23, 2007

NHibernate is senstive to white space. Who'da thunk?

Here is the .hbm file that was causing problems:

       <generator class="foreign">
           <param name="property">
               _maker
           </param>
       </generator>

And the error message it eventually generated:

An exception of type 'NHibernate.HibernateException' occurred in NHibernate.dll but was not handled in user code
Additional information: unmapped property: OzarkInc.BanjoMakinThingy.BanjoFactory.
     _maker

I say eventually because it didn't actually give us any problems until we started saving new entities. Note that I have not formatted the message. The space 'twixt BanjoFactory and _maker appeared as above in our error messages. Which should have been my first clue as to the problem but it took a fellow hillbilly to find it. And since he's a smart'un and doesn't blog, that gives me a chance to increase my readership at his expense. (And since I know he wanders over here on occasion: Craig, consider this a formal goading to get your blog going.)

Anyway, back to my problems which is why you're all here. The simple fix:

        <generator class="foreign">
            <param name="property">_project</param>
        </generator>

So let that be a warning to you. Press Ctrl+K, Ctrl+D in your XML files at your own risk.

Kyle the Spatial

Monday, October 01, 2007

One of my contracts involves what is essentially a document management system where users can search for legal documents based on metadata attributes as well as their contents. I've been working on it since before the days of SharePoint and even before Content Management Server was somewhat affordable. I mention this to cut off any comments that might say, "Why don't you just use a document management system?" It's in .NET and could benefit from migration to another platform. I'm not going to do it for reasons not worth mentioning. ACCEPT IT!

There are two things worth posting about. Neither are new techniques by any stretch. The first is how to search the content and tie that into the metadata search. The second is how to restrict access to the documents (all in Word format) which are not restricted by IIS by default.

Searching

In order to search the contents of the repository, I'm using a technique that's been around for many moons. It starts with Microsoft Indexing Services (right-click My Computer, select Manage..., and it's under Services). I created a catalog and added the directory containing my documents. Easy enough. Now I have a catalog you can query from code using the Indexing Service query provider.

I'd give you sample code but I don't have any; I don't query the catalog from code. It's no good to me on its own. I need to merge the results in with the metadata search in SQL Server. And rather than get one set of results from SQL Server and another from Indexing Services and merging them, I'm letting SQL Server do everything.

To do this, I added a linked server to SQL Server:

EXEC sp_addlinkedserver MyDocs, 'Index Server', 'MSIDXS', '<Indexing Service Catalog Name>'

The first parameter can be whatever name you want. The next two are fixed and the last is the name of the Indexing Service catalog.

From here, you can query the results directly from SQL Server and join them with any other query you want. For example:

SELECT      MetadataField1, MetadataField2, DocumentFileName
FROM        doc_metadata dl
INNER JOIN  OpenQuery( MyDocs, 'SELECT Filename FROM SCOPE( ) WHERE CONTAINS( Contents, ''<search term>'' ) ') q
ON          dl.DocumentFileName = q.Filename
WHERE       <filter conditions>

And just like that, that squirrel's done, as my pappy used to say. The Indexing Service includes a bunch of properties you can return if you like, but for my poor man's document management system, all I need it for is to filter the list of search results.

NOTE: Out of the box, the Indexing Service will index all forms of Office documents. For anything else, you'll need to find an appropriate filter that plugs into the service. Adobe makes one for PDFs but that's the extent of my knowledge.

Restricting access to Word documents

The application uses Forms Authentication to ensure you have appropriate access to the system. There are three roles: admin, subscriber, and guest (and an implied fourth role: ya can't git in). With the default forms authentication setup, anytime you navigate to an .aspx page, it will automatically redirect to the login page. This doesn't hold true for "unmapped" file extensions, such as image files or documents.

By "mapped", I mean that IIS recognizes the extension and maps it to an ISAPI filter. Whenever IIS receives a request for a file with an extension it knows about, it filters the request through the corresponding ISAPI filter, which can then perform whatever funkiness it needs to before and/or after the request.

Without getting too technical about the ASP.NET ISAPI filter (mostly 'cause I don't know too much about its inner workings including whether it actually *is* an ISAPI filter vs. an ISAPI application), I wanted any requests to Word documents to redirect to the login page if the user hadn't logged in. The same as any other page. So in IIS, I went to the application properties and added a mapping for .doc files (from the Virtual Directory tab, click Configuration..., then Mappings) to the ASP.NET executable (usually C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll or something akin).

With that in place, users can no longer navigate directly to Word documents. Such requests will be re-directed to the login page. But there is one last requirement: guests aren't allowed to view documents. Easy enough: add a separate web.config to the documents folder restricting access only to subscribers and admins:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
     <system.web>
          <authorization>
               <allow roles="subscriber, admin" />
               <deny users="*" />
          </authorization>
     </system.web>
</configuration>

Note: You can also accomplish this with a <location> element in your application's main web.config file. I picked this method because I have a feeling I'll be moving the documents out to a separate virtual directory altogether very soon.

And that's that. I shan't go into the details of setting up your roles but as you may have guessed from the web.config, that is a requirement in order for this to work. It's pretty straightforward Forms Authentication stuff so Google should be able to help you out easily enough. If not, my door is always open.

So with these two techniques, I now have a method for users to search the contents of documents without allowing them to actually open them. Maybe I can get a job at www.experts-exchange.com.

Kyle the Restrictive

Friday, September 21, 2007

I'm faced with a bit of a quandary, which isn't so unusual except that this time, it doesn't involve a sister-cousin and a priest. I have carte blanche to work on an updated version of an application for my dad's company. And excited am I at the prospect of applying some of my recently obtained knowledge in a relatively unrestricted space.

The quandary I've been mulling over, though, is the UI. The original app is web-based and seven years old when choices were fairly limited when you built an app that needed to be accessible in multiple offices. It is fairly XML/XSL/XMLHTTP-y which is what I was into at the time but for the most part, it's your average everyday ASP app.

Fast forward to 2007 and your options include, but are not limited to: "Traditional" ASP.NET, ASP.NET AJAX, Smart Client/ClickOnce, Ruby on Rails, Silverlight, SharePoint, MonoRail, Spring.NET, ASP.NET AJAX Control toolkit, CAB (okay, I'm not really serious about that one), WPF, WCF/Web Services. And various combinations thereof.

And those combinations can be a little tricky. How does ASP.NET AJAX fit in with Silverlight? Can I reasonably use ASP.NET AJAX Controls within a MonoRail view? Is it even possible to get CAB to compile? It seems that making a decision to use one of these may have an impact on how to (or even whether to) use others.

So let it not be said that having free reign on a project is always a good thing. At present, I'm planning to fall back on my standard consulting strategy. Namely, start with technology that makes sense for the project and put all the shiny ones on my wish list aside. If I can justify at least investigating using any of them later, then I will.

Not that that makes the decision any easier. "SmartClient or web app?" is a pretty fundamental question with pros and cons on both sides. Hopefully, my one brother will insist that he has to be able to use it at home on his iMac in which case, I don't have to think about it. After that, I'll start with MonoRail (and add "of course" to that statement to make it sound like I roll with the big boys) and see where life takes me.

I've said it before: It's hard out here for a hillbilly.

Kyle the Chosen

Wednesday, September 19, 2007
After a year and a half as the sole developer on a content management project, where my programming was limited to writing utilities to assist with data loads and *shudder* writing OScript, it is freakin' fanTAStic being on a real development team again. And an agile(ish) one at that. It's great being able to discuss nice meaty problems like how to layer your application or how best to deal psychologically with the frustration that is the VSTS merge tool.

Now this being my first real agile experience (or at least the first one that's been officially called that), I'm not totally familiar with the conventions. But it seems to me that agile shops could benefit from a role that I'll call The Littlest Hobo, for lack of a better term. That is, someone who goes from project to project, lending a hand where pain points exist.


Maybe tomorrow, he'll wanna settle down. But until tomorrow, he'll just keep codin' on
Many projects may have something like this in some regard. I imagine the scrum master plays this role for higher level impediments but I'm thinking at a more detailed level. Someone whose sole job is to pair with a developer for a morning on a task, then review code on a different project in the afternoon. The next day, he or she would examine the build process of a third project and see if it could be improved (and it always can). Another time, perhaps he or she could mentor someone on ReSharper shortcuts while they code.

Essentially, I'm thinking of someone working outside of a single project who can provide an outsider's perspective during the development process. And it doesn't necessarily need to be one person's full-time job. It could be a role that is passed around among senior developers every week. It doesn't even need to be a role that is fulfilled every week either. If you have a small group, maybe one person takes it for a week, and then it stays unfilled for a couple of weeks.

The impetus for this idea was an upcoming code review. Few people will deny the benefits of a code review in theory but in practice, I've been on both sides of the review and very often, there is no "ideal" time for a code review. Often, one or both of the reviewer and the reviewee are none too pleased to be ripped away from their work even if we recognize that it is something that needs to be done. It's difficult to coordinate a review time that isn't "crunch" time on one project, let alone two (presuming the reviewer is on a separate project).

That's where The Littlest Hobo could help out. This person's schedule could be almost set in stone save for the specific projects and people involved. E.g. Tuesday morning: Pair with someone. Tuesday afternoon: Review code on some project. Wednesday morning: Increase code coverage for some project. Thursday afternoon: Code review. Monday morning would be reserved for filling in the blanks where it says "some project" or "someone".

Personally, I think it would be a helluva fun role. Not full-time, mind you, but once every couple of months it would be a nice break from the ol' day-to-day, doncha know.

And for you nostalgic Canucks who are already singing it in their heads, here's the theme song.

Kyle the Nomadic
Wednesday, September 12, 2007
The hillbilly is feeling brief so I'll cut to the chase. The following test succeeds in NUnit but fails in MbUnit:

            decimal? nullableDecimal = 100m * 3.281m;
            Assert.AreEqual( 328.1m, nullableDecimal );


The error in MbUnit: Equal assertion failed: [[328.1]]!=[[328.100]]

The way to get this to pass in MbUnit (and still in NUnit) is:

            decimal? nullableDecimal = 100m * 3.281m;
            Assert.AreEqual( 328.1m, nullableDecimal.Value );


If you write out the value of nullableDecimal to the console you will indeed see that it is 328.100 so I suppose technically, MbUnit is correct in claiming that the values aren't equal, although it sure looks like it's comparing string representations rather than actual values.

So in this case, my opinion is that NUnit handles things better because it allows you to use the variable in a more natural way. I.E. It doesn't shove in your face the fact that the variable is nullable.

Caveat: Don't take this as an endorsement for NUnit. The hillbilly still prefers MbUnit because he likes to pretend it stands for "Mountain boy unit".

Kyle the Nullable

Monday, September 10, 2007

Have been following a small, but growing, discussion on various approaches to design. The initial post I saw was by Jeremy Miller on the various double D's (heh!) with a sort of rebuttal/clarification by Scott Bellware. Personally, I don't feel I'm experienced enough to add my thoughts on the various flavours of x-driven design but I would like to add one: UI-driven design. (And my apologies to whomever posted saying they like to start from the UI. That prompted this introspective but I forget where I read it first. Jeremy Miller or Tim Heuer maybe?)

At my current POB, we recently had a nice little design session where the team hunkered down and hashed out high-level pieces of the new feature. And while the ideas were flying around, I kept wondering how some of them would be presented in the UI. I asked more than once how the screen would look and I thought the same question even more but kept it to myself 'cause I think the team was getting a little annoyed at the question.

But I didn't ask in a "are you sure you've thought this through" kind of tone. There are many cases where I simply can't grasp the subtleties of a feature unless I see how it's going to work in the final product.

One feature we discussed: adding a user to a role for a particular project. There are any number of ways that could be designed, all valid, all maintainable, all happy and shiny. And if we were to build this in JP's Nothin' But .NET course, we'd pick one, build out the domain, add some database code, then add in a screen to tie it all together at the end. And it would be good, partially because it's a classroom setting and the example is somewhat canned but mostly because JP would have the solution in his head already.

But for me personally, I like to see the screen first. How is it going to be laid out? Does the screen show all users in all roles in all projects and let you maintain it on a global level? Or do you pick a project first and manage all the users within it? Or do you select a user and manage his or her project roles? Or both? These decisions could potentially have impacts on the design, not the least of which is defining what the aggregate root is.

It seems natural to me to start with the UI. Specifically, the view. The thing that holds all the controls but isn't wired up to anything. From there, I can drive out the domain pretty easily. I don't necessarily need to start at the presenter and work up to the database but at least I have something concrete in my head that I'm working toward. And it makes sense to me to work more from the mindset of, "how is the user eventually going to use this?"

There is a danger that you code too much to the UI. That you might pollute the domain with UI constructs. After all, what is a screen but a final visual representation of a user story anyway? So why bother with the screen? But when the user story is "An administrator should be able to add a super user to a project", that still leaves a lot of room for negotiation.

To tie things back to the example, we went back and forth on the responsibility of the screen. And it wasn't until we laid out exactly which components (i.e user controls) would be on it that it become more obvious what that responsibility was. And in this example, we didn't crowd around a computer banging out HTML. Our UI consisted of a bunch of boxes on a whiteboard. But when it was finished, let me tell you, this hillbilly had zero questions about how the design would look.

Kyle the User

Wednesday, September 05, 2007

Quick nugget o' information today 'cause I'm still on the clock.

MbUnit has a couple of command line parameters I've been using lately: filter-namespace and filter-type. Both can be useful when you have several hundred tests and don't want to run all of them when you're working on one area of the app.

The informational nugget: when you use either of these parameters, it will include tests marked with the Explicit attribute in your test run. Assuming, of course, those explicit tests are included in the filter.

Kyle the Filtered

Thursday, August 30, 2007

Having been having a merry old time moving projects around in our solution in Team Foundation Server. We had a few that had strayed from the folder where they were supposed to live and we can't have free-thinkin' VS projects now, can we? Anyway, there was a bit of a learning curve involving more than one rollback. Plus I coined at least three new words and phrases but it's all good now, as the kids say. So forthwith is my guide to doing the same in your project (as in your software project, not your Visual Studio project, rather your Visual Studio solution, I'm...ummm...rambling, aren't I).

Underlying guidelines:

  • One at a time. Don't try to get cocky and move all your projects in one shot. You'll save yourself days of pain if you move them individually within one "check-in" session. (OK, maybe not *days* of pain but certainly precious minutes.)
  • Rebuild and run your tests often. After you re-add your projects, before you check in, after you re-get the latest version, pretty much every second step of the process.
  • If at all possible, make sure everyone has checked in pending changes, *especially* if they have stuff checked out in one of the projects you intend to move.

Now to the heart of the matter:

  1. Make sure you have the latest version of the solution and have nothing checked out.
  2. Rebuild and run your tests.
  3. Remove the project from the solution. TFS should check out any projects that have a reference to the one you just emasculated.
  4. Physically move the project to where you want it to be in Windows Explorer.
  5. Re-add the project to the solution. It will be marked as "not under source control" which is a bit of a lie.
  6. Loop through each project in the solution checking to see if it has been checked out. This is your indication that the project has a reference to the one you just moved. Re-add the reference to the moved project.
  7. Re-build and run your tests.
  8. Open the "Change source control" dialog. (Alt-F, R, O)
  9. Unbind the project you just moved and click OK. It should be easy to find as it will be marked as Invalid.
  10. Add the project back to source control. (With the project selected, Alt-F, R, E.) With any luck, TFS should add it in the appropriate path, adding any necessary folders along the way.
  11. Re-build and run your tests.
  12. Check-in your changes.
  13. Re-build and run your tests.
  14. Open the Source Control Explorer (from Team Explorer) and find the project in its old location. Delete it and check-in your change.
  15. Re-build and run your tests.
  16. Repeat ad infinitum.

One thing to watch out for is references to third-party assemblies. When I re-added our data access project, the compiler complained about a couple of NHibernate methods not existing. I dropped and re-added the NHibernate reference and they went away. If I had to guess, I would say that I have an old version of NHibernate in my GAC which the project tried to use after I moved it.

Kyle the Gatekeeper

Monday, August 27, 2007

How's this for obscure? Our solution contains a .dbproj file, which for those not in the know (including me up until about three days ago), is a type of project that is added when you install Visual Studio Team System for Database Professionals (pka DataDude after the legendary surfer that built it). We also use Cruise Control on a build server which does *not* have Visual Studio Team System for Database Professionals installed.

The issue was that the build would fail on the build server because of some reference to VSDBPro in the dbproj. Specifically:
D:\ccnet\projects\CritterClassifier\Source\Database\EHTDB.dbproj(75,11): error MSB4019: The imported
project "C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0\TeamData\Microsoft.VisualStudio.TeamSystem.
Data.Tasks.targets" was not found. Confirm that the path in the <Import> declaration is correct, and
that the file exists on disk.

No problem, says you, why not simply ignore the project in the configuration that the build server uses? Well, says I, don't be actin' all high 'n mighty 'til you gone done tried it yerself! If you do, you'll discover that the error still occurs, although it doesn't actually cause the build to fail. (Yeah, it sounds whacky but I ain't elaboratin' so you'll have to try it to see it in action.)

The error doesn't actually occur when the project is compiled, mostly because the project isn't compiled during the build. It happens when the .dbproj file is loaded. (NOTE: We're using msbuild against the .sln file.) Opening the .dbproj file in a text editor, you'll see:

 <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v8.0\TeamData\
Microsoft.VisualStudio.TeamSystem.Data.Tasks.targets" />

My fix: add a Conditional attribute to the <Import> element:

 <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v8.0\TeamData\
Microsoft.VisualStudio.TeamSystem.Data.Tasks.targets" Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v8.0\TeamData\
Microsoft.VisualStudio.TeamSystem.Data.Tasks.targets')" />

This tells whomever is parsing this sucker not to import the project if the file doesn't exist. Of course, you won't be able to compile the project in this case but the build server doesn't need to know that...

Kyle the Finagled

P.S. Another potential fix is to compile the projects with NAnt instead of MSBuild, which I think is preferable if you can get away with it.

Wednesday, May 16, 2007

Have been gathering requirements for the land surveying application I'm working on for my brothers and it's an interesting exercise doing so remotely. But one of the things that has worked remarkably well is using an instant messenging client rather than a phone call.

There are two things I've come to like about it: First, there's a copy of what was said. Granted, it's not in the most structured format but at least it's searchable from a SharePoint site.

Secondly, and your results may vary, but I find it's easier to stay focussed on one aspect of the requirements when you're typing things out. People are less likely to "blurt" things out when they have to type it in. This is typically more pronounced if you can type faster than they can.

And it forces them (eventually) to explain things in a way that's easy to understand. I put (eventually) in parentheses there because it takes a few initial prompts of, "what do you mean?" before some people get in a mode where they put some thought into what they're typing. But when they do, they are a lot less likely to start sentences without knowing how they are going to end, which is a problem I find myself battling sometimes when I'm speaking aloud.

It's kind of a variation on the theme: The act of explaining a problem is enough to identify a solution. A theme I've been sorely lacking in my little caribbean hovel. Of course, it helps that the client is my own family and they know how anal I am about grammar in MSN Messenger.

But in general, I still find most people put more effort into what they type than what they say. Maybe it's the impression that anything typewritten is more formal than the spoken word. Maybe in the back of their mind, they're considering that what they say will be saved and used against them. Whatever the case, I'm liking the results.

Plus you don't need to brush your teeth before talking to them.

Kyle the Remote

Monday, May 07, 2007

I got pretty lucky with my next "contract". I'll be doing some work for my dad's company, a land surveying company where not only my dad, but all three of my brothers and my mother also work. That's literally my entire immediate family (Mrs. Hillbilly and the young'un notwithstanding).

It's an interesting environment, to be sure. My mother's nickname is the Office Nazi. Rather than Casual Fridays, they enjoy Potty Mouth Friday where everyone swears like sailors. This was apparently such a resounding success, they also implemented Racial Slur Wednesday, followed by Repentence Thursday ("I'm sorry I called you a Hebe, man").

So yeah, it ain't exactly Corporate Challenge Country.

But yes, I'm lucky to be working on this contract because I basically have carte blance on how to build the application I'm working on for them. But therein lies the rub, if you can forgive a Shakespeare-quotin' Hillbilly.

Carte Blanche can actually be a scary phrase, especially when you're neck deep in Professional Development mode. Forthwith, a list of technologies and methodologies I originally considered for this application:

  • TDD
  • DDD
  • WCF
  • WPF/E (and now Silverlight)
  • WF
  • SharePoint
  • ASP.NET AJAX

This doesn't include all of the development tools I also wanted to learn (or update my deprecated knowledge of) for the underlying code. To wit: Rhino Mocks (and mocking in general), NUnit, NAnt, NCover, Cruise Control, Spring, MonoRail, Windsor, and pretty much any other little doohickey that caught my eye in the last two months.

And keep in mind, I'm on a team of one stuck in a place where "development" refers more to how the government can find creative ways of giving away crown land.

So this morning's little epiphany is to scale back. This thing does eventually need to be deployed in the next three to six months. Yes, the deadlines are loose and yes, they'll be pretty forgiving but they are also putting out a healthy chunk of cash for this and will be expecting the same as any other client. To wit, learn on your own time and your own dime.

I'm sticking with TDD and DDD for the time being and probably ASP.NET AJAX for the GUI. Rhino Mocks, NUnit, NAnt, NCover are in but everything else will have to wait until after the first release or, more likely, an independent side project.

Kyle the Ambitious

Thursday, November 02, 2006

Haven't done anything remotely technical recently so I'll rip off another blogger's post today to keep the content flowing. In this case, JP Boodhoo's Tips on becoming a more effective developer.

It's a great list considering he probably just described what he does every day anyway. If he's reading, JP, consider making that post more permanent so that it can be revised as time passes. One item I think he left off though was: Be wicked smart.

Anyway, it seems to be sound advice and I found myself muttering, "yeah, yeah, I know I should" as I went through the list feeling guilty.

On a side note, it didn't help that I was up playing Lego Star Wars 2 until the 3:30 the night before reading this. And let me tell you, a hillbilly gets surly when he rolls out of bed at 10:00 and reads that he should have been up five hours earlier. @*%$ keener!

I jest of course. I am generally an early riser myself. (Or at least I thought I was. Five AM?!? I don't even *buy* alarm clocks that go off before six. And yes, it's possible to train them not to do so. The trick is to make an example of the first one and let him spread the word to the other alarm clocks through their secret network.)

But I've also fallen off the bandwagon of late with that. I work from home and it is waaaaaay too easy to roll out of bed whenever you wake up (usually 8:00), especially when you work in a time zone two hours ahead of the rest of your team.

As a segue, I'm going to modify JP's list slightly for people that work from home. Firstly, I like the idea of shutting down e-mail during the day (or as one commenter suggested, learning to respond only to urgent requests).

Turning off IM, though, is not an option. For the most part, it's my only means of communication with the office. But as I mentioned in an earlier post, if would be friggen fanTAStic if Messenger offered a Block This Group option. My family is getting far too bold with their technical support requests.

And specifically for home-workers: prepare each morning as if you're going to work in the office. To a point, at least. That means taking a shower and getting dressed in something other than pajamas. Doesn't have to be the full suit and tie but at least dress as if you're going out to do errands. For me, it's mostly a psychological thing. Makes me feel more like I've left the home and more importantly, helps with the disconnect between work and home. Once in a while, you can work in your underwear if you like, just to say you did, but I find I'm much more productive in pants.

And my final tip: buy my version of a PDA. Namely, a PAD. Stands for pen-assisted-data if you're wondering. I've tried Palms, I've tried iPaqs, I even tried my wife's Blackberry. The PAD is far superior. Stories data in any format and is infinitely more disposable in the event you leave it in the airport. Downside is that synchronization is more manual but I love those little things.

Sunday, September 17, 2006

There's a very distinctive method of driving in the Bahamas. I call it faith-based driving.

At first, I called it that because it appeared that they put a lot of faith into a higher power when they drove. The most obvious example comes at stoplights. When a signal light turns green, faith-based driving allows drivers who are turning to start their turn even though other drivers in the oncoming lane clearly have the right of way.

So at first, I attributed these drivers' blatant disregard for traffic laws to their strong faith in some Supreme Being, most likely Our Lady of Rapid Acceleration. Particularly strong Believers are those two, three, four, even five cars behind in the turning lane who follow the first one in a manner that severely tests the patience of the oncoming drivers.

Like I said, my first thought was drivers' faith in a higher power. More recently, I've drawn a different conclusion that is probably more accurate. To wit, people don't have faith in an unseen overlord so much as they have faith that other people on the road don't want to crash. That is, the patience of other drivers isn't really a variable. Other drivers allow idiocy on the road because they are either: a) painfully aware of how hard it is to get money out of an insurance company, or, more likely, b) not insured.

It's not quite as profound or religious, but it is a fundamental truth nonetheless, and one that I think underpins the entire Bahamian driving experience. It is still faith-based but the faith is grounded in more humanistic traits than theological ones.

But my epiphany didn't end there. This is a technical blog after all and since I have been banned for life from blogging about anything else (and someday I'll find a way of relating *that* story in a snippet of C#), I'd better get to the point quick.

As I sped through the streets of Nassau during a power outage severely testing my theory, it occurred to me that faith-based programming is just as prevalent. I have seen my share of code with comments along the lines of (depending on your particular religion-du-jour):

// I pray to God/Buddha/Allah/Zeus/Odin/Bill this works. If you are supporting this code,
// I would suggest locating your nearest farmer's market and cozying up to the booth that
// sells live chickens.

This is usually followed by code that is clearly functioning by sheer force of will alone.

But the second part of faith-based driving applies to faith-based programming as well. Other drivers and software users have the same basic goal: to avoid crashes. And both faith-based drivers and programmers will take advantage of this in their crappy driving habits/code. Whereas drivers will barrel through a stop sign assuming no one else would dare take them on, some developers will tell users in what order buttons are pressed and simply assume no user will possibly veer from that path. In the event one does and the application invariable crashes, that user will do what comes naturally: not press those buttons in that order anymore.

And like faith-based driving, the worst offenders are those who don't know any better. I'm guilty of being a faith-based programmer at times. In fact, I can think of one example not two days past where I had somehow assumed users wouldn't possibly press the back button on their browser at one point in the app I was building.

But whereas once I was blind, now I hear. And I will encourage you, pilgrims, to join me in combatting faith-based programming. Starting with your own work. The key idea is: don't have faith in your users. They will click where you want them to click for many days, maybe even months.

But at some point, usually that specific moment in time when you have, after months of therapy, completely vanquished all memory of the application's inner workings from your brain, one of them will fight baser instincts and, thinking he or she is a "maverick" who "doesn't play by the rules", click the Reverse Transaction button right after the Process Cash Transfer button simply because he or she was told not to.

And you'd better have accounted for it. Because eventually you'll come up against the user-equivalent of the person I "met" today: that rare driver with strong moral convictions, strict adherence to traffic laws and a truckload of insurance.

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Copyright © 2008 Kyle Baley. All rights reserved.
 
LATEST POSTS
 
POPULAR POSTS
 
LINKS
 
BLOG ROLL
 
CATEGORIES
 
ARCHIVE