Rob Kraft's Software Development Blog

Software Development Insights

Robert’s Rules of Coders: #7 Use Constants For Values That Don’t Change

Posted by robkraft on October 17, 2015

All programming languages, at least that I know of, support the concept of variables that are used to hold values that change while the program is running.  But a lot of cases exist where we need to define a value to our code even though that value will not change as the program runs, and we have three options for providing this value.

We could simply code the value (3.14 in this example) where it needs to be used:

Circumference = 3.14 * diameter

We could create a variable and assign the value to the variable:

Double pi = 3.14

Circumference = pi * diameter

We can declare a special type of variable known as a constant:

Double const pi = 3.14

Circumference = pi * diameter

Of the three options above, using a constant is usually the best option for several reasons.

Variables over values

First of all, if the value will be used in many places in the program, you will often save yourself time by placing the value in a variable or a constant so that if the value ever changes you only need to change it in one place.  You may decide that instead of using 3.14 that you prefer to use 3.14159 in the calculations.  If your variable is a string for a format such as “mm/dd/yy” you may decide later that you want the format to change to “mm/dd/yyyy” and using a variable or constant makes the change easier, and more accurate because you are less likely to overlook some.

Use Variables To Make Code Changes Easier

Use Variables To Make Code Changes Easier

Second, when changing the value you are less likely to change the wrong value when you use a variable than if you use a value.  In the example below, you are less likely to change the tax rate from 3.14 to 3.14159 if you are using a variable than if you are using a value.

Variable Help You Change The Correct Value

Variable Help You Change The Correct Value

Third, variables make your code more readable. Many people may know that Pi is 3.14 and recognize the value in code, but few would recognize the number 8 as representing the number of planets:

  • For I = 1 to 8
  • //do some code
  • Next I

Is less clear in meaning than the following:

  • For I = 1 to NumberOfPlanets
  • //do some code
  • Next I

Constants Instead of Variables

Values that won’t change while the program is running can be defined as “constants” in most programming languages. This informs the compiler that the value will not change and the compiler can make the program a little more efficient. Often, what the compiler does is the equivalent of a find/replace everywhere the constant is used. This means that the variables will not need to be placed on the memory stack reducing the RAM required by the program to run.

By declaring that your variable is a constant, you also ensure that your own code does not attempt to unintentionally change the value of the variable while the program is running.

Here are some examples of good places to use constants instead of variables:

  • When your program has a name that you show on Title Bars and in log file messages such as:

String const PROGRAMNAME = “My Program Name”

Note: some languages have conventions for constant names such as using all upper case letters for the name. I recommend following the conventions of the language you code in.

  • When your program formats a value in many places, especially if that format may ever change:

String const DATEFORMAT = “mon , dd, yyyy”

  • Values that almost never changed that are used in multiple places:


  • Messages or part of messages that occur frequently in the code.  This also helps you reduce the number of spelling errors.

String const ERROROCCURREDHEADER = “An error has occurred!”

When you write programs that have code in multiple assemblies, or projects, or dlls, you may want some constants to be used across the whole program, and others used just within a single assembly.   Use scope and careful naming conventions to correctly place those constants.  If a constant will only be used within one assembly, then declare the constant within that assembly and don’t make it globally accessible.  If you want the same constant used by several assemblies, place it in an assembly all the others can reference and give it a good name like GlobalConstants.

Solution for Program with Three Projects:

  • Project1 named SharedAlgorithms
    • Contains a class named GlobalConstants with these constants:
      • String const ERROROCCURREDHEADER = “An error has occurred!”
      • String const DATEFORMAT = “mon , dd, yyyy”
  • Project2 named TaxCalculations
    • Contains a class named TaxConstants with these constants:
      • Double const TAXRATEFORMISSOURI = .08
      • Double const TAXRATEFORKANSAS = .12
  • Project3 named AppUI
    • Uses the constants from the SharedAlgorithms project, but not the constants from the TaxCalculations project because it does not need any of those values.

Warning: In many languages, you need to recompile both the AppUI project and the SharedAlgorithms project in the example above if the GlobalConstants are changed.  If you don’t, AppUI will continue to use the values the constants had at the time it was compiled, not the values the constants in SharedAlgorithms currently have.

Go to Robert’s Rules of Coders for more.

