About this blog
Random thoughts on C#, Windows NT, VoIP, and whatever else crosses my mind
Entries in this blog
Maybe I should write something on it once in a while. Really, a 5 year gap between posts is pretty sad.
Step 1: In the Regional Options control panel, change your language to Welsh.
Step 2: Use System.Data.OleDb and watch all hell break loose.
Definitely one of the weirdest bugs I've seen.
People often ask what the point of attributes is, and how they can be used effectively. I thought I'd talk a bit about one of the ways we use attributes in our apps, and as a bonus give you a few details on our boot process.
A bit of background
In our apps, all of the different components are divided into groups such as 'Shutters' and 'Services'. Services are the bits of code that sit in the background and listen to telephony events, or manage database connections, or keep track of contact lists, and so on. Shutters are the GUI components. Shutters tend to rely on services to figure out exactly what needs to be displayed. For example, the contact shutter asks the contact service for a list of contacts to display. Each of these components consists of a primary class, plus various helper classes as necessary.
Because shutters depend on services, it makes sense to initialize the services before initializing the shutters.
We want our application startup code (known as the 'boot manager') to be as generic and reusable as possible - it shouldn't have to know about the details of each particular shutter or service, and of course the lists of necessary shutters and services shouldn't be hard coded. So the question is, how can we ensure that the services are started before the shutters are initialized, while maintaining genericity? Wouldn't it be nice if, say, we could pass an assembly to the boot manager, and have it automatically initialize any services and shutters inside the assembly? How can we pull this off?
Attributes to the rescue!
As mentioned above, each component consists of a primary class. These primary classes contain the initialization code that needs to run when the application starts up. So let's take each one of these primary classes and tag it with an attribute indicating that it is a service or a shutter. We'll call this attribute 'Bootable'.
public class MyImportantService
public class MySuperImportantShutter
On startup, assemblies get passed in to the boot manager, which examines the assemblies for any classes with these attributes. It groups them into services and shutters, and initializes them one after another.
Problem solved! We can now be sure that services are initialized first. But this leads to another problem - dependencies between services. It is quite conceivable that one service might depend on another; the contacts service mentioned above might use the database service to talk to the DB where the contacts are stored. We need a way of ensuring that the database service is initialized before the contacts service. At this point we have to make the assumption that the programmer writing a service knows what other services it depends on. Given this, all that is needed is a 'Prerequisite' attribute that indicates which other services need to be running before the service in question can start.
public class MyImportantService
public class MyOtherService
public class GDNetJournalService
After the boot manager builds the lists of services and shutters, it then orders them based on prerequisites, and starts them as above. (If our intrepid programmer decides to code in a circular dependency, he will be greeted with an exception on startup)
So there you have it - a way of using attributes to ease the pain of initializing your application.
(Yes, I know, this is supposed to be a .NET-focused journal. But I have to use Java for school, so I think it's ok to sneak in the occasional Java-related post.)
In my never-ending search for a decent Java IDE, I recently decided to install Borland's JBuilder 2005 Foundation. What a mistake that turned out to be. I simply can't comprehend how such shoddy products can actually be released. The forms designer is so slow and buggy as to be beyond useless. The entire IDE is a train wreck of miserable performance, astronomical memrory usage, and sheer ugliness.
I guess it's back to Eclipse for now.
I found this one yesterday. The bug description went something like this: "Start app. Press a key. App crashes."
D'oh! This one was caused by some weird interactions between our keyboard shortcut handler and our new localization code. Apparently some strings that weren't supposed to be localized were, which broke some of our accelerator actions. But hey, it's early in the product development cycle. Things are allowed to break.
(And no, this bug wasn't my fault!)
(And how NOT to write performance-oriented apps for .NET)
I recently looked at writing some code to integrate with ACT! 2005. ACT! is a personal information management application along the same lines as MS Outlook or Lotus Notes. When I installed the demo and found that it was a .NET application, I was intrigued. When I found that there was an SDK available, I was even more intrigued. Did I finally find an application that makes integration simple and relatively painless? (None of Outlook, Notes, GoldMine or previous versions of ACT! fall into this category).
My hopes were crushed when I actually looked at the contents of the SDK. Some 20-odd megs of assemblies, a few samples, and some incredibly pathetic documentation. The documentation consists primarily of short snippets demonstrating how to perform very specific tasks. Nowhere is there any indication of what any of the assemblies actually do. A high-level design overview or detailed description of the class heirarchy? Nah. We obviously don't need those. Browsing the ACT! discussion groups shows that I'm not alone in my disdain for the SDK.
The moral of the story: If you want your app to be extensible, don't underestimate the value of good documentation. All the functionality in the world isn't worth much if nobody can figure out how to use it.
Incidentally, ACT! 2005 is also one of the slowest applications I've ever used. And I use the term 'used' loosely; it's barely tolerable on my P4 2.8 Ghz dev machine.
Sometimes painfully slow. Changing from Debug to Release mode takes 30-40 seconds (that's just changing the setting in the IDE, not recompiling). I work with reasonably large solutions, but still ... it makes me want a faster computer. And don't get me started on how badly compiling bogs down the IDE, to the point where the output window can't even display text without lagging. Grr.
AxTools CodeSmart 2003 is a pretty cool VS.NET addin that we recently got a site license for at work. I haven't really had a chance to explore all of its features yet, but after a bit of playing it looks like it could be quite useful.
In other news, Outlook 2003 uses some undocumented MAPI properties for new contact fields such as 'IM Address'. Thank goodness for OutlookSpy, and no thanks to MS for once again making it unnecessarily difficult to write code that integrates with Outlook.
I was recently bitten by a bug in the .NET framework. Apparently, calling ChannelServices.UnregisterChannel(foo) doesn't actually unregister the channel properly and close the socket. Subsequent attempts to call RegisterChannel() for a socket on the same port fail with an "Only one usage of each socket address is normally permitted" exception. I worked around it by leaving the channel open for the entire lifetime of the application.
ReactOS 0.2.4 was released a few days ago. Download it here, or have a peek at the changelog here.
And here's my first journal entry. I won't be saying much about my personal life in this journal; I plan to keep the posts technical, and focused on topics such as:
-Projects I'm working on at school
-Interesting technial issues I come across at work (I write .NET-based software for corporate VoIP phone systems)
-Various graphics & systems programming projects that I am working on
That's all I have to say for now ... the real point of this post is just to test out the journal system.