Hidden Coupling in .NET Applications


This post deals with ways we couple applications and components together without realizing it. In this post, I will focus on a couple of things to watch out for and provide a couple of design hints to avoid coupling.

Coupling through objects

One way we couple is through the objects we use. You do not find this as much in the SOA world, as the objects passed are attached to the service, via the definitions in the WSDL. You are then free to change the underlying objects, as long as the public interface does not change. This is not completely true, as you can adorn objects in WCF, which makes the interface less immutable, but the basic rule holds true. Anything published should remain the same, at least on that service call (or until you can completely deprecate the method).

But there are instances where one writes a custom method of talking to an application. While this is not extremely common in .NET, I have seen it in some vendor solutions we have. On this public interface, you require an object to be passed. And, if not set up correctly, you not only expect an object, but you expect the object from the 2.04.56.2375 assembly version. Ouch!

The easiest way to avoid this is already covered in paragraph one of this section. Use a web service of some type (ASMX, WCF, etc.) to hide the actual object type. This forces the user to create his own implementation of the object, but you can supply that library. In many cases, the client object does not require all of the FUD in the server object, so this is sane.

Coupling Through Config

This one is a dual edged sword, as there are certainly instances where pulling directly from configuration is acceptable. Microsoft, itself, has many objects that are coded to pull directly from configuration. I have found that this idea limits the usefulness of the objects, but the objects are designed for web applications, so it is okay. I would still argue it is better to pass information to the objects and make them stupid.

In the case of Microsoft, the majority of the objects pulling directly from configuration use common bits of information, like a connection string or a part of the configuration that is automatically created for you when you first create a site. These items are less likely to cause a problem.

But let’s consider a “what if” scenario. It is a real one, as I just got bit by it. Suppose you needed to send a message to a service and you got back this error.

Object reference not set to an instance of an object.
Source: COMPANY.BRAND.Protocol
Stack Trace: 
   at COMPANY.BRAND.Messaging.Message.AddToDispatchQueue(IPAddress ip_address, Int32 port, String device_address, Int32 timeout, Int32 retry_count, Boolean cancel_on_retry_limit, Boolean duplicate_check, Boolean halt, DispatchMode mode) in P:\BRAND\Matchbox\trunk\lib\Protocol\Messaging\Message.cs:line 148
   at _Default.Button1_Click(Object sender, EventArgs e) in d:\projects\websites\ColoTest\Default.aspx.cs:line 37

Buried deep in the code base is an object reference. This could well be a problem with any number of object calls. Proper troubleshooting says look at the source code. But, what if you don’t have source?

Next step would be to look at the help documentation, but what if there is none?

You can also go to pulling out Reflector and examining the source. As a last ditch, you could examine the DLL in an editor and find the IL.

In this case, I decided to copy the entire configuration file from a working website to this test application. Sure enough, things started working. Thinking it through, it is a call to a database table that is the issue. The code probably looks something like this:

SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["GatewayConnectionString"].ConnectionString);

Instrumentation and Logging

This is a broad topic, as there are a bunch of ways to skin this cat. In anything you develop, there should be a way of examining the system to see what it is doing. This includes both metrics (how many messages are traveling through each second, for example) and the ability to trace whether messages are going through correctly.

One of the easiest ways to instrument is to make sure all messages are stored someone so they can be looked at. This can be individual files or in a log file. It can also be in some other persistent store. If you are using a storage mechanism, you better make it configurable so you can shut it off. As an illustration of why this is important, examine the following log folder. These are logs for a single unit communicating to this backend:

 logs

Yes, that is on the nature of 11 MB of information, per day, that nobody is likely to ever look at. In this case, it is not that bad, as the system is still in test. But if this were a production system, it would produce files more to the tune of 35 MB of raw data, 23 MB in messages, 3 MB of warnings (not sure why these were never ferreted out) and ? MB of subscription messages. This is fine for development and testing, but ridiculous for a production system.

Summary

Be careful where you place your calls to config. As much as possible, try to feed the objects rather than have them pull from the system silently. In addition to making errors easier to spot, this one tip makes for a more testable system, as you can send a mock in for that particular object in your test harness. And you know how I love unit tests. Open-mouthed

You should also make sure separate systems talk to each other in messages. If there are objects, they should be defined in the contract and not tied to a physical implementation of a particular library, as you may end up with versioning issues. As mentioned, WCF and ASMX both solve this problem.

Finally, make sure you have a way to find information about your system. While the focus, for most, is on finding problems, there is a good reason for knowing what is happening when everything is going right.

Peace and Grace,
Greg

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: