- Implementing Lean Software Development
- Lean Software Development: An Agile Toolkit
- Microsoft .NET - Architecting Applications for the Enterprise
- Test Driven Development: A Practical Guide
- Fit for developing Software: Framework for Integrated Tests
- The Art of Agile Development
Saturday, 20 June 2009
Books I currently flip through #6
Thursday, 18 June 2009
XPath
I know it's probably smoother with Linq to Xml but my project had to compile under VS2005 so I used the .NET 2.0 library which does not contain Linq but contains XPath.
Starting from the following xml file:
<pigs>
<piggy infected="false" name="bob"/>
<piggy infected="false" name="alfred"/>
<piggy infected="true" name ="rodrigo">
<disease name="swine flu"/>
<disease name="boredom"/>
<disease name="pig blues"/>
<address>confidential</address>
<phonenumber>01234546576</phonenumber>
</piggy>
</pigs>
To load the XML in memory:
XmlDocument doc = new XmlDocument();
try
{
doc.Load("piggy.xml");
}
catch (XmlException e)
{
Console.WriteLine("Could not load the file. Detail: " + e.Message);
}
To query elements based on their name:
XmlNodeList allPigs = doc.SelectNodes("/pigs/piggy"); // Returns all nodes called 'piggy' located inside the root-level node called 'pigs'.
foreach (XmlNode node in allPigs)
Console.WriteLine(node.Name + " " + node.Attributes["name"].Value);
To query elements based on their attribute name:
// Returns only infected pigs
XmlNodeList infectedPigs = doc.SelectNodes("/pigs/piggy[@infected='true']");
foreach (XmlNode node in infectedPigs)
Console.WriteLine(node.Name + " " + node.Attributes["name"].Value);
To return a single node (same query as above but only one node is expected):
// Returns the single infected pig
XmlNode infectedPig = doc.SelectSingleNode("/pigs/piggy[@infected='true']");
if (infectedPig != null)
Console.WriteLine(infectedPig.Name + " " + infectedPig.Attributes["name"].Value);
To do a query relative to the current node:
All queries above were made relative to the top of the document. But it you call SelectNodes against an XmlNode, you can do a query relative to that node. Just ommit the '/':
// Query relative to the current node. Returns all diseases for the infected pig
XmlNodeList diseases = infectedPig.SelectNodes("disease");
foreach (XmlNode node in diseases)
Console.WriteLine(node.Name + " " + node.Attributes["name"].Value);
Resources:
MSDN: XPath Syntax
LINQ to XML queries
XML Support in SQL Server 2005
Monday, 1 June 2009
Webforms vs MVC (London .NET User Group)
- Webforms has a tendency to hide HTML and actually generates a lot of goo.
- MVC relies on you knowing HTML but once you learn it, things get pretty easy.
- Webform's page lifecycle is complex
- Webforms is for morons.
- MVC is too complicated,
- Webforms has a lot of ready-made controls, lots of 3rd party vendors
- Uses a familiar event model
- MVC is for hippies.
Friday, 15 May 2009
C++/CLI Cheat Sheet
- Declare a string
System::String^ myString = "";
- Declare a null reference
System::String^ myString = nullptr;
- Pass a string by reference to a method (the reference to the string will be modified, not the string itself since strings are immutable). Use %:
void MyMethod(System::String^% myString)
{
}
- Declare an array of strings
cli::array<System::String^>^ stringArray = gcnew cli::array<System::String^>{"Skype","Blogger"};
- Declare a managed member inside a native class
class IAmNative{gcroot<IAmManaged^ > managedMember;
public: IAmNative():managedMember(gcnew IAmManaged()) {}
};
- Declare a managed member that will self destroy
#include <msclr\auto_gcroot.h>
class IAmStillNative{ msclr::auto_gcroot<IAmStillManaged^> managedMember; // Will be disposed when IAmStillNative is destroyedpublic: IAmStillNative():managedMember(gcnew IAmStillManaged()) {}
};
- Convert a native STL string to a managed string
System::String^ ToManaged(const std::string& nativeString){return gcnew System::String(nativeString.c_str());
}
- The same backwards:
std::string ToNative(System::String^ managedString)
{char* str = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(managedString).ToPointer();
std::string result(str);
System::Runtime::InteropServices::Marshal::FreeHGlobal((System::IntPtr)str);
return result;}
- Instantiate managed types, call managed methods from native code provided it compiles with /CLR.
- Instantiate native types, call native methods from managed code
- Link to the native types of a mixed static lib (/clr)
- Declare managed methods that have native types in their signature
- Link to the managed types of a mixed static lib
- Link to managed types in a DLL if those managed types have methods with native types in their signature.
Wednesday, 29 April 2009
First Contact with DevExpress
- GridControl
- VGridControl
- PropertyGridControl
- TreeList
- If all you do is setting the DataSource then the control doesn't know anything about the data layer, which is good.
- However if you add columns from the designer (either manually or from a datasource) then you create a tight coupling with the data layer, which might be ok depending in the type of app you're creating. I find the designer is great for discovering functionality but when given a choice, it is better to write code: this avoids having the UI know too much about the data.
- Both theVGridControl and PropertyGridControl use reflection to display the properties of an object.
- For some reason PropertyGridControl works fine for public properties with exotic types (such as collections) while VerticalGridControl simply doesn't display collection properties -unless there is something I missed...
- The DemoCenter that comes with the DevExpress install
- The blonde and brunette from DevExpress TV
Tuesday, 30 December 2008
T-SQL vs PL-SQL
Good:
- T-SQL: stored procedures return result sets very easily: all you have to do is write a select statement without any 'INTO'. PL-SQL: you have to select into a ref cursor and define this ref cursor as output parameter.
- T-SQL: stored procedures do not rollback automatically if something fails. Until SQL Server 2005 you had to test @@ERROR after each and every statement and goto a handler to rollback. Ugly, tedious and error-prone. In 2005 you can use a TRY CATCH, which is much more elegant. However you still have to rollback explicitly
PL-SQL: sprocs are atomic. Any error inside a sproc rolls everything back up to the point where the sproc was called. - T-SQL: no %TYPE! You can't refer to the type of a column without repeating it.
- T-SQL: RAISERROR does not break the flow. It simply returns an error string or message but the sproc still returns normally. Unless you use it within a TRY block, in which case the flow is diverted to the CATCH block (for SQL 2005 and beyond). Depending on the severity level you specify, RAISERROR within a TRY block either
- returns an error number without breaking the flow
- jumps to the CATCH block
- breaks the current database connection (wow!) (provided you have sysadmin role)
- PL-SQL: raise_application_error throws an exception, exits the current sproc, rolls back till implicit savepoint at the beginning of the sproc...
- Oracle does not have a BOOLEAN column type, although you can define a BOOLEAN variable in PL/SQL. SQL Server has a BIT column type where values can be only 0 or 1.
Sunday, 28 December 2008
Using NUnit with C++ - Part 2
- the test project is a C++/CLI DLL compiled with /CLR option.
- the project containing the code under test has an additional project configuration that generates a static LIB instead of an executable.
- the test project links to the native LIB above.
Monday, 1 December 2008
Get time in HH:mm format regardless of the local culture
Monday, 17 November 2008
Using NUnit with native C++
NUnit was designed to be used with managed apps. So what?
All you need to do in order to test native code is create a C++/CLI project to host the test files. To link the test project to the native C++ project, simply add a configuration to the solution and call it ReleaseUnitTests for instance. This configuration will build the native C++ project as a static library as opposed to an executable. The C++/CLI test project links to this library and can call into any public method of the native project.
Job done! Who needs cppunit?
Detailed steps:
- Install NUnit.
- In Visual Studio Pro, create a native C++ project and call it CatHouse
- Add a class called Cat with a public method void Feed()
- Add another project to the solution: choose Visual C++ > CLR > Class Library and call it CatHouseTests. This will create a mixed assembly containing both native and managed code.
Add a C++ managed class called CatTest. Declare it public because we want it to be a managed type that can be seen by Nunit. Add a public method called TestFeed(). - Open CatHouseTests project properties, go to Common Properties > References and add the nunit.framework.dl assembly.
- In CatTests.h, add the line using namespace NUnit::Framework.
- Now you can add the [TestFixture] and [Test] attributes to the class and test method declarations respectively.
- By default the CatHouse project has a Debug and Release configurations. Add a new one called ReleaseUnitTests: in Build > Configuration Manager in the Active Solution Configuration drop-down, select New. In the dialog, type ReleaseUnitTests and in Copy settings from choose Release. Click OK. Now all projects have a configuration called ReleaseUnitTests.
Using Configuration Manager, ensure that the Debug and Release solution configurations build CatHouse only and not CatHouseTests. Ensure that ReleaseUnitTests builds both CatHouse and CatHouseTests, both having project configuration ReleaseUnitTests. - Open the properties of project CatHouse and in Configuration Properties > General, select Configuration ReleaseUnitTests. Change configuration type to Static Lib (that will make it possible to link all the content with the test program).
- Make CatHouseTests link to the .lib generated by CatHouse. In Project Properties of CatHouseTests, go to Common Properties > Add New Reference > Projects > CatHouse.
- Add a #include "Cat.h" in CatTest.cpp and change the project properties so that it knows where to find the include.
- In the TestFeed() method, instantiate a Cat object on the native stack and call its Feed() method.
- Build the solution in Release mode then in ReleaseUnitTests mode.
- In the NUnit GUI type Ctrl O, select the CatHouseTests.dll. The TestFeed test should appear in the tree view.
Saturday, 15 November 2008
TechEd EMEA 2008 Developers Wrap
- now I know there is a descent framework for unit-testing native C++ code in VSTS2008 Dev. Ok you have to write C++/CLI but the next best thing is cppunit so... VSTS2008 Dev is apparently the best tool around for the moment.
- database unit-testing in VC9 DBPro where it creates a C# class for you that automatically calls a T-SQL sproc where you write your test.
- other tools: I had an overview of the tools available for managing unit-tests and IOC containers: Pex, TypeMock, TestDriven. They're on my list of things to try out next.
- It's worth digging into SpecExplorer 2007 and see what can be done with it. The idea of creating a simplified state model of your system and having the tool generate all possible paths for you is very interesting.
- I am now a bit more familiar with IOC frameworks, interface-based coding and TDD so I feel more confident to start writing my first unit-tests. One day maybe I'll write tests before the code...