Category: Uncategorized
Collection of useful items
QuickCode.NET
log4net
NAnt
NUnit
CodeSmith
Reflector
NUnit add-in
SourceBrowse
Filemon
FxCop
SecondCopy
I intend to compile a list of other must-haves
Related is the DXHogHunt which identifies which directories on your machine are taking all of the space.
Ultimate Resource for .NET Namespaces
It links to newsgroup articles explaining the details required.
Replacement for ShellExecute
System.Diagnostics.Process.Start
This is much cleaner than the PInvoke version of:
[DllImport(“shell32.dll”)]
public static extern int ShellExecute(IntPtr hWnd,
string lpszOp, string lpszFile,
string lpszParams, string lpszDir,int FsShowCmd);
static void Main(string[] args)
{
int hWnd;
long noth;
ShellExecute(0, “OPEN”, @”D:\WINNT\NOTEPAD.EXE”,
null, null, 0);
}
Useability issues
The .NET Framework has a LinkLabel control. The purpose of this is to allow hyperlinks &c.
However there is no desgner for this. You have to add the associated links in code.
While this is flexible it is more difficult than necessary to use for the simple case. Borland would have implemented the designer here.
Borland’s big problem has been marketing and sales. Even when they have a superior product they cannot get the market to accept it. Of late they seem to be diversifying into earlier stages of the lifecycle – requirements (CaliberRM), design (Together and Bold) and configuration/planning (StarTeam). It is difficult to complete against the Microsoft Universal licence (allowing access to almost all the development tools for a fixed annual fee) – Microsoft make their money off of the server products that the customers require. Borland could launch a product as a Visual Studio extender – adding in the missing property editors.
Microsoft Documentation
However a lot of it leaves much to be desired.
There is a classic joke about a helecopter pilot that is lost in fog in Seatle.
He hovers near an office block and shouts out “Where am I?”
Upon hearing the answer “You are in a helecopter” he knows that he is at
Microsoft HQ’s documentation department and is able to fly diretly back to the
airport. The answer being both entirely accurate and completely useless.
This is a classic example. I have been trying to find out the purpose of
the EditorBrowsableState.Advanced option.
The documentation reads:
The property or method is a feature that only advanced users should see. An editor can either show or hide such properties.
This is again entirely accurate but completly useless.
The sample code that is linked to uses the EditorBrowsableState.Never option.
Why document the obvious case?
More Missing Stuff
While VS.NET is a real combine harvester in that it can perform a wider range of editing
than the Delphi IDE it seems to be lacking in some basic smarts that were in Delphi 1 ten years ago.
In Delphi when you rename the main form the equivalent of Application.Run is automatically updated. This may be a small thing but unless you want every app to have Form1 as it’s main form this is going to get rather old very quickly.
In Delphi when you leave an event handler empty (no code or comments) and build then the IDE removes it from the event handlers of associated objects. When you rename a control that has an event handler named after it the event is renamed and all of the IDE linked references are updated. If you have coded against it you need to fix these up yourself.
These are small things, but do grate.
Real World Unit Tests
If you are really lucky you are working on a greenfield project that has clear static requirements, a simple yet detailed design document, a full set of acceptance tests and plenty of time to write the unit tests. However in the real world you don’t have any of these.
Typically you will have an existing code base, some of which is covered by unit tests and the others not.
You need to prioritise where to write the unit tests.
Carefully constructed tests can excercise a large part of the system in a few tests.
For example if you use a Facade to import data into the system (considered an atomic step, but actually exercising a lot of validation, parsing and persistance code) you can exercise the most frequently used 25% of the system in a handfull of tests.
If a test fails you can use other smaller more detailed tests to narrow down the error.
The only downside to this is that a single error in a fundamental system can cause hundreds of failures.
If one area of the system has failed frequently over a number of builds then it is an obvious target for some new unit tests.
If any area of the system includes scripting, dynamic sql or stored procedures they need to be called at least once by the unit tests. This will excercise the database creation script during either the build process or by the Continous Integration server (You do create a new database as part of your build process don’t you?). Anything that is not checked by the compiler is ripe for typos to cause havoc. Stored procedures are great – when compiled they report certain errors (the sql does not make sense) however they can ignore the fact that tables or fields do not exist.
Tests need to be fragile with respect to the functionality tested, but be immune to minor changes in call symantics. This is where some simplifying Facades really help – they isolate the test code from change, encourage reuse, make the test code easier to read and can provide ideal debugging fodder (either after the test has been run or set breakpoints and run a single test).
An alternative to NUnit
The format of the tests is identical so that tests are portable between them.
It has a sister project AUT that is trying to develop unit testing into a full software engineering discipline.
Advance Unit Testing articles:
Part 1
Part 2
Part 3
Part 4
Part 5
These definately deserve some attention.
Most useful XP Idea
If you want to ignore most of the XP practices the best to adopt would be the automated unit tests. These are developer tests, not formal QA acceptance or regression tests. Things that should be tested here are that the stored procedures actully exist, that they run with typically data without catastrophic failures. It is best to think of these as a replacement for asserts.
(Personally I replace any assert that will stop program execution with an equivalent exception – this makes it far more friendly to a unit test.)
An assert will warn you that an error condition occours while a unit test demonstrates what happens when the error condition occours.
There is a problem with the typical gui unit test addins – they write one stub test per public or protected method. This creates lots of almost irrelevent tests. The best way to think of unit testing is in terms of testing buisness functionality. This allows unit tests to be used as documentation of buisness scenarios. Plus if you omit to reset your database in the teardown (and always reset the database in the setup) then you have the oppertunity to have a tested buisness scenario that can be used as the starting point for manual UI testing. This technique alone saves hours of debugging time – write a test to recreate the exact condition that you are looking for and if you go one line too far in the debugger and destroy the test condition it is usually a matter of seconds before you can recreate the exact data that you were using.
Automated Unit tests become especially valuable when you are working across multiple streams of development. The project I am currently working on has 4 current development streams (one pure development plus three live customer streams). Since these are slowly diverging (certain new features only get added to the later streams – fixes to those units in older streams cause divergence) a fix or enhancement may need to be implemented in several places.
Tests need to be focused (test one functional area) and atomic (failure of one test should not stop the system). It is fine (even preferable) to use parts of your system to setup tests for other areas.The test framework that I use has a set of Facades that abstract away parts of the system and uses them to simplify tests.
For example if your system delt with processing customer orders (these arrive as XML documents) you could write a Facade around the code that parses and stores the incoming document and use other classes to generate the data.
So the start of the test would be:
TOrderImporterFacade.ImportOrder( TSimpleOrder, 100, ‘FooBar’ );
This would use the class TSimpleOrder to create a order for 100 FooBar’s
You could then check the outstanding orders
CheckEquals(100, TStockFacade.OpenOrdersCount(), ‘Before Restocking’);
Use another Facade to perform the buiness functions.
TBuisnessFacade.Restock();
And again peform the same check.
CheckEquals(100, TStockFacade.OpenOrdersCount(), ‘After Restocking’);
This technique is less fragile with respect to functional changes, the tests are far easier to read,
and it is very easy to add a new buiness scenario as an experiment.