Saturday, August 26, 2006

Have MSBuild script collect userinput

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/have_msbuild_script_collect_userinput.htm]

MSBuild is great for automated batch processes. It's easy to set properties in the script itself using the . However, MSBuild is powerful enough that you can also collect user input with a WinForm.

Why would you do this, given that the whole point of a build process is to be automated? ... Because MSBuild is an automation language, it can be used not just for builds but to
ultimately automate any task. For some tasks that you kick off manually (like installations, deployments, instrumentation, etc...) you may want to collect the user input up front.

Doing this requires three steps.

  1. Use MSBuild's exec task to call a WinForm exe (that you create with a Windows Form project). Note that you may want to compile the windows project first, and then call the newly created exe.
  2. Have the WinForm app close, returning an error
  3. Back in the MSBuild script, collect this error information and handle it how you want.

The first step is easy, lets look at the second one. There are several different ways we can return error information from a WinForm.

  1. We could throw an exception, but that just pops up a messy JIT window, tells the user that the app failed, and doesn't return an error to the build process.
  2. We could have the WinForm write out to a log file, and then have the MSBuild script fail if that file exists - but that requires extra files and is messy.
  3. We could modify the return code of program.cs (just like you can modify a console app's return code) to return an integer, and that set that int with a static variable. This is our best option of the three - no external files, and the error is handled gracefully.

With this technique, everything becomes easy: Our MSBuild script can be simple:

  "EndPoint">
   
    "WindowsApplication1\WindowsApplication1.csproj"
        Targets="Build"
        Properties="Configuration=Debug" />
   
    "Start UI" />
    "WindowsApplication1\bin\Debug" Command="WindowsApplication1.exe" />

    "Done, do other stuff now..." />
 

The WinForm is easy:

  static class Program  {    ///     /// The main entry point for the application.    ///     [STAThread]    static int Main()    {      Application.EnableVisualStyles();      Application.SetCompatibleTextRenderingDefault(false);      Application.Run(new Form1());      return _intReturnCode;    }    private static int _intReturnCode = 0;    public static int ReturnCode    {      get { return _intReturnCode; }      set { _intReturnCode = value; }    }      }

 

We can then set the static variable "ReturnCode" anywhere in the WinForm by setting Program.ReturnCode.

(Note that we can also have the WinForm use Console.Writeline(), which will be logged in the MSBuild script).

Having the MSBuild script take user input is an easy trick to perform, and may be helpful for certain tasks.

Friday, August 25, 2006

Things that fundamentally improve how you program, Part II

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/things_that_fundamentally_improve_how_you_program_part_ii.htm]

About a year ago, I posted on Things that fundamentally change how you program, listing several things:

  • Object Oriented Code
  • Unit Tests
  • Regex Expressions
  • Xml
  • Code Generation
  • Consciously seeking Tools

A year later, there are new things I would add to this list:

  • Continuous Integration - Besides just checking in your code to a general repository, there's a huge benefit to have the repository's source code continually tested with a regular build. A simple build may just compile and run unit tests. However, by doing this whenever someone checks in new code, you can catch many errors because they propagate and do real damage. A popular (and free) Continuous Integration framework is CruiseControl.
  • Automation, especially of processes (such as with MSBuild). The point is that complicated processes are two tedious to repeatedly do manually. For example, a build process may take 30 minutes, and with Continuous Integration you may do this 20 times a day. There's simply no way to manage it without automation.
  • CallBacks and Ajax/Atlas related technologies. This changes how websites operate, from the postback model that sends the entire page back and forth, to a asynchronous request that sends just a small packet of data, which enables you to make a rich-UI.
  • Virtual Machines (such as VMWare) - I'm exploring this more, but essentially Virtual Machines let you make a "guest" image of a machine that runs in isolation on a host. This can be great for expanding your build process, testing in different environments, and studying applications with a ton of configuration to them (without messing up the main host machine).
  • Blog Aggregators - In our industry, learning is critical. If you stop learning, not only does the job become dull, you risk losing your job. Blogs are a great way to learn new quick and practical ideas from veterans in the trenches. A blog can publish info much faster than a book. Reading blogs is a great way to inject a bunch of new ideas into your head. The problem is that no one wants to manually check 20 different web pages, so you'll want a way to aggregate all the new blog posts into an easy-to-read inbox (as if they were email). Two free blog aggregators are RssBandit and SharpReader.
  • Visiting Tradeshows or users groups. Anytime you get out of your cubicle, and meet other experts face-to-face in the field, it will make you more confident. User groups are usually free, let you bump shoulders with other real people, and keep you in the loop about new technologies and trends. Along with reading high-profile bloggers, this helps you never to get "surprised" by some sudden technical development that changes how your app functions. It also gives you assurance in knowing how other people implement things.

All of these things are easy to get started, but they will fundamentally improve how you program. If you want to be a better developer, you'll get a high return from investing in these things.

Monday, August 21, 2006

Creating Database Unit Tests in 10 minutes.

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/creating_database_unit_tests_in_10_minutes.htm]