Posted in Code Design, CodeProject, Coding | Leave a Comment »

Robert’s Rules of Coders: #6 Don’t Use Magic Numbers

Posted by robkraft on September 7, 2015

When someone refers to a magic numbers in software, they probably have one of the following three scenarios in mind:

  • A value that is used to determine the behavior of the code, but the value itself provides no meaning
  • A value that has been hard coded in several locations in the program, that is unlikely to change, but might
  • A value that is well known in some software and that will not be changing

Using a magic number directly in your code can lead to problems and it is recommended that you avoid or minimize the use of them.  Let’s examine each of the three types of magic numbers and the risks associated with using them.

Example One with Magic Numbers

Example One with Magic Numbers

The first type of magic number in the above example is the value for the AccountType.  When looking at the code, most programmers will not know what the values of 1, 2, and 3 represent.  This type of magic number is common when the programmer is comparing the AccountType to a value that has come from a database or file and the value was persisted as a 1, 2, or 3.  But many programming languages today support the concept of an enumeration, or enum, that can be used to make the code more readable:

Example Two Eliminating A Magic Number

Example Two Eliminating A Magic Number

Using an enumeration in place of a hard-coded magic number offers several advantages:

  • The code is easier to understand for humans. The code is easier to write for humans because we don’t have to reference documentation elsewhere to know what an AccountType of 1, 2, or 3 means.
  • It is easier to alter a value. If the source of the data decided that the value 2 should represent “No Taxes” and 3 should represent “No Federal Tax”, the code could be adjusted where the enumeration is defined.  That is much easier than searching all of the code to replace 2s with 3s and 3s with 2s.
  • It is easier to review the code where the enumeration containing all of the possible values are defined for accuracy and completeness.

The same block of code above also includes another type of magic number with the values of 1.1 and 1.03 to represent tax rates.  I suspect you already realized that hard-coding the tax rate is risky because the values change so often.  But some magic numbers are less obvious such as in this example:

Example Three with a Magic Number

Example Three with a Magic Number

In this example the magic number is the number 50.  There are 50 states in the USA as I am writing the article, but that number could change.  If you have coded the number 50 representing states in several places in your program, someone will need to change them all if that number of states changes.

Example Four Without Magic Numbers

Example Four Without Magic Numbers

Using constants to eliminate this type of magic number provides several advantages:

  • The code is easier to understand for humans. We know right away that we are looping through the number of states and don’t have to question what the value of 50 represents.
  • It is easier to alter the value. If the USA adds one more state we can change the constant defined in one place in the code and be done with our changes. A programmer could do a find and replace across all of the code on the value 50 easily enough, but the number 50 might be used in other places referring to something other than the number of states in the USA.
  • A developer could accidentally type 60, 500, or even 49 instead of 50 and the compiler would allow the code to compile without warning.  This problem is less likely when the important value is only coded once and a variable name is used throughout the program.

The third class of magic numbers are numbers that indicate types of files or the beginning and ending of streams of bits in protocols.  These magic numbers are generally dependable, but you should still avoid coding them in the flow of your code logic primarily for readability.  One example is the use of FFD8 and FFD9 at the beginning and ending of JPEG files.  Instead of hardcoding this magic number inline in the code:

Example Five With Magic Numbers

Example Five With Magic Numbers

Consider defining a constant to improve readability.

Example Six Without Magic Numbers

Example Six Without Magic Numbers

There are some drawbacks to eliminating magic numbers, but the benefits of eliminating them usually outweighs the drawbacks.  Drawbacks include:

  • The programmer might want to know the value of the constant or enumeration and would need to refer to where the value is defined to discover it.  This could take a little time if the constant or enumeration is not defined closely to where it is being used.
  • It makes the source code a little bit longer. In compiled languages, this is almost never a concern, but it non-compiled languages like javascript it might have a small impact on performance.

Go to Robert’s Rules of Coders for more.

Posted in Code Design, CodeProject, Coding | Leave a Comment »

Robert’s Rules of Coders: #5 Organize Your Code

Posted by robkraft on August 30, 2015

When you write programs that consist of many lines of code, where the threshold of “many lines” probably begins around fifty lines of code, you should consider organizing your code in ways that will make it easier for you to maintain it in the future.  Breaking the code into many functions is a good start, but when you have a lot of functions it can become difficult to manage and remember them.  At this point you should consider grouping related functions, and in most programming languages placing the groups of related functions into separate files.

