I've been faithless the last couple of months, doing lot's of code in C# for ASP.NET instead of using a real programming language, i.e. C++. Actually, C# is pretty nice and ASP.NET is a very productive environment for Web Application programming.
During this time I've come across a usage pattern that I really want to discourage. C# is a beautifully typed language, especially with the introduction of Generics (not to be confused with Templates in C++, they are two very different things) - so why do so many people insist on stuffing things into strings and objects?
A typical example is the Guid structure in C#. It's essentially byte-array holding the 16 bytes of a GUID, a Globally Unique Identifier. Very useful, and very common. But very frequently stored and passed as a string, or even worse, as an object.
I use a code policy that states that an object that has a specific type should always be stored, referenced and passed as that type. Even if it does come into the code in the form of a string, you should still convert it at the first opportunity and then keep it in it's natural typed form.
The rationale for this is that you can get some very nasty and hard-to-find runtime bugs with late effects, causing errors, instability and exceptions long after the initial problem occurred. Consider for example a Guid entering the system as a string, being stored as a string and then used. It might not be in the correct format, but that will not be discovered until way too late. If you follow a code policy to convert it into the appropriate type from the start, you'll automatically catch such things very early.
Work is also progressing on Xecrets, the safety-deposit box on the net that will launch in the summer time frame. I've given notice to my "day job", and will start working full-time on AxCrypt, AxCrypt2Go and Xecrets in June.
Thursday, February 22, 2007
Wednesday, February 7, 2007
Quitting my day job
Finally! It's decided. I'm going to start spending serious time with AxCrypt and related services. AxCrypt and AxCrypt2Go will remain free and open source, and to finance it I'll also be developing and provide Internet-based services. These will be available for trial, to all registred AxCrypt-users, and later as subscription services. I've spent some time preparing for this, including developing the new site which looks fairly similar to the old one, but in fact is a full-fledged application whilst the old one was basically static HTML.
So, the good news is that in the summer time-frame, I'll be working more or less full-time with AxCrypt and AxCrypt2Go. The even better news is that I'll make Xecrets, the new Internet-based subscription service that complements the free software available. There'll never be a requirement to register or pay anything to use AxCrypt or AxCrypt2Go.
I am hoping to provide such great value for money that many of you actually will find the subscription service so useful that you'll be glad to pay a small amount for that, while at the same time providing financing for AxCrypt-development.
The philosophical view here is that encryption software is good to have open source, and software licensing is a slight evil, that unfortunately often is necessary to finance the product. I'll be trying for the best of both worlds here, providing free software (after all, there's absolutely no additional cost for me to provide a second copy of AxCrypt once the first is produced) but also providing services on the Internet, where a reasonable fee for the server and bandwidth cost feels fair and hopefully generating enough additional revenue to also support AxCrypt development.
The Xecrets subscription service will start as a safety-deposit for your secrets, such as logons, PIN-codes etc. Always available, and always protected. When you need them, you can logon to the Xecrets-site and search your secrets in a standard free-text search way. Your data is never stored decrypted on the server disk, nor is your decryption key.
Most, if not all, of us have a multitude of logon-codes and PIN-codes to keep track of. With Xecrets you have the possibility to have them available, protected and backed-up for a very low cost - $1/€1 per month.
There are endless possibilities and variations, but all things have to start somewhere, and this is what I'm planning right now.
These are the plans - please let me know your thoughts! I'm open for all suggestions that will help me keep providing the community with free software, while also being able to afford to spend sufficient time doing so. Mail me now!
So, the good news is that in the summer time-frame, I'll be working more or less full-time with AxCrypt and AxCrypt2Go. The even better news is that I'll make Xecrets, the new Internet-based subscription service that complements the free software available. There'll never be a requirement to register or pay anything to use AxCrypt or AxCrypt2Go.
I am hoping to provide such great value for money that many of you actually will find the subscription service so useful that you'll be glad to pay a small amount for that, while at the same time providing financing for AxCrypt-development.
The philosophical view here is that encryption software is good to have open source, and software licensing is a slight evil, that unfortunately often is necessary to finance the product. I'll be trying for the best of both worlds here, providing free software (after all, there's absolutely no additional cost for me to provide a second copy of AxCrypt once the first is produced) but also providing services on the Internet, where a reasonable fee for the server and bandwidth cost feels fair and hopefully generating enough additional revenue to also support AxCrypt development.
The Xecrets subscription service will start as a safety-deposit for your secrets, such as logons, PIN-codes etc. Always available, and always protected. When you need them, you can logon to the Xecrets-site and search your secrets in a standard free-text search way. Your data is never stored decrypted on the server disk, nor is your decryption key.
Most, if not all, of us have a multitude of logon-codes and PIN-codes to keep track of. With Xecrets you have the possibility to have them available, protected and backed-up for a very low cost - $1/€1 per month.
There are endless possibilities and variations, but all things have to start somewhere, and this is what I'm planning right now.
These are the plans - please let me know your thoughts! I'm open for all suggestions that will help me keep providing the community with free software, while also being able to afford to spend sufficient time doing so. Mail me now!
Saturday, May 27, 2006
Look to windward!
I've now had had AxCrypt2Go available for download for quite some time, but received very little feedback. Perhaps it's already perfect... It does work! It's not easy to get time for development, the last couple of months have been very busy. The last couple of weeks I've been working on an OEM-version of AxCrypt, and that's very nice since revenue somehow does tend to result in making it easier to find the time.
The experience from this round of OEM deal is very positive, I'm quite happy that the code is still possible to work with, in fact it's quite easy and so far the changes and additions even if minor have been implemented without too much trouble. This is really one of the important measures of code quality in my mind, it's ability to adapt to new situations and be worked with for a long time before you just have to make that decision to rewrite it from scratch...
I'm eagerly waiting when I can drop all support for Windows 98/ME/NT and convert to full Unicode support. There are currently some issues with texts and file names that would be nice to get rid of. I'm still happy that I originally was so careful to make the code prepared for Unicode, so I'm not really expecting any big troubles. The only regret so far is that I decided to encode filenames and passphrases as ANSI. This will require some legacy code for a long time to support even in a full Unicode implementation. Too bad.
So the lesson for today is that if you are aware of a future technology shift, don't just prepare your code for it - ensure that your persistent data already takes it into account from the start, if at all possible. I could easily have done this with AxCrypt, but didn't - a fact I'll now regret for ever... ;-)
The experience from this round of OEM deal is very positive, I'm quite happy that the code is still possible to work with, in fact it's quite easy and so far the changes and additions even if minor have been implemented without too much trouble. This is really one of the important measures of code quality in my mind, it's ability to adapt to new situations and be worked with for a long time before you just have to make that decision to rewrite it from scratch...
I'm eagerly waiting when I can drop all support for Windows 98/ME/NT and convert to full Unicode support. There are currently some issues with texts and file names that would be nice to get rid of. I'm still happy that I originally was so careful to make the code prepared for Unicode, so I'm not really expecting any big troubles. The only regret so far is that I decided to encode filenames and passphrases as ANSI. This will require some legacy code for a long time to support even in a full Unicode implementation. Too bad.
So the lesson for today is that if you are aware of a future technology shift, don't just prepare your code for it - ensure that your persistent data already takes it into account from the start, if at all possible. I could easily have done this with AxCrypt, but didn't - a fact I'll now regret for ever... ;-)
Thursday, February 16, 2006
Performance profiling rocks!
Performance profiling is sooo cool! I first encountered this concept in the early 80s, then it was a C-preprocessor that inserted calls to a statistics gathering function in all relevant places, and then you got a nice log file to analyze. Behind the scenes, not much has changed, but of course we have IDE-integration and all that.
AxCrypt2Go had a problem with displaying a list view taking significant time. With a profiler, it was an hours work to isolate the two major culprits and redesign the code to use those parts much less frequently. Without a profiler, it would have been pure guesswork, and possibly unsuccessful.
If you don't have a profiler for your favorite development environment, go get one now! Don't wait. Btw - I'm using Compuwares community edition, it's got some pretty nice features and like AxCrypt - it's free!
AxCrypt2Go is not exactly progressing at blinding speed, but that's simply due to having lots of other things taking time in life. Such as computers ;-) AxCrypt is becoming too successful, so I need to upgrade servers and software to handle the load of registrations and update notification e-mails which is taking some time from development unfortunately.
Still, it's now got most of the very basic functionality of windows and navigation, right-click interface and AxCrypt-compatible encryption and decryption. Just a few more clean-ups and disabling of some non-functioning options, and it's time for an alpha to get some feed back on the basic interface idea (it's a Windows Explorer-like window with a tree view for navigation and a list view for actions using the right-click as usual).
If you're reading this, and would like to be notified of the alpha, drop me a mail!
AxCrypt2Go had a problem with displaying a list view taking significant time. With a profiler, it was an hours work to isolate the two major culprits and redesign the code to use those parts much less frequently. Without a profiler, it would have been pure guesswork, and possibly unsuccessful.
If you don't have a profiler for your favorite development environment, go get one now! Don't wait. Btw - I'm using Compuwares community edition, it's got some pretty nice features and like AxCrypt - it's free!
AxCrypt2Go is not exactly progressing at blinding speed, but that's simply due to having lots of other things taking time in life. Such as computers ;-) AxCrypt is becoming too successful, so I need to upgrade servers and software to handle the load of registrations and update notification e-mails which is taking some time from development unfortunately.
Still, it's now got most of the very basic functionality of windows and navigation, right-click interface and AxCrypt-compatible encryption and decryption. Just a few more clean-ups and disabling of some non-functioning options, and it's time for an alpha to get some feed back on the basic interface idea (it's a Windows Explorer-like window with a tree view for navigation and a list view for actions using the right-click as usual).
If you're reading this, and would like to be notified of the alpha, drop me a mail!
Friday, January 27, 2006
auto_ptr revisited
Hooray! AxCrypt2Go can now display icons for AxCrypt-files (although just the small one right now). Anyway, it's a proof of concept, now I'll have to refactor that code into something I can publish. That's one of the advantages of open source - it can't look too bad, so it has to be fixed. But that's not what I want to write about today, not really. I realized that I was not running the compiler at the highest warning-level (4), but only 3 and that's normally a principle I want to follow. Highest warning level, and treat warnings as errors. This actually led to a good thing today, because I just clarified something a little bit in my mind about how to use std::auto_ptr to the best effect. As it turns out, the compiler will complain about the following construct:
auto_ptr<char> s;
// Do something...
s = auto_ptr<char>(new char[100]);
The reason this is not a good idea is rather subtle, but basically it's due to the fact that the temporary object is not a reference to an object, it's an object, and you can't really make a reference to a temporary object like that. At least it's pretty bad form... It's a similar situation where you can't use a temporary object as a parameter for a non-const reference formal parameter to a function.
The way to do this is of course:
auto_ptr<char> s;
// Do something...
s.reset(new char[100]);
This led to some other code being affected, specifically code where methods had the following type of signature:
auto_ptr<char> Func() {
auto_ptr<char> t(new char[10]);
// Do something to set t to something
return t;
}
This looks neat, and is apparently a good idea to ensure that allocated objects are automatically delete'd as part of the auto_ptr destructor. However, this messes things up in other parts of the code since once again for similar reasons as above.
The resulting pattern rule is:
I'm a strong believer in what I call "code policy". Code policy is about formulating rules of coding, a bit like design patterns but more generic small snippets of wisdom accumulated through experience. I use probably 50 - 100 such "code policies" whenever I write code, and it's certainly been extremely useful. It takes the burden out of making many small decisions, and I may start document them for peer review in the future - that could be fun!
auto_ptr<char> s;
// Do something...
s = auto_ptr<char>(new char[100]);
The reason this is not a good idea is rather subtle, but basically it's due to the fact that the temporary object is not a reference to an object, it's an object, and you can't really make a reference to a temporary object like that. At least it's pretty bad form... It's a similar situation where you can't use a temporary object as a parameter for a non-const reference formal parameter to a function.
The way to do this is of course:
auto_ptr<char> s;
// Do something...
s.reset(new char[100]);
This led to some other code being affected, specifically code where methods had the following type of signature:
auto_ptr<char> Func() {
auto_ptr<char> t(new char[10]);
// Do something to set t to something
return t;
}
This looks neat, and is apparently a good idea to ensure that allocated objects are automatically delete'd as part of the auto_ptr destructor. However, this messes things up in other parts of the code since once again for similar reasons as above.
The resulting pattern rule is:
- Always return a pointer, not an auto_ptr, when an object is allocated.
- Never store a pointer, always wrap it in a auto_ptr object when it's kept around for more than passing on in the same statement.
I'm a strong believer in what I call "code policy". Code policy is about formulating rules of coding, a bit like design patterns but more generic small snippets of wisdom accumulated through experience. I use probably 50 - 100 such "code policies" whenever I write code, and it's certainly been extremely useful. It takes the burden out of making many small decisions, and I may start document them for peer review in the future - that could be fun!
Monday, January 16, 2006
API or Application Programming Inconsistencies
Got the mail out anyway now. Back to coding - or actually not so much coding as struggling with other issues. Latest is the issue to get Visual Studio to like WTL - the Windows Template Library that AxCrypt2Go will use for it's GUI. I haven't really succeeded, but I guess I'll just live with it, but it's a bit frustrating to implement a program with a library that does not support Intellisense - and lacks documentation to boot. But it is free... Here's an example of how fun it can be to program the Win32 API - it's an oldie and still goodie, but it serves as a nice example of why it's important to think about things before coding...
The Win32 API call GetModuleFileName is declared as:
DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename, DWORD nSize)
It gets a file name of a running executable, and places it in the buffer pointed to by lpFilename, restricted in number of chars by nSize. So far so good. But how do you figure out how large a buffer you need? Well... The function will return the number of chars copied. If there is not enough room, the result is truncated and nSize is returned. There is no way for the caller to determine if the result was truncated or just exactly fit! To make matters worse - it is definitely not bounded by MAX_PATH as some functions are, it may return an arbitrarily long path, when prefixed with \\?\, if that format was used when the executable was loaded.
All this leads us to ridiculous code like the following (truncated for brevity):
DWORD dwMaxLen = 0, dwLen;
std::auto_ptr<_TCHAR> szModuleFileName;do {
szModuleFileName = std::auto_ptr<_TCHAR>(new _TCHAR[dwMaxLen += MAX_PATH]);
dwLen = ::GetModuleFileName(hModule, szModuleFileName.get(), dwMaxLen);
} while (dwLen == dwMaxLen);
There are many variants on the above, but the point is we must use a trial-and-error loop! A much nicer version is a better API like, for example, GetTempPath. This function will instead return the number of characters required to hold the result, thus easily enabling the caller to determine if the provided buffer was large enough or the result was truncated. Even better, it allows the following pattern:
DWORD dwLen = GetTempPath(0, NULL);
std::auto_ptr<_TCHAR> szTempPath(new _TCHAR[dwLen]);
dwLen = GetTempPath(dwLen, szTempPath.get());
No loop, just the right amount of data etc. It makes a difference! It should be noted that as far as I can determine, both these APIs are the same age... So - the morale of the story - always think about how the caller can use your API, and never make assumptions about the size of data.
Ok, back to actually writing the program I'm supposed to be coding...
Back from 2 hours of coding - net result: 10 lines of code. Lean and mean, and using the basic API has it's price. All I'm trying to do is to enable my app to display icons from the system icon list plus one single private icon (the ugly one that's used to indicate AxCrypt-encrypted files). This turns out to be a major headache, since the list view control needs a single image list and an index into that to display an icon, and we the contents of the system icon list is dynamic, so we can't just copy that and be done with it. The strategy now is exceedingly complex, may it's time to re-evaluate and check if list views can be coerced into displaying icons some other way. Readers: any ideas?
The Win32 API call GetModuleFileName is declared as:
DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename, DWORD nSize)
It gets a file name of a running executable, and places it in the buffer pointed to by lpFilename, restricted in number of chars by nSize. So far so good. But how do you figure out how large a buffer you need? Well... The function will return the number of chars copied. If there is not enough room, the result is truncated and nSize is returned. There is no way for the caller to determine if the result was truncated or just exactly fit! To make matters worse - it is definitely not bounded by MAX_PATH as some functions are, it may return an arbitrarily long path, when prefixed with \\?\, if that format was used when the executable was loaded.
All this leads us to ridiculous code like the following (truncated for brevity):
DWORD dwMaxLen = 0, dwLen;
std::auto_ptr<_TCHAR> szModuleFileName;do {
szModuleFileName = std::auto_ptr<_TCHAR>(new _TCHAR[dwMaxLen += MAX_PATH]);
dwLen = ::GetModuleFileName(hModule, szModuleFileName.get(), dwMaxLen);
} while (dwLen == dwMaxLen);
There are many variants on the above, but the point is we must use a trial-and-error loop! A much nicer version is a better API like, for example, GetTempPath. This function will instead return the number of characters required to hold the result, thus easily enabling the caller to determine if the provided buffer was large enough or the result was truncated. Even better, it allows the following pattern:
DWORD dwLen = GetTempPath(0, NULL);
std::auto_ptr<_TCHAR> szTempPath(new _TCHAR[dwLen]);
dwLen = GetTempPath(dwLen, szTempPath.get());
No loop, just the right amount of data etc. It makes a difference! It should be noted that as far as I can determine, both these APIs are the same age... So - the morale of the story - always think about how the caller can use your API, and never make assumptions about the size of data.
Ok, back to actually writing the program I'm supposed to be coding...
Back from 2 hours of coding - net result: 10 lines of code. Lean and mean, and using the basic API has it's price. All I'm trying to do is to enable my app to display icons from the system icon list plus one single private icon (the ugly one that's used to indicate AxCrypt-encrypted files). This turns out to be a major headache, since the list view control needs a single image list and an index into that to display an icon, and we the contents of the system icon list is dynamic, so we can't just copy that and be done with it. The strategy now is exceedingly complex, may it's time to re-evaluate and check if list views can be coerced into displaying icons some other way. Readers: any ideas?
Thursday, January 5, 2006
Platform woes
Busy times... Still working on mailing out the update notifications, and just got a bug report about AxDecrypt not working on Windows 98. As it turns out it's quite true, and the reason is that a common library, AxPipe, had a dependency on two functions that are not available on that platform. It really is quite a bother to support all these platforms. I'll personally be pretty happy when Windows 98/SE/ME goes to the grave, but I suspect that will be a short-lived euphoria. Then along comes Vista and we get to do this all over again, supporting two widely differing platforms. There's already the problem with x64 Windows, which really requires a separate compile to work properly. It amazing how much developer time is spent on issues like these, instead of fixing real bugs and implementing new useful things
Subscribe to:
Posts (Atom)