www.codinghillbilly.com   kyle.baley.org  Subscribe / Contact
 
 
 
 
LATEST POSTS
Thursday, June 25, 2009

This post is over a week in the making. I attended AltNetBeers #9 last week in London which is making a quick rise in my list of top developer-related events, big or small. And that’s not just because I got one of the best compliments ever from someone who claims his non-IT friend reads a single IT-related blog (take that, Hanselman!). Anyway, it’s nice to know I’m reaching my target audience.

The event was not altogether removed from what Sebastien outlined at the one I attended last year which shows a degree of vision to which I only aspire. We spent a couple of hours talking on a topic of choice (as voted by attendees), then socialized until the place closed down at the unreasonable hour of 11pm. I’m told much merriment ensued afterward but, after posing for a picture, I made my way back to the hotel.

The topic at hand, and I’m paraphrasing: How do we become better developers today, and how do we create them tomorrow? Nice and subjectively vague, just how I like my open spaces. The runner up topic, brownfield applications, seemed suspiciously planted so I threw my weight behind the one we eventually chose.

Kinda concerned at how often this image is relevant to my posts

Conversation ran the usual gamut from apprenticeship programs (and thanks to Neil for the extensive historical thesis into the concept) to showing passion to defining professions to just going out there and doing it. My position through most of it was to focus more on the non-technical skillz, to the point where I think I pooh-poohed actual book learning more than I should have. If you decided, based on my advice, to drop out of university, I’d advise you to politely grovel to your dean to get back in. It’s still important. But take a psyche course or two when you go back.

Alas, we didn’t offer as much practical advice to the first part of the question as I would have liked so I’m expanding on the closing comment I made. It was essentially: Follow your instincts.

Now, there’s a danger with throwing out a broad statement like this because I made it in a very specific context. Namely, in a crowd of people who had taken time out of their lives to come to an IT-related event (albiet, one with more social activities than your average code camp; it *is* held in a pub after all). These are people who, at some level, have made a conscious decision to improve themselves on their own time. They could have had much better things to do but their instincts told them that this was an event that was more important than attending the new West End show, Deliverance: The Musical. (Side note: I know I just made that up now but MAN, the Duellin’ Banjoes scene would rock live; I suspect they’d lose a lot of people at intermission though.)

A lot of people have questions like, well, how do I make myself a better developer. The fact that they are asking those questions is the first step. The next step is to trust that they can muddle their way through their own answer. Because as we proved last Wednesday night, the same answer may not work for everybody. Me? I’m not much of a book learner. Nor, ironically, do I get much out of scanning blog posts (other than creating my own internal Google index so I know where to look later when the topic becomes relevant to me).

It’s dead simple to make yourself a better developer nowadays. Resources are plentiful and mostly free. And the ones you pay for, like conferences and training courses, are easy enough to rank with a little research (e.g. JP’s Nothin’ But .NET, Oredev, NDC). All it takes is a focused effort to make yourself better and to put some thought into how you go about it. You alone know which bloggers out there speak the same language you do. And you alone know which technologies will help you in your daily life and which ones interest you. Yes, SharePoint developers are in high demand but is it a product you want to learn and spend eight hours a day working with? (That’s not meant to be facetious actually, stop laughing.)

There will be much second-guessing and wondering which way you should go. And that’s fine. I won’t pretend I’ve made the right decisions all the time but like the software we’re supposed to be writing, most decisions are reversible. Humming or hawing about a contract in Dubai? Go for it. If you don’t like it, go home when it’s done. Worried about being away from your family that long? Well, you have some soul-searching to do but once you’ve made the decision, move on to the next one.

Was it the right decision? In my experience, unless you have direct and obvious evidence to the contrary, the answer is always yes.

Like I said, the topic is generic enough that pretty much everyone’s opinion will be valid, likely because it has worked for them personally. The underlying message I want to get across isn’t so much how to improve yourself (because you already know how to do it), but rather, if you’re in the London area, AltNetBeers is not to be missed. Many thanks to Neil, Toby, Scott, Andrew, Chris (both of them), Paul, Christian, and Lorenzo for the conversations and, of course, to the incredibly humble and reticent Sebastien Lambla for organizing and chairing the event, and also to Neil Robbins for the geek lunch two days later.

Kyle the Well-Shod

Thursday, June 11, 2009

I got an e-mail from someone wondering why his ASP.NET page was getting bigger and bigger and what this huge hidden INPUT tag was in the source. I smiled knowingly and went about my reply. That’s not the reason for this post but it is the context which led to it.

If you have an iTouch or iPhone with auto-correct turned on, here’s a little typing exercise for you. Type the following two words without having to press backspace to correct them:

  • ViewState
  • RedWings1