Unit testing the database is hard - and there are mixed reactions to it. My take is that there could be legitimate logic in the database (transactions, SQL aggregations, reusable functions, complex SP like paging, etc...). The problem with unit-testing the database is creating a test database and filling it with data. At Paylocity, we created a tool called the MassDataHandler to help us unit-test our data layer. We recently open-sourced this tool, and you can download the beta here.

The MassDataHandler is a framework to assist with Database Unit Testing. The framework makes it very easy to insert test data into a database, which in turn makes it very easy to write database unit tests. The user merely needs to specify their relevant data in a simple XML fragment, and then the framework uses knowledge of the database schema to do all the grunt work and convert that XML data into SQL, from which it populates the database.

The XML fragments that contain the test data are robust and refactorable. You can include expressions like variables substitution and identity lookup, default row templates, and include statements to import sub-templates. Because the framework already knows the database schema, you only need to specify the relevant data, and the framework can auto-populate the rest of the row’s required columns with dummy data.

For example, the following Xml script would insert data into three tables - providing you variables, default row templates, and automatically handling the identity lookups and non-null fields:

  <Root>

    <Variables>
      <Variable name="lastName" value="Simpson" />
    Variables>

    <Table name="Customer">
      <Row CustomerName="Homer $(lastName)" />
      <Row CustomerName="Marge $(lastName)" />
    Table>

    <Table name="Product">
      <Row ProductName="KrustBurger" Description="best burger ever" />
    Table>

    <Table name="Order">
      <Default LastUpdate="12/23/1997" />
      <Row CustomerId="Customer.@1" ProductId="Product.@1" />
      <Row CustomerId="Customer.@2" ProductId="Product.@1" />
    Table>
   
  Root
>

Download the MDH Framework Beta here.

By making it so easy to insert and maintain test data, the MDH framework helps you write database unit tests.

Sunday, August 20, 2006

How to program what you enjoy

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/how_to_program_what_you_enjoy.htm]

We all want to program what we enjoy - else our job gets boring. Loving your job also builds Technical Confidence. Some people just wait, hoping that the perfect project will fall in their lap, but there are things you can do to help your cause:

  1. Make a list for yourself of what you want to program. If you don't know what you want, no one else will know for you.
  2. Work little bits of these things into daily features. Perhaps you can demo a new coding technique, framework call, or trick.
  3. Make an objective business case for it so that it's not "Bob wants to play around with new tech X (wouldn't we all)", but rather "Bob can add value to the team using new Tech X".
  4. Tell your manager so that they can look out for you. If your manager knows that you're interested in "X", then they can at least try to send that kind of work your way.
  5. When you get the opportunity to do part of the new tech on something small, nail it.
  6. Invest your own time (off the clock) to build a prototype of something. You can then show this to management (you're not just some dreamer wasting their time, but a solid contributor with a tangible prototype). It also helps you Continually learning better coding methods, and demonstrates your commitment to management ("Bob did this on his own time, imagine what he could do if we let him do it full time").

Saturday, August 19, 2006

Hiring based off years of experience

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/hiring_based_off_years_of_experience.htm]

I often see a job openings that require "X years of experience". While this makes sense as a general rule, there are a lot of exceptions. The problem is that you're hiring a developer to design and ultimately write code, and the computer doesn't care how old you are. Instead, it cares about what you type into the keyboard, i.e. do you know how to program? The question is how does a developer know how to program? Recruiters look at "years of experience" because they hope it will equate to "knowledge of programming", but there are many reasons where the correlation breaks down:

  1. A younger dev may have worked 50-60 hr weeks. An older may have only worked 40 hr weeks (so the younger actually has more experience).
  2. A younger dev may continually work on new features. An older dev may just do redundant work (so the younger actually knows more).
  3. A younger dev may continually solve hard, new problems. An older dev may just copy and paste code (so the younger has better problem solving skills).
  4. A younger dev may have a huge background in related technologies. An older dev may have slightly more "experience" in the specific requested technology - but nothing else (i.e. 5 years Java + 6 months C# is better than just 1 year C#).
  5. A younger dev may have started programming when they where just 10. An older dev may have just started after college (so the younger actually has more experience).
  6. A younger dev may just be smarter, and can pick up new concepts quicker. An older dev may be slower and while he knows the current concepts, can't pick up new ones (which is huge because the technology keeps changing, so you continually need to learn new techs).
  7. A younger dev may be motivated (perhaps seen through extra-curriculars like open-source projects and articles). An older dev may be apathetic.

Of course "years of experience" matters - certainly you want senior devs and architects to be experienced veterans. But "years of experience" is only one factor to determine how qualified someone is, and it's a weak factor if two candidates are only a few years apart. Assessment tests, writing code on a whiteboard, checking for extra-curriculars, in-person interviews filled with conceptually questions, even certifications, etc... can all tell you much more about their skill level than "number of years".

On a a related note, it reminds me of back in 2002 when recruiters would say "This position requires 3 years of ASP.Net experience", and I explained to them that ASP.Net hadn't been around that long. "Years of experience" is a nice generalization, or minimum bar, but ultimately we're all trying to hire motivated and talented people - regardless of their years of experience.

Sunday, August 13, 2006

Refactoring Your MSBuild Scripts

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/refactoring_your_msbuild_scripts.htm]

