Friday, December 29, 2006

Good article on achieving a zero-bug count

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

James Shore wrote a great article on achieving zero-bug count. It's part of his up-coming book.

Some of the things I really like are how he emphasizes that bugs are not "okay" or "necessary", but rather that the team should take active steps not to just prevent bugs, but to prevent the cause of bugs. For example, being required to explain why a bug occurred, such as adding a textbox to your bug-tracking system that requires the developer to explain what caused the bug.

The problem with bugs is that they take 10x longer to fix than create. So if you can improve your process to reduce bugs (which takes more time upfront), you can then go into an "upward spiral", where things keep getting better and better.

It's a thoughtful article.

Monday, December 18, 2006

Different Types of Comments

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

Programming enterprise apps and their supporting processes, I've used at several languages. Most of them have different ways to make comments.

Characters Languages Multi-line vs. Single-line Characters
// C#, JavaScript Single 2
/*  */ C#, SQL, CSS Multi 2,2
' VB Single 1
REM DOS Single 3
XML, HTML Multi 4, 3
<%-- --%> ASP.Net Multi 4, 4
-- SQL (single line) Single 2

I didn't have any big dialogue on this, I just found it interesting - 7 different ways to comment code for a set of languages that are often used together for a common goal. I'm sure that someone with a strong Compiler background could explain the significance of multi-line comments vs. single-line comments, and number of characters involved to create the comment identifier.

Sunday, December 17, 2006

ASP.NET AJAX Control Toolkit - making it simple

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

Looking at the newly available ASP.NET AJAX Control Toolkit, there are several things I really like about it.

  • It has a quickstart with a sample page for each control.
  • It takes less than 5 minutes to download and get running.
  • The controls are mostly cross-browser compatible.
  • It's free.
  • It's open-source.
  • It's practical - i.e. the controls are based on useful needs, not just flashy toys.

I especially like the ModalPopup and PopupControl. The first presents just that - a modal popup (which nicely fades out the screen). The second provides a dropdown-type control which is great for X-Pickers (Date-Pickers, Employee-Pickers, Color-Pickers, etc...)

Even if you're in an older shop that already developed a lot of your own controls, it's still worth investigating because these are (1) standardized, (2) likely to continually improve with the support of an entire community, and (3) potentially better and more robust than a control that a single dev whipped up a year ago under schedule pressure.

What I notice is that these controls abstract a lot of complicated DHTML features, like drag & drop, multi-layering, and DOM-modification, all while being cross-browser compliant. In a way, it's reduced advanced DHTML to mere copying and pasting.

Tuesday, December 5, 2006

Types: is operator, GetType method, and typeof keyword

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

A common .Net question if "how do I determine if object x is of type y? For example, you may only want to perform certain operations on certain objects. Sometimes this can be solved by having that object implement an interface. But, there are other times you'll just need this ability. .Net provides easy ways to do this. Consider the code snippet below (notice that this is actually an MSTest unit test, but it's very easy to demonstrate quick code snippets because you can directly step into the code.

We notice a couple things:

  • is operator - shows if object x is of type y. If this condition is true, then you can cast the instance to the given type. This accounts for inheritance. For example, all types (such as System.Int32) inherit from System.Object.
  • GetType() method - a method on System.Object (and therefore available to all types) that returns the Type of the object. The Type class has a "FullName" property which returns a string of the name. Notice that you can tell the name of immediate type here, but it doesn't inheritance. For example, for an object on type "System.Int32"  the "is" keyword accounts for the current type (int) and the base type (object). GetType requires an instance and returns a type.
  • typeof keyword - Takes a Class an returns a Type (almost the inverse of typeof).

    [TestMethod]
    public void Type_Int32()
    {
      int i = 5;

      //Show 'is' operator
      Assert.IsTrue(i is int);
      Assert.IsTrue(i is object);
      Assert.IsFalse(i is double);

      //Show GetType and typeof
      Assert.IsTrue(i.GetType().FullName == "System.Int32");
      Assert.IsTrue(i.GetType() == typeof(System.Int32));

      //Declare Type instance
      Type t1 = null, t2 = null;
      t1 = i.GetType();
      t2 = typeof(System.Int32);

      Assert.IsTrue(t1 == t2);

    }

Notice that this same pattern can be applied to both value types (like a System.Int32) and reference types (like an XmlDocument):

    [TestMethod]
    public void Type_XmlDocument()
    {
      XmlDocument x = new XmlDocument();

      //Show 'is' operator
      Assert.IsTrue(x is XmlDocument);
      Assert.IsTrue(x is XmlNode);
      Assert.IsTrue(x is object);
      Assert.IsFalse(x is double);

      //Show GetType and typeof
      Assert.IsTrue(x.GetType().FullName == "System.Xml.XmlDocument");
      Assert.IsTrue(x.GetType() == typeof(System.Xml.XmlDocument));

      //Declare Type instance
      Type t1 = null, t2 = null;
      t1 = x.GetType();
      t2 = typeof(System.Xml.XmlDocument);

      Assert.IsTrue(t1 == t2);

    }

By using the is operator, GetType method, and typeof keyword, you can effectively manage type information and solve several problems in various ways.

Monday, December 4, 2006

Essential .Net Chapter 3: Type Basics

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

 

