Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Example of Code Structure for COM+ Component : Page 2

In this article Jimmy Nilsson shows you his ordinary code structure for COM+ components, that you can use as a template for your own apps. The article is filled with tips and advice about where to get a reference to the ObjectContext, how to build a robust error handler, how to work with interfaces, and more.


advertisement

Let’s take a look at the code flow, when everything works out as expected.

  'Do some work...

ExitHandler:
  On Error Resume Next
  'Clean up, for example ADO-stuff.

  If lngErr = 0 Then
    jnskSetCompleteMTS strSource, mobjCtx

As you "know", we will get Try, Catch, Finally semantics in VB.NET, but until then I try to simulate the same stuff with VB’s old error handling scheme. (I know that I’m not achieving that fully when it comes to clear syntax, but the functionality is quite close.) The ExitHandler label will always be used at the end of the methods flow. Therefore you have just one place to put your clean-up code. It’s good practice to clean up after yourself. It’s also a good way of avoiding strange problems. A classical example has been (is?) that if ADO-objects weren’t closed explicitly, they would empty the error object, when VB closed the ADO-objects implicitly. Before I start cleaning up, I say that I don’t care about new errors.



After cleaning up, I take a look at the local error variable lngErr. If it’s zero, everything is OK, and it’s time for SetComplete. How can lngErr not be zero you ask? Well, be patient and you will soon find the answer.

Once again, I have my own sub for accomplishing a task. This time it’s the SetComplete that will be taken care of by jnskSetCompleteMTS. As you might have guessed, I have several arguments for doing this, such as:

  • It gives a nice and central place for adding "custom interception", such as trace calls. (I’m sorry for nagging, but this will be covered further in another article.)
  • It moves the need for conditional compilation sections out of the regular code.
  • It’s a preparation for a possible need in the future.

The following code will run when the code reached an error.

  Else
    jnskSetAbortMTS strSource, mobjCtx
    On Error Goto 0
    Select Case lngErr
      'Case ???
      Case Else
        jnskErrRaise doErrUnexpected, lngErr, _
        strError, lngErl, strSource, mobjCtx
    End Select
  End If
  Exit Function

If lngErr is not zero, we enter the section where we will investigate the problem further. Before doing that I will do a SetAbort. It could be argued whether this is a good idea because perhaps we can do something to recover from the problem higher up in the call hierarchy. I agree that SetAbort isn’t what should be used all the time, but most often I do it like this instead of using DisableCommit. "Simple is beautiful".

Error trapping is then deactivated so that we will pop out of this method when we raise a new error. After that the error is investigated. If we didn’t expect this error, a last resort would be to raise an unexpected error. jnskErrRaise takes an enum for which error was raised (in this example the sample component lives in the layer I call Domain and that’s the reason for using "do" as the prefix to the new error code). I also send all other relevant information to the jnskErrRaise sub so it can do an Err.Raise and some other interesting stuff like logging the error etc.

ErrorHandler:
  jnskErrSave lngErr, strError, lngErl
  jnskStop
  Resume ExitHandler
End Function

When an error occurs in the regular code, I will go to the ErrorHandler above. The first thing I do there is to call a sub (jnskErrSave) that will save the error information in my local variables. That way you don’t risk the problematic effect of having the error object emptied. (The error object is still valid in jnskErrSave since I don’t set up any error trapping in that sub.) Note that I will save the Erl information to the local variable called lngErl. This means that if you have numbered the lines of the code, you have caught information about the exact line where the error happened. That is really powerful, when it comes to trying to find an error.

After that I call jnskStop which is only a sub, acting as a persistent breakpoint. I often find it interesting to get a halt in my code as close to the error as possible. If I have places in my code where I expect errors to happen, I don’t have the problem as with the regular "Break in Class Module" that can be set in the VB IDE, since using jnskStop is configurable.

Finally I jump to the ExitHandler (as you saw earlier) for further processing of the problem.

WAS THAT ALL THERE IS TO IT?

No, of course not! This is only the beginning. I was lazy and trapped only the unexpected case. I didn’t really do anything with the problem in this example. I only popped it. Some errors should of course be taken care of locally.

