Pages

Friday, 15 May 2009

C++/CLI Cheat Sheet

My C++/CLI pocket reference...
  • 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 destroyed
 
public:
    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;
}
Things you can do
  • 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
Things you can't do
  • 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

Recently I had the opportunity to use DevExpress controls for WinForms. Overall I wouldn't say those controls save you time if you compare with regular Windows Forms controls. The time you save in coding you spend it reading documentation and experimenting with the controls. However the results are definitely superior to WinForms: better looking and with plenty of niceties that come for free (grouping, sorting, customizing, dragging and dropping, advanced tooltips, etc...) The controls I used to far:
  • GridControl
  • VGridControl
  • PropertyGridControl
  • TreeList
GridControl Comes with plenty of default features such as very powerful grouping and filtering options accessible to users at runtime. To populate it, simply set its DataSource to a DataTable or an IList.
  • 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.
VGridControl and PropertyGridControl
From a distance VGridControl looks like a Property grid control. The main difference is you can display many records at a time while a property grid control displays a single record.
  • 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...
TreeList The first column contains the tree, the other columns display data in a grid. Handy when each node of the tree contains usefull info and you don't want users to click each node to see the info. Instead you display the info directly in the grid and users can sort and filter as they see fit.
Most of the effort with the DevExpress controls is working out what they do. Two main sources:
  • The DemoCenter that comes with the DevExpress install
  • The blonde and brunette from DevExpress TV

Tuesday, 30 December 2008

T-SQL vs PL-SQL

"Oracle PL-SQL is the same as Microsoft T-SQL. If you know one, you know the other"

Not really.
Here are a few differences, some of them can have a serious impact of the way you write sproc code.

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.
Bad:
  • 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...
Other differences:
  • 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

Follow up from part 1 We've been experimenting at work with writing unit-tests against native code for 2 months now. We're using NUnit together with CruiseControl and it works fine.
  • 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.
What if the code under test is C++ compiled with /CLR? For some reason I thought it wasn't possible to create a static LIB when the /CLR option was active. C++/CLI is very flexible and you can generate a static library containing a mix of managed and unmanaged code. The purpose of building a mixed static lib is to easily import native code into a test project. We keep the test project and the code under test in separate solutions.

Monday, 1 December 2008

Get time in HH:mm format regardless of the local culture

DateTime.Now.ToShortTimeString() returns a string that depends on the culture. DateTime.Now.ToString("HH:mm") is deterministic. Use DateTime.Now.ToUniversalTime.ToString("HH:mm") to get the current HH:mm time in UTC.

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:

  1. Install NUnit.
  2. In Visual Studio Pro, create a native C++ project and call it CatHouse
  3. Add a class called Cat with a public method void Feed()
  4. 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().
  5. Open CatHouseTests project properties, go to Common Properties > References and add the nunit.framework.dl assembly.
  6. In CatTests.h, add the line using namespace NUnit::Framework.
  7. Now you can add the [TestFixture] and [Test] attributes to the class and test method declarations respectively.
  8. 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.
  9. 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).
  10. Make CatHouseTests link to the .lib generated by CatHouse. In Project Properties of CatHouseTests, go to Common Properties > Add New Reference > Projects > CatHouse.
  11. Add a #include "Cat.h" in CatTest.cpp and change the project properties so that it knows where to find the include.
  12. In the TestFeed() method, instantiate a Cat object on the native stack and call its Feed() method.
  13. Build the solution in Release mode then in ReleaseUnitTests mode.
  14. 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

What I got out of this TechEd Saw a total of 15 sessions and did 4 labs. If I had to pick just one thing, that would be VC9 DBPro (VSTS2008 Database Edition) with its database deployment and sproc unit-testing features. I saw a talk about it then played with it at the lab. It has the potential to remove a LOT of pain from schema upgrades. Because most sessions I picked were centered around unit-testing I'm a bit less ignorant about the subject:
  • 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.
Integration Testing:
  • 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.
Methodologies

Friday, 14 November 2008

Friday - TDD and Interface-based Programming

DVM303 - Understanding Test Driven Development Speaker: Roy Osherove This is my 3rd session with Roy following from Designing for Testability and Future of Unit-Testing. TDD helps with
  • trusting your tests
  • designing the app (because it forces you to take the point of view of the client)
  • implementing stuff that works partially as opposed to not at all
  • code quality
  • documenting the code
  • reducing integration testing time, reducing number of bugs in production