I had the opportunity to publish an article for .Net Developer’s Journal: Refactoring Your MSBuild Scripts.

MSBuild is Microsoft’s new build engine. It is intended to replace NAnt, and in a way, DOS. It is an extensible Xml-formatted list of build commands. You can read the official MSDN documentation for MSBuild here: http://msdn2.microsoft.com/en-us/library/ms171452.aspx

There are already several basic tutorials for MSBuild, I wanted to write an article that was a little more advanced, and explain how to write better scripts.

Also, check out Sayed Ibrahim Hashimi's MSBuild blog: http://www.sedodream.com. He's written an entire book on using MSBuild.

Wednesday, August 9, 2006

Dealing with pressure-hacks

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/dealing_with_pressurehacks.htm]

Life is tough, and sometimes that forces us to make tough decisions. For developers under time and money pressure, that means occasionally writing code hacks that you’re not proud of.

I’ve met some developers who think that the only reason that hacks exist is because other people are dumb. Certainly many hacks are caused by ignorance, but many are also caused by unrealistic time, money, or features constraints that pressure someone into writing bad code. The critics seem to think that if only the world were as smart as them, then all code would be perfect – just like theirs (sarcasm). Ironically, these critics never seems to have had to dealt with the pressure themselves – they can tell you how you’re supposed to do it, or how their last company (that’s 10 times bigger) did it, or what the “Best Practices” are, but they don’t actually implement it themselves.

The best way I can think of to handle pressure-imposed-hacks is to:

  1. Acknowledge that it is not ideal, and identify the problems.
  2. Ask if others have a better idea (that can be implemented under the same pressue).
  3. Document your hack, ideally in the source code or wherever else it matters.

The first step brings everyone to the same page. The second gets others’ feedback – maybe they know a helpful trick that will make everyone work. The third reaffirms to your fellow developers that while you’re aware that this isn’t ideal and you’re not trying to hide it, the code needs to be completed and this gets it done. These steps require humility and confidence from the coder: they admit what they don’t know something, but they can be confident that their approach at least solves the problem. Ultimately the company stays in business not by the critic who points fingers at everyone, but by the developer who makes the project work – even if it has an occasional hack.

Open question to readers - what do you think about hacks due to excessive pressure? Any interesting stories?

Monday, August 7, 2006

Giving good feedback

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/giving_good_feedback.htm]

Software is complicated, and we therefore must often get feedback from other people. Some people do not know how to give good feedback; they:

  1. Blindly stamp it with approval - maybe they're shy, don't want to offend, or just don't know how to give feedback.
  2. Point to useless details that don’t really help - maybe they don't understand how to improve it, but still feel compelled to say something.
  3. Give completely impractical advice - maybe they don't know what's going on, or didn't want that feature in the first place.
  4. Use it as an ego booster and try to rip the other person apart - maybe they're just a jerk. (Or, another theory: many socially awkward nerds go into software development. Perhaps they're just desperate for affirmation, and want to dim your candle to make theirs look brighter).

Feedback should be constructive and practical - it's goal should be to make something better. Here are some ideas how:

  1. Do you understand what the thing is that you're evaluating? If not, save everyone time and admit that ("I'm sorry, I'm not really sure what this is supposed to do, so I can't really comment on it."). You can always learn more about it such that you can have an opinion later.
  2. Point to something positive. The developer invested time and effort in what they're showing, so affirm something ("this took a lot of effort", "I like how it functionally works", "that's a nice algorithm").
  3. See what you can practically improve (an algorithm, refactor it, better performance, etc...). Start with the most important improvements first, limit your suggestions to what they can handle, and make it practical.
  4. If they did something poorly, and it's a touchy subject, try comparing it so something else good that they did. Compare these two feedbacks: (A) "Your first module had great performance, any way to make this second one perform well too? Perhaps we can run the profiler on it?" and (B) "This second module performs too slowly. Fix it."

Giving good feedback doesn't just help the recipient, it helps you too. You can help influence things for the better, others will respect you more, and it can be more mentally challenging (and therefore grow you as a developer).