Archive for February, 2005

No True Object Programmer, Part Deux

Edit (2/28): What I have to say about raising an event asynchronously in VB is very incorrect. If you got here by googling “raise event async VB“ (or thereabouts), do not listen to me. Read Bill McCarthy's comment about it.


Well, Bill loves VB.NET, and knows a lot about it. I am in a slightly different camp, in that I (arguably) know a lot about it because I am forced to use it at work, but I haven’t grown to love it very much.

But as to your difficulty in parsing VB.NET code, well as you said, VB.NET is actually more natural. It is probably more that you need practice reading and writing the code.

I concede that this is probably true. I’ve been staring at C/C++/Java/C# since I was 11 years old, so it’s quite likely that’s the only reason I find it more natural. It doesn’t really help that I switch between VB.NET and C# projects on an almost hourly basis these days. I’ll jump to the VB project and start typing:

StringBuilder sb = …

Whoops. Wrong one. Apparently I can’t make the jump as effortlessly as the woman shouting into a cellphone on the train next to me last week weaved an intricate and impressive unbroken stream of Spanish/English (“Spanglish?”).

So yes. Readability is probably a personal problem.

This started out, I guess, as a discussion about which language was “more OO.” That’s may be a vague metric, so I’ll try to limit the discussion here to which language lets you accomplish the task at hand in the simplest possible way with minimal connectivity and shared knowledge between your objects.

In the case of events, I think that at best, this is a draw. This is an opinion.

VB wins when it comes to a few useful abstractions: the RaiseEvent keyword, and declarative event handling (the WithEvents/Handles keywords).

In a comment on Bill’s blog, I referred to these as “leaky abstractions” (to borrow shamelessly from Joel). What I mean by that is, they work beautifully in the simple cases, but in more sophisticated situations they break down and you’re forced to understand what is actually going on. VB may or may not leave you with a way out, once you’ve done the learning bit.

My first example here was raising an event asynchronously. Here is code that accomplishes calling event handlers on another thread in C#.

internal class MyClass
{
    public event EventHandler MyEvent;

    protected virtual void OnMyEvent(EventArgs e)
    {
        this.MyEvent.BeginInvoke(this, e, null, null);
    }
}

Here is code that accomplishes the same task in VB.NET.

Friend Class SomeClass
    Public Event MyEvent As EventHandler
    Private Delegate Sub EventRaiserDelegate(ByVal e As EventArgs)

    Protected Overridable Sub OnMyEvent(ByVal e As EventArgs)
        RaiseEvent MyEvent(Me, e)
    End Sub

    Protected Overridable Sub OnMyEventAsync(ByVal e As EventArgs)
        Dim del As EventRaiserDelegate = AddressOf OnMyEvent
        del.BeginInvoke(e, Nothing, Nothing)
    End Sub
End Class

Bill’s correct, you can raise an event asynchronously in VB.NET, albeit in a roundabout way. Unless there's a radically different method I haven't thought of, I need to write and then call OnMyEventAsync, which calls a traditional event raiser on another thread.