Chapter 3 of Don Box's book Essential .Net: the CLR explains the basic of types. While this is a common topic. Don has a clear way of explaining things. He does a good job of explaining the concepts of types in a way that transcends individual language syntax. This chapter connects a lot of dots, and makes a lot of sense once you've already been using an OOP language like C#. While most of this I've already seen before in other C# books, Don has a good way of explaining it:

Types - "A CLR type if a named, reusable abstraction." (pg 49) - I constantly have junior devs asking "What is a type?" I've heard several answers, like "A type (or form, or kind) of data", but I think Don's phrasing helps clarify the intent.

Sealed vs. Abstract - He explains how the class modifiers sealed (cannot be inherited) and abstract (must be inherited) are really opposites.

Const vs. Readonly - He discusses the difference between the const (made constant at compile time) and readonly (set in the type initializer at runtime, and then no longer editable). For example, consider this code snippet:

  class TypeDemo
  {
    public TypeDemo()
    {
      c2 = 456;
      c2 = DateTime.Now.Second;
    }

    public const int c1 = 123;
    public readonly int c2;

    private void MyMethod()
    {
      //This would cause a compile error:
      //c2 = 123;
    }
  }

Params - He discusses the params keyword in a method signature, which lets you pass in a variable amount of parameters into a method. The called-method receives these params as an array. Using Ildasm to view the code, one can see that the params keyword generates the System.ParamArrayAttribute.

    public static void DialEm(string message, params string[] numbers)    {      //Do stuff    }    public static void CallFred()    {      DialEm("Hi Fred!", "123", "456", "789");    }

Constructors - He explains about static vs. instance constructors. Looking at the IL, it's interesting to note that the static method has the name ".cctor", and the instance method has the name ".ctor" (only 1 c).

Interfaces - He points out that interfaces can strongly-type the context that an object should be used in. SO if you have objects AmericanPerson, CanadianPerson, and Turnip, you can have the first two objects implement the IPerson interface so that methods (at compile time) can uses those in a "person" context. By having an object implement multiple interfaces, you allow it to clearly be used in multiple contexts.

Overall, this chapter constantly transcends just the C# language and points to what the IL actually looks like. Constantly seeing the IL helps to fill in some gaps and see the significance of certain coding decisions.

Lastly, Don observes about the importance of types that "Developers spend most of their time defining new types in terms of existing types." (75). This is an interesting observation, and something that code generation is actively trying to address. For example, without codegen, a developer will spend a significant amount of time constructing objects that map to their database, like an "Employee" and "Customer" object. However, with codegen, the developer ideally just generates these objects based of of existing schema (such as a database or an xml file).

Sunday, December 3, 2006

What Flat Tires Can Teach You About Your Build Process

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

While driving with my wife this weekend, we started hearing a strange bumping sound in our car. We didn't want to stop because it was the start of a Chicago winter, we were already late to our destination, and our 16-month old son was in the car. However, we quickly pulled over anyway - just as we started smelling burning rubber. Sure enough, we had a flat tire. After demonstrating my amazing car skills and impressing my wife (that's sarcasm - I have no car skills), we got the tire changed. We then drove back home and everything was okay.

