Alt.Net Geek Code Generator


Scott Hanselman talked about this one night down in the lobby of the Marriott in Redmond, and, surprising nobody, actually followed through with it!

Sweetness. Go generate your own.

Technorati Tags: ,,

author: Scott C. Reynolds | posted @ Tuesday, April 22, 2008 7:50 PM | Feedback (0)

Why Alt.Net?


Disclaimer: This post represents my own views of alt.net and is merely an expression of what I would like to see it become. This is not necessarily the view shared by anyone else. I do not speak for this group.

So this alt.net thing has been around for almost a year now (as a named concept anyway), and with the upcoming Seattle event, I've been wondering what my place in this world is, what my contribution can be, and most importantly, what my passion in software is, and how I can work toward it. I want to go to Seattle next month and have something to say, something I believe in, and not just be an observer. The following is a quick dump of my thoughts on the subject.

Thus far my exposure to alt.net has been through various mailing lists, twitter, and blogs by community members. I have virtually met a lot of smart people and great developers through this, but the direction, when it exists, is split. A common goal and purpose seems elusive. Often discussions surrounding alt.net either devolve into the purse fight type of discussion, or filter into a "how can I use/why is [NHibernate, Rhino Mocks, NUnit, Castle] better than [some thing I do RAD|The Microsoft Way]"

Had I my druthers, I would love to see alt.net evolve into a community practicing a variety of (I hesitate to use "best practices" but alternative terms escape me) methodologies with a variety of tools aimed at doing software well, and doing it right, and more importantly, teaching that philosophy, and teaching those practices.

I will forgo the use of labels that may be seen as derisive and divisive, and state my observation from my career that developers fall into two very broad camps: those who at least lurk but maybe participate in "community" activities (blogs, conferences, mailing lists, etc) and those who, for whatever reason, do not. I will call the former Group A, and the latter Group B. Group A may or may not be doing things right. They may or may not be up on the latest tools or methods, but they are out there trying to learn. Group B, contrary to popular may still be out there trying to learn. Those guys just do it primarily through books, magazines, Google, the MSDN library, and their immediate coworkers. Just because a developer hasn't plugged into a community does not mean he doesn't care.

I feel like alt.net, in some part, can be a group that is willing to stand in the gap between Groups A and B and find ways to deliver the right messages to Group B. Developer B may work with one or more Developer A's. We have an opportunity to not just educate A at a code-camp or in a blog post, but help him further educate B, and educate the pointy-haired boss as well. There was talk at one time of alt.net books, and while some thought the idea laughable, the truth is, Group B developers buy books, maybe they have a book budget, and they do what the books say. This is a way to touch non-community-involved developers. Jeremy Miller has made a step in the right direction I believe by publishing an alt.net editorial in MSDN magazine. Lots of Group B types get MSDN magazine. It comes free with MSDN Subscription. Companies that employ Group B types also hire consultants. The consultants can be bringing the message and making sure they are leaving the place better than they found it, not just from a code standpoint, but from a knowledge and understanding standpoint as well. The point is, Group B can be reached if we are willing to find a way and work for it. The question becomes, I guess, is it worth the effort? I say it is. All boats rise with the tide, and if we can force ourselves (not just alt.net mind you, but all Group A types) out of the cabin and into stowage once in a while (it's a funny analogy don't crucify me) then we should see a rise in the industry as a whole.

Alt.net is partially about tools, with good reason. There are good and bad tools out there. There are a lot of great tools that are open source or not "endorsed" by Microsoft that aren't being used simply out of fear. However, talking about tools is not enough. Pushing and IoC container on a developer if he doesn't understand the need it fills and how it fills it is as bad as Microsoft pushing Enterprise Library. I say pushing not because MS made the statement "Thou shalt use EntLib" but because by putting it out their they gave it the de facto endorsement as "the Microsoft Way". How many shops are using EntLib where it is unnecessary, or using it incorrectly, because they were not properly educated on the underlying principles? The tools are a means to an end. But before choosing a means (or an end for that matter), we should be making sure developers are making educated choices.

We need to be teaching people to fish, and moreover, making sure they have the tools to teach the rest of their tribe to fish. There was talk about a "street kit" of sorts aimed (I believe) at this purpose, and I hope to see that come to fruition. But it can't just be about teaching the tools. It has to be about teaching the concepts. To that end, we should be working with each other to make sure everyone is on the same playbook, that we are presenting a unified, educated front when taking the message to the masses. If five different people present TDD you will come away with five different understandings of the why, but a good idea of how to set up a test harness. This is unacceptable. It's an incomplete education, and it leads to misuse and abuse and later abandonment of a good practice. One of the things that David Laribee and others wanted to see happen was the idea of "peer review" for material relating to software development. Sadly, this seems to come up as the exception rather than the rule, at least in the public forums, and as a result we are potentially doing a disservice to the consumers of the information we present in blogs, conferences, and code camps. If we truly want to see software move closer to science and engineering as a discipline then we should be equally disciplined in our research and publishing.

We can't ignore the complexity of a real-world developer's work situation. Jacob Burkhardt said "The essence of tyranny is the denial of complexity." I think that is completely appropriate in this context. I have seen too many conversations about "how do I adopt [x] when my manager/client/stakeholder/team members don't understand it" yield no practical information about how to work with this complexity of environment. Not everyone is out there writing software commercially or as a hired-gun, making their own rules, and working for people that also understand software. Getting buy-in on something as simple as TDD is a non-trivial problem in many IT shops. To that end, I feel like alt.net can do some work to create real, tangible evidence of why the practices we preach are the right practices, why they work better than alternatives, and how to be flexible and still implement them in spirit, or incrementally, to gain the buy-in of those who may be in charge. We need case studies and testimonials that give concrete evidence of how well these practices work. Anecdotal evidence isn't enough.

It's been said that people want to eventually remove the "alt" from alt.net.  I find this to be a powerful goal, but it won't happen, in my estimation, until we are willing to stand in that gap and find a way to bring these practices in a uniform, demonstrable, repeatable way to the masses that exist beyond the glass walls of the alt.net community.

And that's why I'm in the game.

Guys I would love to hear feedback. Am I living in an ideal dream world thinking this goal is achievable? Am I wrong to even think it's that important? I just want to open up some discussions.

