# Friday, 01 December 2006

From Beyond Code, this made me smile:

Sorry for the delay
A priest was being honored at his retirement dinner after 25 years in the parish. A leading local politician and member of the congregation was chosen to make the presentation and give a little speech at the dinner. He was delayed, so the priest decided to say his own few words while they waited.

"I got my first impression of the parish from the first confession I heard here. I thought I had been assigned to a terrible place. The very first person who entered my confessional told me he had stolen a television set and, when questioned by the police, was able to lie his way out of it. He had stolen money from his parents, embezzled from his employer, had an affair with his boss's wife and taken illegal drugs. I was appalled. But as the days went on I knew that my people were not all like that and I had, indeed, come to a fine parish full of good and loving people.".....

Just as the priest finished his talk, the politician arrived full of apologies at being late. He immediately began to make the presentation and gave his talk. "I'll never forget the first day our parish priest arrived," said the politician. "In fact, I had the honor of being the first one to go to him in confession."

Moral: Being late can be (very) costly.

Kate

Friday, 01 December 2006 08:13:25 (Eastern Standard Time, UTC-05:00)  #    
# Thursday, 30 November 2006

Like Dilbert, this list of top 20 excuses developers give to testers is only funny because it's true. I'll tell you that the answer listed as #1 there is banned in our offices -- and we have quite a bit of process in place to make sure deployments are complete, for just that reason. Personally, I find #8 the funniest - and again, only because I have in fact heard it... mostly from former employees :-). Number one winner in the comments: Billy Hollis - "We're not shipping your machine."

Kate

Thursday, 30 November 2006 09:02:24 (Eastern Standard Time, UTC-05:00)  #    
# Wednesday, 29 November 2006

To follow up on my post about pinning pointers, let me ask one of those tricky questions that someone asked me. If I have an array of things, how do I pin the whole thing? If I ask for a pinning pointer based on element #3 of the array, can I use pointer arithmetic from that pinned pointer to reach elements #4 through #11? Do I have to pin each element one at a time?

The answer is that pinning any element of an array pins the whole array, and that once you have a pinned pointer to one element of the array you can do the usual pointer things. This includes not only incrementing it to move through the array, but if it's a char* you can pass it to things that expect strings and those things will never know the difference. Here's an example from MSDN:

array<Byte>^ arr = gcnew array<Byte>(4);
arr[0] = 'C';
arr[1] = '+';
arr[2] = '+';
arr[3] = '\0';
pin_ptr<Byte> p = &arr[1];   // entire array is now pinned
unsigned char * cp = p;
printf_s("%s\n", cp); // bytes pointed at by cp will not move during call

This sample prints out ++.

Kate

Wednesday, 29 November 2006 08:42:29 (Eastern Standard Time, UTC-05:00)  #    
# Tuesday, 28 November 2006

As I mentioned earlier, I recorded a DNR episode while at Tech Ed Developers in Barcelona. A bunch of us got together to talk about Agile development. As I said at the time, at Gregcons we're not "formally Agile" (stop laughing) but we do a lot of things that fall under the Agile umbrella, because they just plain make sense.

I haven't had a chance to listen to the recording yet, but Scott Bellware has, and he liked it. Among other things, he says:

Kate Gregory nailed a quintessential a-ha moment in agile adoption: "You go through this phase of saying, that's way too extreme; I would never do that; what kind of weirdo does that?.  And then a year later, you're doing that."

Agile practices go deep and often work at subtle levels.  The very practice of agile development puts the sharpness in your perspective that you'll need before you can see the difference between pre-agile development and agile development.  Kate's statement perfectly captures this experience of the agile practice paradigm shift.

Happy to help, Scott. Thanks for listening!

Kate

Tuesday, 28 November 2006 07:34:03 (Eastern Standard Time, UTC-05:00)  #    
# Monday, 27 November 2006

I use search engines for a variety of reasons. Sometimes I want to find out how to do something. Other times, I want to find the official page about something so I can link to it here or send it to someone. Since most of the things I want to learn are related to things I already know, and since I blog about a lot of what I know, I have a bit of an occupational hazard:

One of my mentoring clients complained about this to me. "I decide to search the Internet instead of calling you to ask and what do I find? A bunch of stuff you wrote!". Believe me, it's worse when all I can find is a bunch of stuff I wrote. And Peter Near, a fellow MVP, Flyertalker, and Ontarian, has the same problem.

I would get in the habit of excluding gregcons.com from my search results if not for two things: first, a lot of my stuff is published on other sites, and second, from time to time my old words help me remember something I'd forgotten. So I guess I'm stuck with it.

Kate

Monday, 27 November 2006 07:25:06 (Eastern Standard Time, UTC-05:00)  #    
# Sunday, 26 November 2006

