Monday 18 May 2009

A Potted History of My Windows Framework

I thought that before leaping into a few posts about my experiences porting my Windows Framework to 64-bit Windows and GCC that I would spend a few minutes explaining how it has come to be the way it is. If you've looked at the source code to my various libraries you'll see a mixture of Hungarian & Java'ish notations, plus some MFC'isms and two different comment styles. Some parts of the framework are very old and as I only spend part of my free time on it, it is in a way, treated very similarly to commercial code - new features often come first and consequently it has accrued a significant level of Technical Debt.

The oldest parts of the code actually date back 15 years or so to my first framework which was written in C as I started my professional career writing Windows 3.x applications in C. This was the Petzold era and the code was pretty much adapted straight from his famous book - Programming Windows.

However, this version didn't last very long as I soon got back into C++ again at work and discovered the late Paul Dilascia's book Windows++. Instead of starting from scratch though, I refactored most of the C library, which was written in an OO'ish style, into classes. The code also followed the house style of their C++ framework as I was used to it.

It was still just a framework without a purpose though until I went freelancing and got my first contract. I now had a need for an application to track my hours for billing and so Task Tracker was born. The contract involved maintenance on an MFC based application and during this time I realised that it would be beneficial if I could reuse code from my framework and potential applications in my professional work. I didn't want to be tied to the real MFC framework tough - after all the point of re-inventing the wheel was to learn, so I decided to refactor my core framework to be more like MFC in style so that moving code between work and home would be easier.

It turned out to be a good move as I continued to work on MFC based code for the next 10 years and I got to reuse some of my classes like CIniFile & CPath quite a lot. During that time I read the classic Design Patterns book and tried to apply some of it to my own MVC like framework as that was the one area of code that I wasn't going to reuse outside my own apps. I also went through an "everything should be a reference" phase as I couldn't decide on how best to deal with object lifetimes.

The main thing missing from my codebase though was use of the STL which was largely down to the fact that MFC doesn't use it and so it doesn't tend to be the default choice. Also I had written my own containers because Visual C++ 1.5 had no template support (and frankly I wouldn't have known what to do with it then anyway :-) and that had created a large body of legacy code to refactor.

My last contract, which although heavily COM/ATL based, was an entirely different beast however. They used STL extensively and was beginning to use Boost for more than just shared_ptr. They also used STLport instead of the Dinkumware offering and there was little to no use of Hungarian Notation. And there was not a line of MFC code in sight! However the biggest factor was the large number of ACCU members that worked there...

After joining the ACCU, I almost went back to basics and began to discuss quite fundamental issues, like style, testing, C++ conformance, tools etc and I began to realise that my personal codebase was somewhat of an embarrassment. So I decided it was time to try and modernise it by deprecating my own containers, switching to the more lightweight Doxygen style comments, using size_t consistently, etc. The most important change though was dropping my own variation of Hungarian Notation and using the more common camelCase convention.

Structurally I have started to split off parts of the Windows C++ Library into a new base class library called Core which I hope to make reasonably platform independent. The single biggest effect of this is that std::string has now become the default string class instead of my own MFC-like CString. My new XML library is the first to take advantage of this and I hope to ensure both libraries compile with GCC as well as Visual C++.

The changes are not just in the code, but also in the way I develop it. I have written my own simple Unit Testing framework which loosely follows the xUnit style and have adopted TDD when possible whilst making changes to all the libraries. Core has the most test coverage as it is the newest and was created using TDD from the start. The other libraries are gaining coverage as and when I make changes.

So, is it worth it? I've always viewed my framework as a playground - somewhere outside of work to play around and make mistakes - but more importantly to try out new things that I hope can then be fed back into my professional career to make me more valuable to a potential employer. I'm still learning heaps every time I refactor, so I guess it is :-)

2 comments:

  1. I'm not volunteering - not unless you can offer some valuable reciprocical service, anyway ;-) - but one thing you could do that would help a *lot* would be to get someone else to review it. (I know this because I review code for a living.)

    I've had a quick squiz, and noticed a few things, and believe it could benefit greatly.

    I always say to clients to think of code review and refactoring as the work of an art historian in revealing and polishing an old master. Helps take off a little of the ego-singe. =P

    ReplyDelete
  2. I'm always up for reviews and [constructive] criticism - my wife makes sure of that :-) I suppose that I have never expected any of this code to be used by anyone but me and so have not solicited it. Also I still have a long TODO list to wade through of things *I've* spotted, so I think I'll get that mountain under control first.

    I suspect that "quick squiz" closely followed by "noticed a few things" does not bode well either :-)

    ReplyDelete