www.codinghillbilly.com   kyle.baley.org  Subscribe / Contact
 
 
 
 
LATEST POSTS
Saturday, August 29, 2009

Another in the series of “reviewer feedback I’m going to deal with using dicey justification techniques” for Brownfield Application Development. This time, there were concerns that the topics covered in the book don’t go in-depth enough. One reviewer said he or she would need to reference other works in order to learn more.

My justification for that: Good!

We cover a lot of topics in the book. Automated testing, continuous integration, dependency injection, object/relational mappers. Given the scope that we chose, we can’t get in depth. That’s the choice we made when outlining said scope. But if all we’ve done is piqued someone’s interest enough to seek out more information elsewhere, I’ll consider that a success.

That said, clearly we need to set expectations for the reader. One of the underlying themes of the book is to foster a sense of curiosity and, more importantly, a sense of pride in one’s work. To make the reader aware of potential new things and encourage them to delve deeper. In short, to start the journey, not to end it. This is where careful wording at the beginning will improve things, I think.

Next up, why we’re not going to take out the alcohol-fueled rants on datasets.

Kyle the Justified

Friday, August 07, 2009

A common piece of feedback we got for early reviews of Brownfield Application Development is that the automated testing chapter should come before the automated build/continuous integration chapter. This was an awesome bit of feedback mostly because we could ignore it and instead get some air time on my blog on why we're doing it this way.

When I come into a project, my most immediate goal is usually to get it into a continuous integration environment as soon as possible. And the bare minimum for that is to get the source code and compile it. If there are tests and they pass, that's an added bonus. I'll add them to the CI process afterward.

For me, it comes down to treating your environment just as incrementally as your code. I want my CI environment up and running now. Maybe the tests pass, maybe they don't. If I dump them in there now, that adds a variable into the mix I don't want to deal with at the moment.

There's some element of personal preference, I suppose. But it's also borne from experience. At one time, I had some minor frustration trying to do everything in the automated build before dumping it on the CI server and having it fail. Just like we check in smaller bits of code more often, I like to enhance my CI process in small chunks more often.

Incidentally, CI is why we cover version control first. Not because we think you don't know anything about version control, but so that you can get your source repository prepared for continuous integration. Any hack can dump code into SVN. The important thing is whether you can get it back in an immediately useful state. Continuous integration can help determine if it's immediately useful.

Alas, the rest of the feedback for the book was not so easily dismissed. Damn you people and your "values".

Kyle the Edited

Monday, April 20, 2009

One of the more entertaining and satisfying sections Donald and I have written for Brownfield Application Development is on Development Project Archetypes. That is, the types of people you encounter on a development project. Donald’s been outlining them on his blog for the last couple of weeks and is about halfway through the list. To date, he’s covered:

  • The Ivory Tower Architect
  • The Absentee Client
  • The Disenfranchised Client
  • The Process-Heavy PM
  • The Front of the Magazine Architect
  • The Ex-Tech Project Manager

Rest assured that developers themselves will not be spared before the list is through. Beware these people. And for the love of all that is hillbilly, don’t be any of them.

Kyle the Cautionary

Tuesday, February 24, 2009

Donald Belcham and I had a conversation today that started “I believe in the iron stool.” I know what you’re thinking, “I’ve had conversations with you. They all start that way.” But the context was different this time.

We were discussing a section of the upcoming book (Google it yourself if you care about it, I feel weird linking to it so shamelessly) that dealt with the iron triangle.image It’s a familiar enough graphic. Time, resources, and functionality are inextricably connected with quality such that you can’t vary any one of them without affecting the quality of your code. Reducing resources, in absence of any other change, will reduce overall quality of the system.

A common (though slightly different) summary of the triangle is: “the software can be on time, on budget, with all the features. Pick two.” This completely ignores quality (or functionality, if you swap “all the features” with “high quality”) but is a nice catchy number to bring out in a meeting to show we’re a self-deprecating kinda crew.

The stool came in from Jeff Atwood’s take. That is, the three components are legs of a stool and quality is the seat. Reduce the time and the quality slides.

As Don and I explored each of these, it became very easy to come up with scenarios where they both broke down. For example, what if we reduce the scope of the project? With the iron triangle, that kind of implies that the quality will drop. The iron stool metaphor implies that if we increase the number of resources on a project, we necessarily have to up the time and the scope in order to maintain quality.

In the end, neither of us had a nice fuzzy feeling talking about it, even though the iron triangle is so well-known in the industry.

But the underlying message is a good one: You can’t look at any of the major factors in isolation. Changing time, scope, resources, or quality all have an effect on the overall project. We talked back and forth about how best to describe the problem. Maybe a square makes more sense? Or a dodecahedron?

The issue we had was in the treatment of the variables. To me, time and resources are inputs, scope and quality are outputs. The inputs are directly related to the outputs but they don’t interact in the same way. Increasing one side means you must increase the other in order to maintain balance.

Once the word “balance” was mentioned, a more appropriate metaphor became obvious. (Well, in fact, the words “balanced” and “unbalanced” were mentioned about five times in rapid succession before someone made the connection. It was actually pretty comical re-reading the conversation.) Namely, a scale. On one side, we have two components: resources and remaining time. On the other, quality and remaining scope.

Here’s the important part. At all times, the scale must remain balanced because each side is precariously perched over a MOLTEN PIT OF LAVA!!! If either side sinks low enough, the entire project goes up in a fiery spectacle that, while entertaining to watch, means at least one person is going down in flames. And we don’t want to see...hmmm...that actually would be pretty funn---no, no, we don’t want that. That would be bad. Failed projects, bad!

With a scale, it is not possible to make a decision about one component in isolation. If you increase the scope, for example, you have to do one (or more) of the following to maintain the balance:

  • Lower the quality
  • Increase resources
  • Increase time

imageSimilarly, if you want to increase the quality, you need to add a corresponding number of resources and/or time. Or drop the scope.