I've recently been asked (again) about pinning pointers so I decided to blog it, so that next time I can just email the link and save everyone a little time :-)

When you're working in C++/CLI, there are two kinds of indirect access to objects: handles and pointers. A pointer is that good old friend (fiend?) we've known for so long and it holds the address of a place on the native heap or the stack. You get a pointer by using the new operator with a type, or the address-of operator, &, with an instance:

Customer c("Microsoft");
Customer* pc1 = &c;
Customer* pc2 = new Customer("CTV");

Pointers stay still. You can cast them to ints, stick those ints into collections, do whatever you like to them, and later cast them back to pointers and dereference them and if they were pointing to something on the heap, like pc2 does, they will still be pointing to the same place on the native heap the whole time. What's more, the instance they point to will not have gone anywhere unless you explicitly delete it yourself.

Handles are the new kid on the block and they sorta-point-to a place on the managed heap. You get a handle by using the gcnew operator with a type, or the make-me-a-handle operator, %, with an instance:

Employee e("Kate", "Gregory");
Employee^ he1 = %e;
Employee^ he2 = gcnew Employee("Brian","Gregory");

Handles don't stay still. If you found a way to get the value out of them and then stuck it somewhere and let the handle itself go out of scope, the garbage collector might clear away the item on the heap, making the number meaningless. Even if you kept the handle in scope, the garbage collector might move the item to somewhere else, making the number meaningless.

Now normally this is nothing more than an interesting fact, one of the differences between handles and pointers. But what if you have some information contained inside a managed instance and you need to pass it to some native code that doesn't know about handles? Now you not only need to convert somehow, you also need to ask the garbage collector not to move that heap item while you are holding a pointer to it. This is called pinning. Let's switch to simpler types so you don't have to worry about what's in an Employee object. I need this most often with strings - I have some managed code that gives me a String^ and I need to pass it to some native code that needs a LPCWSTR or the like.

String^ title=HandyLibraryFunction();
{
   pin_ptr<const WCHAR> str = PtrToStringChars(title);
   NativeFunction((LPCWSTR)str);
}

PtrToStringChars is a handy function you will find in <vcclr.h>. Those brace brackets are important -- when the pinned pointer goes out of scope, the garbage collector is allowed to move the item again. You really need to minimize pinning time or you will ruin your app's performance, so I've artificially shortened its lifetime to release it as soon as possible. And whatever NativeFunction does, it better not take a copy of the pointer it's given and save it away for future use, because it will be a dangling pointer once str has gone out of scope -- even if title is still in scope.


The concept is much the same when you want a member variable from a managed instance. Grab hold of it and use the pin_ptr template to pin it and give you a pointer, which you can then work with following all the rules of pointers. Let go of it as soon as you can.

Kate

Sunday, 26 November 2006 17:51:25 (Eastern Standard Time, UTC-05:00)  #    
# Saturday, 25 November 2006

Here's a little oddity I happened across. It's a patent application:

The present invention provides a system and/or method that facilitates expanding keywords within an existing computer programming language by employing a whitespace keyword containing embedded whitespace. A whitespace component can receive code, and create a whitespace keyword based at least upon a successive comparison of adjacent tokens. The whitespace component creates a whitespace keyword by replacing more than one token with a single token containing embedded whitespace. Moreover, the whitespace component can utilize a lexical analyzer to group code into tokens and a parser component to parse the code.

This actually makes sense to me (assuming you accept that the idea of software patents in general makes sense.) It was a huge leap to take a language like C++, where keywords are separated by spaces, and extend it to become a language where some of the keywords actually contain spaces. After all, so many of us already have words like ref and value as variable names: the only way for C++/CLI to work is the conceptual leap that says "ref isn't the keyword, ref class is the keyword." If you wonder how that's actually done... read the patent application.

Kate

Saturday, 25 November 2006 14:54:42 (Eastern Standard Time, UTC-05:00)  #    
# Friday, 24 November 2006

There are quite a few products, generally older products, that aren't going to be supported on Vista and probably aren't going to work on Vista. One of the not supported announcements that seems to be catching people by surprise is about SQL Server 2000 and it's free sibling, MSDE. They seem to have run afoul of UAC, which really does require you to change your application.

If you are using SQL Server 2000, you should upgrade to 2005 anyway: it has a lot of improvements for you. But MSDE users don't generally even realize they are using a database: they're using an application that uses a database. Whoever made that application needs to tweak their install so it uses SQL Express (which is just as free as MSDE ever was, and doesn't have a governor) instead. And if that's you, learn about Vista development while you're at it in case your application ends up needing changes too.

Kate

Friday, 24 November 2006 14:24:51 (Eastern Standard Time, UTC-05:00)  #