Here is where I think the claim that VB is “more OO” breaks down. The representation of the event as a list of functions (which is what C# gives you) was significantly simpler for us in this case. We got the job done with less code, so in my mind C# wins the OO battle here.

As to events in Vb.NET, I'm sorry but there is no "inadvertant GC rooting". I don't know who told you that, but you/they were sorely mislead.

On serialization, Vb.NET has absolutely no problems with XML serialization. There is however an issue with binary serialization and MarshalByRef classes. The real problem is MarhsalByRef classes, eg a Windows.Form, cannot be binary serialized. If you need to work around that, you can do so in Vb.NET 2005, and more elegantly than C#.

Poor terminology on my part, I guess. What I was referring to with “GC rooting” was the situations where a programmer attempts to dereference an expensive object so that it may be collected. A common mistake is leaving events wired up (and hence, a reference that has a gc root).

Is that any more difficult to deal with in VB than it is in C#? No, not really. Touché. But am I justified in calling an event a “leaky abstraction” if they require a deeper understanding of function pointers and GC in order to keep your program from hogging memory? I think so.

So that leaves the last sitch: serialization. MarshalByRef is actually not what I was thinking about, but it’s closely related. MarshalByRefObjects are at least serializable, and unless you are persisting to a storage medium you will succeed in serializing a graph if your only mistake is having a ObjRef going along for the ride.

Objects that are not [Serializable()] at all are a bit more problematic. You’ll get an exception which will be difficult to track down if you have event handlers wired up to any of these. C#’s got an easy way out (google it; my post is getting really long, dammit). The hacks VB will force you into in some cases is likely to make you cry. I know it made me cry.

So which language is “more OO?” That’s impossible to answer objectively, and it probably makes no sense to even try, but I’ll tender a personal opinion.

My feeling is that VB gives you some keywords that are useful for simple OO. Unfortunately, it obscures some of the underlying nuts and bolts, and this gets in the way of your own attempts at OO abstraction. C#, on the other hand, is a little better at ensuring that the realities of the CLR are quickly accessible if you need them.

In an ideal world, we’d have both in one language. But forced into a choice, I’ll opt for seamless access to the guts. Keeping my own objects as loosely coupled as possible is what I’m most interested in doing.

No True Object Programmer

Did you love the No True Scotsman argument? Well, get ready for the arguments!!

Explicit Interface mapping. This is incredibly cool. Unfortunately a lot of people just don’t get how important this concept is to true OO.

He continues:

As to VB.NET over C#, VB.NET is actually a far more OO language when you look at the actual implementation details.

(did I hear a record scratch?)

Far more?

At the risk of Ad Verecundiam, I’ve actually been on the phone with a Microsoft employee who said these words: “C# is a much better choice if you intend to do object development.”

Bill doesn’t expand on that argument really, other than the appeal of the End keyword. It would be a silly thing to get into an argument about, but my feeling is that End XXX makes VB code less readable. I would like to see more reasons why this could be true.

I apologize for any haughty, dismissive tone. I wrote this while working on a brick of Parmigiano Reggiano and sucking down a bottle of Chianti, so it just kind of came out that way.

N-Tier Remoting Frustrations

Link.

People DO want n-layer, because that provides reuse, maintainability and overall lower costs. Logical separation of UI, business logic, data access and data storage is almost always of tremendous benefit.

People MIGHT want n-tier if they need the scalability or security it can offer, and if those benefits outweigh the high cost of building a physically distributed system. But the cost/benefit isn’t there as often as people think, so a lot of people build physical n-tier systems for no good reason. They waste time and money for no real gain. This is sad, and is something we should all fight against.

I think I agree with this in total.

The project I work on has hit basically every problem with Remoting that exists.

  • Unbelievably slow dataset serialization (see KB829740). Kind of a big issue for us because many of our developers aren’t so comfortable with creating their own data structures / objects, and consequently were relying very heavily on ADO objects. I resolved the speed issue by implementing my own formatter sink.
  • SocketExceptions (specifically, WSAENOBUFS) when transporting huge amounts of data. To some extent this is mitigated by better hardware. Although Q322975 refers to this as a “BUG,” we spoke with the Remoting development team through our premier support guys and they refer to this as designed behavior. There isn’t a quick fix (ie, registry change) here, so I’m going to have to try putting in a compression sink to get us some headroom.
  • The lack of a default remote call timeout. This killed us in production because of 1) a network problem and 2) some bad codes that circumvented the HttpRuntime’s executionTimeout in a very unfortunate way. It took us 4 horrendous days of the servers crashing every 20 minutes with three Microsoft CPR people on-site to finally figure out what the problem was.

There are probably a few others which I am forgetting now. I am still talking to MSFT reps about the second, but I have no expectations that that will get anywhere.

