Be (2x) More


Say, for instance, you are given a seemingly impossible task, that over the next thirty days you are to be twice as good as you are today. How might you accomplish that? Would you break it apart? Try to focus on the most meaningful changes first? Tackle them one at a time, perhaps utilizing some sort of list? Congratulations, you might be an engineer. Would you instead, shift uncomfortably in your chair, attempt to point fingers at others, pretend you’re doing fine, and quietly start looking for a new job? Congratulations, you’re an asshole.


First, let me say, that the goal of attaining the unicorn status of the 10x programmer is probably unattainable, but 2x is definitely within your grasp.

Improve your basic skills

The 2x speedup is not, I repeat, NOT from a new language or toolkit, it’s from mastering the basics. Using Angular instead of static html pages does not make you a better programmer. It’s possible, that once mastered, you can be more proficient in setting up rich, responsive and scalable single page web applications, than you would using a simpler toolchain, however this is not going to help you attain 2x in the next thirty days, so don’t waste your time. I don’t mean to pick on Angular, it could easily be React+Redux or any other such framework-du-jour. The point is that there are better uses of your time.

If you were a chef you would practice knife skills

If you were a ninja, you would practice nunchuck skills.

If you were a hairdresser you would practice cutting doll hair.

Why would software be any different?

Master basic keyboarding Skills

  • Do you hunt and peck?
  • Can you navigate your OS / Editor without your mouse?
  • Can you type quickly and accurately for sustained periods of time?
  • Did you know that holding control while moving left and right can advance a whole WORD at a time. Magic!
  • Have you learned the joys of Ctrl+A and Ctrl+E instead of home/end?
  • Seriously, rebind that shit. Your life will change for the better.
  • You don’t have to go full emacs or vi binds, given the learning curve, but that could be a worthwhile long-term goal.

Set aside time to practice programming

Do it on the company dime or not that’s up to you. The point is to seek measurable improvement.

  • Write a function.
  • Now delete it.
  • Write it again.
  • Delete it.
  • Continue until the function is perfect or your boss notices what you’re doing.

Get better tools

If you’re not willing to invest in yourself, then why would anyone else?

Do not decry your company for failing to provide you with adequate tools. Go out, find the tools, and if your company won’t buy them or approve them quickly buy them yourself or LEAVE.

Be pragmatic

Practice Taco Bell Programming

functionality is an asset, but code is a liability.

There is of course, value in re-inventing the wheel, but only to learn more about wheels. In the next 30 days, you have no such luxury. Work smarter, not harder.

Pick the simplest solution that could possibly work, test the hell out of it, and move on. My colleagues don’t have the luxury of the beautiful Linux tools that the author talks about here, but we should at least learn the lessons the Unix way. Make small composable units and combine them to make even more useful units. Repeat until you are the master of the universe.

Okay hopefully the non-nerds didn’t make it this far, and they don’t think to read up. I want them to take this seriously too, but honestly, nerds, realize your value. You are more vital to the company than they are. Now that you know that, stop being cowed into doing things by people just because they talk loudly at you or as “are you sure?”. These are laughably transparent attempts at manipulation, and they shouldn’t work on you. Man (or woman) up and do something about it.

Transform this

My scrum master said that we’re behind schedule

into this

My scrum master said she was going for coffee, anyone want one?

PS: It wouldn’t kill you to write a few tests too. Code fearlessly because you’re backed by tests


Don’t think I forgot about you. This concerns you too. If you would like to help these nerds achieve their dreams of literally doubling their output, and attain all the moneys that you so desperately want, then could you please do the following?

Understand the power dynamics, and stop abusing them

My favorite programming joke of all time goes like this:

How can you tell if you’re dealing with an extroverted programmer?

(pause for dramatic effect)

He’s staring at YOUR shoes!

(hold for applause)

Why does this joke work? Because it’s true. I touched on it perhaps a little too softly last time, so I’ll spell it out in no uncertain terms. Programmers are, generally speaking, afraid of confrontation and really bad at communication. If you take advantage of this fact, not only are you a terrible person, but you’re also doing yourself a disservice because again, you have no idea how this shit works.

If a meek expert tells you it’s going to take several days because of the [a bunch of shit you don’t understand], and you say: “Have it in by tomorrow”, they will likely not argue. You have just torpedoed your own project. Stop it.

Stop Breaking My Flow

Flow is great.

This post was conceived and authored in a single day. Granted, it has been brewing for the last 10 years or so, but today was the day that it became manifest because I had a long swath of uninterrupted time to compose my thoughts.

If you stop interrupting people, they will produce double the output in half the time. They’re on a different schedule than you are, and you should respect that, or at the very least understand it. Maker Schedule vs Manager Schedule

Armchair Psychology 101

Freakanomics reminds us that people respond to incentives, but rarely in the way you expect. You cannot just pay people more money and expect better outcomes. In fact, you actually get worse outcomes.

Axiom: People are willing to work harder on something they care about, the quality is better, and they tend to stay at companies where this is true longer.

Sadly, you cannot force people to care, but you can trick them into it. Much like smiling to fool your brain into thinking you’re happy, you too can manipulate others to achieve your financial goals. Bonus: it’s good for them too.

  • When they make something you like, praise them.
  • When they make something you don’t like, tell them how they can make it better.

If you consistently pretend that the work they do matters, they might just start believing it.

One of my most rewarding work memories happened on a conference call to some vendors I had never met. The business owner I had been developing for said the phrase “They’ve built us a wonderful tool”. It took a handful of seconds and zero effort on his part, and it motivated me for months. If you can’t do this, you’re a bad leader, or a sadist, or both. Shout out to Matt Watters, wherever you are.

Mythical Man Month

If you are a project manager, scrum master, product owner, program manager, middle manager, release manager, delivery manager, and you have not read this book, you are wrong.

This is required reading for anyone in the software field, but doubly so if you are in charge of any aspect of delivery.

How does a large software project get to be one year late? One day at a time!

TLDR here are the cliff notes:

  • Software projects fail a lot.
  • More people slow down a project.
  • Estimates are hard.
  • Fixing bugs often results in more bugs.

I think that’s everything. As always, please don’t fire me.

❤ Ross

Nailing the Interview

[ understand your audience ]

Disclaimer: This is taken from my personal experience interviewing candidates. I am by no means an interviewing expert, well-studied as a human lie detector, nor have I ever dedicated an ounce of time or energy into reading a book about the art of the interview. Luckily for you, neither has your interviewer. Most likely, the person sitting across from you (the candidate) is a normal human being of average intelligence who merely wants to see if you’re the type of person they could see themselves working with for an extended period of time without wanting to pull their hair out.

Note: If this is a consulting firm, then they just want to ensure that they can use you to extract the maximum amount of dollars from clients without them growing suspicious. Your actual personality probably doesn’t matter at all.

[ don’t panic ]
That’s easy, right? Don’t sweat profusely and make the interviewer feel weird you big dummy. Just plug your glands and remember to smile, but not too much… oh god, what do you do with your hands? Are you talking too fast? Too slow? This is how humans stand right? I think so.

Seriously, just relax. It’s already a really tense situation for everyone. Just be cool, okay? The interviewer will sense your anxiety, and will respond to it by asking you really easy questions. This might seem good, but really it’s like letting a kid win at basketball to make him feel better about being adopted. You want to prove that you are a smart, confident individual, and looking nervous until you get a few pity questions lobbed your way isn’t going to do anything to help your case.

[ know the bare minimum ]
If I ask you about design patterns, and all you can talk about is Singleton, the interview is fucking over. You should be able to explain language and technology agnostic concepts such as:

  • Basic Control Flow
  • Object Oriented Design Patterns
  • Data-Structures
  • Static vs. Dynamic Typing

There is a lot to know in the world of computer science, and often there is so much that we tend to forget the core topics. Know the basics inside and out so that you and the interviewer are speaking the same language. This is not to be confused with buzz-wording. These are not merely words you say and the interviewer quietly nods approvingly. You’ll be expected to know enough about any of these to talk about them in detail. If you don’t, I suggest you read up on them now and save yourself from getting in to trouble with the next piece of advice.

[ don’t bullshit me ]
There is nothing more repugnant than an interviewee who tries to bluff. It oozes out of them like a lanced boil:

“Oh yeah, polymorphism. It’s been a while, but I can do it. I just don’t remember the specifics. I would just google it. <sheepish grin>”

What was your plan here? Did you think I didn’t know enough about the topic I just asked about to call you on your obvious bullshit? Just own up about your lack of knowledge. The risk of outing yourself as an obvious charlatan far outweighs the minor inconvenience of admitting “I don’t know”. There are plenty of things I don’t know, and when people ask me about them, I try to be honest. Not knowing something doesn’t make you seem incompetent, but being a phony makes you seem like a dickhead who is wasting my time. In my head, the interview is over. I might explain how wrong you are, but there is no real way of clawing your way back from this position, so please, remember what your mommy told you: honesty is the best policy.

[  be smart, or have a plan to get smarter (or both).  ]
If you can’t impress me with your technical prowess today, at least show me some passion and have a plan to improve your skills tomorrow. If you are a “senior” developer and you haven’t learned anything in a while, you may want to reconsider this choice and pick up a book. “Good” in this industry is a moving target. If you are not improving, you are in fact regressing relative to the rest of the industry. Find some useful resources, and have them at the ready. Exclaim proudly: “No! I don’t know what a closure is, but I’m doing some courses on Javascript in my spare time, and I’ll be sure to pay attention when that bit comes up!”

[  be memorable ]
I see a lot of people, and they are all pretty generic. We all tend to do the same sorts of things in our day-to-day, e.g. making the button say this instead of that, or when the user clicks the thing, do some other thing. It’s boring, and repetitive, and not at all entertaining to hear re-told. Talk to me about something awesome you built, or about that time you brought down production, or the hard-to-find bug that saved your coworker hours and sent him into a fit of face-palming. I probably won’t ask, so just blurt it out. The less likely it is to come up in conversation, the better.

[ show me the code ]

Get yourself a github account and put up something, a pet project, an experiment, a few Project Euler solutions. Something with your name on it that is indicative of your coding style. This is equivalent to your artists’ portfolio, and there is really no reason not to have it available.

[ accept defeat gracefully ]
Sometimes, despite your best efforts, things will not go well. There are lots of reasons for this, but generally, it will mean that you are not the candidate the interviewer was looking for, and you know it. Resist the urge to ask “how did I do?”, it just feels desperate. Instead, ask the interviewer if there were specific areas where you are weak. If he or she has lots to tell you, just accept your fate, and try to turn the experience into something positive. Smile, take notes, and learn the things they mention. Your next interview will be better.

Tune in, well, let’s face it, whenever the hell I decide to get off my ass and post something, for an F-bomb filled tirade about passion.

-smugly yours, Ross

VSPerfCmd and you!

I love writing fast code. There’s something so deeply satisfying about having something perform well that gives me a rush and I hope the same is true for you, my little smuglords-in-training. Performance will probably continue to be a major theme for a lot of my posts here, so if you at all interested in going fast, please read on. If you like your code shitty and slow, well, I guess go find another article, or eat paste or whatever it is you do, but you should probably read on. Who knows, you might come across some student beauticians who aren’t used to geniuses, you might impress them! Plus, making something fast teaches you how to take advantage of all the resources you’ve got available, and there are plenty of useful things you can learn during that process.

The free lunch is over

In case you didn’t know it by now, you don’t get exponential software speed for free anymore. You can’t just rely on better hardware to make your code run faster. Sorry, your job just got harder. Writing performant code now requires a little something extra during your development cycle, namely, profiling to find your hot-spots. Maybe it’s I/O related, or your CPU isn’t taking advantage of cache, or you have an opportunity to parallelize something, or make it asynchronous, or perhaps you’ve tried to apply parallelism and now you’ve got some kind of thread synchronization happening around a shared lock causing your application to hang. In all of these scenarios (and many more) profiling tools can be invaluable in determining the root cause of the performance loss.

If possible, this should be done early on in the life of the application to establish ongoing metrics, but even for large-scale existing systems it can help to profile your application when debugging to get a general sense of what the performance characteristics of the app are, and whether or not you’ve accidentally introduced a feature which hurts performance.

Performance testing in development.

This is by far the best possible way to do performance testing. You can isolate testing behavior more reliably, and you get the immediate feedback if you correct the bottleneck, and may find that this uncovers other bottlenecks that need fixing also. There are of course plenty of tutorials on MSDN about how to use the performance wizard, here let me google that for you, but if there is one thing my internal smug-sense won’t allow me to do, it’s use a GUI when there is a perfectly good Command line interface available.

Show me the code already! Save your pathetic prose for someone who cares!

Here I’m using powershell to help me automate the repetitive bits of instrumenting and running the profiler. Sampling is good, but if you really want to go deep, I find that just instrumenting the assembly from the start is the best approach. I would highly recommend adding this to your powershell profile for ease of use. This assumes that sn.exe is on your PATH.

function get-assemblies([string] $path, [regex] $expr) {
	# if you havin' regex problems I feel bad for you son
	# I got \d+ problems and matching text ain't one.
	dir $path | where { $expr.IsMatch($_.Name) } | select Name

function instrument-binaries ([string] $basePath, $assemblies) {
    $profilerPath = "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Performance Tools"

    if (-not ($env:Path.Contains($profilerPath))) {
    	write-host "appending vs_profiler path to Path environment variable."
        $env:Path += (";" + $profilerPath);

    push-location $basePath

    if (-not (test-path ( where.exe VsInstr.exe ))) {
        write-host "VsInstr.exe is not installed!"
    } else {
        $flag = "is a delay-signed or test-signed assembly"

        foreach ($instr in $assemblies) {
            $path = [System.IO.Path]::Combine($basePath, $instr);

            VsInstr.exe $path /ExcludeSmallFuncs

            $output = (sn.exe -v $path)
            $resign = (($output -match $flag).Count -gt 0)
            if ($resign) {
                write-host $instr needs to be resigned...
                # assuming your keyfile is in the project root.
                # adjust accordingly
                sn.exe -Ra "$path" ..\..\your-keyfile-here.snk


Invoking the script then might look like this (and could itself be another script in your profile):

$path = "c:\dev\product\bin\debug"
$assemblies = get-assemblies $path "MyCompany.*\.dll"
instrument-assmblies $path $assemblies

That’s it. Your assemblies are now ready to be poked and prodded by the profiler. Let’s see what that might look like.

function begin-profiling ( [string] $session, [string] $report_path ) {
    if (-not (test-path $report_path )) {
        mkdir "$report_path"| out-null

    $env:_NT_SYMBOL_PATH = "srv*C:\mssymbols*"
    $profilerPath = "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Performance Tools"

    if (-not ($env:Path.Contains($profilerPath))) {
        $env:Path += (";" + $profilerPath);

    # make sure the profiler isn't already running.
    VsPerfCmd.exe /Status

    if ($LastExitCode -ne 0) {
        $name = $session + [DateTime]::Now.ToString("MM-dd-yyyy-hh-mm")
        $report = $report_path + $name + ".vsp"

        VsPerfCmd.exe /user:Everyone /start:Trace /output:$report /CrossSession

        write-host "Profiling report will be stored in:" $report
    } else {
        write-host "Profiler already running. New session will not be started."

I could probably go more in-depth about these arguments, but just trust me when I say that they were arrived upon through much trial and error, and represent my best attempt at a general solution that works for both dev and production profiling. We finally invoke the real profiler VsPerfCmd.exe, setting the output path to our desired report folder. The /user:Everyone is just for convenience in production. You can use this to restrict which users have access to write to the profiler report.

begin-profiling "my_app_startup" "c:\perf\reports"

# trace it all baby!
VSPerfClrEnv /TraceOn
VSPerfClrEnv /TraceGCLife
VSPerfClrEnv /InteractionOn

start-process /some /args /maybe:?

Run your test scenario, whatever that looks like. Close your application (the profiler will block if you forget). Then shut down the profilers. This is actually really important. You won’t see any data written to your report until after the process being profiled terminates.

function end-profiling {
    VsPerfCmd.exe /GlobalOff
    VsPerfCmd /Shutdown
    VsPerfClrEnv /off

    write-host "Profilers detached."

You did it! /slowclap

You can now double-click your .vsp report (in whichever directory you specified in begin-profiling) and review your findings inside the comfort of Visual Studio. You’ve captured a lot of interesting data I’m sure. That /InteractionOn flag enables Tier-Interaction Profiling, which will keep track of all the ADO.Net invocations executed under the profiler. It sure beats asking a DBA to run a trace on the database eh? You’ve also got CPU metrics, and some default windows performance monitor counters you can examine as well.

Okay, that’s all for now. Next time we’ll talk about production profiling, or whatever else I feel like talking about. Maybe the continuation of that other postYou’ll just have to check back and see. Comments help. If you like this, let me know. If you want hands-on labs, I could probably accommodate that too.

Anyway, until next time.

Yours smugly,

Ten shocking reasons to stop using LINQ. Some may surprise you.

Okay, the title is a total troll, I just thought it would be funny to create it as link-bait in light of a recent Scott Hanselman article about how these things are the death-throes of the internet. Sorry Scott!

When Microsoft first introduced these Haskell-inspired query operators in the 3.5 release of the .net framework, like so many others, I was ecstatic. I watched every video Erik Meijer put up on channel9, started reading about the functional concepts that underpinned the new features, learned about the compiler-generated state machines and deferred execution, but most prominently I used LINQ everywhere.

I call it the law of the instrument, and it may be formulated as follows:
Give a small boy a hammer, and he will find that everything he encounters needs
pounding. — Abraham Kaplan

This is commonly referred to as the Law of the instrument. It’s a bit cliché, but in this instance it was true, I had one hell of a hammer, and before me all I could see was a vast IEnumerable<Nail> begging to be sorted, and reversed, and selected. A few years and many a mangled and bent nail later I have come to regard Language Integrated Query, much like its functional forebears, as perhaps too powerful for the average programmer. The allure of function composition, the terse yet readable query operators, the syntactic sugar of the more SQL-like declarative syntax are all amazing advances to the language, and the minds behind it are truly remarkable. Sadly, not all advancement is to the betterment of all, and I’m of the opinion that LINQ is one such tool which has been abused for ill.

To be fair, many of these justifications stem from the fact that most .net developers did not do their homework when 3.5 first came out, either out of laziness or because they were trapped in an environment with antiquated tooling, and now the educational content is simply harder to find. It’s not new and exciting anymore, so nobody writes about it.

  1. Seductively easy to not filter and sort at the database level.

This is a huge pet peeve of mine which is why it is at the top of my list. I cannot fathom the laziness that drives a person to write code like this:

    var products = FetchAllTheThings()
    	.Where(item => item.Price > 500.00m)
    	.OrderBy(item => item.Price)

Seems harmless enough, but let’s break this down. Firstly, I’m taking it as assumed that FetchAllTheThings() is responsible for reading from the database (possibly over the network) but is not backed by Linq-to-sql or Entity Framework, because that would enable this query to actually be rendered to the database. In this case I’m talking specifically about technologies which are not linq-friendly like direct reads from an SqlReader or some homegrown micro-ORM that your best and brightest devs put together 10 years ago to protect the less savvy from harming themselves or others.

So with those basic constraints in mind, let’s take a look at the above query in more detail. The result set is potentially huge, could continue to grow over time, and we have no control over it. We throw away most of the results between the where and take, so all that I/O and ORM work was essentially a complete waste. Worst of all, none of this needs to be expressed as managed code; these are all directly mapped functions of SQL server. I will be the first to admit that t-sql is far from an elegant language, but in the domain of sorting, filtering, projecting, aggregating, and indexing it remains the most efficient way to leverage the power of your relational database. Linq-to-objects abstracts the details away, but this code is non-trivial and took only seconds to write. The performance implications are huge, and the amount of thought that needed to go into writing it was dangerously low.

This pattern of unapologetic disregard for coding decency reminds me a lot of Hedonism Bot from Futurama. In my head, this is how I imagine them.

Yes, bring me all the data, I shall pick what I like and discard the rest.

I trust the memory-orgy heap has been garbage collected and made ready for my next indulgence.

From one million records I need only one. How decadent!

  1. Complex expressions quickly become unreadable.

Repeat after me: “instructions are for processors, code is for humans”. If the next person who comes along after you cannot quickly comprehend what your code is doing then you have done him or her a disservice, and should feel bad about that, unless you are a sociopath, in which case, as always, you feel nothing.

There is something magical about LINQ that takes all rules about formatting and throws them out the window. The generally accepted pattern is to put each query operator on a separate line. This is seen as preferential to the epic one-liners whic happen just as often, but I would argue that both are code smells.

        var seq = setOfThings
                .Where(w => w.IsSpecial || w.HasValue || w.HighPriority)
                .OrderBy(x => x.Price)
                .ThenBy(t => t.Discount)
                .Select(s =>
                        Name = s.Name,
                        Price = s.Price.ToString("D")

It’s actually quite hard to produce knowingly ugly example code that gets this message across. It’s like trying to will yourself to spell something incorrectly…

At any rate, as readable and concise as the query operators are by themselves, the composition is something that has quickly spiraled out of control. Imagine how this would be to debug (which I’ll touch on later).

I think a more hideous example is the mixing of the declarative “query syntax” and the extension methods where there is no support for things. Like FirstOrDefault() and ToList(); You get these extra parenthesis that just wrap around your weirdly out of place code haiku as below:

   var seq = (from thing in setOfThings
              where w.IsSpecial || w.HasValue || w.HighPriority
              orderby thing.Price, thing.Discount)
              .Skip(10) // oops, we've run out of query support.
              .Select(s =>
                        Name = s.Name,
                        Price = s.Price.ToString("D")


Okay, this post has gotten a bit wordy. I had no idea I was bottling up all this nerd-rage about LINQ. I’m definitely not going to get to all 10 without people losing interest, so I’ll break it up into multiple posts.

Tune in next week for the next exciting installment: “More ways LINQ causes code-tumors.”

Confessions of a code-reviewer: What’s in a name?

There are only two hard things in Computer Science: cache invalidation and naming things.

— Phil Karlton


This is an honest plea, free of smugness or sarcasm: Please make your names count. When thinking about what to call something, think about the fact that your code may well outlive you, or at the very least your tenure with your current company, and make it something meaningful enough to stand the test of time. Your fellow developers will thank you, and who knows, you might even find that the life you save is your own. Maybe you aren’t too thrilled with your current team and you’ve decided to take revenge, or your pants don’t fit quite right, or you’ve got a bad marriage, whatever it is that compels you to write a function called fnCalcCurSal just stop; put the keyboard down and read below. Good names improve understanding, and bad names, well, bad names make your code look terrible and people will point and laugh at you. Don’t become an object of ridicule. Rise above, and cast your scorn down upon those who use silly names.

This is a cobbled together list (in no particular order) of official guidance from the Microsoft Framework Design Guidelines and my own personal opinions on what makes a good function name. Feel free to disagree.

Things to absolutely avoid in method names

(things get a bit dicey with variable names because opinions on those are more diverse)

  1. Acronyms
    1. industry standard or otherwise, they really don’t belong in the method name. The most glaring reason for this is that the upper-case characters which make up the acronym break the flow of upper to lower case which makes CamelCase so nicely readable.


      // not a great name

      Here we’ve blended the acronym CPR with the first letter of the word On, and hampered readability, even if only slightly.

  2. Abbreviations or Phonetic Substitutions
    1. This isn’t LOLCODE people, NoAbrvFuncNamsPls KTHXBYE
  3. Hungarian Notation

    Good advice from uncle bob.

    … nowadays HN and other forms of type encoding are simply impediments. They make it harder to change the name or type of a variable, function, member or class. They make it harder to read the code. And they create the possibility that the encoding system will mislead the reader.
    –Robert Martin

    And more here from Linus.

    Encoding the type of a function into the name (so-called Hungarian notation) is brain damaged—the compiler knows the types anyway and can check those, and it only confuses the programmer.
    –Linus Torvalds

    Hungarian Notation is a code smell. Forget you ever used it, and never use it again.

  4. and / or / with
    1. If your functions contain these words, you are probably over-describing what the function is doing, rather than how it should be used, or the reason it should be called.
  5. Implementation specifics

    I haven’t seen this in any publications, at least none that leap to mind, I’m just offering it as good advice if you want your code to remain self-documenting. If your function advertises itself as having certain behavior, and the underlying implementation changes, then the name of the function should change to remain consistent. Knowing this, avoid leaking information which the caller has no business knowing. Encapsulate your ideas and name your functions with a little detail about behavior, but mostly think about the reason someone might call your method, not exactly what it does.

    For instance, you wouldn’t want to choose a name like GetDataFromSqlServer because this includes information that the caller really shouldn’t be privy to. He shouldn’t care where you got the data from. If sometime later you decide to change the source of the data, this method (and all calls to it) would need to be changed. The inverse is almost worse in a way. If the implementation strategy changed but the callers still believed they were getting data from SQL Server that might also be bad. Again, consider why not how.

As programmers, we owe it to ourselves and our fellow geeks to write good code; code we can be proud of. I hope this list has been helpful, and if you have any additional tips I may have missed feel free to comment below.