The major benefit is that you, and other developers, can more easily find the code you are looking for when you want to examine or modify it.

You may consider placing all functions you use to generate and send emails into a single file that you name Email.Code.  You may move all of your functions for formatting strings into a file name StringFormatting.Code.  Organizing your code into separate logically grouped files provides the simple benefit of helping developers find the code to be worked on more quickly.  For example, if you are on vacation and I need to fix a bug related to emails in your code, I can find the bug more easily if the email code is in its own file than if all of the program code is in one single large file.

Having many separate files for your code also helps you track changes in the code when you are using a source code control system; which you should be doing.  For example, if I made a change several months ago to the Email.Code and I now realize that my change might have broken something, I can use my source code control system to review the changes made to Email.Code more easily than I can use it to review the changes to All.Code.

Business developers often use the technique of object oriented programming to help determine how to organize their code into separate files.  The programmer may put all the code related to customers in Customer.Code, and all of the code related to products in Products.Code.  Although placing code in separate files is not what object oriented code is really about, it is a natural side effect.  Large object oriented applications may use several files for a single “object”. Instead of just a single file for Customers, the code may be broken into several files such as CustomerProperties.Code, CustomerPersistence.Code, and CustomerBusinessRules.Code.  Once again the primary reason for multiple files is usually because programmers have learned that many small source code files are easier to develop with than a single large file of code.  Another benefit when there are multiple developers may be that each developer focuses on a different area of expertise and one developer focuses on …Persistence.Code files and another developer focuses on …BusinessRules.Code.

An additional approach to organizing code, and I choose the word additional because it could and should be used along with organizing code by object and function, is to group code in different layers of the application architecture together.  Many applications today consist of at least three layers:

  • a User Interface (UI) layer,
  • a business logic layer,
  • and a data persistence layer that stores data in files or databases.

It is very beneficial for developers to keep the code in these layers separate because it makes it easier for the developer to make some changes in the future.  On such change could be storing data in a different type of database.  Another could be replacing the desktop UI with a web page UI.

In object oriented development, developers following the SOLID principles, will implement the “Single Responsibility” principle which leads them to limiting each “class” to doing just one thing, hence the term “Single Responsibility”.  Although this does not necessarily dictate that a developer will only have one class per file, that is often the case and thus followers of the “Single Responsibility” pattern are likely to organize code into separate manageable files.

So instead of placing all of your code in a single file like this:

File1: AllMyCode.code

All Code in One File

All Code in One File

Break the code into separate files like this:

File1: UICode.code

Code In 1st File

Code In UICode.Code file

File2: ProductCode.code

Code In ProductCode.Code File

Code In ProductCode.Code File

File3: CustomerCode.code

Code in CustomerCode.Code File

Code in CustomerCode.Code File

File4: EmailCode.code

Code In EmailCode.Code File

Code In EmailCode.Code File

Go to Robert’s Rules of Coders for more.

Posted in Code Design, CodeProject, Coding | Leave a Comment »

Robert’s Rules of Coders: #4 Make Functions Short

Posted by robkraft on August 18, 2015

Functions are easier to understand and thus easier to maintain when they are short.  You can often make functions shorter by finding patterns in a large function and extracting those lines of code comprising the pattern into a separate function and calling the separate function as shown below.

One Long Function

One Long Function

One Short Function With The Same Results

One Short Function With The Same Results

Note: The FormatForOutput function is not shown because I believe you can figure out what it does.

But even when you have a long function with no lines of code that are duplicated, you can often make the code more readable and easier to maintain by separating the code into functions.  Consider this example:

One Long Function

One Long Function

Long Function Broken Into Short Functions

Long Function Broken Into Short Functions

Note: The 4 new functions are not shown because I believe you can figure out what they do.

Most developers will be able to understand the 2nd example better than the first.  But there is another big benefit that applies in a lot of languages.  Let’s assume that an error occurs with a message of “Object variable is null”.  In the first example, the error message might show a call stack that says our program named Program1 called the method MainCodeBlock and this error occurred within MainCodeBlock.

Call Stack from First Example:

  • Program1
    • MainCodeBlock