But getting back to my main point (yes, I had one). The really frustrating part about this for me is that I don’t even consider our middle tier to be necessary. We put it there primarily for security purposes, and I don’t know, maybe we get that. But with respect to the way most of our developers write code, this is no help. It doesn’t necessarily create a logical service boundary, because nobody really gave them the direction to do that. To an extent it just makes the spaghetti worse.

Now for my secondary point. A lot of this is certainly our fault. But what drives me crazy is comments like this one:

This does assume you listened to advice from people like Ingo Rammer, Richard Turner and myself and avoided creating custom sinks, custom formatters or custom channels. If you ignored all this good advice then you’ll get what you deserve I guess…

It’s frustrating as hell to be backed into creating workarounds for lousy performance which you (well, your boss, who mandated this architecture) were never warned about and then to be openly mocked for doing so by the ‘experts.’ If we had known that Remoting would be throwing us this many problems, we probably would not have tried to use it for n-tier, and maybe with a little luck we would have decided against our flavor of n-tier altogether.

Get us some better advice, folks.

Getting some grease under my fingernails

I decided I needed some debugger extensions specifically intended for ASP.NET hang dumps. Psscor has a few nice ones but I figured I would learn a lot in the attempt, anyway.

Here’s how the project is breaking down.

Days 1-2: Messed around trying to learn how to use the build utility that comes with the Windows 2003 DDK. This would have been faster if I had looked at a makefile more than once in the previous five years.

Day 3: Toyed with the idea of using LoadLibrary on psscor and filtering the output, but instead decided that I was insane.

Days 4-5: Got pretty familiar with writing an extension on my own, and what the implementation details would be. It was becoming pretty clear that I would need to get some info on the structures if I was to have any hope of getting finished.

Days 5-7: Downloaded the SSCLI and realized that it’s got a (pretty old) version of SOS.dll in it. I have a few moments of euphoria here and radically switch approaches: I will now start with this and extend it to suit my needs.

I pretty quickly found out that this DLL is assuming the SSCLI execution engine and won’t work with the Microsoft production ones (mscorsvr in my case, or mscoree). No problem, I assume that won’t take too long to fix.

The problem is that this thing is filled with code like this:

// Note this is possible to be spoofed, but pretty unlikely
// call XXXXXXXX
if (spot[-5] == 0xE8) {
    move (*whereCalled, retAddr-4);
    *whereCalled += retAddr;
    //*whereCalled = *((int*) (retAddr-4)) + retAddr;
    if (*whereCalled < 0x80000000 && *whereCalled > 0x1000)
        return;
    else
        *whereCalled = 0;
}

(your guess is as good as mine).

I’m not sure if they had their best programmers working on this thing. I don’t know. Perhaps they just never expected someone like me to look at it in depth.

So that’s where I’m stuck for the moment. I’m going through it, commenting it and trying to understand it. I will eventually refactor it quite a bit. At the moment there are a lot of very long, very hard to follow functions in it. But, it’s good to look at some unmanaged code for a change.

Goodbye to the Good Doctor

Definitely the most upsetting celebrity death that I can remember.

The Danger of The Code Project

I’d say it’s the sheer number of hacks available with minimal discussion or explanation, coupled with the tendency of these kinds of sites to outrank MSDN on google for certain things. This isn’t necessarily a critique of The Code Project site specifically, but rather internet code snippets in general.

I was writing a Windows service today, and I wanted it to have a tray icon to provide access to some options. This isn’t as straightforward as adding a NotifyIcon component, because by default services aren’t allowed to create windows and so forth.

After some googling I came across this.

Now, bitter experience has already taught me never to trust internet code samples. I won’t go into that. But what was interesting was that this article goes so far as to mention:

I am assuming that Microsoft left this out for a reason…

Well, as it turns out, they did. There are at least a few security concerns in this situation, and one should be more educated on the subject than I am to attempt it. At that point I backed up and went with a client/server control model. It was more robust anyway, but it would take longer to write.