How to write a unit test with TDD?
  • add attribute [Test] to methods, [TestFixture] to classs
  • naming: tests must have a good name to document their intention: method + scenario + expected behaviour.
Content of the test:
  1. arrange (instatiate objects)
  2. act (call the method under test) ,
  3. assert (check the expected result)
Writing process That's the interesting bit, the part that's totally couter-intuitive and requires a good dose of self-discipline.
  1. Make it Fail: write a test that fails because the method is not doing what's expected. Purpose: test your test
  2. Make it work: with minimum code, make the test pass by writing anything even if it's stupid as long as it doesn't break any other test.
  3. Make it better: refactor but do not add functionality and make sure the test still passes.
  4. Want to add more functionality? Ok but write another test first.
Tools:
  • use Testdriven to run test by right-clicking method in the middle of the method. Apparently TestDriven allows you to run a test even if you don't have a fully working executable.
  • If you use VSTS, use the built-in MSTest because it brings a lot of integration benefits. It runs slower though. Usually unit-tests are kept in a separate VS project.
Tip from Roy: it's a bit of a culture change so implement it incrementally and don't mention it by name to avoid scaring people off! ARC213 Intentions & Interfaces - Making Patterns Concrete Speaker: Udi Dahan Very sarcastic talk by Udi, making fun of the abuses of the visitor and strategy patterns. "Make your roles explicit" Instead of overriding virtual methods, use generic interfaces. You then retrieve concrete objects for those interfaces from service locators. In the end he was recommending Inversion of Control containers as Roy did in his testability session but with a different approach. Roy's emphasis was on writing code so that unit-tests stick to PC-COF while Udi's angle was on making it easy to change code in large projects. Slides.

Friday - DB Deployment and Unit-Testing with DBPro

TLA03-HOL - Introduction to Visual Studio Team System 2008 Database Edition I took this lab as a follow-up to Brian Randell's talk on Tuesday. This is by far the most useful tool I learned about at this TechEd. You start by creating an empty database project.
  • Then you import the schema from an existing database. VSTS automatically creates a folder struture for schema objects in the solution folder. Each db object has got its own script therefore you can commit them all into CVS if you need to (you don't have to use Foundation Server).
  • To add an object, right-click Add Table in the Schema View. This generates a script skeleton that you edit as you see fit (add columns, add options, etc...). Save the file and the Schema View is updated automatically. Change an object in the Schema View and the script is updated automatically.
Schema compare That's where it gets interesting:
  • Choose a target database to compare the offline schema to the target schema.
  • A view appears that shows all changed, new or missing objects.
  • Select one of the changed object in the lists and view the difference (new column, changed line in sproc, etc..)
  • You can also preview the DDL script that VSTS is about to generate
  • You can enable/disable individual differences from the list if you don't want them to be part of the script or force some to be in the scripts if you really want them to be there.
  • Export the DDL script to a .sql file then edit if you need to tweak it before testing it against a pre-prod database.
So the tool is nice because it does the dirty work for you, leaves you a high degree of control and makes the schema differences absolutely crystal clear. Database unit-testing
  • You can create a unit-test for a sproc.
  • VSTS automatically creates a test class that calls the sproc that contains the unit test. All you have to do is write the T-SQL for the sproc that does the unit-test. DB Sprocs tests are therefore perfectly integrated to all other tests.
  • You can attach a Pre-Test and Post-Test to a sproc test in order to put the db into an known state.

Thursday - Testing in Team System

TLA13-HOL - Visual Studio Team System code name "Rosario": Team Development Unit Test management Everytime you run tests it automatically creates a new test run with a default name and records all the test results. So you keep a history of what tests were run and when and which ones passed or failed. Types of tests you can create VS is used to managed both unit-tests and integration tests. You can create:
  • coded UI tests (where you write UI tests using automation as opposed to record/replay)
  • Database unit-tests to test T-SQL stored procedures.
  • Generic tests. This is actually an external program that will look like an ordinary test from within visual studio. You specify the command line arguments to call the external program. You have the option to redirect the standard output / error to the test results or not.
  • Load tests. That's quite fun: you can simulate heavy load conditions with many users. Among other things you can define a load pattern (constant load or increasing load) and the distribution (percentage of appareance for each test).
  • Manual tests: simple text file describing a manual test procedure. This is there for auditing purposes only obviously.
  • Ordered test: specify a list of tests to be run in a specific sequence in the situation where order counts (that's for integration tests only, unit-tests should not be order dependent)
Impact analysis: as you change code, VS gives you the list of recommended tests (tests that should be re-run as a result of your changes)