Capitalization doesn’t matter.

If you have the same issue I have, this will be impossible. In any application, whether it be Safari, Notes, Lucky Ladies of the Ozarks, or Twitteriffic. As soon as you type “viewst”, it is impossible to press the A or D keys. Similarly, when you type “redw”, the next key can not be I or J. In order to type these words out, you must enter some other letter, then backspace to correct it. Then it will let you type the one you want.

A quick BinG/oogle didn’t provide any answers but the iridescent Scott Reynolds provided one clue by suggesting that auto-correct was the culprit, which, of course, it was. That said, I’ve never had auto-correct actually prevent me from typing anything, only suggest.

No solution for me as yet except to turn off auto-correct, which I should do anyway, given the number of times I type tunderin’. Of course, the fact that it’s trying to prevent me from typing ViewState in the first place suggests that this is actually desired behaviour.

Kyle the Touched

1Those of you who know about my knowledge of sports may wonder how I discovered this one. Easy: I didn’t. Twas the mighty @HuntJason.

Friday, June 05, 2009

To me, nothing is more disheartening than having my optimistic view of the world negated. Yes, sometimes people do irrational things on a regular basis but in the back of my mind, I always think there is a middle ground that can be achieved somehow. That hope is never lost. Or at the very least, that it won’t affect me personally. (Side note: I jest. Look it up.)

So here’s a question: What would you do if people more experienced than you were brought in to your team to work with on a project? Would you react with fear that you wouldn’t be able to keep up, or that your job was in jeopardy, or that they’d go crazy trying to implement “new-fangled” ideas like MVP? Or would you welcome the opportunity to learn and advance your craft.

What happens when they start introducing concepts that they know in their heart of hearts will make the application better but that you don’t agree with at first glance? Do you dig in your heels and violently oppose them? Or engage in a debate to come to some common understanding?

These are leading questions, obviously, and you know what my answers are to these questions. This post is more about the people, the ones that answer yes to the former questions rather than the latter above, even if they do it subconsciously.

Simply put, it’s frustrating. I’ve tried to rationalize the responses I get but the only conclusion I can come to the fits is that there are people in this world who are not only unteachable but are also steadfastly against even trying to learn. I was so sure that these people didn’t exist.

For someone who always thinks people want to do their best and always want to improve themselves and their craft, it’s depressing. Maybe I’ve just been lucky in my career that I’ve never encountered them, or maybe I’m just insulated from them because the people that I hang with, that go to or speak at user groups and conferences, are pre-inclined to the continuous learning disposition. But it’s not just in my industry. I can’t think of a single person I know well that doesn’t want to be better at what they do, whether it’s accounting, or land surveying, or nursing.

It’s not the lack of knowledge that bothers me so much as it is the close-mindedness. Listening to barely concealed sarcastic comments like “how many cool patterns can we put into this app?” Counter-arguments like “We’ve always done it this way” or “we need to be consistent with our other applications” or simply “I don’t like it.”

I can deal with disagreement. There are others on my same team that I don’t always agree with but that I respect. When we debate the merits and pitfalls of one method vs. another, it’s based on experience and rationality.

But here’s the distinction: if, at the end of these rational debates, we end up not using my method, I’m still happy with the code I’ve written. And that I’ve gained a new perspective. Being forced to go back and remove all INNER JOINs from our stored procedures because they’re “too confusing” makes me feel like I’m losing some unseen war.

And it’s one that I didn’t think even existed, let alone had to fight.

Kyle the Disenchanted

Tuesday, June 02, 2009

“Yield” is not generally a word we hillbillies understand all too well as my meanderings yesterday can attest to. I’ve been using the yield keyword for nigh on three years now while having only a vague understanding of how it works behind the scenes. And even now, I’m not quite sure where my logical fallacy is but I’m sure that over the time it takes to write this all out, I’ll have formed an opinion.

Here is a the first test I wrote for a new class:

[TestMethod]
[ExpectedException( typeof( ArgumentException ) )]
public void Should_throw_exception_if_search_term_is_not_provided()
{
    var sut = new VacationDestinationService();
    sut.FindDestinationsByRegion(string.Empty);
}

Bear with me on the ExpectedException. I’m pretty sure my problem is that I’m writing the wrong tests but for now, let’s just follow the “thought” process.

To get this test to pass, I created the following class:

public class VacationDestinationService
{
    public void FindDestinationsByRegion( string region )
    {
        if (string.IsNullOrEmpty(region))
        {
            throw new ArgumentException("C'mon, feller. You gotta pick a place.");
        }
    }
}