But which line of code within MainCodeBlock?  We don’t know and it could have been caused by many of the lines.  However, if the same error occurs in the second example, our call stack would look like:

Call Stack from Second Example:

  • Program1
    • MainCodeBlock
      • SavePriceToDatabase

In the second example, we have narrowed down the problem to the SavePriceToDatabase method and have only a few lines of code to consider as the source of the error.  This is another benefit of smaller functions.

Finally, for those of you that write unit tests as most good programmers should, you have functions neatly wrapped up and ready to be called by those unit tests.

In summary, short functions provide these benefits:

  • They organize your code, making it easier to understand and maintain.
  • They make it easier to pinpoint bugs when you have a call stack.
  • They make it easier for you to write unit tests for your code.

Go to Robert’s Rules of Coders for more.

Posted in Code Design, CodeProject, Coding | Leave a Comment »

Robert’s Rules of Coders: #3 Use Good, Meaningful Names

Posted by robkraft on August 6, 2015

Code is much easier for humans to read when the variable and function names reflect what they mean and do.  In ancient times, like the 1960s, some programming languages did not support long variable names, but today most every language supports long names with no penalties.  Although some exceptions may be tolerated for very common usages such as the variables “I”, “j”, and “k” for loops, you should strive to use meaningful names in all cases.  Would anyone honestly say that the first block of code below is easier to understand than the second?

Code with and without good names

Code with and without good names

Good, meaningful names not only make your code more readable, but they may also remove the need for you to add comments or documentation to the code.

When we first began writing javascript in the 1990s we used short variable names because we wanted to reduce the size of the files to make them faster.  Today, you should probably not do this because the data is compressed by default by technologies like gzip, and Internet speeds are faster, and if you are writing enough code that the size of your javascript is a factor you should be using a minifier tool to make the javascript smaller for you.

Aside from long names, what makes a variable or function name good?

  •  Good names reflect the value stored in the variable or explain what the function does. “Counter1” is better than “c”, but “ActionCounter” is even better. Giving variables relevant names reduces the time it takes people in the future looking at the code to figure out what it does. And that includes the future you. This applies to function names also. A function named “UpdateActivityCount” is better than “CountUpdater”.
  • Try not to use negative logic in variable and function names. It takes our brains a little longer to deduce the meaning of negative logic statements.
    • IsValid is usually a better name than IsNotValid
    • DoesValueExceedMaximum is usually better than DoesValueNotExceedMaximum
  • Follow the conventions of the language you are coding in. If the language uses CamelCase, you should use CamelCase. If the language uses Hungarian Notation (txtFirstName, intItemCount), you should use Hungarian notation. If the language uses all upper case for the names of CONSTANTS, you should use all upper case for CONSTANTS too.
  • Don’t reuse variable names for different purposes.
Example of Reusing a Variable

Example of Reusing a Variable

  • The function name should describe what it does not how it does it.  This allows you to change how the code in the function works without needing to change the function name. This helps the function remain a black box.
    • Name the function GetAllCustomers, not CallDatabaseUsingADOtoGetDataFromCMCUSTTable.
  • Avoid names that might match keywords. Naming a variable “Name” or “Date” might compile safely at first, but it might fail after an update to the language is installed, or if you include a new library in the project. Also, it may not be obvious to other developers that the variable name is one that you created instead of one that is built in.
  • Follow a consistent pattern
    • If your Foo object has a Retrieve method to get data from the database, then your Bar object should also have a Retrieve method to get data from the database, not a Get method. Using the same method and property names across objects when the methods serve the same functions reduces the learning curve for new developers.
    • You should also strive to use consistent noun and verb pairings.  Naming two functions CalculateLastSaturday and CalculateLastSunday is usually easier for programmers to remember than having one function named CalculateLastSaturday and the other named FigureOutFinalSunday.

Finally, remember to rename your variables if the meaning of the value they store changes and rename your functions if the things the function does changes.  We are writing code for humans, not for computers.

Are there any more good rules that should be added to this list?

Posted in Code Design, CodeProject, Coding | Leave a Comment »

Robert’s Rules of Coders: #2 Avoid Global Variables

Posted by robkraft on August 2, 2015

Global variables are variables that can be accessed from anywhere in the program.  It is appropriate to use a global variable when you have a value that is a constant and thus won’t change as the program runs, but it is rarely appropriate to use global variables for values that change while the program is running.

