I have mixed feelings about frameworks. On one hand they make lots of things easier. There is no end of good press about Rails. Many of the python web frameworks get glowing reviews. I've been using .NET since inception and have had mostly positive experiences with it. A good framework makes a lot of things easier. It provides good abstractions for common tasks, but doesn't prohibit you from doing some esoteric things. If the framework is provided for specfic things like web programming (Rails) it will make anything related to that task feel somewhere between easy and effortless. If the framework is more general purpose in nature (.NET) it will provide enough libraries, abstractions, etc. to make sure you focus more on solving your particular problem rather than wrestling with the environment or solving a particular facet of a problem (writing a good data structure to hold objects, efficient sort routines, etc.). For example, here is an overview of the .NET framework "The .NET Framework is a development and execution environment that allows different programming languages & libraries to work together seamlessly to create Windows-based applications that are easier to build, manage, deploy, and integrate with other networked systems." I don't mean to pick on .NET here, but it is the framework I have the most
experience with. While it does make things easier, that is different than making
them easy. The framework's abstractions do not absolve you, intrepid programmer,
from knowing what is actually going on under the covers. Here I will cover
one example of where knowing what's going on under the covers and how using
that knowledge leads to a much better experience for people using applications
you write.
We are working an an API for a product that runs in Excel. It makes use of the .NET framework and uses VSTO so we can use .NET assemblies in Office. The API is callable from Microsoft Excel's VBA Programming language. In order to facilitate this some of our objects that we use internally are given a COM Callable Wrapper so they can be used from VBA. To make our objects visible we gave them the COMVisible attribute, set the interface type to dual and gave the objects their own guid. The object definitions look something like this:
So all was well in our intial tests. Things worked the way we expected, objects were visible in the debugger, we could get and set all the attributes, etc. All was going according to plan. Then they went off to some other testers and they started having issues when they did things like
If they referenced it from the collection later then tried to set a property a runtime error would get generated. What was going on? Taking a look at it in the debugger gave us our first clue. Looking at the type we saw that the collection elements were all "myNamespace.GymMember". There were no instances of any classes in the collection at all. Just the name of the type. Odd.
Looking at this we knew that something was wrong. Obviously a reference to
the object was not being returned, the type name was. A little digging shows
that the object's type is returned in the ToString class by default, so that
is what was likely happening. So how do we return a reference? Just for the
heck of it I added a ToObject method that looks like this:
And then called the ToObject method wehn adding it to the collection like so
Lo and behold, this worked. I now had a way to easily add object references. The syntax still wasn't very nice. So a little more digging. It had been a while since I had done any hard core COM programming so I had to brush off some of my old books and see what could be done. I knew enough that I could probably do something with Dispatch IDs. A little digging and I found that the default property of a COM object could be defined by assigning it a Dispatch ID of 0. Could it really be that easy?
By assigning the dispatch ID of 0 we are able to get back some VB code that should look familiar:
The whole point of this diatribe is that while frameworks are in fact very
helpful most of the time, they do not excuse you from knowing what is going
on under the covers. As in the example above, the framework gets you most of
the way there but often those last little bits that really make something shine
depend on a good knowledge of, or being able to find good knowledge about,
what you are working on.
[ComVisible(true),
Guid("2E45AEE9-86AD-9dl3-S29-6983350AH788"),
ClassInterface(ClassInterfaceType.AutoDual)]
public class GymMember
{
public string Name = "";
public string Address = "";
public int ID = -1;
public GymMember() { }
public GymMember(string Name, string Address)
{
this.Name = Name;
this.Address = Address;
}
...
}
Dim myCollection as New Collection
myCollection.Add newObject
public GymMember ToObject
{
get { return this; }
}
myCollection.Add newObject.ToObject
[ComVisible(true),
Guid("2E45AEE9-86AD-9dl3-S29-6983350AH788"),
ClassInterface(ClassInterfaceType.AutoDual)]
public class GymMember
{
public string Name = "";
public string Address = "";
public int ID = -1;
public GymMember() { }
[DispId(0)]
public GymMember ToObject
{
get { return this; }
}
public GymMember(string Name, string Address)
{
this.Name = Name;
this.Address = Address;
}
...
}
myCollection.Add newObject