Of course, I don't want this class to return void in the long run, but it gets the test passing.

Here's the next test:

[TestMethod]
public void Should_retrieve_search_results()
{
    var sut = new VacationDestinationService();
    var results = sut.FindDestinationsByRegion("North America");
    Assert.IsTrue(results.Count() > 0);
}

Again, don't get semantic on me. This isn't *really* the actual test. But like most developers, I don't want to get bogged down in dependencies and explaining context.

To pass this test, I modified my VacationDestinationService accordingly:

public class VacationDestinationService
{
    public IEnumerable<string> FindDestinationsByRegion( string region )
    {
        if (string.IsNullOrEmpty(region))
        {
            throw new ArgumentException("C'mon, feller. You gotta pick a place.");
        }

        var destinations = new List<string>(new[] {
            "Ozarks",
            "Appalachia",
            "Western Manitoba"
        });
        foreach ( var destination in destinations )
        {
            yield return destination;
        }
    }
}

And lo! This passes our test. So I re-run all my tests again before checking in, and lo!:

image

“What?!” says I, “Why is the first test failing?” Reaching for the debugger yields (teehee) no help because setting a breakpoint in FindDestinationsByRegion doesn’t do anything. That is, for all intents and purposes (pet peeve: NOT “intensive purposes”), the code in FindDestinationsByRegion is not called in the first test anymore. Hence, the exception isn’t thrown. Hence, the test fails.

If you’re the type of guy/gal to dive into the IL for this kind of thing, then you may know where this is heading. From what I can gather, the yield causes this method to execute only when the results are iterated. That is, even if we call this method and gather up the results in a variable, the code still won’t execute. But as soon as you throw it in a foreach loop, then you’ve got gold, baby.

Maybe this is what smarter people mean when they throw out terms like “delayed execution”. Maybe this is the cornerstone of lambdas. All I know is that I can’t check in my code until I’ve solved this problem to my liking.

As a test for this theory, I modified the first test slightly:

[TestMethod]
[ExpectedException( typeof( ArgumentException ) )]
public void Should_throw_exception_if_search_term_is_not_provided()
{
    var sut = new VacationDestinationService();
    sut.FindDestinationsByRegion(string.Empty).Count();
}

Note the extra call to Count() at the end of the second line. Now we are not only retrieving the results, we are iterating over them. This test passes.

So what is the big picture? Is the code wrong or my tests? Assuming I *do* want to throw an exception if the argument is wrong, is the code correct? What if someone provides an empty string to this method and never iterates over the collection? Apparently, this method won't fail in that case, but that may not be a bad thing. Or it could be because then we have code that's kind of useless.

It seems to me that the test should be modified to cause the iteration to happen and force the exception. If someone wants to call this method without iterating, I see no problem with that. I don't think.

Another thing I did was to replace the yield and return the List itself. This worked too but I don't like the idea of modifying my code for what appears to be a faulty test.

Was expecting to have formed an opinion by now but it's still kind of fuzzy. I'll let it sit for a while and perhaps a solution will present itself to me in the form of a better developer fixing it.

Kyle the Iterative

Monday, June 01, 2009

This post is brought to you by the letters M and V and P. I mention that at the beginning to set the pre-requisites.

I woke up this morning, broke open our application, and am currently staring at this method in our presenter.

public void Start( )
{
    if ( !IsAuthorized( ) ) return;
    if ( !ValidateHeritage( ) ) return;

    if ( !IsCousin( ) ) return;
    if ( HasSiblings( ) ) return;
}

My first reaction to this was that it didn’t actually do anything. The way it’s currently set up, it appears to check a bunch of guard clauses and exit if they are met. But there isn’t any actual code being executed if the guard clauses aren’t met.

Digging deeper, I discovered that the guard clauses are actually doing more than guarding. They are calling methods on the View and otherwise changing state. For example, the IsCousin method:

public bool IsCousin( )
{
    if ( _user.AuntsAndUncles.Contains( _prospect.Mother ) 
         || _user.AuntsAndUncles.Contains( _prospect.Father ) )
    {
        _viabilityCount++;
        View.DisableSafetyChecks( );
        return true;
    }

    return false;
}

Clearly, this is ain’t your mother’s guard clause. It’s updating a local variable and doing some fanciness in the UI as well as guarding.

So maybe it’s just an issue with naming. Obviously, it’s not a guard clause, so maybe I could rename it to make that clearer. An obvious name isn’t leaping out but in any case, something feels wrong about having all these methods return a boolean.

An alternative I’m considering is separating the guard clauses from the actions:

public void Start()
{
    if ( IsAuthorized( ) == false )
    {
        SetNotAuthorized( );
        return;
    }
    if ( ValidHeritage( ) == false ) return;

    if ( IsCousin( ) == false ) return;

    if ( HasSiblings( ) == false ) return;
    
    IncreaseViability( );
    DisableSafetyChecks( );
}

Clearly, this is more verbose. But it looks better to me because the guard clauses don’t actually do anything except check the state of something. The actual flow of code is more obvious (isn’t it?).

Maybe the original method is fine and I’ve been reading too much on Command-Query Separation lately. Or maybe there’s an alternative. In which case, I’d love to hear it, even given the very limited context I’ve provided.

And in order to solicit as many opinions as possible, and because I know how much we all love to prove each other wrong, I’ll make the claim that my alternative is THE DEFINITIVE way of doing this.

Kyle the Reversed

Friday, May 29, 2009

I’m in the early stages of writing a web app with a friend who has been somewhat on the periphery of ASP.NET MVC. As in, when someone says “let’s build a web app”, he doesn’t automatically reach for the MVC project template as I typically do. Bear in mind, he’s also not a web forms fan either.

Instead, he has a very specific architecture in mind that has taken me some time to come around to. A simplified version of it is thus: there is one web application for the various HTML files (and yes, they will be HTML only) and another for the “services”. The services one will serve up primarily JSON to the client which will interact with it with a very healthy dose of JavaScript. This is one reason we’ve decided on OpenRasta for the services layer.

I’ve deferred to my friend on some of this because I feel like I have too much emotional investment in MVC these days (as you can tell by my tendency to erroneously drop the ASP.NET part of the name). Suffice it to say he’s led development on some major league websites that have more traffic in an hour than I have cycles in my family tree. So I feel confident in his evaluation skillz. He has a more rounded view of the world, partially because of his experience with these websites and partially because he hasn’t been drinking the kool-aid as much as I have for some of this stuff.

One of those areas where he isn’t tightly coupled is with JavaScript libraries. Me, I’m a jQuery guy. Not because I like it better than the other libraries but because it’s the only library I’ve ever used and it hasn’t caused me any pain. He has only a passing knowledge of a few of them and attacked the problem of which one to choose more objectively.

To that end, we’ve settled on MooTools, at least for the time being. The main technical reason for this is because jQuery is getting too popular and we don’t want to be perceived as jumping on the bandwagon. We feel that if it’s good enough for Microsoft to throw its support behind, then we need to look at something else.

I jest, of course. In fact, our research shows it to be faster than jQuery and I have it on pretty good authority it is well-suited if you plan to have a somewhat complicated object model on the client. During my spike, I did find it to be more verbose than jQuery but not prohibitively so.

Another JavaScript library we’re playing with is Embedded JavaScript, which is a view engine for JavaScript. With it, you can define views like so:

<h2><%= petNameForRack %></h2>
<ul>
<% for( var i = 0; i < guns.length; i++ ) { %>
    <li><%= guns[i] %></li>
<% } %>
</ul>

This would be stored in an external file and you render it with some JavaScript like so:

function renderListOfLovers( )
{
    var jsonRequest = new Request.JSON( {
        url: "http://localhost/Services.Web/Lovers",
        method: "get",
        onSuccess: function( gunRackList ) {
            gunRackList.Racks.each( buildItem );
        } ).send( );
}

function buildItem( item )
{
    target = $("destinationDiv"); 
    var div = new Element( "div" );
    var view = "views/MyListOLovers.ejs";  // Contains the view shown above
    new EJS( {url: view} ).update(div, item);
    div.inject(target);
}

That's mostly from memory so don’t be cuttin’ and pastin’ none. In the first function, we call out to our OpenRasta service which is configured to return a list of gun racks as JSON by default. When that call succeeds, it creates a new DIV, renders the view in it, then injects it into into a target container.

All in all, it’s an interesting way of doing things. It’s nice that JSON has become kind of the de facto standard for passing stuff around with the various frameworks because it would be a pain to have to retrieve the list from OpenRasta in one format, convert it to another to work with MooTools, then another to work with EJS.

All of this pretty much worked out of the box, too. The spike involved very little actual troubleshooting. It was mostly getting used to the syntax (e.g. I would have thought the MooTools inject function would act on the target rather than the item being injected).

I also discovered you can throw an instance of a custom MooTools class into a view as well with no further changes required. Maybe that’s obvious if you are intimately aware of how JavaScript handles classes but my own experience has been limited to: new ActiveXObject(“MSXML2.XMLHttp”);

On the EJS side of things, it also comes with a bunch of view helpers which are analogous to the dumping ground that is HTML extension methods with ASP.NET MVC.

One roadblock I’ve hit is that while you have the power of a full-fledged library at your disposal with MooTools, in the EJS views, you are limited to only what it supports between the angle brackets. But as a wise man said: in the end, it’s just JavaScript so you can make it do what you want anyway.

How this will end up playing out when things get hairy is still anyone’s guess. But the pain-free spike has been pretty encouraging so far.

Kyle the Scriptified

Thursday, May 28, 2009

There is some discussion on a group about countries and states and cascading and such. Essentially centring around the ideas that: a) not every country has states/provinces/islands/territories, and b) some countries *are* states (e.g. Singapore, which also apparently does triple-duty as a city, who knew?).