Functions should usually return the same output when given the same inputs.  Global variables in functions can cause the function to return different values, making the function less reliable and more difficult to write unit tests for.

A Bad Program With Global Variables

A Bad Program With Global Variables

In the block of code above, you can see that the value returned from CalculatePrice() is not predictable.  In the first case it returned 11.00, but in the second case it returned 10.50 for the same inputs.  Here is a second version of the program:

Same Program Without Global Variables

Same Program Without Global Variables

The second version of the program has the following advantages:

  • The programmer can see all the factors that affect the TotalPrice.  None are hidden.
  • The programmer can write unit tests against the CalculatePrice() function more easily.
    • Assert.That( CalculatePrice(4, $2.5, 10%) = 11.00)

The problems with using global variables include the following:

  • Global variables can be modified from anywhere in the program, making the output of functions using them less predictable
  • Rules that you code in one place about setting the value of a global variable may not be adhered to in other places. For example one block of code may do this:
Setting Global From Spot 1

Setting Global From Spot 1

But another block of code in the program may do this:


Setting Global from Spot 2

  • A function or component that uses global variables becomes “tightly coupled” to the other components that use the global variable.  This entanglement increases programmatic complexity which means the program is probably more difficult to maintain and enhance, and also that it is difficult to replace one component of the program without affecting others.
  • In multithreaded programs, global variables may not be thread-safe.
  • In some languages, global variables make it difficult to add new components to an existing program because the new component may contain its own global variables with the same name.

When you have an object that you think should be global so that it can be used everywhere, you should probably use Dependency Injection.  Don’t be deceived by the Singleton pattern for a global variable replacement because that often becomes just a more complicated version of a global variable.

Posted in Code Design, CodeProject, Coding | Leave a Comment »

Robert’s Rules of Coders: #1 Write Subroutines Profusely

Posted by robkraft on August 1, 2015

Most programming languages support the concept of a subroutine.  A subroutine is a block of code that your current code calls (aka executes) to run some more code.  Subroutines are called by many different names, with some of the most common being ‘function’, ‘method’, or ‘procedure’.

Subroutines serve two primary purposes:

  1. They allow you to easily reuse some of your code
  2. They organize your code, making it easier to read and maintain.

A program without subroutines

A Program Without Subroutines

A Program Without Subroutines

A program with subroutines

A Program With Subroutines

A Program With Subroutines

The advantages of the program that uses subroutines include:

  • The code is easier for another person to read, and that other person could be the future you.
  • Code that is re-used provides these benefits
    • You spend less time writing code because you can use code that already exists, the subroutine that you wrote.
    • The subroutine is already proven to work when used the first time.  You won’t have to spend time fixing logic errors and typos each subsequent time you want to do the same things.
    • If you discover a bug in the subroutine you can fix it in the subroutine which fixes it for all places from which it is called. In the first program above, if you found a bug formatting Item1PriceOut the same bug would probably also exist in formatting Item2PriceOut and need to be fixed there too.
    • If you decide something should be changed, such as using “<strong>” instead of “<b>” when formatting your string you can make the change once instead of making it in several places.
    • You can optimize the code later. Perhaps you later learn that you can call ConvertToDollars() and the formatting to two decimal places will be handled for you. You can make the change in the subroutine instead of making the change several times as you would have to do in the first program above.
Easily Change a Subroutine

Easily Change a Subroutine

  • The subroutine is more likely to be testable from an automated test.  Many languages allow you to write “unit tests” that can be run regularly to insure your code keeps working as intended even after you make changes to it over time.  It is easier to unit test code isolated in a subroutine than it is to unit test code that is just part of a larger code block.
    • Example Unit Tests:
      • Assert.That( FormatForOutput(7) = “$7.00”)
      • Assert.That( FormatForOutput(7.1) = “$7.10”)
      • Assert.That( FormatForOutput(555) = “<b>$555.00</b>”)
  • The size of the code is usually smaller when using functions, taking less disk space.
  • The size of a compiled version of the program is probably smaller, taking less disk space.
  • The size of the program in memory is probably smaller, using less RAM.
  • The memory allocated to variables is more likely to be re-used which therefore requires less RAM.

Use Subroutines Profusely

