Thursday, March 1

Complete years between 2 dates

A problem we have had calculating ages was due to it using the SQL Server "DateDiff" function. This counts the number of times a day crosses a boundary, e.g.

DateDiff(year,'12/31/2006','1/1/2007') is 1, as it crosses the 2006-2007 boundary.
DateDiff(year,'1/1/2006','12/31/2006') is 0 as it doesn't cross a year boundary.

I have written a function "yeardiff", which calculates the number of complete years between 2 dates, so

YearDiff('12/31/2006','1/1/2007') is 0
YearDiff('1/1/2006','12/31/2006') is 0
YearDiff('12/31/2006','1/1/2008') is 1

This function works by calculating the number of days the start date is into the year, subtracting this from both start and end dates (so the start date is 1 January), and calling DateDiff on the resulting date.

Here's the source code for this function:


CREATE FUNCTION yeardiff
(@start as datetime, @end as datetime)
returns int
AS
BEGIN
declare @years as int

declare @daysintoyear as int
declare @firstdayofyear as datetime
declare @newstart as datetime
declare @newend as datetime

set @firstdayofyear = convert(datetime,
'1/1/'+convert(varchar,year(@start)))
set @daysintoyear =datediff(day, @start, @firstdayofyear)

set @newstart = dateadd(dd, @daysintoyear,@start)
set @newend = dateadd(dd, @daysintoyear,@end)

return datediff(year,@newstart,@newend)

END

Tuesday, February 6

Nant and licensed 3rd party controls

I've been having some problems building a project containing licensed grid and graph components from ComponentOne using NAnt. The project built correctly in Visual Studio, but when built with NAnt I got a box saying the component was not licensed.

I've found some others have had similar problems, but no solutions have been posted. I go it working after a lot of trial and error as follows:

1) Use an <exec> task to run the license compiler (lc.exe).
2) Ensure the /target: command does not contain a path.
3) Ensure your <csc> task does not contain a path in its output section.
4) Ensure the licenses file is included in the resources section. This did not work when it was included as an argument with an <arg value="/resource" element.
5) Copy the file to the correct destination directory at the end.

Here's the relevant part of my build file.


<target name="project" description="build project"
depends="..." >


<exec program="C:\Program Files\Microsoft
Visual Studio 8\SDK\v2.0\bin\LC.exe"
commandline="/target:project.exe
/complist:c:/nantcheckout/project/Properties\
licenses.licx
/outdir:c:/nantbuild /i:c:\nantbuild\C1.Data.2.dll
/i:c:\nantbuild\C1.Win.C1Chart.2.dll
/i:c:\nantbuild\C1.Win.C1Chart3D.2.dll
/i:c:\nantbuild\CAInterfaces.dll
/i:c:\nantbuild\CDERules.dll
/i:c:\nantbuild\clTreeViewHashT.dll
/i:C:\WINDOWS\Microsoft.NET\Framework\
v2.0.50727\System.configuration.dll
/i:C:\WINDOWS\Microsoft.NET\Framework\
v2.0.50727\System.Data.dll
/i:C:\WINDOWS\Microsoft.NET\Framework\
v2.0.50727\System.Deployment.dll

...

/>

<csc target="winexe"
output="PCOBrowserGE.exe" debug="false"
define="TRACE" >
<sources>
<include name="c:/nantcheckout/
project/*.cs" />
<include name="c:/nantcheckout/
project/Properties/*.cs" />
</sources>
<resources>
<include name="c:/nantcheckout/
project/Properties/*.resx" />
<include name="c:/nantcheckout/
project/*.resx" />
<include name="c:/nantbuild/
project.exe.licenses" />
</resources>
<arg value="/reference:C:\nantbuild\
c1.win.c1chart.2.dll" />
<arg value="/reference:C:\nantbuild\
c1.win.c1chart3d.2.dll" />
<arg value="/reference:C:\nantbuild\
c1.data.2.dll" />
</csc>

<copy file="pcobrowserge.exe" tofile="
c:/nantbuild/project.exe" />
</target>

10 Characteristics of a great programmer

Steve Riley has complied a great list of the 10 characteristics of a great programmer.

I'd agree with everything on the list - the one thing that is missing is that great programmers know why they are doing what they are doing - there's no point producing an excellent solution to the wrong problem.

Thursday, January 25

Cakes

Cote writes about requirements gathering and cakes.

If your powerful boss asks you for a cake, you can't easily find out the details of what he wants. You have to find out via secondary sources (e.g. the boss's calendar, asking the baker what sort of cakes the boss has ordered before). The calendar may not be up to date, and the baker may not remember accurately.

This takes longer and is more likely to go wrong. If there are more steps than necessary in finding out requirements, the solution is to understand what the difficulty is with asking him directly and work on reducing these difficulties.

Wednesday, January 24

Personal Search Filter

If you want to find out information about something, you will typically enter terms into a search engine.

The search engine will determine which results are most relevant (by using a complex algorithm based on how important it thinks the pages are). Everybody using this search engine will see the same results.

The things you want to see might not be the same as the things others want to see. However, you are more likely to want to see things that people "compatible with you" liked. If A likes B and B likes C, and B also likes D, then chances are that A will like D.

You could filter the results of your search (from the search engine) through a personal search filter. This would reorder your searches depending on

1) Things you have liked before
2) Things that people compatible with you have liked before.

When you visit a web page, you record whether you found it valuable. This updates your personal search filter and how compatible you are with other people. If you liked page A and B didn't like page A, you will not value the opinion that B liked page C. However if B liked A, you would be compatible with B and their opinion would affect your search filter.

This can be seen below:

Friday, January 12

Anti-tests

Charles Miller describes the concept of an "Anti-Test", which is a test that verifies a bug exists.

This can be written when the problem is discovered, even if it's not going to be fixed immediately.

It means that if the problem is inadvertently fixed as a result of something else, we know this has happened, have a look at why this is the case and update our records accordingly. The test can then be changed to a normal test to make sure it doesn't go wrong again.

When you're ready to fix an anti-test, you can change it to a normal test - it should now fail (and this change should be easy to make), fix the bug and make sure the test passes.

NAnt version

I've been trying to add version numbers to a NAnt build script using the <version> task, and come across a problem with the script in Marc Holmes' "Expert .NET delivery" book.

The task increments a property called "buildnumber.version", not "sys.version". Adding the following line to the script (as described here) seems to fix it.

<property name="sys.version" value="${buildnumber.version}" />