Another important component to this is that you don’t always have direct control over the components. As you near the end of the project, you may determine that you are running out of time. That is, you notice that your remaining time is going down faster than the remaining scope and the scale is starting to list to one side. So you need to make adjustments in order to maintain balance. Ditto if some of your resources start running out the door. At all times, the scale must be monitored to ensure external factors haven’t chipped away at one side of your scale.

There are still plenty of assumptions to be made. For example, not all resources are of equal weight. Simply adding resources to a project, doesn’t imply that quality will automatically go up, or that the project will be done earlier. I’m sure I read somewhere around this interweb that adding more resources near the end of a project can actually be a hindrance rather than a help. Whether or not that’s actually true, it jives with my experience.

But just the same, I like the analogy in general. It appeals to my innate sense of “I’ll never understand unless it’s in metaphor form”.

Kyle the Analogous

Wednesday, December 10, 2008

There have been numerous posts about hiring the "right" people. One of the more ideal characteristics is a passion for the industry and for learning new techniques. But as I look at more and more code written by these zealots (and I don't mean that to be derogatory because I count myself as one of them) and because I have been thinking about brownfield applications lately for some reason, a kind of pattern seems to emerge in projects written by them.

The way to recognize this pattern is if you can tell what the developer has been learning or reading about from scanning various parts of the codebase. Here's a scenario:


New guy: How are we handling dependencies in the code?

Eager and enthusiastic veteran: Oh, it's awesome, man! At first, we were just newing shite up. Then I went to JP's course and he had this pretty cool hand-rolled IoC container so we started using that in the service layer. Eventually, we took the plunge and brought in Windsor. We don't use it everywhere but some of the newer presenters do. But then we saw the new stuff in StructureMap so this one part of the app is using that.

NG: So you have four different ways to get new instances of a class?

EaEV: Yeah, but don't worry your purty li'l head over it none. We'll be standardizing on one soon.

NG: Oh yeah? Which one?

EaEV: Well, it *was* going to be StructureMap but NInject looks pretty cool...


The point being: How do you handle implementing new techniques as you're learning them? You have a web application built by a team that still things they're coding in classic ASP and now you want to move it to an MVP pattern.

Naturally, for new screens, you can do this pretty easily. But as the code grows, you eventually get to a mishmash of new MVP screens and old code-smackdab-in-front screens that everyone treats like your disfigured, but still oddly attractive sister/cousin who's kept locked in the basement except during family reunions/speed-dating sessions.

What's worse, the problem is exacerbated as new techniques come in vogue and as new people are brought on to the project.

Also, for the most part, we usually don't want to go refactorin' just for the intellectual exercise. Most of the time, I like to move to a pattern or implementing some new technique on an as-needed basis. Which means you don't overhaul the entire application just because you're working in one area. If your admin section is working, I say leave it alone, despite your psychological issues with DataSets. (But at the first sign of bugs or new features in that area, bring in your hacksaw and have at 'er.)

In any case, it's cute little dichtomy. You certainly don't want to keep doing things the old and busted way but you are hesitant to fork part of the application down a new and inconsistent path.

And this isn't limited just to large projects. I'm experiencing it even know on an application I started earlier this year. An application, I might add, where I'm the sole developer. It's an MVC app with bits of Fluent NHibernate in it but not all the mappings have been migrated over yet.

The way to avoid this, of course, is to stop learning. But if you're one of those eager types, then let's explore some options. Unfortunately, all I've got are the thoughts in my head. And keep in mind, these are the same thoughts that evoked that little speed-dating analogy a few paragraphs up.

// TODO: Refactor this when the client stops reporting bugs and adding features

This is kind of the bare minimum you can do to at least acknowledge that some work needs to be done. It's well-intentioned but not very practical. Most of the time, we leave these comments because we want to cover our asses in case someone goes looking through the code and spontaneously goes blind. In any case, if the client isn't reporting bugs or adding features, that means no one is actually using the app.

The "Refactoring" Iteration

"That's it. I've had enough looking at this code. You, Mr. Project Manager Person, tell the client that we have deemed the application unpalatable and that we are holding it ransom until such time that it we feel warm and fuzzy about working with it again."

Don't need any limbs to count the number of times this has worked for me.

Leave it the way it is and strive for consistency

If you think you can get away with this, I applaud your ability to hire Type-B programmers.

Deal with it

This is probably my default approach. Hunker down and get your work done within the constraints laid out for you. Fix what you can, when you can. The application will morph. Try to control the shape and rate in which it does so. Knock of one head of the hydra at a time and hope three more don't grow in its place. It's probably not the most glamourous position to take but like any stance that involves lowering your standards, it's easier to attain your goals.

None of this strikes me as being all that encouraging, which is probably why this post lingered in my //TODO list for so long. I'm not sure there are any solutions to this other than to practice deep breathing exercises whenever you look at the code. Best I ever hope for is to provide value for my pay and try to learn something as I go.

Kyle the Acknowledged

Monday, October 27, 2008

I'm in the early stages of a new project with the dashing and debonair Brian Donahue. On the plus side, despite his misgivings, the codebase is in pretty phenomenal shape all things considered. SVN repository, automated build and tests, ActiveRecord, views reasonably separated into MVP. Even a half-finished CI process which is impressive for a one-man team. Like any codebase, it has its share of issues but all in all, I won't be using this as a sample app for a brownfield application.

On the minus side, he reads my blog so I'll have to be more subtle in the digs I make toward my workplace.

Anyway, one of the first things I like to do when I start looking through a steaming pile of excrement that someone calls "codebase" is check out the warnings that are lingering. The code had its share with the vast majority related to an upgrade to the latest version of Rhino Mocks but without changing CreateMock. This was an easy fix as a global search and replace from CreateMock to StrictMock got rid of over 80% of the errors.

The rest were a flurry of ReSharper refactorings until I got to the final four. Four assemblies reported the error: found conflicts between different versions of the same dependent assembly.

Double-clicking this error gives a helpful message offering to add a binding section to the assemblies app.config file. I say helpful seriously there because, while I had no intention of keeping that section in the app.config, at least it was able to tell me what the error message couldn't. Namely, which assembly was causing conflicts.

Or so I thought. The new app.config section seemed to indicate that there were NHibernate conflicts among various projects when I knew for a fact that we had exactly one copy of the NHibernate dll in the entire project.

AssemblyGraph

Here's where Reflector comes in. More specifically, here's where it's extensibility comes in. Through the use of the Assembly Graph add-in, I was able to generate a picture of the dependencies. (Click on the image to the right for a bigger version.) As you can see, all referenes to NHibernate are going to the same assembly.

But as you can also see, there are three semi-related assemblies that aren't being referenced at all. Which means they can safely be removed from the various projects, yesno?

You probably think that's foreshadowing's cooler cousin, foreboding, but it's not. The answer is yes, I was able to remove them with no ill effects.

The reason I know there are no ill effects? Unit tests, baby! None o' this "let's take a stroll through the application and see if it still works" nonsense for me*. Remove the reference, run through the build process and watch the magic happen.

The reason this is important: I'm pretty sure this add-in doesn't account for dynamically loaded assemblies. And while I'm also pretty sure we would have no reason to dynamically load some peripheral NHibernate assemblies, it's nice to have a suite of unit tests backing up that assertion.

So to re-cap:

  • Unit tests good
  • Automated builds good
  • Reflector good
  • Assembly Graph add-in good
  • Subversion good (I haven't provided explicit evidence of this here but it's worth mentioning.)

Kyle the Reflectively Assembled

*Brian, if you're reading, I'm lying. I did actually go through each section and make sure it's working. But back me up if anyone asks.

Monday, October 20, 2008

I'm preparing my presentations for DevTeach and have come to realize that there is a price to pay for creativity. Here are the abstracts for three of my presentations.


Guerrilla Refactoring

Greetings, comrades. Welcome to the resistance! Our quarry today is a shamefully designed application that grows fat with duplication and crusty with hard-codedness. It feeds on itself behind a shield of corporate deadlines, each one stricter than the last. The cowardly code mocks us with cries of "We don't have time! We don't have time!" while features are grafted onto the application haphazardly with no thought to future reform!

But fear not! We have studied our enemy and have altered our attack plan accordingly. No more frontal assaults. We must liberate the code in focused skirmishes from its bourgeois oppressors! Patiently, we shall advance, tightening our grip in an ever-widening net of unit tests as we hunt down bugs like the dogs they are!

So join me, brethren and sistren! With our allies, the Design Pattern Legionnaires and the Dependency Liberation Front, we will train you to take your rightful place in the movement toward a better world, where features are not divided into tasks that are meted out to the "database gal" and the "guy that does the UI because he has PhotoShop installed". Rather, they will be fully and utterly DEMOLISHED by fully armed, multi-functional, and domain-inspired programmers full of KNOWLEDGE AND FURY!!!1!!!

Viva La Revolucion!

(adapted, of course, from my original post on the subject)


Implementing a Brownfield Ecosystem: A Cultural Extravaganza

So you missed Folklorama again, eh? Of course, you did. It's in Winnipeg. Well, fear not, coders! In this session, we'll throw so much culture at you, you'll think you're back in high school biology.

A very important aspect of Brownfield applications is shifting the culture of your team. This starts with your project's ecosystem. Many developers in Brownfield applications don't even realize how many hoops they jump through during the course of a day to do simple things like checking in code and building the application. image

In this session, we'll implement a full-fledged ecosystem for a Brownfield application. Working from the perspective of a single developer in a team, we'll cover topics such as the structure of your version control system, your check-in process, automated builds, and continuous integration. In the process, we'll talk about common pain points and common areas of friction that we can overcome with a few simple tool choices and a couple of mindset tweaks.

I'll be getting by with a little help from my friends as we simulate a team environment using well-placed and impeccably groomed plants in the audience who will act as other developers in the team, some working with me, others not so much.


Adding automated tests to an existing codebase

It may seem like heresy but there are actual real-live applications out there inimage the world that don't have unit tests! No, really! And I know it sounds crazy, but you could be brought on to one of these applications and be tasked with adding automated testing to them. 

Rare as these circumstances may be, it'll help to be prepared for them. Because it won't be as fun as you are probably imagining right now. For example, how do you automate a test for a web form that connects to a database, displays a form, then posts that data back to the database?

In this session, we'll look at techniques for integrating tests into an existing codebase that has never had them before. When do you write tests for existing code? How do you test a mammoth method/class? How do you know if you aren't breaking anything else? For answers to all these questions and more, read Michael Feathers' Working Effectively with Legacy Code attend this session.

 


You see my dilemma. I wrote these in a fit of imagination without stopping to wonder how I would differentiate one from the other. For example, how do I talk about refactoring without mentioning automated tests? How do I implement a brownfield ecosystem without doing same?

 

In the end, I believe there will be overlap among the presentations. Indeed, I will probably use the same sample application for all three. I've justified it in my head by saying that the overlap is probably a good thing to help people see the interaction 'twixt the various concepts. Plus, it means I can focus on a single element in, say, the refactoring presentation and leave some of the details to the automated tests presentation.

In any case, here is some clarification on the goal of each presentation:

Guerrilla Refactoring: How can you refactor an application for maintainability when there is no explicit buy-in from the PM and/or the business (and/or the rest of the development team)?

Implementing a Brownfield Ecosystem: A walk-through on adding source control, CI, and automated testing to an existing application. I'm planning to use plants in the audience to simulate a team environment to demonstrate what happens to you personally when others don't play by the rules. The "cultural" part comes because this is very much an exercise in changing your team's development culture. It was originally intended as a practical follow-up to Donald's Parachuting into a Brownfield Application presentation but I notice he's not doing it this time around.

Adding automated tests to an existing codebase: Here, we'll dive deeper into automated testing for an existing app. It will be sort of a continuation of the brownfield presentation which will add the testing framework but not go any further. Admittedly, it will borrow heavily from Feathers' book but I see that as a good thing.

For completeness, the fourth session I'm doing is on TDD for MVC applications. This one is more disparate than the others and should be a fun one as well, even if the abstract for it is the most boring of the four.

Kyle the Synergistic

Sunday, September 28, 2008

Not feeling too subtle today so I've given the punchline away in the title here. After wandering neck-deep into MVP and MVC, I'm now thinking about refactoring brownfield applications toward them. And it occurred to me: is it reasonable to refactor to MVC? Then, is it feasible? Then, is it even possible?

I've built started three or four MVC applications and love the framework for greenfield apps. But assuming you have a nice, healthy (and I'm using the definition "of great size") web application, would you go through the exercise of converting it to MVC?

Here are some reasons why I wouldn't.

First and foremost, your URLs will change. Instead of http://myapp/ProductList.aspx, you have http://myapp/Products/List. Depending on the size of the app, I'm not sure I'd trust a global search and replace for that. Besides which, I'd rather be using one of the helper methods to generate the URLs in MVC.

Granted, you might be able to get around this with some combination of HttpHandler or HttpModule. Whether or not there is enough benefit to be gained from MVC to go through this exercise probably depends on the size of the app, your deadlines, and just how much blogging material you want to generate.

This segues into my next point. Unless you plan to refactor every page all at once, you need a way to have WebForms pages sitting along side MVC pages. Which means you need to be able to navigate directly to some .aspx pages in some cases, and to controller actions in others. This might be possible in the same project but it makes my head hurt thinking about it. You'll be giving the routing engine a hernia with all the heavy lifting it would have to do. Either that or, again, implement your own HttpModule before the routing module in the pipeline.

Alternatively, you'd create a second web project, an MVC one, and move your UI over to it over the span of many moons. Your URLs will really get messed up as you'll be essentially working in two separate web applications.

All of this presumes your logic is separated enough to withstand such a change. When talking about refactoring to layers in the brownfield book, we recommend doing so incrementally. That is, start by creating a seam and move all the code into it leaving a little bit behind in the UI. Then repeat for the big bulk of code you moved all the way down the line to the data access. (There, now you don't have to read Chapter 8.)

Refactoring to MVC feels like this would be hard to do. Mind you, it shouldn't really be any harder than refactoring to MVP. Maybe just feels that way because of the brownfieldedness of the apps I have swirling in my head. (Full disclosure: many of which I contributed to.)

Speaking of MVP, one of the main reasons I think this is too much work is because MVP is such a reasonable alternative. Maybe not 100% idea, but it's a very viable compromise. On the one hand, yes, you still have to deal with the ViewState and the ASP.NET Pipeline and all the happiness that comes from trying to separate concerns in a real application as opposed to the contrived examples in books and blogs that make it look so easy. On the other hand, it's less work to attain and in the end, you'll end up with a more maintainable application.

So after all this windage about why I wouldn't refactor to MVC...has anyone...y'know...tried it?

Kyle the Armchair Refactorer

Sunday, August 31, 2008

I'm working on a chapter on layering for the upcoming Brownfield book, and for better or for worse, we're including a section on the onion architecture. I've heard the term mentioned for some time now but for the life of me, I can find only one meaty series of posts on it in recent months. That one caused a bit of a kerfuffle but the ado was big enough that I said to myself, "hillbilly, you don't want to be treadin' into dem waters anytime soon." But I need some excuse to do some extemporizin' and I'm hoping this will help crystallize things in my head.

I'll start with my own version of the diagram because I spent enough &*%$ time on the thing. Wanna get some mileage out of it.

image

Jeff's explained it pretty well, I think. It's clear that the Domain is at the centre and thus, is the focus of the application. I've skipped the Domain Service layer for two reasons:

  • It should be part of the Domain layer
  • There's a good chance that your domain services should really be methods on your domain objects. (e.g. FundsTransferService should really be a TransferFundsTo method on the Account object)

So here's where my take comes in. I don't like the onion metaphor, or the diagram a whole lot. For someone coming at it from a traditional n-tier approach, it's confusing. It looks to me like the UI talks to Application Services, which talks to the Domain. That is, it's not obvious that the outside layers can talk to any inside layer without some fancy footnotin'.

The problem I think is with the term "layer". It implies a level of insulation. That is, the Domain looks like it is insulated from the UI and Infrastructure by the Application Services layer. Which isn't the case by any stretch.

Next issue is that the diagram does *not* make clear what was a hard concept for me to understand initially. Namely, that the interfaces for the repositories live in the domain but the implementations in the infrastructure. And it's done without the UI referencing the infrastructure layer (usually with an IoC container).

Then there's the whole UI segment abutting against the infrastructure which is kinda wacky. Can the UI talk to the Infrastructure? Does the Infrastructure even use the Application Services? In my experience, not really. It interacts directly with the Domain.

Which brings up another issue. How does the use of DTOs affect this diagram? I'm on the fence about this, but I've seen cases where the UI doesn't ever use domain objects. The objects are translated into DTOs by the Application Services. So the UI "layer" doesn't technically have access to the Domain "layer".

Having said that, I don't know if I could come up with a better diagram. As it is, I don't know if I could even properly define "Application Services". All I know is that, for someone relatively new to this, an analogy should not need three posts to explain it.

When Jeff's posts came up, I read them with interest and they jibed with my understanding of onions in general, so I moved on. The metaphor seemed natural but I admit, I didn't look into its meaning too much. Hillbillies aren't a naturally metaphorical species.

Now I'm having to dive into it a little more and I find myself wondering if it will do more harm than good. To the inexperienced, it looks like a vastly different take on the traditional n-tier diagram. And on more than one occasion, it occurred to me that they aren't really that different. To oversimplify, you could just substitute the domain layer for the business logic layer, change the direction of some arrows, and have a passable draft of it.

On the other hand, this line of thinking does *not* bode well for me finishing chapter 8 this weekend.

Kyle the Indecisive

Monday, July 07, 2008

This started as a promotion for the dimecast I recently did on the Check-In Dance but I think it's worth reviewing in more detail.

Don't know if he coined the phrase but I first heard of the Check-In Dance from Jeremy Miller. His post on the subject is still, some three years later, accurate. In it, he describes it in relation to continuous integration but in my screencast, I talk about it in a more general setting.image

But I'm being vague. Here's the problem it solves. In a multi-team environment, it is very easy to check in code that "doesn't work". Often it works fine on the developer's machine but when it is merged into the main version control repository, which is also being updated by other developers, we end up with a version in the repository that won't compile.

Here's an example. We have a class Artist:

public class Artist
{
    public int Id { get; set; }
    public string First { get; set; }
    public string LastName { get; set; }
}

And here is some code in a user control that uses it:

protected void Page_Load(object sender, EventArgs e)
{
    var artist = new Artist();
    artist.First = "Frank";
    artist.LastName = "Sinatra";
    labelFirstName.Text = artist.First;
    labelLastName.Text = artist.LastName;
}

Now our first developer, we'll call him Huey, is working in the code and decides that First is incorrectly named. It should be FirstName to be consistent with the LastName property. So he changes the name of the property to FirstName and updates the Page_Load code that calls it. The code compiles on his machine and he checks in. All is right with the world.

Cut to our second developer, Lewis. He's working away on some new code that uses the Artist class. Let's watch!

public void SaveArtist( int artistId, string firstName, string lastName )
{
    var artist = new Artist{ 
        Id = artistId,
        First = firstName,
        LastName = lastName
    };
    _repository.Save( artist );
}

Notice that Lewis is using the original implementation of the Artist class because he is oblivious to the changes Huey is making. But when he's done, he compiles and again, it works fine on his machine. He checks in and goes home with the knowledge of a job well done.

The next day, another developer, Jackson, comes in to work. He's been away on vacation so the first thing he does is get the latest version. And lo! It won't compile. Heckuva a thing to greet a guy after two weeks of R 'n R at the local World's Strongest Man retreat. Now he has to go digging into code he hasn't looked at for weeks to find out what's wrong before he can be productive.

The culprit here is Lewis (and even Huey though he didn't really make any breaking changes). He contaminated the "one true source" in the version control repository but checking in code that, while it worked locally, does not work in the context of the entire application.

As Captain Understatement would say, this is bad. At this point, we have an application in version control that no longer compiles. Any developers that get the latest version are not able to work. And the onus to fix it is implicitly on the next developer to get the latest, not on Lewis, who created the problem. In any case, Jackson must either fix the problem or track down who made the error and calmly explain that it would be peachy keen if he fixed it when it tickled his fancy.

Either way, this situation should be considered tantamount to eating babies or using genetically-modified dandelions as a base for your hooch. Your version control repository is sacred ground. It is not meant to be trod upon by blasphemous developers working in a vacuum. At any point, your client (or anyone) could walk in and ask for the latest version of the code and you should be able to give it to him with confidence.

What Lewis should have done was the check-in dance:

  1. Make his changes to the First property
  2. Compile them locally and test to make sure they work
  3. Get the latest version of the code from version control and merge them into his local copy
  4. Compile again and test to make sure his changes still work
  5. Check-in

The third and fourth steps are the important ones and the ones Lewis skipped. They are the ones that give you the requisite confidence you need in your version control repository.

Like I said earlier, this version of the check-in dance differs slightly from Jeremy's. He was talking in the context of a continuous integration environment. This is something you should strive toward but if you don't have it yet, this version will help you get into the mindset. And even if you aren't interested in CI, the check-in dance is still a necessity to keep your repository as pristine as <editor's note: this metaphor has been removed to ensure CodeBetter does not get blacklisted by corporate web filters>.

A word on the merge in step 3. There is no doubt that this can be messy. Especially if you aren't checking in often. What can I say? Not much you can do if you want to keep your repository clean. Either check-in often or start cozying up with a merge tool vendor.

Keep in mind, though, that if you don't encourage a culture of checking-in often, you'll end up with developers that either avoid the check-in dance, or avoid checking-in at all. It's basic conflict-avoidance. If it hurts when I move my arm like that, I'm going to stop moving my arm like that.

In either case, you are wasting expensive time. If you don't use the check-in dance, you are wasting the time of the developer who has to track down an error in code he didn't write. And if your developers aren't checking in often, they are wasting time doing massive (i.e. more error-prone) code merges.

At this point in this little odyssey, I probably shouldn't be talking about wasting time. So I'll wrap up. If you want more info, I'm happy to continue this in the comments. Also, I've already linked to Jeremy's post and my dimecast on the subject above. Donald and I also talk about it in our DNR episode.

Kyle the Versioned

Thursday, June 26, 2008

I've become rather acutely aware that my content has been lacking of late in the technical department. But I do have a couple of community announcements to make that are time-based so I'll compromise a bit and combine them into a single post. Then I'll take a hiatus until I have something more generically useful to say.

First off: Next BahaNET meeting is tonight at the usual digs, IPBS House. And based on past experience: When I say Moseley Lane is right after the entrance/exit to Harbour Bay off Shirley Street, I mean it's RIGHT after. As in about three feet. You can basically make a U-turn from the Harbour Bay exit on to Moseley Lane. Don't miss it.

The topic will be: connecting a website to a database. We'll discuss basic CRUD operations and yes, we will be dragging and dropping for better or for worse. You have to know your audience. Take comfort in the fact that I'll attach a bunch of codicils as I'm presenting. Hopefully, I'll be able to demonstrate the Dynamic Data thing as well, assuming I have time to look into it.

Next announcement: Donald Belcham and I recorded an episode of .NET Rocks earlier this week and through the magic of technology, it is already available. The topic, as you may have guessed, is Brownfield development. Elapsed time 'twixt the initial e-mail and the finished product was about ten days, which is pretty amazing. Even if Carl refused my request to digitally enhance my voice so that it sounds like Humphrey Bogart. ("Of all the apps in all the contracts in all the world, she had to refactor mine.")

And to top it all off, Derik Whittaker will be releasing the first in my series of Brownfield casts tomorrow at www.dimecasts.net. First one is on setting up your version control structure. There are many more to come and feedback is welcome.

Kyle the Supersaturated

Monday, June 09, 2008

The obligatory follow-up post to the 99% of you (give or take 2%) that didn't attend my presentation, to let you know that I gave a presentation. This one is pure entertainment value only so if you're looking to code better, maybe Greg Young or Matt Podwysocki will finally post something technical.

I talked about Brownfield application development at the Florida Tweener weekend. On a side note to Joe Healy: Florida 'Twixter sounds a lot cooler. It's because of the 'x' (Come to think of it: Florida 'Twixxxter would be even better...). Nevertheless, he pulled off a pretty cool event in record time. At least from the brief bit I saw. I talked for an hour from 8:30am until 9:30am, then bolted like a cockroach (not the Bahamian kind, they're a little more lackadaisical when the lights come on).

Reason for my leaving was that I had left my family alone with a credit card in the middle of theme park central. So the rest of the day was spent at Universal Studios Orlando and its sister park, Islands of Adventure, with them. My entertainment gland was supersaturated by the end of the day. Tip: when you're going for a single day, the Express Plus passes are just about the best money you can spend there. Seriously, bring a bag of peanuts and use the food money for these incredible time-savers. By my estimate, we saved no less than three hours of line-waiting during the course of the day. Longest line was RipSaw Falls for thirty minutes. All others were less than five.

The trip home was a noble little disaster. Delayed leaving Tampa, which meant getting bumped to a later connecting flight in Miami. (Little known fact: Miami's airport code, MIA, is actually a double-entendre. I'll let you figure out the other meaning. Hint: it has to do with luggage.) This usually isn't a problem because there are anywhere between two and forty-seven flights from MIA to Nassau on any given day, depending on the blood alcohol level of the American Eagle pilots.

Today, however, all twelve remaining flights (must have been a heckuva bender last night) were oversold. And it took a couple of batted eyelashes and an eight-year-old's temper tantrum* to get us on a flight out of Fort Lauderdale the next morning on an oversold flight. All due credit to American Airlines' customer service people. They may not be competent as a rule, but they were unflappably nice in the face of a customer service disaster that, by the time we got there, looked like it had started during the Clinton administration.

Once flight confirmation was achieved, we set out to find a hotel in Fort Lauderdale. This may sound like an easy task unless you are intimately familiar with the wireless internet access in MIA, which does not recognize the Bahamas as a country for credit card processing. Nor, in fact, does it recognize the internet at all. Luckily, Mrs. Billy has a travel agent on speed dial...

The cab ride to the hotel in FLL was the highlight of the day. The driver was Kurdish and if you *really* want to hear about a "tweener weekend", listen to his stories about living 'tween Iran and Iraq for half his life.

Rest of the trip was uneventful which, ironically, makes it the best part of the flight home.

Back to the presentation. It went pretty well, I think. Started out with three early risers but ended around twenty-five strong. For me personally, it was another case of wondering why I go through the expense as I walked to the venue and wondering why I don't do this every weekend as I walked back to the hotel afterward. It really is fun though I still need to work on my audience participation skills.

The show, unfortunately, was not taped as I copied the slides over to one of the TechEd computers and barely had enough time to get the projector working. As it is, I was mike-less throughout and I'm not exactly Rush Limbaugh when it comes to voice projection.

Next up on the North American tour will be a couple of talks in the home turf. One in Calgary and the other in Edmonton. Both at the end of July and that's about as detailed as it gets so far. The Calgary site lists me as presenting on ASP.NET MVC which is good to know. Gives me a place to start anyway...

Kyle the Homebound

*Bonus trivia: I performed one of these acts myself. You may be surprised at which one. And at the level of success I achieved

Wednesday, May 21, 2008

I was invited to speak at the Florida Tweener weekend which is the weekend 'twixt the two TechEd weeks in Orlando. The schedule is up and I had no idea what the scale of this thing would be! Not only is there a full day .NET code camp but also over a dozen other activities. The ones I'm excited about are the Day of Agile, the Day of Silverlight, the Open Space, and the Mickey Mouse Club.NET session. The last one's not on the schedule yet but I have high hopes.

For my part, I'll be presenting on Brownfield applications, mostly because I have the presentation ready (well, actually Donald Belcham has the presentation ready). Luckily, I'm the first session in the morning on Saturday which leaves the rest of the weekend to drink it all in.

Oh, and don't be dissuaded by the registration process. "Click to attend" is an appropriate name given how much &*%$ clicking you have to do to sign up.

Kyle the Tween

Tuesday, May 13, 2008

I've had "searching" on my mind lately but in a very narrow focus. Specifically, I have a Brownfield application for a client I dig up every so often whenever new features need to be added to it. (Off topic: As soon as I can re-brand the sucker, it'll make a dandy little sample app for some Brownfield-related posts and webcasts. There, I said it on the Internet so the guilt will be that much greater if I don't follow through.)

One of the key components to this application is a document repository that you can search both with meta-criteria as well as a full text seaLegalSearchrch of the documents (see screenshot).

The meta-criteria part is boring. Bunch of lookup tables in a SQL Server database and I'm building up a SQL query manually in the search process. (I *did* say this was a Brownfield application.)

The full text search is done through a kind of poor-man's search index. I'm using a custom catalog with Microsoft's Indexing Service, available on Windows Server 2000 and later.

To do this, and I'm going to skim partially because it's not really the focus of the post but mostly because I think it's outdated, I create a catalog that indexes the document folder. Then, I make the catalog accessible to SQL Server so I can combine queries to it with queries to the metadata. Here's the SQL to do so:

EXEC sp_addlinkedserver <linkedServerName>, 'Index Server', 'MSIDXS', '<name of catalog>'

Now I can write queries like the following:

SELECT DocumentID, Title, Date, Filename
FROM doc_list_view dl,
OpenQuery( <linkedServerName>, 
   'SELECT Filename FROM SCOPE( ) 
    WHERE CONTAINS( Contents, ''<queryTerm>'' ) '
) q
WHERE Date BETWEEN 'January 1, 1850' AND 'December 31, 2008'
AND q.Filename = dl.Filename
ORDER BY Date DESC, Title

Easy as raccoon pie, yesno? The nice thing about this is that it will automatically index all Microsoft Office docs and PDFs are handled by installing Adobe Reader 8.0 (though it's a separate download for 64-bit).

Fast-forward to 2008 and the Indexing Service is no longer turned on by default on either Vista or Windows Server 2008. Posed a problem for the client who runs it locally on his laptop but it was easily remedied simply by turning the service on. For my own newly-minted Server 2008 machine, Indexing Service and the new Windows Search can't run together. And I'm loathe to enable the older technology so it's time to update if I can.

That led me to this page which confuses me to no end. Starting with the terminology: Windows Search, Windows Desktop Service, Instant Search, Windows Indexing Service, Indexed Search, MSN Desktop Search are the terms used to discuss various incarnations of the technology. And that's not including codenames or different versions of the same technology. Adding to my addlement is when Microsoft changes terminology from one page to the next. One example is this page which, in the section on the History of Windows Search, leads you to the download page for Windows Search for Windows Server 2003. That one is titled: Description of Windows Desktop Search 3.01.

So now I'm facing the unenviable, but oddly ironic, task of having to search through the myriad of search options for a solution that will run on Windows Vista, Windows Server 2008, and Windows Server 2003 (where the main site is hosted). At first glance, it seems Windows Desktop Search is the way to go for Server 2003 as it appears the new Windows Search is API-compatible with it.

In any case, this'll make one heckuva a sample for the Brownfield series on managing integration with external systems. Because as you've probably guessed by now, there are no automated (or even manual) tests for this whole process.

Kyle the Researched

Wednesday, April 02, 2008

Suppose it would have been more appropriate to make today's announcement yesterday but c'est la vie, que sera sera, ou est la biblioteque and all that.

I'm wbaley_cover150riting a book with Donald Belcham on practices and techniques that can be used on brownfield applications. The official site is at www.manning.com/baley where you can order the first four  chapters (which makes it sound like we've written more). Chapter 1 is free and as a preview of it, the last sentence is: "The one thing about brownfield development that will double your rate as a consultant, repair your failed side career as a bass guitarist, increase your "performance", and make you a babe and/or dude magnet is....".

Couple of trivia tidbits:

  • The guy on the cover was our third choice. First two were the Marquis de Sade and a hooded executioner, both of which we felt would have been more suitable for the topic. We settled on this one primarily because of the whiskey jug.
  • The TLA in the title is not an accident

There is a forum available for reporting errors, omissions, and criticism (constructive, reconstructive, destructive, instructive, or otherwise-structive).

So there it is, folks. The first Igloo/Hillbilly collaboration.

Kyle the Brownfielded

Tuesday, January 15, 2008

Floridians beware! The Hillbilly descends on your fair state in the next few weeks:

FlaDotNet - West Palm Beach, January 22, 2008   6:30pm

Introducing MVC in .NET
OnLoad, OnPreRender, OnRender, OnInit. Traditional web forms development makes it sound like you're some crazed Santa Claus born from the imagination of Tim Burton. But it doesn't have to be that way.

In this session, Kyle will free you from the shackles of the ASP.NET event model and show you a shiny, happy world. A world where web developers write application code, not plumbing. A world where "ViewState" is the eighth word you can't say on television.

Such a world does exist. And Kyle can take you there with the help of Microsoft's shiny, new implementation of Model-View-Controller. And you will see a place where the air is clean, easily maintained, and testable.

 

South Florida Code Camp - Miramar, February 2, 2008    7:30am - 5:45pm

Not one, not two, but THREE doses of the Hillbilly:

Introduction to TDD, Mocking, and Dependency Injection
I know, I know, why would we need TDD? It’s not like requirements ever change, right? Users are always crystal clear when describing them and once they’re written down, everyone *knows* they’re set in stone.

So this session will be more of an academic exercise for those purely hypothetical situations where, say, your client claims he “forgot” about a key feature one week before delivery and that it “absolutely has to” be in the application and, wouldn’t you know it, it’s going to touch every single layer of the application.

Crazy talk, maybe. But indulge a budding theorist and join me for a demonstration of TDD in action and how it allows you to wholesale replace entire sections of your application with confidence. Along the way, we’ll discuss how you can test components entirely in isolation from each other through the power of mocking and dependency injection.

ASP.NET MVC and AJAX
No abstract for this one because I was originally going to re-hash my Introducing MVC in .NET presentation before David Hayden decided he wanted me to work for my money. But unlike Justice Gray, I'm folding like a new shirt and tweaking my presentation.

Brownfield Software Development: Inheriting Code
What a mess this code is! If only the mucky-mucks would let me rewrite it from scratch. (I’d *never* make the same mistakes the previous team did.)

But alas, I’m stuck adding features and making bug fixes to this convoluted codebase that has no unit tests, has no CI process, and is not even completely in the source code repository. And I’m scared to make changes because the first time I tried, some users couldn’t log in, the app crashed for others, and for one unfortunate person, a big gaping hole opened up under his desk when he tried to enter an order.

In this session, we’ll take an existing application and move it to a state where we can make changes with confidence. We’ll implement a continuous integration process and start you on the addictive road to refactoring. And once you get your first hit, you’ll never start a greenfield application from scratch again.

 

I'm rather excited about the last one even if it seems the least sexy of the topics. I think it has the most potential to help people in the NOW instead of some hypothetical future.

Kyle the Re-presented

Saturday, January 05, 2008

The "How to" is gone from the title to be resurrected at appropriate intervals. In my last post, it was brought up in the comments that it was, and I quote, "naff". Wikipedia helped me with a definition which confused me a little because "cheesy" and "tacky" were the exact adjectives I had in mind when I started using the device some eight months ago in a fit of Kubrick-love (and looking over that link: yoy, I gotta stop writing my thoughts down).

No matter, the Hillbilly is nothing if not easily swayed by anonymous commenters. So the "How to" will be limited to posts on Guerrilla Factoring and Code Coverage Nazis and the like. Back to the show!

The topic of the day is MVP and/or MVC within an MDI application and the blog will act more as a sounding board this time around because I'm having trouble putting my thoughts into something concrete I can type. It probably could also apply to a master form that uses MVP/MVC and which contains several user controls that use the same pattern. If it does, that's not my fault.

Here's the scenario: The main container form has a menu item that says Open which will open the currently selected item as an MDI child. And ummm....I suppose that's it really now that I think about it.

Off topic

If anyone needs further proof that comments tend to end up as distracting noise, consider the following comment lifted directly from one of our classes:

//Ajouter le dernier élement ou le premier si aucun AND/OR

Semi-related suggestion: If you're going to cut and paste code from the web, consider translating the exceptions into the users' first language.

At the moment, both the main form and the child forms are monolithic hydra-like beasts forms that contain all presentation logic and a good chunk of business logic. And so, being a diligent hillbilly, I'm adding a presenter to the main form. Clicking on Open passes the call on to the presenter. Which does....?

My first reaction was that it would create the child forms (which I'll call Estimates, mostly because that's what they are) and maintain them. This would be the easiest implementation because it would involve cutting and pasting code without thinking about it too much. But it feels funky to be manipulating Windows.Form objects in a presenter. Plus how would one interact with them? If I wanted to, for example, save an Estimate, would I need to call a Save method on the Estimate view which would delegate to its presenter? Or do I maintain a list of Estimate presenters instead and make the calls directly on them? And so on, and so forth.

Then I took a step back (tripping over the sofa) and thought "what's the model here?" The main form is generally just a window manager, I think, and its model should reflect that. So rather than having the presenter do all the form management, it should delegate to a WindowManager. Which sounds to me like it would be a UI-based model but a model nonetheless.

Jeremy Miller's StoryTeller has a similar UI metaphor (hierarchical view on the left, tabs on the right) and provided some guidance in this regard. It threw me at first with the main form being a mere 68 lines long (compared with ours at 2344 lines). In it, he passes everything off to an ApplicationController, which is managed through his hierarchical view. The ApplicationController has all necessary dependencies injected into it and it handles opening screens, mostly by delegating them on to the panel that is going to house them.

This kind of jibes with the conclusion I had eventually come to above. And this post was a couple of days in the making so don't be assumin' all of this is off the top of my head.

So in summary: The model for the main form of an MDI application is a window manager/controller that knows how to open other windows.

Thanks for listenin' and if the end result makes me look good, I'll come back and let you know how it turned out.

Kyle the Round-about

Wednesday, January 02, 2008

Caution: This post has very little technical content but may contain traces of inspiration and could induce vomiting. Do not read if you have heart problems or a healthy streak of cynicism. As you can imagine, hillbillies are optimists by nature.

Happy New Year to all! And this being Day One of Ought-Eight, I thought I'd take some time to reflect back on the past year and consider my goals for the next...

...ok, now that I've done that, let's move on to something interesting.

The Igloo Coder, Donald Belcham, writes on Brownfield applications. It's a term that has been applied to land reclamation and is likely a term you haven't heard before, at least as applied to software development. But I bet you already know what it means. And it ties in nicely to my initial posts here at CodeBetter, most of which have focused on what is pretty much the textbook definition of the term.

As luck would have it, I've also started work on another Brownfield application. It was last developed upon in January 2007 and is filled with the most heinous practices imaginable. Another hand-rolled data layer with a series of classes exposing static methods returning DataSets in some cases, domain objects in another. Again, all logic in the forms. No tests to be found. No patterns applied anywhere. No CI process. In fact, it's not even in a source control repository. It had one developer who clearly had no clue what he was doing.

And if that seems uncharacteristically harsh, that's because the developer was me.

I'll save you re-reading the last paragraph and remind you that it was last worked on in January 2007, less than one year ago. That's right, kiddies, the hillbilly has risked destroying the gargantuan backlog of credibility he has built up by admitting he was once a young, inexperienced coder who had lost his way. And it wasn't that long ago.

OK, I'm saying that a little tongue-in-cheek which I'm feeling more and more compelled to point out now that people who don't know me read this thing. The part I'm jesting about is where I make it sound like I'm on the one true path and everyone else is lost. And that I'm no longer inexperienced. Let me throw out a blanket statement that that will never be true and move on.

To shift focus back to the part that isn't going to solicit a bunch of comments that I'm elitist, the point is that for all the talk I do on patterns and NHibernate and IoC and all the other...ummm...alt.net tools and techniques, it was a *very* short time ago that I practiced precious few of these techniques and used even fewer of the associated tools, if any.

The app I'm lambasting here uses the *original* Enterprise Library data access block. The one with the static SQLHelper class. And I actively chose to use it over the new one. In November 2006. It was my decision to use stored procedures for all aspects of data access because I simply didn't know NHibernate existed. It's very likely, given the circumstances around this particular app, I would have looked at it and decided I didn't have time to learn it, but the fact remains it was not even an option in my mind at the time.

Now here I am about a year later and, like many developers, I shake my head at my naivete. But here's the cool part. At the time, I was doing things so much differently than I was the year before that and loving the way the new techniques made things easier. This year, the same thing applies. I now know the magic behind an IoC container and can use it to make my code that much more testable. I can take out my data access layer completely and replace it (for the most part) with some config files. And TDD, for all my initial misunderstandings, has made software development more fun than it has been in years.

In short, software development remains today just as fun as it did a year ago.

And I have no reason to doubt I'll be thinking the same thing next year when I look back at this application once more. Like Alec Baldwin says in Glengarry Glen Ross: Always Be Closing.

Kyle the Resolute

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

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