I recommend using subroutines when you see that you have two or more lines of code that are the same over and over in the program.  One thing that makes a programmer a good programmer is the ability to see patterns.  So even though these lines of code are not the same, a good programmer will see that there is a pattern and extract that pattern into a subroutine:

Can You See A Pattern?

Can You See A Pattern?


Pattern Implemented in a Subroutine

Pattern Implemented in a Subroutine

In this case, the second program has more lines of code, but if you need to modify Item3PriceOut and Item4PriceOut the program with subroutines will become the shorter program.  And it will be easier to maintain.

Use Subroutines to Hide Complexity and Third Party Dependencies

Use subroutines for anything that might change and is used more than once, especially third party dependencies.  For example, if you use a third party tool called 123Logger in your code like this:

3rd Party Code Inline

3rd Party Code Inline

Replace it with code like the following because if you ever want to change to a different logger than 123Logger, you will only need to change your code in one place.  You are writing your code so that it is not as dependent on how the third party logger software needs to be called.

3rd Party Code in a Subroutine

3rd Party Code in a Subroutine

When you decide to use XYZLogger instead of 123Logger, you can change your code to look like this:

Using Different 3rd Party Code

Using Different 3rd Party Code

There are even better ways to handle third party dependencies like this for larger applications, but this approach is a good start.

Posted in Code Design, CodeProject, Coding | 1 Comment »

Microsoft SQL Server Violates the Commutative Law of Basic Math

Posted by robkraft on April 16, 2015

I love SQL Server.  I’ve been a SQL Server expert for decades, but just a few days ago I found a bug in SQL Server when performing simple math calculations.

These two queries yield different results:

  • select 1.0 * 3/2
  • select 3/2 * 1.0

The first query returns 1.5, and the second query returns 1.0.  Different results violates the Commutative rule of math that tells us the order of operands should not matter.

I understand why this is happening.  SQL Server looks at the data type of the first argument and rounds the results of calculations to that data type.  So in the first query, 1.0 is a float (aka double); but in the second query 3 is an int (aka integer) with no decimal places so 3/2 rounded to fit in an integer is 1, not 1.5.  But just because we can explain it does not mean that it is acceptable.

This problem affects real code.  The problem occurs not just with values, but when doing similar calculations with columns in tables.

  • create table CommTest (int1 int, int2 int, dbl1 float)
    insert into CommTest values(3,2,1.0)
    select dbl1 * int1/int2 from CommTest
    select int1/int2 * dbl1 from CommTest

The first select in this query will return 1.5, and the second select will return 1.

The fix is to cast the first variable as a float “select cast(int1 as float)/int2 * dbl1…”, but that is challenging to remember and difficult to apply if you have code generating SQL for you.  The better solution is probably to do all math in the program calling the database; at least if SQL Server is your DBMS.  Though this is not easy when you just have a reporting tool like SSRS for your front end.

Until Microsoft fixes this, which I doubt they ever will, developers just need to be extra careful.

This problem does not exist in other database management systems.  At least I know it does not exist in Microsoft Access nor Oracle.  For reference, I tested this on SQL Server 2014.

Posted in SQL Server | Tagged: | 2 Comments »

One Cause of ORA-00600 with qctstc2o1

Posted by robkraft on February 24, 2015

Today one of my queries failed on Oracle because the query had too many columns.  The query is very simple, but returns 1023 columns of output.  The query is simply





If I remove any of the joins from the query it will succeed.  If I return fewer than 1000 columns it will succeed.  But if I run it as is I get this error:

Error report:

SQL Error: ORA-00600: internal error code, arguments: [qctstc2o1], [1], [0], [0], [1], [0], [0], []

00600. 00000 –  “internal error code, arguments: [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s]”

*Cause:    This is the generic internal error number for Oracle program exceptions. This indicates that a process has encountered an exceptional condition.

*Action:   Report as a bug – the first argument is the internal error number

Posted in Coding | Tagged: | Leave a Comment »

A Simple Build Summary Email For Your Development Environment. Tests Included!

Posted by robkraft on January 13, 2015

We cobbled together a simple system to provide us a single email each day to tell us if all of our jobs and unit tests were successful on their overnight runs.

An example of our daily build summary email.

An example of our daily build summary email.