Back in the comfort of our warm home, I started thinking how a flat tire reminded me of a broken build:

  • Both are dangerous if ignored: You will ruin your entire wheel and eventually car frame if you keep driving with a flat tire. Likewise, you will cripple your application with so many compile and test errors if you keep checking in code despite the build already being broken.
  • Both give you clear warning signs: A car with a flat makes an obvious sound, thumping feeling, and smells of burning rubber. A broken build (if you have a continuous integration system like Cruise Control) gives you clear emails about the exact build failure.
  • Both don't get fixed by ignoring the problem: A car tire doesn't magically get un-flat. A broken build doesn't magically get fixed.
  • Both require stopping what you're doing to fix the problem: In development, I constantly hear "but we're to busy to ". Just like fixing a flat requires you to stop the car (even if you're already late), fixing the build requires at least one developer to stop their features and check in a fix.
  • Both can be fixed with relatively little effort: A high-school kid can change a flat time in 10 minutes (i.e. it's not expensive or rocket science). Likewise, if you have continuous integration (and hence can see the exact code-checkin that broke the build, and the exact error that went wrong), it's usually very obvious and quick to make a fix - definitely much easier than if you wait and let the build errors grow.

Wednesday, November 29, 2006

Ildasm: Viewing attributes

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

Yesterday I mentioned ILdasm to view the meta data on an assembly. One of the benefits of .Net is that it requires meta data for all assemblies. You can even create your own strongly-typed meta data via attributes. For example, both NUnit and MSTest use attributes to indicate that a certain method is a unit test. Because all the meta data is public, these external programs can use reflection to loop through all the methods in an assembly, and check which methods have which attributes.

These attributes show up in the IL. If you use Ildasm to view a method, you'll see which attributes it has. The IL snippet below has both the [TestMethod] attribute used by MSTest, and my own custom [Duration] attribute.

.method public hidebysig instance void  Duration_String_1() cil managed
{
  .custom instance void [Microsoft.VisualStudio.QualityTools.UnitTestFramework]Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute::.ctor() = ( 01 00 00 00 )
  .custom instance void TestDemo.Duration.DurationAttribute::.ctor(float64) = ( 01 00 7B 14 AE 47 E1 7A 84 3F 00 00 )             // ..{..G.z.?..
  // Code size       18 (0x12)
  .maxstack  2
  .locals init ([0] string s)
...
  IL_0011:  ret
} // end of method Strings::Duration_String_1

Of course, you'd probably never use Ildasm to read the attributes, but it's good to know that everything is consistent - i.e. meta data is public for any .Net assembly - it's not cryptic information only for debug more or something (like a *.pdb). So it makes sense that external programs like MSTest and NUnit can read these attributes.

Tuesday, November 28, 2006

Measuring the CLR, using ILdasm

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

I've been looking more at the .Net CLR, i.e. how .Net really works under the hood. Because most of my work and hobbies are application development, it's easy to take the CLR for granted.

I've been reading Don Box's (with Chris Sells) Essential .Net Volume 1: The Common Language Runtime. I'll try to blog more about each chapter as I read it. Obviously given the popularity of both authors, it's a good book. Even though it's for .Net 1.0, it's still very practical.

It makes it much easier to understand something if you can observe and measure a cause and effect. Many devs I see don't try to understand the CLR because they can't measure much about it - such as how much memory some code takes, how fast the code runs, what happens when it gets compiled, etc... For example, many devs use try-catch to do business logic checks, and don't worry about performance because it "works fast enough on my machine."

I'm no CLR guru (you can see the official Microsoft CLR bloggers here), but I'll be blogging my adventure digging deeper into the CLR.

To kick it off, I started with Ildasm (view MSDN tutorial here). As every .Net book points out, .Net languages (like C# and VB.Net) get compiled into MSIL - Microsoft Intermediate Language - or just IL for short. This allows .Net to be language independent, because no matter what language you code in, it gets compiled to the same IL. Ildasm lets you see that compiled IL.

First, you can see the IL Specification here.

You can run Ildasm by opening the VS command prompt and just typing "ildasm". If you go to File > Open, you can browse for an assembly, load it, and then view its IL and meta information.

Here are some immediate benefits of what you can see with IL:

  1. Whether this is a debug or release assembly - the Debug version will have an extra line:
        // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute
  2. The meta data for the assembly (like company name)
  3. What other assemblies this one references.
  4. The actual IL. So, for example, you could see the number of boxing and unboxing operations by checking for the box and unbox IL commands.
  5. All the types and classes in the assembly.k

A super-version of IL, which can take an assembly and convert from the IL back to a .Net language is Lutz Roeder's Reflector. This is very useful for reverse engineering an assembly - even Microsoft's own system assemblies.

I'll blog more about this in my upcoming posts.

Monday, November 27, 2006

Logical puzzles

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

This is a cool website: http://www.techinterview.org/

It lists a bunch of logic puzzles that you'd likely see in a tech interview. Nice way to start the morning.

Sunday, November 19, 2006

Adding an Event to a User Control (Code Sample)

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

I had talked about how to trigger an event from a UserControl.

This ability has many benefits, such as with refactoring. For example, suppose a UserControl is hosted on many different pages, and each page requires that the control have slightly different validation that incorporates values from the host page. One way to do this is to have the UserControl call a validation method on the host page.

Here's a code snippet you can download that shows how to have a UC call a method on its parent. The idea is to add an event member to the control, and hook it up with a delegate. (I had initially seen this technique from an article on MSDN several years ago).

This specific example has four files:

  • A UserControl - RecordNav.ascx and RecordNav.ascx.cs
  • A host page - HostRecordNav.aspx and HostRecordNav.aspx.cs

The UserControl contains an event "UpdateDate" and the host page adds a method to handle the event: RecordNav1_UpdateData.

    RecordNav1.UpdateData += new AspxDemo_Events_RecorNav.UpdateDataEventHandler(RecordNav1_UpdateData);

Wednesday, November 15, 2006

CNUG Presentation followup - MSBuild with source code samples

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

Yesterday's presentation at the Chicago .Net Users Group went well. Paylocity sponsored it with a presentation on MSBuild: A Process Automation Language.

You can download the presentation and code samples here.

Here's the abstract:

.Net 2.0 introduces MSBuild – Microsoft’s new build engine with a process-oriented scripting language. While MSBuild is marketed for compilation and build processes, it is really a full-fledged automation language. It includes structured control flow, variables, refactorability, error handling, logging, and powerful extensibility. You can easily integrate MSBuild into your own enterprise processes and start adding value right away.

Tuesday, November 14, 2006

Multi-tasking with background processes

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

A miscellaneous thought for the day: Given enough time, what (non-computer) background processes do you run in your everyday life? Letting the dishes soak to get out a tough stain, or letting clothes air-dry?

If you have the time, these processes are very cheap yet effective. People who don't have the time pay for extra products to make these processes go faster (a powerful dishwasher, chemical cleaning products, or clothes dryer). It's the old cliche - time is money. Software development is the same way. Being able to just kick off a background process that does work for you can be a great way to increase productivity. It's like being able to do two things at once, such as integrating your code (continuous build on a build server) and doing local development, or running a local pre-checkin script to verify for unit test errors and reading a design doc.

It gets especially cool if you have access to other machines (or virtual machines), and you can kick off more than two things at once - like having a database integration test run on Machine X, performance tests run on Machine Y, Static Code Analysis / Unit Test coverage run on Machine Z, all while catching up on email.

All this really requires is the desire to multi-task, and the hardware to do it. Given that a computer is much cheaper than a developer, if one is multi-tasking properly, it could be well worth the investment

Monday, November 13, 2006

Presenting at Chicago .Net Users Group on MSBuild

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

This Wednesday (Nov 15) I'll be presenting at the Chicago .Net User's Group on MSBuild: A Process Automation Language. Pizza starts at 6:30pm, the presentation at 7:00.

.Net 2.0 introduces MSBuild – Microsoft’s new build engine with a process-oriented scripting language. While MSBuild is marketed for compilation and build processes, it is really a full-fledged automation language. It includes structured control flow, variables, refactorability, error handling, logging, and powerful extensibility. You can easily integrate MSBuild into your own enterprise processes and start adding value right away.

It should be a good time.

Sunday, November 12, 2006

Does .Net 2.0 make developers "dumber"?

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

 

When .Net 2.0 came out, it had a slew of powerful new features that made many things easier. Some people have asked: "Does .Net 2.0 make us all dumber?" The thinking is that .Net 2.0's new power spoils us, much like calculators spoil many of today's kids from no longer being able to do basic arithmetic.

My answer is no - .Net 2.0 does not make us all dumber, for at least three reasons:

  1. By simplifying certain tasks, .Net 2.0 frees up mental resources so that we can focus on other, more interesting things instead. This doesn't make a dev dumber, it just lets them focus elsewhere instead.
  2. .Net 2.0 doesn't just take existing things and make them easier, it also breaks new ground such that you can do more with the same effort. For example - ASP.Net 2.0 introduces web callbacks - an alternative to postbacks. It's a standard tradeoff: callbacks are more powerful, but require more effort. This actually lets a dev be smarter, by making it practical for them to deal with more complex techniques.
  3. Some things an average dev just couldn't do before - like web parts. Having this new power doesn't make the dev dumber, it just means that the same intellectual effort can go farther now.

There will always be a spectrum of smart, average, and below-average developers. As the technology continually grows, I think the trend isn't that the whole spectrum is getting dumber, but rather that it's getting more polarized. For example, .Net drastically lowered the entry-level for web programming (so less-smart people could start becoming web developers), but it also let you do more (so power users could do more).

Friday, November 10, 2006

Ego Star vs. Humble Average

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

There is an interesting conflict between skill vs. humility:

  1. Software teams requires smart people
  2. Smart people tend to be more egotistical (because they think they're smarter than everyone else)
  3. Egotistical people can hurt software teams because they ruin the chemistry and are no fun to work with.

So, the problem is that a smart person helps the team, but smart people usually have egos, which hurt the team. It prompts the question, would you rather have a coworker that is an egotistical star, or a humble average? (Of course everyone wants the best of both worlds, but life affords very few of those).

I see pros and cons to all the options on the spectrum. If you're doing a highly-complex feature, you may need the skills of the egotistical star, and may just need to tolerate the ego that goes along with it. If you're doing more commodity-type work, the humble average guy could be sufficient.

Personally, I'd like a balance, but find teamwork to trump ego. Because in enterprise architecture, you're always on teams with other people, and getting along with those people makes a world of difference. I'd rather be 10% late, and appreciate the team, then 10% early and hate the job.

I also find it's easier to learn from humbler people because they're more willing to share ideas, don't take criticism personally, and put the good of the project ahead of their personal ambitions.

Questions that I'd ask when trying to pick a person for a team:

  • Is this position on a team - will they be working with other people?
  • Are the skills replaceable? A developer's whose skills are easily replaceable doesn't have the right to be egotistical.
  • Can you constrain/redirect their ego to something constructive (such as convert it into pride of ownership for difficult components, which helps the team).

Thursday, November 9, 2006

MSBuild: Read and Write from a File to a Variable

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

MSBuild lets you easily read and write values from files into variables. While you could write your own custom tasks to do this, MSBuild provides out-of-the-box functionality with the ReadLinesFromFile and WriteLinesToFile tasks.

You can read from a file into a variable:

    <ReadLinesFromFile File="Version.txt">
      <Output TaskParameter="Lines"
        PropertyName="Prop1" />
    ReadLinesFromFile
>

This will store the contents of the file "Version.txt" in a dynamically created property "Prop1".

You can also write to files:

      <WriteLinesToFile File="myFile.txt" Lines="This is a test value." Overwrite="false" />
      <WriteLinesToFile File="myFile.txt" Lines="A second line." Overwrite="false"
/>

Wednesday, November 8, 2006

Interview Tips

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

I've had the privilege of giving a lot of interviews at three different companies. The ideal is to find a win-win combo: a good candidate that fits within a good team. Here are some random tips to help the candidate and interviewer.

Candidate

  • You know that you are going to be asked certain questions, so be ready for them. You should have prepared, ready answers for questions like "What do you know about our company?", "What's the most difficult task you've done?", or "Why do you want to work here?"
  • Be prepared to actually write code on a whiteboard. You wouldn't believe how many developers cannot write the 5 lines of code for something as simple as the textbook problem "return X factorial". Sure, they've coded before (or so their resume says), and they could probably solve it with Visual Studio, but still. The thinking is that if on a scale of 1 to 10, writing "return X factorial" is a 1, if the candidate can't even do that on a whiteboard without an IDE, then it's pointless to go farther.
  • You want to show the interviewer that you can think, not just regurgitate facts. If they ask you a simple coding question, check if it's appropriate to "think out loud" so that they don't just see some final answer, but rather your intellectual process. This is also great for getting "partial credit" if your answer is wrong.
  • Have a realistic expectation of your abilities. For example, I constantly see devs who call themselves "Senior .Net Lead Architect" for a 1 person project they did their first month out of school. It's especially scary if they can't even tell you what a design pattern is.
  • Build up your technical confidence.
  • Everyone has "project experience", and eventually they all blur together. Be prepared to emphasize your extracurricular activities.
  • Know some of the industry terms and buzzwords.

Interviewer

  • Have standard questions you can ask everyone, which lets you compare candidates against the same benchmark.
  • Ask both technical questions, and behavioral questions.
  • Show respect to the candidate: (1) It's only professional, (2) They may very well be a lot smarter and more experienced than you, (3) You may need them more than they need you - i.e. a smart candidate will have multiple job offers, why should they work at your company?
  • Focus on concepts, not trivia. Any professional team recognizes that you can learn new concepts (especially with the technology constantly changing). Software Engineering is too deep to waste your time memorizing trivia from reference manuals. Who cares if you can list all 19 constructor overloads of Foo.
  • Avoid the ego at all costs. Do not assume that the candidate is some helpless hack who is at your mercy for a job. I've seen people get an ego rush from having the opportunity to interview - they research some obscure trivia, and then hammer a senior candidate on it, and take a sense of pleasure in trying to "push around" someone who they really have no business to be in the same room with.
  • Could you pass your own interview?

Tuesday, November 7, 2006

Foreach loop in MSBuild

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

Yesterday we mentioned how MSBuild can handle conditional logic. It can also handle looping using the concept of "batching" and ItemGroups.

<Project    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">        <ItemGroup>        <ExampColl Include="Item">            <Number>123Number>        ExampColl>        <ExampColl Include="Item">            <Number>456Number>        ExampColl>        <ExampColl Include="Item">            <Number>789Number>        ExampColl>    ItemGroup>    <Target Name="ShowMessage">        <Message Text = "Number: %(ExampColl.Number)"/>    Target>Project>

The first step is to make an ItemGroup - which is simply a group of items that you can potentially loop through. Each ItemGroup needs the required "Include" attribute. For a basic example, lets just set this to "Item". The power comes in that you can add your own custom attributes to the ItemGroup, such as "Number".

You can then reference (and loop through) the ItemGroup using "%(.)", such as "%(ExampleCol1.Number)". When run, the above snippet produces the following output. Notice the Message task being called three times - once for each item in the ItemGroup.

Target ShowMessage:
    Number: 123
    Number: 456
    Number: 789


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.01

There's a lot more that you can do with Task Batching, but this is a helpful start. You can replace the Message task with any task you want, and use the '%' character in any attribute of that task. It's a lot cleaner than the DOS for loop.

Monday, November 6, 2006

Conditional Logic (If-Then-Else) in MSBuild

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

MSBuild provides the ability to do an if-then-else control structure, using the Condition attribute, which is available to every task. Simply put, the task only runs if the given condition is true.

An If-Then-Else means "if the condition is true, run the first statement, else run the second statement". This is logically equivalent to: If 'X' is true, run S1; If 'X' is false, then run S2. We can use the task's Condition attribute, with the ! ('Not') Operator to achieve this. For example, in the snippet below, if the variable "RunTask" is true, then the first line is run, else the second line is run.

    <Message Condition="$(RunTask)" Text="Do X" />
    <Message Condition="!$(RunTask)" Text="Do not do X" />

You can see a list of allowed conditional expressions in the MSBuild reference. It includes operators ( <, >, <=, >=, ==, !=, !, And, Or), parenthesis, and even an "Exists" function to see if a file exists.

Friday, November 3, 2006

The Benefits of Reinventing the Wheel

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

When someone else already makes a good, working tool, you may not want to reinvent the wheel and build a similar thing yourself. Of course we want to reuse code and not waste time repeating someone else's work. However, as an extracurricular activity, there can be benefits to creating your own version of an interesting tool:

  • Great learning opportunity - You'll understand something better when you build it yourself. You can then also compare your solution with the industry standard, and check for general trends to possibly improve your programming (i.e. "I did it this way, but they did it that way... ah... that's why they did it that way.")
  • A sense of personal accomplishment - you may a fun tool. That someone else already made a similar tool doesn't diminish your own adventure.
  • An appreciation for the tool when you see how hard it was to write.
  • The possibility that you can write it better.
  • You can customize it to your unique needs.
  • If the tool isn't free, you can now have your own copy that you don't need to worry about licensing for.
  • It's fun to write cool tools - even if someone else already has. Especially when you're a younger developer, you need to start somewhere - you can't always write flashy new things that no one has seen before.

Thursday, November 2, 2006

Taking notes with Microsoft OneNote

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

In our profession, there is a constant need to take quick notes. Ideally, there'd by a way that is (1) quick to load, (2) flexible, (3) searchable, (4) different information formats (pictures, outlines, tables, paragraphs), and (5) low maintenance. I've played around with several techniques:

  • Using Notepad files on my desktop
    • PRO: very quick to load and make edits
    • CON: very little formatting (outlines & tables), no image support, not scalable
  • MS Word
    • PRO: Lots of formatting ability
    • CON: To bulky, html is bad
  • FrontPage
    • PRO: Lightweight, friendly HTML that can easily be used on the web, easy hyperlink to other pages
    • CON: Each resource (like an image) is its own external object - not embedded as a single file.
  • Visio
    • PRO: Decent for formal images
    • CON: Designed mainly for diagrams and modeling, not for note taking
  • Wikis
    • PRO: Optimized for easy entry and search-ability
    • CON: Entered with plain-text formatting limits your options
  • Custom Tools - I've looked at SourceForge's Freemind, and tried to build some things myself

Also, all of these are funneled to a specific purpose designed to make formal documents, not informal note taking. Enter Microsoft OneNote - a desktop app designed explicty for note taking. Some benefits:

  • Quick start up (it can run in the tool tray)
  • Draw with a pen to scribble any diagram
  • Automatic outlines
  • Can just copy in images
  • Auto-saves everything
  • Can just start writing anywhere on the page.

It looks like it has a lot of potential, and provides a decively different niche than other office products (Word, FrontPage, Visio, or Excel) that may be used for the same task. I'll curious to check it out more.

Wednesday, November 1, 2006

SQL Tip: Concat entire column into a single CSV string

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

Sometimes in SQL, you'll want to concat an entire column's values into a single string.

For example, say you have a parent-child relationship (like state-city, or entity-code), and in a parent's list page, you want to display a column with the CSV string of all the children.

State City
IL Chicago
IL Springfield
IL Rockford
WI Madison

You can concatenate a list of values into a CSV string like "Chicago, Springfield, Rockford" by continually selecting into the same variable:

        declare @sCsv varchar(1000)
        set @sCsv = ''

        select @sCsv = @sCsv + City + ', '
        from MyTable
        where State = 'IL'; --any filter clause here

        --remove final ","
        if (Len(@sCsv) > 1)
                select @sCsv = substring(@sCsv,1,len(@sCsv)-1)
        return @sCsv

Tuesday, October 31, 2006

Regular Expressions: "Does not start with...."

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

 

A coworker recently asked me how to have a regular expression check if something does not start with a certain value. For example, how to tell if an input value does not start with 'abc'.

Note that it's very easy to see if something does start with a certain value, just use the anchor-to-first-start char '^'. For example, this regex will check for all strings that start with 'abc' (followed by any \w character(s)):

    ^abc\w+

To see that something does not start with a given value, use the Grouping Construct 'Zero-width negative lookahead assertion":

    ^(?!abc)\w+

This would handle the following cases:

Pass - none of these start with 'abc': Fail - all of these start with 'abc':
defg
ab
xyz
11999
abc
abcdef

Note that there are four similar grouping constructs based on the combos of Positive/Negative - Lookahead/Lookbehind

  • Positive Lookahead
  • Negative Lookahead
  • Positive Lookbehind
  • Negative Lookbehind

You can download a free regex editor from MVP Roy Osherove

Sunday, October 29, 2006

A Dozen Extracurricular Activities to be a Better Developer

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

 

I talk to a lot of developers, see a lot of resumes, and give a fair deal of interviews. One of the biggest gaps I see is a lack of any extracurricular activities - i.e. work-related tasks not required by your current job. Empirically, I notice a direct relationship between a dev's technical confidence and the quality of their extra curriculars. Here are some ideas of good extra curriculars that won't just make your resume stick out, they'll make you a fundamentally better developer.

  1. Write a technical article (such as for www.codeProject.com, or any website in the Codezone community).
  2. Start your own blog
  3. Give an internal presentation to your company
  4. Mentor newer developers
  5. Help out with your companies technical interviews
  6. Get a certification
  7. Get a patent (obviously not feasible with most companies, but the larger ones may support it)
  8. Start an open-source project
  9. Attend a user group (for example, if you're in Chicago, consider attending the Chicago .Net User's Group)
  10. Participate in online forums, answering others questions (which goes great with having your own blog and writing articles)
  11. Make your own personal website
  12. Help your non-technical friends set up their own web sites.

No matter where you are, there's likely at least some of these you could do in your current job.

Thursday, October 26, 2006

Why use Stored Procedures over direct SQL calls?

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

Two main ways to interact with the database: using a stored procedure vs. using a direct SQL statement. Here's a brainstorm of the pros and cons to each:

Technique (called from managed code): Pro Con
Stored Procedure
  • Performance, as SP is already on the database
  • Reusability - multiple sources (including other SP) can call a SP.
  • Security, especially against SQL injection attacks.
  • Maintainability - you can create the SP (and run and test it) in a database editor.
  • Powerful - A SP consists of multiple SQL statements.
  • Deployment - Modifying a database object is often easier than redeploying managed code.
  • Code Generation - You can code generate a data access layer off of stored procs (although most of the time it's code-generated off of table schemas).
  • Have to install each SP on the database
Sql Statement
  • Quicker to get started, especially for simple code and a RAD, non-production app.
  • Sql string is stored in managed code, so no need to install on the database.
  • Flexible - you're generating any SQL statement you want.
  • Lacks most of the benefits of a SP.

In general (of what I've seen), many enterprise apps will use Stored Procs, while sometimes a RAD will use raw SQL statements.

What has your experience been?

Wednesday, October 25, 2006

Getting data snapshots with the MassDataHandler

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

The other day I had a to investigate some data corruption. A certain table started out with one set of data, I ran an upgrade process, and QA told me it wasn't upgrading correctly. The problem was that I needed to compare two snapshots of SQL data, from the same table. I know there are many ways to solve this problem. The way I solved it was with the open-source MassDataHandler.

One of the main purposes of this free tool is to convert data back and forth between an Xml format and stored SQL data in a database. So, with the "Use Existing Data" feature, I took a snapshot of the table (using a select clause to specify the columns and order) and saved it as an Xml file. I then ran some black-box upgrade process, and took a second snapshot of the table. Because I now had two xml files, I could easily just diff them (I prefer using Beyond Compare for this).

The idea was to reduce the problem from an unknown state (how to compare Sql data) to a known one (how to compare two Xml files).

Tuesday, October 24, 2006

The MassDataHandler 1.2 has been released!

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

This is a free, open-source tool to assist with database unit testing. The new version offers several new features:

  • The GUI now offers the ability to ignore primary keys when generating from existing data.
  • The Build process has a reusable script to drop all foreign keys from a database. This makes it easier for you to adapt the demo script to your own project.
  • The Readme has been updated with better documentation.
  • A few miscellaneous bugs have been fixed.

You can download it here.

Monday, October 23, 2006

Comments as version control

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

At every company I've been, I see source code with old code commented out instead of deleted. In a sense, this is almost using commenting like a primitive form of version control. I see pros & cons to this approach:

Pro:

  • In environments where requirements constantly change, some developers are more comfortable seeing how the chuck was previously written so that they can easily revert.
  • You may be intending to switch back to the previous code, and it's easier to see it if the code is commented out, as opposed to digging through version control.

Con:

  • As Steve McConnell suggests in Code Complete, the purpose of comments is to show the intent of your code. Using comments as version control can be misguided.
  • It can imply a lack of confidence. If the code is really no longer used, why not just delete it and make your code leaner.
  • It can bloat the source code very quickly, requiring future developers to read through more.

I think ideally old and obsolete code should be removed instead of commented out (makes for leaner, easier-to-read code), but I can see the other approach in certain development cultures.

Sunday, October 22, 2006

How many ways to represent True and False

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

I was recently serializing data from both the database and user input, and it made me reflect on how many ways you can represent a boolean value as a literal string. For an English-language app (no globalization), here are several ways to represent a boolean:
  • TRUE / FALSE - converting from a literal string.
  • T / F - users who only want to enter the first character.
  • Yes / No - non-technical users who want "friendly" terms.
  • Y / N - again, users who want to only enter the first character.
  • 1/0 - A bit, such as how SQL Server stores booleans.

And of course, the first three options can be case insensitive and trimmed white space (i.e. "tRUe" becomes "TRUE").

I had talked about using Convert.ToString to convert different objects to string, so I'd initially look at it's related method: Convert.ToBoolean. But one quickly sees that that won't handle all the cases (and with good reason). The only literal string it takes from this group is "true"/"false". For example, it would handle converting the integer 1, but not the literal string "1". Having a single function that just converts these different inputs to a boolean is a nice convenience. Here's a sample:

public static bool ConvertToBoolean(string strVal)
{
  if (string.IsNullOrEmpty(strVal))
    return false;

  strVal = strVal.ToUpper().Trim();

  if (strVal == "TRUE" || strVal == "T" || strVal == "1"
    || strVal == "YES" || strVal == "Y")
    return true;
  else if (strVal == "FALSE" || strVal == "F" || strVal == "0"
    || strVal == "NO" || strVal == "N")
    return false;
  else
    throw new ArgumentException("Cannot convert '"
    + strVal + "' to Boolean.");
}

Wednesday, October 18, 2006

What to do before just asking someone?

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

Some projects have the local superstar. Any whenever anyone has a question, rather than figure it out for themselves (or even try to), they just ask their local star. There are two problems to this approach: (1) It eventually burdens that "star", and (2) It weakens the average guy's ability to find out info for himself.

Sometimes you need the answer right away, so you'll just ask someone. (And it would take too long to figure out yourself). However, most of the time it's worth first taking a stab at it yourself. Here are some ideas:

  • Tell yourself that you're just going to try for the next 5 minutes (If you say "I don't have 5 minutes", consider does anyone else?)
  • Read the documentation (feature spec, help doc, inline code comments, etc...)
  • Google the buzzwords, especially if it's a unique error message (like '__pendingCallbacks[...].async' is null or not an object)
  • Step back and think of the higher level concepts (maybe there's a knowledge gap you need to fill)
  • Step through the code in the debugger (such as to see the context it's being used in)
  • Use SQL Profiler to find data sources (what SP does this call?
  • Start at the problem and try working backwards
  • Find the steps necessary to deterministically reproduce the problem, then take a divide and conquer approach, checking each part of the code in isolation to see if it is the cause.
  • Work on something else and come back to the problem later with a fresh mind.

While having other star coworkers is a nice safety net, it is a luxury that may not always be there. And during those times, it will be nice to have had the practice at figuring out answers for oneself. Besides, the more someone practices at solving problems, the more likely it is that they'll become that goto guy that everyone else asks questions too.

Tuesday, October 17, 2006

Sql Tools - Profiler and SqlCommand

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

Everyone knows how to use SQL Management Studio, but there are two other useful tools that SQL Server 2005 has.

  • SQL Profiler - This lets you profile the SQL Server calls. It's very effective to determine what page is making which calls (and how long those calls take). It's much easier to just run profiler, as opposed to stepping through all the code to find what SP gets triggered when you click Button X.
  • SqlCmd - This is the command line for SQL Server (replaces osql for SQL 2000). It's useful when you need to Automate, or don't want the full SQL GUI installed (such as when you have limited space on a build server).

Monday, October 16, 2006

Converting to a string

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

In web development, we constantly need to get string values (from objects of different data types) that we can display to the user. For example, ints, dates, bool, and even custom objects eventually need to be rendered as some string. There are different ways to handle this conversion, but I think one of them is best.

      //Fail if type is wrong, such as an integer
      //Compile error: Cannot convert type 'int' to 'string'
      string s1 = (string)i;

      //Fails if object is null
      string s2 = i.ToString();

      string s3 = Convert.ToString(i);

As the code snippet shows, there are at least three standard ways: (1) casting, (2) calling the ToString method - which every object has, and (3) using the System.Convert class. I think the third way is often the best because the first will throw a compile error if the the object is an incompatible type (like converting a value type int), and the second will fail at run time if the object is null (not possible with value types like integers, but very likely with other reference types). However, using System.Convert handles both of these cases - you can convert value types and handle null instances of reference types. This lets you use a consistent approach for your conversions.

Sunday, October 15, 2006

'__pendingCallbacks[...].async' is null or not an object

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

I was doing so ASP.Net 2.0 callbacks (see an overview here: http://dotnet.sys-con.com/read/192509.htm), and kept getting this error when I did a document.location redirect on the ReceiveCallback JavaScript function.

Microsoft JScript runtime error: '__pendingCallbacks[...].async' is null or not an object

Looks like a flagrant Microsoft bug: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101974

People have different suggestions

What worked for me is the setTimeout. However, I needed to pass a parameter to the variable, so I used a technique like so:

var _gRValue;
function ReceiveCallback(rValue)
{
  _gRValue = rValue;
  window.setTimeout('__ReceiveCallback(_gRValue)',0);
}

function __ReceiveCallback(rValue)
{
  //Do stuff here
} //end of method
 

To handle the nature of setTimeout, I stored the returned data in a member variable.

Backwards: "I wanted to do Unit Tests, but my manager wouldn't let me"

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

I've heard this before when I give interviews or meet new developers at tradeshows.  The thinking seems to go that "While I'd personally love to do this best practice of 'Unit Tests', adding them takes a lot longer (like adding a new development phase), which costs extra money, therefore I need managerial approval." This is fundamentally backwards.

The whole point of Unit Tests is that:

  1. They save you time: Obviously with regression testing, but also by stubbing out the context so you can very quickly test things in isolation (without wasting tons of time constantly re-setting up that context). They also help you to see all the boundary test cases, and hence prevent future bugs.
  2. They are free to use - open source tools like NUnit can be downloaded for free and instantly used for your own personal development. It's not like you need to purchase a separate expensive tool, or hire out some auditor to review your code.
  3. You write tests as you develop, not afterwards.

Here's an analogy: Think of your schedule like a bucket, and your tasks are like rocks that fill up the bucket. You can't increase the size of your bucket, or decrease the number of rocks, therefore the bucket (i.e. your schedule) seems full. However, there are gaps between the rocks (just like there are gaps between tasks - like setting up the context and regression testing). You could pour sand into a full bucket, in the cracks in between the rocks. That's what unit tests are like. If you do them as you develop, you can squeeze them into your schedule without overflowing it.

Friday, October 13, 2006

What makes programming fun?

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

A brainstorm of some ideas. (Feel free to add your own in the comment section).

  • Writing new, interesting code
  • Not hunting down regression bugs
  • Not repeating yourself
  • Sharing work with others
  • Learning new things
  • Seeing your code just work

Certain methodologies, like Agile and TestDriven.Net are designed to fulfill many of these things. For example, by having sufficient unit test coverage, you minimize your regression bugs and get to focus more on new things.

Thursday, October 12, 2006

The myth of the "perfect past project"

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

In today's world, developers switch projects a lot. Whether it's a consultant at the same company who keeps jumping between 3 month projects, or a developer who switches jobs every two years, most people can refer to some "previous" job. I notice an interesting trend, that some people insist that they've had that perfect project in the past - the one (unlike their current job) where everything was done properly. It almost comes across as their development life was great before (i.e. their last job did it "right"), but their current employer is a bozo. Many people can refer to a good previous project because some other star (not them) made it good. For example, a past project may have had awesome process or tools - but someone else set it up. It seems like a bluff (or the grass is always greener on the other side thinking), but because you don't know about their previous project, and have to just take their word for it. But, you can always ask what they did to make that last project so great, and what they can do on the current team (besides just reminiscing about the "Good old days") to make the current project better.

Friday, September 15, 2006

How to make maintenance easier

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

Almost everyone would rather create something new than fix something broken (especially someone else's broken code). However, it's inevitable that some maintenance will always be required. Here are some ideas to make maintenance easier:

  • Reduce the amount of work that must be maintained by refactoring your code.
  • Add Unit Tests for easier regression testing, and to make sure that your maintenance doesn't break something else.
  • Document your work so that it's easier to understand, perhaps with inline comments (maybe using NDoc), wikis, or more traditional word documents for feature designs.
  • Design you code to be maintainable - perhaps use simpler algorithms (if all else is equal), loosely couple components so that it's easier to understand, make flexible code, etc...

Sunday, September 3, 2006

Creating Database Unit Tests - new install UI

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

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.

It is an open-source .Net app available here.

We recently improved the install process for the app by having a GUI form collect environmental info for SQL 2005, MSTest, and MSBuild. The install script uses the concept of Having an MSBuild script collect userinput.

If you're looking to test your data layer, check out this free tool. It's now easier to install.

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).