I would be interested to know how many authors of production code grabbed and used this code snippet without a second thought. It was the top search result for my terms, so I’m guessing it would be a high number.

The tendency of people to believe everything they read is of course not new.

Managed Debugging with WinDbg, Part 1 of N

There seems to be relatively little information about WinDbg available, so I will try to post some things as I figure them out myself.

We had a severe-to-extremely-severe production problem last week, and my recent activity with WinDbg was another example of “learning with a gun to your forehead.”

Getting the Right Extensions

If you are doing any kind of managed debugging, you will want the current set of extensions which can be found here.

The simplest thing to do is just drop the .dlls in the install directory for WinDbg. The two dll’s in this set that will be most important to you are psscor.dll and sieextpub.dll. Psscor has a lot of tools for dumping the contents of managed objects, and the second has some powerful functions for showing application and thread state.

There is a third extension, sos.dll, whose functionality is mostly overlapping with psscor.

Extensions Basics

Load an extension into WinDbg like so:

0:000> .load psscor

At any point, you can see the extensions you have loaded with this command:

0:000> .chain

All of the extensions I’ve mentioned come with help commands. The help for the topmost extension in the chain can be called like this:

0:000> !help

But you can always refer back to extensions further down in this way:

0:000> !sieextpub.help

An Example – Debugging an ASP.NET Hang

This was the scenario we found ourselves in last week. The first thing you will need to do is get a hang dump of the worker process using AdPlus, which I don’t have time to cover here. However, it is relatively straightforward.

Once we’ve got the dump, the most obvious thing to try is to see what the process is doing. To do that, load psscor and use this command:

0:000> ~*e!clrstack

This will dump out the managed stack of all of the threads in the process (the ~*e means that we want to iterate through all of the threads and perform the specified action for each).

That will give us a general idea of what is going on. The stack of one or more particular threads is bound to be interesting, and we can narrow it down to the stack trace of a single thread using:

0:000> ~113e!clrstack

Here I’ve replaced * (all threads) with a single thread, 113. Assuming this is a managed thread, you should see some output like this.

Thread 113
ESP         EIP     

…

0x0dc5f6cc  0x0fa3bb17 [DEFAULT] [hasThis] Void System.Web.UI.Page.ProcessRequestMain()
0x0dc5f710  0x0fa3aedf [DEFAULT] [hasThis] Void System.Web.UI.Page.ProcessRequest()
0x0dc5f74c  0x0fa3a94b [DEFAULT] [hasThis] Void System.Web.UI.Page.ProcessRequest(Class System.Web.HttpContext)

…

For this example, I’ll just show how to figure out which page in the application is executing. Since we’re running inside a page class for a lot of the response, the this pointer should be all we need.

Grab two stack pointers (the ESP register) and use the psscor.DumpStackObjects command, or dso for short:

0:000> !dso 0x0dc5f6cc  0x0dc5f74c 

Thread 0
ESP/REG    Object     Name
0x0dc5f6cc 0x31f0d208 System.Collections.Specialized.HybridDictionary
0x0dc5f6d0 0x0371c55c _ASP.incomeStatement_aspx
0x0dc5f6d8 0x0371c55c _ASP.incomeStatement_aspx
0x0dc5f714 0x31f0d208 System.Collections.Specialized.HybridDictionary
0x0dc5f720 0x070ca198 System.Globalization.CultureInfo
0x0dc5f724 0x070fb010 System.Threading.Thread
0x0dc5f728 0x0371c55c _ASP.incomeStatement_aspx
0x0dc5f73c 0x31f0d208 System.Collections.Specialized.HybridDictionary

Bingo – in this case, _ASP.incomeStatement_aspx is an instance of the page class.

Note that the first argument to dso is the upper stack pointer, and the second is the lower stack pointer. I’ll post some more stuff when I have time.