Given that we have a dozen different jobs that run tests and a dozen that run builds it was helpful to have the results of all the jobs in a single email. To implement this similar to what we did you need the following:

  • A database for storing the results of the jobs. We used SQL Server.
  • A program to write the build results to the database. The C# program we wrote is provided here.
  • A few modifications to your build scripts. Our changes to our Nant builds are shown here.
  • Optionally a testing framework that produces output you can read easily.  We use nunit.
  • A report sent via email. We used an SSRS report to send the email summary each morning.


Here is how we did it:

1) We created a table in SQL Server to store the results of each job.

SQL for Creating Table ZBuildJobs

SQL for Creating Table ZBuildJobs

Here is a sample of the table with data:

Sample Of Table ZBuildJobs with data

Sample Of Table ZBuildJobs with data


2) We created a program that we could call from a command prompt and pass a few parameters to write into the table.   This is our C# program.  It is comprised of just 3 methods.

The App entry code reads the command line arguments.  If there are more than 2 (> 3 in code) then we also look for a number of tests passed and failed to be passed in.

Code Part 1

Code Part 1

The CallDatabase method simply writes the values passed in to the database table.

Code Part 2

Code Part 2

The ProcessTestResults method uses some example code from the Microsoft URL shown to read the results of the nunit test file and count the number of passed and failed tests.

Code Part 3

Code Part 3


3) We modified our nant build files to call the program written in step 2 and pass in a value of success or failure.  For nunit test jobs we also pass in the XML results file created by our nunit tests.

  • Nant includes some built-in properties that we can use to specify a target to call when the nant job succeeds or fails.  So we configured those properties like this:
    • <property name=”nant.onsuccess” value=”BuildSuccess” />
    • <property name=”nant.onfailure” value=”BuildFailure” />
  • For ease of maintenance, we created a property to hold the name of our program from step 2 above that does the logging:
    • <property name=”param.EventLogPgmName” value=”C:\Dev\BuildLogger\BuildLogger.exe” />
  • To include spaces in our job names we need to surround the parameters we pass to BuildLogger with double quotes, and to include double quotes as part of the parameters we needed to create a property to hold the double quotes.  We also have a property to hold our current build version number:
    • <property name=”dq” value='”‘/>
    • <property name=”project.version.full” value=”15.0″/>
  • Then at the start of each build target we add a name for that build, something like this:
    • <property name=”param.BuildNameForLog” value=”${dq}${project.version.full} C# .Net Build${dq}” />
  • If the job runs unit tests, we include a property to specify the name of the unit test output file:
    • <property name=”param.TestResultsFile” value=”${dq}c:\program files (x86)\NUnit\bin\TestResult.xml${dq}” />
  • The final change to our build files is to declare the targets for BuildSuccess and BuildFailure.  These look like this:
    • <target name=”BuildSuccess”>
      • <exec program=”${param.EventLogPgmName}” commandline=” ${param.BuildNameForLog} Succeeded ${param.TestResultsFile}” failonerror=”true”/>
    • </target>
    • <target name=”BuildFailure”>
      • <exec program=”${param.EventLogPgmName}” commandline=” ${param.BuildNameForLog} Failed” failonerror=”true”/>
    • </target>

4) The last step is to build the report.  If you are already familiar with SSRS you will probably find this step to be very simple.  SSRS is easy to use and is free if you have a Standard Edition of SQL Server.  Here I share the more advanced features for the report.

This is the SQL to get the most results of the most recent execution for each job:

SQL for Report

SQL for Report

For each job listed on the report we want to show the record in green (Lime) if it passes and red (Tomato) if it fails.  So I modified the BackgroundColor property of each row and gave it this expression:

=IIF(Fields!Result.Value = “Succeeded”, “Lime”, “Tomato”)

For the two columns with the number of tests that passed or failed, I had to test if the field had null first, then apply the color:

=IIF( IsNothing(Fields!TestsFailed.Value), IIF(Fields!Result.Value = “Succeeded”, “Lime”, “Tomato”), IIF(Fields!TestsFailed.Value > 0, “Tomato”, “Lime”))

We have been very pleased with the results of our Build Summary process and continue to add more things to it.  It was easy to implement and has ran very reliably.


You can download the code from here:

Posted in CodeProject, Coding, Dev Environment, Process | Leave a Comment »


Get every new post delivered to your Inbox.

Join 166 other followers