author: Scott C. Reynolds | posted @ Monday, March 24, 2008 11:29 PM | Feedback (5)

The Safety Net - TDD IRL FTW Part 2


Bad code snippet example FTL I guess.

Ok so I posted before about TDD helping you by providing a safety net against incomplete testing and developer bias. The very first comment I got was on my code example (which I did say, to be fair, wasn't actually real code). Specifically:

that initial code is smelly in the EXTREME. TDD isn't the problem, nor the solution... proper coding in the FIRST PLACE is missing here.

Ok, fair point. The code is not great. My first instinct was to immediately jump to the defense of the snippet as being an example only, but, after giving it a second thought, I decided to turn that into my next blog post instead!

The fact is, the real live code was smelly. One problem evident in the snippet I used is that basically the same work is being done in the catch as the try, and in fact once we got in there to look at it, it was pretty simple to refactor out that whole bit of try/catch altogether and put the function together a little more cleanly.

Ok but back to the point. I would like to submit a complementary but also contrary opinion to the comment above. More to the point, TDD is a solution that helps you ensure proper coding in the first place, and thereafter.

The Fallacy of "Proper Coding in the First Place"

So we've all been new programmers right? We didn't come out of the womb writing perfectly factored code. We all had to learn. And to learn to write good code, you have to write shitty code. And watch it break. And learn to fix it. And recognize those mistakes before they happen at some point and design in the catches for them. Eventually you graduate to smelly code. Then good code. Then more smelly code sometimes because you've been up for too long. Then some really sweet code that nobody but you can understand. Then, more smelly code. Point is, nobody gets it right on the fly every time.

Sometimes you have incomplete data as to the requirements or the eventual scope of a project or even individual set of functionality. If you believe in various "best-practice" axioms you will probably just solve the problem at hand, you probably won't be super concerned with future-proofing during this iteration. You don't want to suffer Analysis Paralysis, spending all day prematurely abstracting and architecting, because as far as you know right now, You Aren't Gonna Need It. So you write the code that needs written today.

For whatever the reason, the idea that all code can be properly done up front and completely future-proof is a fallacy. Code that is in need of refactoring is the majority of code out there in the world. Bet me it's not.

The Safety Net Is Still Down There

Enter TDD. As I said in the previous post you could have covered the possible scenarios with a handful of tests and had confidence that you covered all the bases. Now, let's say that you realize, or someone tells you, that this code is smelly. Or say you wrote it when you were new, and you have learned, and you want to fix it. Or say you have to fix it because someone else wrote it and it's too smelly and you just can't bear to live with it. One way or the other, you're ready to sit down and refactor it.

So changing code that is in production, or is a dependency to some other code, or that maybe you wrote a while ago and just don't fully remember all the nuances of, can be very scary. And dangerous. However, if you have the unit tests in place that cover the existing code, you are in a much better position, and can approach your refactoring with confidence.

If your tests fully test the various result scenarios of a given function you can change that function and know that if you change something fundamental to the result of the function, your tests may then fail, and you will have instant feedback regarding your refactoring. You can augment your code and your tests to the extent required, and when it's green, you're good. (Simplified explanation, this isn't meant as a full on article on integration and regression testing)

Contrast that to having no tests in place. There may be code all throughout your application that depends on this code. You might make some change that introduces a subtle but real break on one of many dependent pieces. Thinking back to the bias of your own manual testing, and the fallability of human QA people, you may end up creating a pretty severe break in your application that doesn't get caught until sometime down the line when it's in production and not trivial to fix.

TDD Turns Out to Be the Solution After All

In my estimation, at least, TDD solves many problems that occur throughout the lifecycle. If you are test-driving your initial code, you have a better chance of getting it (functionally) correct the first time. Later when you realize that, for whatever reason, either the function or design of the code needs to change, having tests in place can ensure that you don't introduce breaking changes to dependent code. It's a process that repeats over and over throughout the life of any non-trivial application - change happens. It's better to have the safety net when making the changes, whether new functionality or refactoring smelly code, than to not.

No Silver Bullet

Now like I've said before, TDD is not magic. You aren't going to magically never break code or miss a bug or introduce a breaking change again just because you wrote some unit tests. You need to practice writing them to cover more and more scenarios. You need to combine them with other tools that should be in your toolbox as well for you to achieve synergy. Design principles like DRY and SRP, patterns like Dependency Injection, coupled with good testing are practices that will further enhance the robustness and elasticity of your code. And as you start to seriously get into the Test-First mindset as opposed to the Test-Because-I-Have-To one, you will see better design start to be derived in your code as you try to keep your tests from being smelly. Get out there and test people.

author: Scott C. Reynolds | posted @ Wednesday, March 19, 2008 10:37 AM | Feedback (0)

The Safety Net - TDD IRL FTW


To the unintiated, the title is: The Safety Net - Test-Driven Development In Real Life For the Win. Warning - This post contains some of my thoughts about *practical* TDD and the reasons for it. This may not all encompass "dogmatic" TDD practice. To me, TDD is all-important first as a safety net. Before you find TDD soluble enough to understand how it helps you drive design, you have to understand that you're putting it there to save your code from you, your QA group, and most of all, changes.

When I think about TDD, I think about it as an applied methodology and try to determine what real-world scenarios it can improve. Often I hear from people that they don't "get" TDD, that it seems like a lot of extra work, or that they can't seem to find a use for it IRL.  Often, I can see where this kind of thing comes from. Much of what is available out there puts the concepts of TDD in a vacuum and segregates it from the problems it can solve, or doesn't give concrete examples of the benefits of the methodology.

Let's take a step toward changing that. I want to talk about something I had today, and basically recap (and expand upon) a conversation I had with one of my developers regarding unit tests.

The Scenario

A piece of functionality released a few months ago is discovered recently to be buggy. As a matter of fact, recent reports lead us to think that the actual code was never released into the wild at all, as it appears to have completely disappeared. The human testers tested and approved this function (which amounted to an if statement checking a boolean field on a domain entity - pretty simple change). The code was released live. We didn't hear anything for a couple of months, then we start getting a flood of emails telling us that it clearly isn't working.  The testers go back and test, it works for them. The developer goes and looks in the code - the check is there. However, clearly demonstrated reports from users show that the expected functionality is in fact not there.

The Root Problem

We dive into it for a little bit today to find the problem. From a human tester perspective, we are finally able to reproduce the problem by testing some scenarios that they never tested in the first place. From a code perspective, once we removed the blinders that were causing us to look strictly at the line of code implemented, it was easy to spot the problem.

public bool CheckAllowedFunction()
{
    try
   {
        bool securityCriteriaOne = SomeDomainFunctionThatCouldFail();
        bool securityCriteriaTwo = TheAddedCheckFunction();
        if(securityCriteriaOne && securityCriteriaTwo)
            return true;
        else
            return false;
    }
    catch
    {
        bool securityCriteriaOne = SomeOtherDomainFunctionForFailover();
        if(securityCriteriaOne)
            return true;
        else
            return false;
    }
}

Do you see it?  What happened is when the code was first written, securityCriteriaOne was the only check. A year later, when we implement the new request, we add securityCriteriaTwo to satisfy the request, and the check for securityCriteriaTwo was never added to the catch clause (this is a very simplified example, and not entirely representative of the code involved, but it is the basic gist with all the business-sugar stripped out).

Ok, so this is a simple enough mistake. You're flying through, you implement something that you've already decided in your head is one simple line of code (developer bias) and you miss a step. Maybe you hit F5 and run it real quick with your favorite bit of test data in the test system, it works (because your bias led you to test for pass rather than for fail). You build it and ship it to QA. They test. They try to break it, because they hate you. But maybe your QA group isn't strong enough to understand and think through possible breaks. Maybe they have their own set of data they test with, and maybe they got the same bias from the spec that you did and subconsciously tested for pass. Maybe, as in this case, the bug is such that by sheer luck (or Murphy's Law) it looks like it works live long enough that you forget about it. Maybe SomeDomainFunctionThatCouldFail(); is only gonna throw an exception on very rare circumstances, or because of some variance in data (as was the case here). Bottom line, it gets missed.

The Cost

Ignoring any potential business costs for now, because those things are intangible until they happen, let's focus on the cost of this bug to development.

I lost an hour of time when I should have been doing something else. My developer lost an hour of time when he should have been doing something else. The bug was critical enough that he had to interrupt what he was doing for a very important iteration currently. The QA guys lost time testing the current iteration to go back and test (under my direction) a plethora of scenarios. The DBA lost time modifying and creating various data scenarios in the database as I had different scenarios tested. My other developer lost time because well, it was exciting, and we interrupted his work, and it was too interesting not to watch. The VP of IT lost time because he had to stop to get a full understanding of what was going on so he could report up. Pretty much an entire IT department lost an hour plus of time JUST TODAY, not including previous days of trying and *not* being able to identify the bug, just for this simple one line of code.

Clearly, that is unacceptable.

Human QA is Unreliable

Look, I love my testers, and they do a good job. They aren't really my testers though. They're tech support guys that do testing when they aren't answering calls or fixing servers. They aren't trained as testers. They don't have programming experience. They simply don't have all the experience needed to create and execute rigorous test scenarios covering wide ranges of data and usages. They are learning and improving every day, but to expect them to be QA rock stars would be unfair to them and delusional at best.

And I think I have it good. Many of you may not have QA people at all. I've been there more times than I can count. Maybe you test your own code. Maybe nobody tests it (been there too).

Not all of us is lucky enough to have real, dedicated, experienced software QA people testing our apps. And even those of us that do still have bugs. Hello Microsoft? You think they don't have QA people that are probably better coders than me? You're wrong.

Humans are fallable. So are their tests. You need to be in a position of comfort with the robustness of your code before it ever sees another human. You need to know that you caught and handled that Null Reference because John McTestalot might not get it this time. You need the unit-test safety net.

How Does TDD Prevent This Scenario

Well, it's not magic. However, mindful application of test-driven practices will prevent problems like this from happening. In our current iteration we are putting out a lot of functionality. We're releasing to QA multiple times a day, and they are coming back with a lot of bugs. These bugs are, with rare exception, very simple errors and things that got overlooked. Off by one. Bounds checking. Null reference exceptions. Basic stuff.

My guys are writing tests. Only recently have we gotten to the point where we're getting decent testing going, and not putting it off because we "don't have time". The tests are far from perfect, because they are *very* new to TDD, but they're getting there, and they're learning. After reviewing some of the bugs, I told them to learn from these bugs, and start incorporating more thorough tests, and more extensive test scenarios. A bounds error or a null reference should never make it out of your IDE, let alone into the hands of another human. These are things that are easily caught with good unit tests.

And that was the case here. No tests. In my estimation, the original code would, at the very least, have had tests that hit both the try and the catch senario and got its true/false assertions in all 4 places. When the new requirement came in, the tests would then have been augmented with a new bit of code to test securityCriteriaTwo. Then the code would have been written. Then one of the tests wouldn't have passed, the code would have been added to the catch block, and three months later we don't lose 15 man-hours on one if statement.

5 minutes to write a simple test 3 months ago, or 15 man hours to track down the bug today? Which do you think is better?

Why Tests Drive

It's TDD, not DDT (development-driven testing). The tests are first-class citizens. They should come first. No matter how you accomplish this, tests should be driving your new code, not the other way around.

As you get better and better at TDD you will see how it drives not only your code, but your design. But for now, let's focus on the reasons for it driving your code.

The word today is BIAS. Developer bias is your enemy. As I said before, you may look at a requirement, decide in your head it's easy, implement it quickly, then make a test for the implemented function, then maybe make a test for a fail condition so you feel good, then you're done. Bias kicked your code in the nuts the second you typed your first curly brace. You aren't going to go after the fact and write good tests, because you are biased toward the implemented function. You are interested in seeing it work.

Now reverse it.  Let the test drive. You write a test to satisfy the basic criteria of the requirement. You then write exactly what code will make it pass. You then write another test with the intention of making it fail. Then you write exactly what code will make it pass again. Lather, rinse, repeat until you simply cannot think of another way to make it fail. Then you're done. You wrote a bunch more code, sure, but by thinking about the the test over the code, you put out a much more robust function.

Think of it this way: The TEST is the important code. The application code only exists to satisfy the tests. You are trying to implement a full range of solid tests, and then, because you have to, write some code that makes them pass. Putting the test front and center in your consciousness removes the bias toward the application code.

TDD Takes Too Long

I think I've already demonstrated the gains here. 15 man hours of productivity lost today due to less than 1 man hour of time not being spent months ago. Find me a sane manager who will take that trade and I'll help you find a new job because trust me, you don't want to spend another minute with that guy.

But, you say, TDD seems like insurance. It's only useful when it comes up. Sure, this is true in a way, but think of it less like insurance and more like prevention.  You are actively preventing disaster, not trying to just cover yourself in case something happens.

But, you say, it takes a long time, and it's a lot of code to write, and I have more test code in my project than I do real code! Yeah, that'll happen sometimes. That's not necessarily a bad thing. As for the time it takes, well, it takes practice. You don't write perfect tests at first, you don't have good scenario coverage at first, and you feel awkward and unnatural writing tests at first. You gotta practice.

Did you always try/catch/finally when you were cutting your teeth in code? Or did it take many many times of unexpected unhandled exceptions before you started to learn?  When you put in a try/catch/finally today, does it feel like so much extra code? Does it take any measurable time that you feel like you should be applying to other code? Of course not. Unit tests are the next step. They are your next try/catch/finally. Keep at it, knowing the benefits, and they will become a natural, flowing, and quick(er) part of your code-writing.

And they will be your safety net.

Tags:

author: Scott C. Reynolds | posted @ Wednesday, March 19, 2008 12:43 AM | Feedback (2)

Twitsticuffs, Open Debate, and The Rules of Escalation


Leaving names out of this out of respect for the participants (yes, all of them) because even though Twitter is open, reposting specific conversations that aren't mine seems shady. Ahem.

So earlier tonight someone went on the warpath about Microsoft, and specifically their mishandling of Open Spaces, via Twitter. Some others chimed in, and budding arguments soon came about. After a bit, people started calling for "escalation", referring to Jeff Atwood's post detailing a Twitter argument and his feelings on what is right or wrong regarding excalating debate via electronic media.

All due respect to Jeff here, but I disagree. I find Twitter to be a wonderfully open medium for this kind of discourse.  Twitter perfectly embodies the Law of Two Feet in this scenario. You can watch the debate, you can participate, you can subscribe or unsubscribe to other participants, or you can simply not check Twitter for a while. It's a perfectly open medium allowing for as much passive aggressive participation as each person desires.

Why should you "escalate" or "take it offline"? Assuming that you should take a conversation to IM or email or a forum or a phone call at some point assumes that nobody else was interested or actively contributing. My thought on this is if you are going to start the debate in the open you had damn well better finish it in the open, otherwise what's the point?

How is this better served in another forum, such as email or a web forum? I don't see it. Twitter encourages not only participation, but by its nature also encourages both brevity and forethought. Contrast this to your typical forum or mailing list flame war: walls of text that people don't read anyway and that don't get anything resolved. Maybe nothing gets resolved in the same argument on Twitter either, but the fact is it was probably a more efficient argument, it wasn't cloistered, and tomorrow it's all but gone. I don't look at yesterday's tweets today, and typically conversations don't cross the boundaries of a participant going to sleep and waking up the next day. Unlike a forum post or blog post which is right in your face the next time you go there.

Now I will say that one thought spanning multiple tweets is probably not Twitter-worthy to begin with. Sometimes you can't help but spill to a new 140 chars, but if that's the norm, then yeah you should probably be blogging it or something. However, I still hold that conversations are every bit as viable on Twitter (if not more so in some cases) as they are anywhere else electronically.

So I say bring on the Twitsticuffs* and let the open debate rage. I for one will not arbitrarily say that some conversation should be "escalated" just because I'm sick of seeing it. If it bothers me that much, I'll unfollow for a while. If it's interesting, I'll participate.

*Twitsticuffs was coined by me today in response to this. I have 98 witnesses! I googled it and it didn't exist. I am henceforth the inventor of the term and hold all rights thereof. (for those of you that don't get it...it's fisticuffs...but with twitter...)

**Twitter is awesome. I've made a lot of contacts and had some great conversations via Twitter, and I hope it continues to grow. For a good explanation of how great Twitter is, go check out Keith Elder's blog post. And sign up and follow me.  Let's have a conversation!

 

Technorati tags:

author: Scott C. Reynolds | posted @ Thursday, March 13, 2008 12:53 AM | Feedback (1)

SubText Quickie - Dumping Mass Trackback Spam


A couple weeks ago I looked at my blog and discovered roughly 7000 trackbacks. Given that I hadn't written anything in a month or more, and that I was pretty sure not *that* many people were linking to my Continuous Integration post, it was clear the spammers had me.

I had to turn off trackbacks for a while because I was getting new spam faster than I could delete them. So I turned it off and left it alone until tonight, when I decided I would stop neglecting my poor blog for the billionth time.

Anyway, SubText is pimp and all, but dumping a mass amount of trackbacks that wasn't marked as spam is pain in the admin console, so I took the 8 hours required to load up my host's shared SQL server and jumped in my database to see if I could take care of this all at once.

The first query you are going to need is:

SELECT * FROM subtext_feedback WHERE feedbacktype = 2

this gets you trackbacks only. (FYI comments are feedbacktype=1)  Now looking through you will probably notice a good bit of the spam is only linked to a couple of entryid values, all 7k of mine were linked to only 3 separate entries, so that made the job of deleting them en masse easy.  Your mileage may vary.

Next step is to update your Pingback/Trackback count appropriately so it displays right on your blog page. Mine after the deletes was a paltry 7 (which is lame I know, but not every link back ends up as a trackback. I really think trackbacks fail as a technology). So your next stop is:

UPDATE subtext_config SET pingtrackcount = $whatever_it_should_be$

And then you're all set.  Spam gone.

Technorati tags:

author: Scott C. Reynolds | posted @ Friday, March 07, 2008 1:24 AM | Feedback (0)

Find Your Value, But Eschew Newton's First Law


Those of us not at MIX08 are likely jealous of those who are. Certainly Twitter has been aflutter with MIX08 tweets, letting the rest of us feel left out in near-real-time. Oh well. That's not the point. Just wanted to get that in there.

The point, as you're wondering, is that while I was watching the keynote stream from MIX08, I found it very easy to succumb to Grass-is-Greener Syndrome (GIGS?). It's super easy to watch something like the IE8 demo, or the Silverlight stuff done by the Vertigo and Hard Rock people, or the just astonishing end-to-end magical technosex that Aston Martin put together using Silverlight, WPF, and the rest of the .net stack, and think about your job and go "what the hell am I doing?" Even looking at AOL's mail demo and being amazed at the speed and usability (in spite of it being AOL of all things) gives you that pause that makes you say "why am I not out there doing these cool things?"

GIGS seems to really rear its ugly head, at least for me (and I imagine a lot of you) anytime something cool happens.  A conference with new shiny things announced (PDC is guilty of this a lot), or another Web 2.0 company (using that term loosely) gets bought for a stupid amount of money despite being simple enough that every developer in the world says "well, I could have done that" (you didn't though, did you?) and wonders why he's toiling away in the salt mines writing the same CRUD-centric line-of-business applications for peanuts and free coffee.

This happens to me. I will freely admit that GIGS takes hold of me from time to time. I was beside myself when Microsoft dumped that cash into Facebook, and further so when I saw Zuckerberg's keynote at the Facebook F8 conference and decidedly couldn't stand the guy ("Today, together, we're gonna start a movement" come on dude you aren't Jobs). Watching the MIX keynote demos I thought to myself "man I really need to get into this cool stuff".  I know I wasn't alone.

At one point yesterday I said on Twitter

I have to stop watching this. it's making me feel really lame as I continue to develop reports

To which Steve Wright replied:

@scottcreynolds yeah, the boring real world, building applications that help make decisions that make $$$

And that kind of brought me back from the ledge and made me take a more honest look at the situation. The situation is that I provide value. Real, tangible, ROI-measurable value. I haven't talked about it much (but I will be in the future) but just over a year ago I released a major piece of software for my employer. We're a pathology laboratory with pretty high volume and I created, from scratch, a system that manages nearly the entire business from specimen processing, diagnosis, billing, logistics, customer service, inventory and supply management, and an obscenely robust and flexible results delivery system. In the first year of service this software has processed 75% of the total case load as the previous system had in its entire lifetime of 3+ years and did so nearly without flaw. Contrasted to the previous system that required external support almost daily, couldn't handle volume, didn't allow us to customize to our client's needs, and in effect cost us business, the new system is, by all accounts from the board of directors down to the lab employees, a huge success for the company. Now I would be remiss if I didn't say that I certainly couldn't have done this without the team around me, but I played no small part, and can take some credit with a clear conscience ;)

So there it is. I took a step back and I found my value. I am providing real value to my employer. My software helps us make more money, and therefore helps all of my users by virtue of the "all boats rise with the tide" theory.  My software also helps in some way to save lives. We diagnose cancer. We have amazing pathologists, such that if I ever have to have a biopsy, I'm getting it sent here. My software allows them to manage a large case load and makes sure that everything is accurate, that patient data is secure, and that mistakes don't happen. I am providing value. Suddenly my own grass is looking pretty green, because my work is important, and I've allowed myself to realize it.

So thinking about all of that got my head in the right direction. It's not about "how come I'm not doing cool new things and making billions of dollars?" it's about "how can I responsibly push technology in my organization to provide real value?"

Now saying all that, I must say that I am not in favor of just accepting that you aren't the one doing the cool new thing, and that you aren't the one making the billions. This is the second half of the title of this post.  Put nicely, inertia should not be allowed to run your life. Put more bluntly, and with all due respect, fuck Isaac Newton.

Inertia is NOT your friend. It's the most evil (and most powerful) of the natural forces. It keeps people in bad jobs, bad relationships, it keeps you from losing weight and eating better, it keeps you from talking to that girl at the coffee shop, it keeps you from innovating, from trying new things, from growing. Inertia is the devil you know.  Stop choosing it. It is a choice, even if a subconscious one. Stop allowing it to sedate you.

If you catch yourself thinking things about how "I could have done x" or "I wish I could do y" then you are succumbing to inertia. Stop wishing and do. If you could have done x...do x++.  Put up or shut up right? If you are unhappy with where you are, if you haven't found your value, or that value doesn't add up to what you think it should be, if you have all these "big ideas", then for your own sake, and possibly that of the rest of us, break those inertial shackles and get going. Wishes are goals that you lack the testicular fortitude to meet. Don't be that guy anymore.

Maybe you don't have some great idea to make some web2 property that will get bought for millions. Want to use some cutting edge tech? Use it to solve a problem not related to your day job. Join or start an OSS project. Just write some interesting code. Want to increase your visibility in your field or community? Blog. Join communities. Speak. Help. Be heard. Want to just learn something new? Do it. Take 30 minutes away from TV time every night and do something new with it.  Got a billion and one half-formed ideas in your head collected over the years? Take one and run with it. Start it up and see where it takes you. Just do something.

Now let me just say I'm lecturing myself more than any of you out there, but I know good and well that it applies to some people that aren't currently sitting in my chair. But for my part, I'm very guilty of allowing inertia to get the best of me.  Sometimes you don't even know it's happening, but trust me, it is, and once you allow inertia to creep in and take hold, it's harder to quit than smoking (more inertia). The old wisdom about habits (what are habits other than inertia?) is true. Good habits are as hard to break as bad ones. Start some new good habits.

So, TLDR summation version: Find your value. If you can't, then maybe the grass really is greener. However, regardless of where you are and what you are doing, beat that bastard inertia into submission and turn it in your favor. Stop wishing you were out there doing something cool, and get out there and do it.

author: Scott C. Reynolds | posted @ Friday, March 07, 2008 12:41 AM | Feedback (0)

Coding Playlist


This is what I listen to while coding. Plug the iPod into my desk speakers, shut the door, and get to typing.  I like solid beats, predictable patterns, and lots of repetition to keep the monkey part of my brain satisfied while I try to concentrate. Some people can't work like that, but I've heard a lot of other programmers say the same thing.  Not sure how Breed got on the list but I know it always gets me going when I'm in a lull.

Sometimes I'll put on a punk playlist when I'm in the mood, but mostly it's this kind of stuff.

What's your list?  Any recommendations?

  • Windowlicker - Aphex Twin
  • This Modern Love - Bloc Party
  • Helicopter -Bloc Party
  • Take It Easy (Love Nothing) - Bright Eyes
  • Going the Distance -Cake
  • Galvanize - The Chemical Brothers
  • Robot Rock / Oh Yeah - Daft Punk
  • Touch It / Technologic - Daft Punk
  • Television Rules the Nation / Crescendolls - Daft Punk
  • Too Long / Steam Machine  - Daft Punk
  • Around the World / Harder Better Faster Stronger - Daft Punk
  • Burnin' / Too Long - Daft Punk
  • Face to Face / Short Circuit - Daft Punk
  • One More Time / Aerodynamic - Daft Punk
  • Aerodynamic Beats / Gabrielle , Forget About the World - Daft Punk
  • Prime Time of Your Life / Brainwasher /Rollin 'and Scratchin' / Alive - Daft Punk
  • Da Funk / Dadftendirekt - Daft Punk
  • Superheroes / Human After All / Rock'n Roll - Daft Punk
  • Human / Together / One More Time / Music Sounds Better With You / Stardust (Instrumental) - Daft Punk
  • One More Time - Daft Punk
  • Aerodynamic - Daft Punk
  • Digital Love - Daft Punk
  • Harder, Better, Faster, Stronger - Daft Punk
  • Crescendolls- Daft Punk
  • Nightvision- Daft Punk
  • Superheroes- Daft Punk
  • High Life- Daft Punk
  • Something About Us- Daft Punk
  • Voyager- Daft Punk
  • Veridis Quo- Daft Punk
  • Short Circuit- Daft Punk
  • Face to Face- Daft Punk
  • Too Long- Daft Punk
  • Daftendirekt- Daft Punk
  • WDPK 83.7 FM- Daft Punk
  • Revolution 909- Daft Punk
  • Da Funk- Daft Punk
  • Phoenix- Daft Punk
  • Fresh- Daft Punk
  • Around the World- Daft Punk
  • Rollin' & Scratchin'- Daft Punk
  • Teachers- Daft Punk
  • High Fidelity- Daft Punk
  • Rock 'N Roll- Daft Punk
  • Oh Yeah- Daft Punk
  • Burnin'- Daft Punk
  • Indo Silver Club- Daft Punk
  • Alive- Daft Punk
  • Funk Ad- Daft Punk
  • Take It Off- The Donnas
  • Your Retro Career Melted- The Faint
  • Someday- Flipsyde
  • I Hate Everyone- Go Set Go
  • Power is On- The Go! Team
  • Huddle Formation- The Go! Team
  • L.S.F.- Kasabian
  • Mr. Brightside- The Killers
  • Golden Skans- Klaxons
  • Word Up!- Korn
  • 9 to 5- Lady Sovereign
  • Gatheration- Lady Sovereign
  • Random- Lady Sovereign
  • Public Warning- Lady Sovereign
  • Love Me or Hate Me- Lady Sovereign
  • My England- Lady Sovereign
  • Tango- Lady Sovereign
  • A Little Bit of Shhh- Lady Sovereign
  • Hoodie- Lady Sovereign
  • Those Were the Days- Lady Sovereign
  • Blah Blah- Lady Sovereign
  • Fiddle With the Volume- Lady Sovereign
  • Love Me or Hate Me (Remix)- Lady Sovereign
  • Ch-Ching- Lady Sovereign
  • Shinobi vs. Dragon Ninja- Lostprophets
  • Hard Wax- Manchild
  • Extreme Ways- Moby
  • How We Do- Mount Sims
  • Starlight- Muse
  • The Hand that Feeds- Nine Inch Nails
  • All the Love In the World- Nine Inch Nails
  • You Know What You Are?- Nine Inch Nails
  • The Collector- Nine Inch Nails
  • Love Is Not Enough - Nine Inch Nails
  • Every Day Is Exactly the Same- Nine Inch Nails
  • With Teeth - Nine Inch Nails
  • Only - Nine Inch Nails
  • Getting Smaller - Nine Inch Nails
  • Sunspots - Nine Inch Nails
  • The Line Begins to Blur - Nine Inch Nails
  • Beside You In Time- Nine Inch Nails
  • Right Where It Belongs - Nine Inch Nails
  • Breed - Nirvana
  • Korobeiniki - Ozma
  • Get Up, Get Off - The Prodigy
  • Spitfire - Prodigy
  • Girls- Prodigy
  • Memphis Bells- Prodigy
  • Get Up Get Off- Prodigy
  • Hot Ride - Prodigy
  • Wake Up Call - Prodigy
  • Action Radar - Prodigy
  • Medusa's Path - Prodigy
  • Phoenix - Prodigy
  • You'll Be Under My Wheels - Prodigy
  • The Way It Is - Prodigy
  • Shoot Down - Prodigy
  • Get Up Get Off (Alternate Version)- Prodigy
  • Firestarter- The Prodigy
  • Smack My Bitch Up- The Prodigy
  • Breathe- The Prodigy
  • Diesel Power- The Prodigy
  • Funky S**t- The Prodigy
  • Serial Thrilla- The Prodigy
  • Mindfields - The Prodigy
  • Narayan- The Prodigy
  • Firestarter- The Prodigy
  • Climbatize- The Prodigy
  • Fuel My Fire - The Prodigy
  • Spitfire - The Prodigy
  • Filthy Gorgeous (Original Radio Mix) - Scissor Sisters
  • Kesta Ston - Slagsmalsklubben
  • Frail and Bedazzled - Smashing Pumpkins
  • Nightfall - Solar Twins
  • Rock the Casbah - Solar Twins
  • Chop Suey - System of a Down
  • Night On Fire - VHS Or BETA

 

Tags:

author: Scott C. Reynolds | posted @ Tuesday, March 04, 2008 12:36 AM | Feedback (0)

Code Snippet: MeasureString


Last night I had cause to measure the rendered dimensions of a string at a given font and width. Without going to much into the why, let's just say if you need to do this you're either doing custom text rendering, or, in my case, positioning report elements relatively in a report suite that doesn't update Control.Height except in some magical layout land that you can't figure out how to access. To get around the problem, I came up with this:

private int MeasureStringHeight(int width, string textToMeasure, Font font)
{
    Bitmap bmp = new Bitmap(1,1);
    Graphics g = Graphics.FromImage(bmp);
    SizeF bounds = g.MeasureString(textToMeasure, font, width);
    int height = Convert.ToInt32(bounds.Height);
    //This part is to convert pixels to inches, which is what I needed.
    //You could just return height for pixels

    return height/g.DpiY;
}

This is not 100% precise, but close enough for probably most needs. If you need a more accurate height, have a look at Graphics.MeasureCharacterRanges.  Additionally, since I'm converting the more precise Float value to an int, and then further converting it to inches, you end up losing several points of precision, but this was my need. You could always just get the SizeF and go from there to be as precise as possible.

There are also several overloads available for MeasureString that will allow you to not specify the width, or specify a bounded rendering area.

Hope it helps someone.

Tags:

author: Scott C. Reynolds | posted @ Friday, February 29, 2008 7:43 PM | Feedback (0)

Dependency Problem Resolved


Major thanks to those that commented here, and my TwitterVerse, who came through for me big time. In particular, Joel Ross pimped my ride and hooked me up with a solution that honestly just never crossed my mind at all (i'm not a web guy...wtf is httpcontext?) but took all of 5 minutes to implement.

He posted the solution here on his blog, so go take a read. This was actually the second solution he posed to me which, in my sleep deprivation I didn't really grok at first, so I went with the first solution he emailed me.  Basically what it amounted to was making a reference to System.Web in the existing static config class, then pulling from HttpContext.Current if it wasn't null to grab a session variable, otherwise it would operate as it always had for the WinForms apps that reference it. 

This solution is not pure I know, I have the System.Web dependency, yadda yadda yadda.  Don't care. Didn't have to change any application in production currently, made one change to one class that had zero upstream repercussions (remember there's 200+ other classes calling this thing), and it got the job done.  Sometimes that's exactly what you need. I'll probably refactor later to remove the System.Web dependency but for now I've got other fish to fry.

Anyway...big thanks again to Joel, I really appreciated it.

author: Scott C. Reynolds | posted @ Wednesday, February 27, 2008 11:22 PM | Feedback (1)

Dependency Problem - Input Desired


Ok so I made a grim discovery today, and I'm just not quite sure the best way to fix it.  I have some ideas, but before I launch into them, I thought I'd throw it through the feedback loop.

Scenario:

200 or so classes that are basically table-mapped entities.  So Account.cs, Location.cs, Customer.cs, etc.  Each one handles all the properties, retrieval, and persistence of its table.  These, as you can imagine, are referenced *everywhere*.

Private constructors, public static creation methods.  So the usage for "get all accounts" is List<Account> accounts = Account.GetAllAccounts(); and "get a single account" is Account account = Account.GetById(guid);

There is a static class CommonConfig that holds the current userid, and the current database connection string.  This is set at application startup on login, and then referenced inside the static creation methods of each entity.

Ok so this structure has been in place for a couple of years, and we've been happily using it without issue.

The issue discovered today though, is we are trying to do a web interface to some of the application functionality, and the static userid is being overwritten across the board when someone new logs in.  This is bad.

The userid isn't important for security so much as it's important to the createdby and lastupdatedby fields of any given row, as well as things like displaying the user name.

So what would be your thoughts on fixing this scenario with the least amount of impact to existing applications?

author: Scott C. Reynolds | posted @ Tuesday, February 26, 2008 4:49 PM | Feedback (4)

Alt.Net Pursefight!


If you are having a problem keeping up with the firehose that is the altnetconf list, or would really just like a distilled look at the more salient points of any day, check out Alt.Net Pursefight!

I seem to have drawn their ire which, I suppose, gives me some nerd-fame. In fact, I make an appearance in 4 of the first 6 posts. Score!  Link to my blog when you talk about me guys, I want to capitalize on this!

The point being made is good though, anyone who just came in to altnetconf the mailing list in the last couple of weeks would probably think that all that happens there is bitching about this or that, and something about book deals.  Also, it's pretty funny.  I laughed and linked it to all my coworkers.  Contrary to the position conveyed by the screenshot there, I can in fact take a joke.

ps I gladly acknowledge that I have been known to be an ass.  I'm not sure when exactly that has happened on the alt.net list such that it would undermine my credibility, but, i'm sure it probably has.  Whatever.  I called today for a redirection, and I intend to hold myself to the same expectations I set.

Anyway...Subscribed!  Good stuff.  The commentary is both funny and pretty much spot-on.

for what it's worth, when you recently follow someone, and only follow people that feed you alt.net material and your twitter screenshots exactly match undoctored views of your recent updates list on twitter, it's not hard to spoil the fun of anonymity.  You didn't hear that from me though, genius. ;]

Tags:

author: Scott C. Reynolds | posted @ Friday, December 14, 2007 12:45 AM | Feedback (0)

Why Use Continuous Integration - Beginner's Overview


The question came up via Buddy Lindsey: "on a beginner's level, why should one use a Continuous Integration solution?"

Here is my honest, un-googled, from-real-world-experience answer as someone who has done non-trivial corporate team-based development both with and without CI.  All of this applies equally to web and desktop development, from a mechanical standpoint there's absolutely no difference.  The differences are in the code.

Preamble

If you are alone, writing code with no team, no release cycle, no QA, or anything of the sort of stuff that represents professional software development, then CI is probably nothing more than mental masturbation , and a nice exercise to do that nets you no gain.

Once you start working on a team and implementing anything other than "code+deploy=profit" as a methodology, then CI becomes more important.

At root, CI is a tool to automate build and build-related tasks.  A typical scenario is some CI "server" that checks the source repository for changes, gets latest, makes a build, and reports success/failure.  If you are running automated tests, CI would run them for you with the build, and would include the output in its report.  If you are running code metrics or static analysis like NDepend, FxCop, and so forth, CI would run those for you post-build and include the output in the report.  Finally, you could configure your CI process to deploy newly-built code to some location, possibly for QA purposes.

So let's take a scenario where you are on a team working on an asp.net website.  You are implementing features and bug fixes from the backlog/list. 

Scenario 1 - Team Development, No Continuous Integration:

Each programmer does his own thing, checks in...whenever, typically before leaving for the day, then bails.  Someone gets latest, build dies, and their work is fucked until the other programmer comes back and fixes his stuff. 

Further, somebody has to push the changes to the test environment (assuming you are developing locally, please do that) and notify QA or whomever that there is changes to the system.  On larger projects this could end up being a quite lengthy process.

Further, if you are doing the testing/code analysis stuff, you want to run that at some point.  It's a pain in the ass to do it yourself every build, so you do it...whenever you get to it, because you are also writing code and pushing releases to QA, and typically it falls by the wayside.

Further, maybe dev1 checks in some changes, but dev2 for some reason doesn't get latest before he deploys to QA (or worse, live).  Dev1 made some important bug fixes that don't make it out there.  If the communication cycle between QA and dev isn't great, this could go unnoticed...forever.

Scenario 2 - Team Development, With Continuous Integration:

Each programmer does his own thing, checks in...whenever, but is encouraged to do so often.  The CI server builds in near-real-time and everyone knows if the build is broken or good.  If the build-breaker is gone for the day, you know not to get latest.

A one-time setup has been done so that each successful build is pushed to the QA site/distro point, and an email is sent to the QA team automatically on success that informs them of new versions.  Further, some systems (depending on your source control) will allow you to read checkin comments, which could (should) contain at minimum what the checked-in change was.  Or possibly using a system like TFS you can mandate that checkins be attached to a work-item.  All of this information can be consumed by CI and included in build notifications.

CI does nothing but CI and therefore is more than happy to run your unit tests, ndepend, fxcop, ncover, and whatever else you want to throw at it every time it builds.  A one-time configuration gives you all of their outputs in a nice consumable web-based report, archived per build, so that it's painless to look at and understand the quality and progression/regression of your code.  Your code and team get better as a result of being painlessly more conscious of quality.  Having CI do automatic deploy from source control eliminates the human error factors as well.

Wrap it up here Scott...

The basic idea is to always automate something that's important but tedious.  Continually building fresh code and running tests and all of that is not only nice, it makes the code and the process more transparent and more adaptable to change.  It brings the code quality and practice of writing software (the mechanical stuff) to the forefront and helps you enforce good practice without spending a ton of human time worrying about it. 

So there is your 20 foot view of CI and why it is useful.

Tags:

author: Scott C. Reynolds | posted @ Thursday, December 13, 2007 7:04 PM | Feedback (6)

Links from the Sharpside [12/10/07]


I think there was something released by Microsoft yesterday in CTP form...if you Google really hard you might catch wind of it.

Dependency Injection Objection - Jacob Proffitt

The Visual Studio Look and Feel - Patrick announces a new NDepend.  Looks awesome, have to download it.  PS post on NDepend coming soon once I finish some of my backlog.  I love it.

Foundations of Programming 4 - Dependency Injection - hot button topic of the week.  The 4th installment of what is so far a quite good series from Karl Seguin

MVC How-To Screencast - some stuff about that thing MSFT did yesterday, and a how-to screencast on MVC

Using script.aculo.us with ASP.NET MVC - yeah yeah I get it, there was web yadda going on. Back to my desktop apps.

A rule engine in less than 70 lines of code - it should be "fewer".  well..that's really all I could ever hope to call Oren on ;]

MonoRail Quickly - Screencast - take THAT ASP.NET MVC!

An Introduction to Fit and Fitnesse - Good timing, I've been in great need of one of these.

Becoming a credible developer - um...yeah.  pretty much.

author: Scott C. Reynolds | posted @ Tuesday, December 11, 2007 12:01 AM | Feedback (0)

Aut disce aut discede (Either Learn or Leave)


Title courtesy of Chris Chapman

Some twittering this morning surrounding yesterday's ALT.Net summit got me to thinking about a broader principle that needs to be applied here.  There is no growth within your comfort zone.  If you always do that which is familiar, you reach a point of utter stagnation.  Some call it a rut.  Some call it doldrums.  Call it what you will, but it's stagnation, made heavier by inertia.  I talked about this before and I'll say it again:  Sometimes you have to shock your system to make real progress.

A lot of lashback for alt.net right now is coming from a position of fear.  A position of not wishing to come out of one's comfort zone.  This is the antithesis of what we should be about.  We should be out there pushing the envelope and making ourselves, our peers, our companies, our products, and our world better.  Chad touched on this in his post about professional responsibility.  I left a comment that I thought I would share to a greater audience.  It's a quote that Scott Bellware twittered one day a couple of weeks ago:

"Society runs on software.  Programming is a social responsibility".

If you believe that we would not be as far advanced as we are without software, if you believe that the geeks truly have inherited the earth, then you have a moral imperative to push yourself out of your comfort zone, advance your skills, and play your part in advancing society.

Yeah, I realize that sounds pretty high and mighty and ivory-towerish to the guy busting his hump in the trenches writing an internal IT app.  But if your application provides value in some way to your company, to society, then you have a duty to step up your game and do it beyond right.  And you have a duty to share your knowledge and understanding with your peers, and when necessary push them out of their comfort zone.  Mother bird pushes the chicks out of the nest and they either fly or fall, but in nature either outcome is better than a bird sitting in the nest its whole life being mouth-fed regurgitated worms.  The same is true of you.

Let's dispel Mort/Elvis/Einstein right now and see the common truth:  all of us, at all levels, need to move outside our comfort zone and improve.  The only two types of programmers that exist are the ones who are pushed out of the nest and the ones who are mouth-fed worms their whole careers.  Even if you have to jump from the nest, please don't be that guy that never tries something new and never grows.

This is the most honest statement about software developers (and people in general) that I can make:  If you aren't willing to learn, you are obsolete and utterly useless.

New and unknown things trigger our fight or flight response just the same as if a bear came crashing through the woods at us.  What will differentiate you from the next guy is whether you choose to adapt, improve, and grow with new challenges or put your head in the sand.

Here's the danger of putting your head in the sand:  if you continue code the way you always have coded, never growing, you will be replaced.  You will either be outsourced, or, more humiliating, replaced by Volta or something similar.  In our profession our real value is not the code we write but the problems we solve with it and our ability to adapt and improvise.  If you can't improvise you will eventually be replaced by the software that someone who can improvise has written that will automate what little you previously did.  And I will have no pity for you.  You could have taken some time now to read some blogs, or some books, or go to meetings, or a geek dinner, or join a mailing list, or do SOMETHING outside of your comfort zone that would have helped you grow.

Now is the time to take some action.  Get out of your comfort zone.  You'll thank me later.

Tags:

author: Scott C. Reynolds | posted @ Sunday, December 09, 2007 1:56 PM | Feedback (1)