As an addendum to that, I would also like to point out that not every country has zip/postal codes either. SO STOP MAKING THE &*%$ THINGS MANDATORY!

In short, if you’re going to list a country as an option, be mindful of its idiosyncrasies.

Kyle the Optional

Wednesday, May 27, 2009

I don’t own a cell phone but I love me my iTouch (which, in fact, is the missus’ cast-off from when she got an iPhone). Given the amount of time I spend waiting for things to happen, being able to whip the thing out to play with at any ti---actually, I’m gonna stop this analogy and move on…

One of the apps I bought on it was Solebon, which is a list of approximately 6,899 solitaire games by my last count. I had downloaded the free version which had about six games. I liked a couple and had a blast with it. So I figured that would scale if I bought the full version. But these days, I never play the thing.image

The reason for that is exactly the reason I bought it: more choices. I thought if I like two games out of six with the free version, then surely I’d like at least ten or so games in the paid version. But whenever I open it up for a “quick” game of something, I’m faced with a screen of thirty odd games to choose from, most of them with cryptic names like “Ambrose” or “Blind Alleys” or “Eight Out”.

There are simply too many to keep track of for me to figure out which ones I might like on a regular basis. And the “random game” feature is only marginally better because I always need to re-read the rules to whatever game I’m playing. In the end, I usually just skip over Solebon and go straight for the stand-alone Cribbage app I also got. Sure it doesn’t show the time at the time and it doesn’t always count points properly. But I don’t have to put any thought into it before I start the game.

This ties back to a project I’m working on, one in which the developers have free reign to decide on which features to include. And as a developer, my naturally tendency is “the more the better”. But as a user, it’s “don’t make me think”. Even during software installations, ninety percent of the time, I select Custom and proceed to accept all the defaults anyway.

Because of this, my teammate and I have been fairly ruthless in deciding on features. Unless it is something that 80% of users can absolutely not do without, it’s on our fictitious “future release” board.

One of the things that has seriously helped us in this regard is Balsamiq. Admittedly, I got a free license for it, but my partner didn’t and he has extolled its virtues on numerous occasions. I suspect we have saved ourselves many thousands of dollars but not working on features that may have seemed like no-brainers until we actually saw them in the context of a screen mock-up. Even something simple like an admin CRUD screen hasn’t gone unscathed. “Do we really need four columns? Will users actually care if they are able to upload a headshot?” BAM! Three days work, gone!

Obviously, this has the advantage of making the product easier to develop (at least in the short-term). But there’s another benefit. No user likes to have features taken away. Even if they are so obscure that only 3% of people use them, those 3% can be pretty vocal when they want to be.

Kyle the Optional

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

Copyright © 2009 Kyle Baley. All rights reserved.
 
CATEGORIES
.NET General (17) alt.net (4) altnetconf (9) ASP.NET AJAX (40) ASP.NET MVC (27) Bahamas (1) Bahanet (8) BDD (1) Brownfield (16) Career (8) Castle (1) Code coverage (1) Coding Style (6) Community (17) Conscientious Coding (33) Continuous Integration (6) dasBlog (12) Development (16) DevTeach (4) Domain (2) Environment (4) Estimating (1) Featured (14) Flamingo (10) Games (1) Hardware (6) Javascript (7) Linq (1) Livelink (6) MbUnit (1) Metrics (1) Miscellaneous (21) Mocking (3) NAnt (4) NHibernate (10) NInject (1) Office (3) Office Development (6) Patterns (5) Presenting (12) Professional Development (14) Refactoring (10) ReSharper (11) REST (1) S#arp Architecture (3) Security (2) Software (11) Sundry (15) TDD (18) Tools (21) User Interface (5) Utilities (7) Visual Studio (8) VSTO (1) Web development (12) Windows (3) Working Remotely (15) Workplace (2) Writing (2)
 
LATEST POSTS
 
POPULAR POSTS
 
 
ARCHIVE