You also have to add more standard code, for example when it comes to trapping errors from ADO and the database. I haven’t shown many comments either, not even headers for the class and the method. You should of course add a lot of those. And more...

Do you think that there is more code here for error trapping than "real" code? This is often the case. But remember the parallel with re-papering. If you want to have a good end result, then the preparation will often take more time than the "real" work. You could of course also easily create an add-in for writing the skeleton for you.

"ADAPTABLE" CODE

Do you like to use the same code structure for components that shouldn’t run as configured components in COM+/MTS? I certainly do because of several reasons, but I will skip those arguments for now. To accomplish that, I’m using a trick by faking an object context interface, an object control interface and a conditional compilation argument that I have called MTS. (The faked interfaces are there only to make the code compilable. I could escape those faked interfaces by adding a lot more conditional compilation sections to my code, but I think this strategy gives much cleaner code since I don’t have any conditional compilation sections in the "real" code, only in my shared foundation routines.) There are of course other strategies that could be used too. You could for example check if GetObjectContext() is returning Nothing. You can also see if ObjectControl_Activate was executed. This is actually yet another subject that needs an article of its own.

I also write my transactional code so that if your transactional component isn’t configured for COM+ transactions, it will use ADO transactions instead. Boy, do I have a lot of articles that I need to write or what?

OBSOLETE STRUCTURE?

Is it really important nowadays to pay attention to the code structure, the obscure error trapping stuff in VB6, and so on, when VB.NET is soon to arrive? Well, in my opinion the answer is "yes". (You would have been surprised if I said "no" here, right?) First, VB.NET won’t be here soon and perhaps you would like to do some work now? I also believe that the best preparation for the future is to have a solid ground with consistent code, error trapping construction that maps the one in VB.NET and as much as possible in general and shared routines. All this should give as smooth a transition as possible when it’s time.

MISCELLANEOUS COMMENTS

Are there any drawbacks with standardised code? Some developers argue that it will lead to a situation where developers stop thinking and don’t understand what’s going on. On the other hand, the code will be consistent and probably easier to understand. Of course, you must always understand the code, otherwise you can’t use it. It will blow up in your face one day.

I don’t use GlobalMultiUse classes for my jnsk-subs/functions. Instead I use plain old code modules. The reason for this is that I’ve had strange problems with GlobalMultiUse classes in configured components and when you have had a problem, you don’t forget it for a long time, right? The problem might have been solved ages ago, but better safe than sorry. (I’m not the only one to having had those problems, by the way. There are every now and then discussions about this in the COM+ newsgroups.)

There was an often-discussed problem in COM+ Component Services version 1, where the error object was emptied when the root object called a second object, the second object and root object both called SetAbort. This problem is solved with Windows 2000 SP1 (and it wasn’t there in the first place in MTS). If you like to use this code structure in COM+ before the SP1, then you have to skip the SetAbort in the secondary object. But do then remember that you shouldn’t use that object (at least not the same method), as a primary object.

In my latest article at VB2TheMax An error that must be trapped I said that if you disable JITA, you won’t get Activate/Deactivate for the ObjectControl-interface. This can be a reason for using GetObjectContext() everywhere instead of keeping a module-global mobjCtx as I do in my proposal above.

As usual with my articles, most of the stuff is also relevant if you use NT4 and MTS.

SUMMARY

In this article I have shown you my ordinary code structure for COM+ components. Hopefully there was an idea or two for you to adopt. Next time I will discuss Assertions and hopefully give you a few new tips on how to use it, we’ll see.

Finally, perhaps you are wondering how the re-papering of the room went? Well, it’s finished any month now.



Jimmy Nilsson is the owner of the Swedish consultant company JNSK AB (www.jnsk.se). He has been working with system development since late 1988 (with VB since version 1.0) and, in recent years, he has specialized in component-based development, mostly in the Microsoft environment. He has also been developing and presenting courses in database design, object-oriented design, etc. at a Swedish University for six years. Jimmy is the author of ".NET Enterprise Design with Visual Basic .NET and SQL Server 2000" and he often speaks at VSLive conferences.
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date