OdeToCode IC Logo

Overflow Exceptions

Thursday, October 11, 2007 by scott

WWWTC #18 highlights the fact that integer overflow detection is ON by default for Visual Basic projects. To change the behavior, you need to go to into the project properties -> Compile -> Advanced Compile Options and click the "Remove Integer Overflow Checks".

In C# projects, overflow detection is OFF by default. To change the behavior, you need to go into the project properties -> Build -> Advanced and select the "Check for arithmetic overflow/underflow" check box.

Changing the C# project settings is one solution to making the unit test in WWWTC #18 pass.

There is another option, too. Use the checked keyword in C#, as Johnathan, Jason, Ronin, and Dave pointed out.

public int AddQuantity(int additionalQuantity)
{
    
// .. some logic

    return checked(_quantity += additionalQuantity);
}

Or …

public int AddQuantity(int additionalQuantity)
{
    
// .. some logic

    checked
    {
        
return _quantity += additionalQuantity;
    }
}

There are a number of other subtleties to overflow detection – try some experiments with floating point and decimal data types to see what I mean, or jump to this article on the The Code Project: Arithmetic Overflow Checking using checked / unchecked.

October Is Scary Schema Month

Wednesday, October 10, 2007 by scott

Ayende kicked the month off with "Schema to wince by…", then "CRM Horror".

Great timing, Ayende! With Halloween right around the corner, let's make October scary schema month!

Here is one that recently made my hair stand on end:

ALTER TABLE [dbo].[EmergencyPatientAssesments]
   
ADD CONSTRAINT [mspk550470] PRIMARY KEY CLUSTERED
(
   
[BaseID] ASC,
   
[PatientVisitID] ASC,
   
[TreatmentID] ASC,
   
[DateTime] ASC,
   
[ActualDateTime] ASC,
   
[AssessmentSequenceID] ASC,
   
[QuestionID] ASC
) ON [PRIMARY]

This healthcare schema defines a composite primary key using 5 varchar fields and 2 datetime fields. If you think the index is scary, you should see the joins…

Do you have a scary schema to share?

What's Wrong With This Code (#18)

Tuesday, October 9, 2007 by scott

Here is another golden oldie:

Numeric overflows are a type of software bug that occur when a calculation produces a result that doesn't fit in the intended storage location. One of the most famous cases of an overflow bug is the overflow bug that destroyed an Ariane 5 rocket in 1996*.

Fortunately, .NET has a dedicated exception to highlight overflow problems. Just run the following VB code and watch the OverflowException appear.

Dim i As Integer
i += Integer.MaxValue
i +=
Integer.MaxValue

So, given this class:

public class LineItem
{
    
private int _quantity;
    
public int Quantity
    {
        
get { return _quantity; }
    }

    
public int AddQuantity(int additionalQuantity)
    {
        
// some logic ...
        return _quantity += additionalQuantity;
    }

    
// other stuff...
}

Why does the following unit test fail?

[TestFixture]
public class LineItemTest
{
    [
Test]
    [
ExpectedException(typeof(OverflowException))]
    
public void TestForOverflow()
    {
        
LineItem lineItem = new LineItem();
        lineItem.AddQuantity(
Int32.MaxValue);
        lineItem.AddQuantity(
Int32.MaxValue);
    }
}

What options are available to fix the problem?

* The article Design By Contract: The Lessons Of Ariane says the real error was a "reuse specification error". Quote: "To attempt to reuse software without Eiffel-like assertions is to invite failures of potentially disastrous consequences".

A 30-Second Introduction to IPv6

Monday, October 8, 2007 by scott

IPv4 is hanging around for the near future, but I took a few minutes to find out what all the IPv6 hexadecimal gobbledygook is about when I type ipconfig in Vista.

Tunnel adapter Local Area Connection* 16:
Connection-specific DNS Suffix . :
IPv6 Address. . . . . . . . . . . : 2001:0:4136:e390:3094:8f8:e755:e2d
Link-local IPv6 Address . . . . . : fe80::3094:8f8:e755:e2d%33
Default Gateway . . . . . . . . . : ::

There are a few limitations in IPv4, the most notable being a 32-bit address space. The free pool of IPv4 addresses is nearly empty. IPv6 addresses are 128 bits wide (the same size as a GUID), and provide a mind-numbingly huge address space. TCPGuide.com says:

If we had been assigning IPv6 addresses at a rate of 1 billion per second since the earth was formed, we would have by now used up less than one trillionth of the address space.

Wikipedia explains the :: notation seen in the output above:

IPv6 addresses are normally written as eight groups of four hexadecimal digits. For example, 2001:0db8:85a3:08d3:1319:8a2e:0370:7334 is a valid IPv6 address. If one or more four-digit group(s) is 0000, the zeros may be omitted and replaced with two colons(::). For example, 2001:0db8:0000:0000:0000:0000:1428:57ab can be shortened to 2001:0db8::1428:57ab.

And Microsoft's IPv6 FAQ explains the % symbol:

Link-local addresses are reused on each link. ... Because of this address reuse capability, link-local and site-local addresses are ambiguous. To specify which link on which the destination is located or within which site the destination is located, an additional identifier is needed. This additional identifier is a zone identifier (ID), also known as a scope ID ... The syntax specified in RFC 4007 for identifying the zone associated with a link-local or site-local address is Address%zone_ID.

Now I know what the output means, but I don't know if I'll ever be able to remember a v6 address like I can remember v4 address. At least the loopback address (::1 in v6) will be less typing than its v4 counterpart (127.0.0.1).

Joe Albahari's LINQPad and LINQPad Challenge

Thursday, October 4, 2007 by scott

JoeA's LINQPad is an indispensible tool for LINQ development.

Write a query expression and view the results, the generated SQL, and the extension method / lambda equivalent. Works for both C# and VB!

Joe also dares developers to take the LINQPAd challenge:

  1. Locate the shortcut for SQL Management Studio on your Start Menu and move it some place else.
  2. In its place, insert a shortcut to LINQPad.
  3. For the next week, perform all your ad-hoc SQL queries using only LINQPad.

Teachers say language immersion is highly effective when learning a new language. I'm sure the LINQPad challenge is a worthwhile endeavor to learn the subtleties of LINQ.

Killing Software Projects with Modal Verbs

Tuesday, October 2, 2007 by scott

Modal verbs are the words that express a degree of certainty, like: may, can, will, shall, must. You see them in RFCs all the time:

1. MUST This word, or the terms "REQUIRED" or "SHALL", mean that the definition is an absolute requirement of the specification.

In the old days, software analysts would descend from mountain peaks with reams and reams of software requirements arranged in three-ringed binders. These requirements also came with words like "must" and "may". After a couple months, developers would repurpose the binders as doorstops and monitor risers. 

The days of thick binders are over, thank goodness, and the days of more frequent face-to-face communications are here. The communication has to be obvious and lucid in order to work, however. Analysts were good at using the "proper" language to shape results. The same decisiveness has to come across in today's whiteboard and water cooler discussions.

What the tech lead says: You may want to possibly refactor that class.

What the junior developer hears: The code is gold!

I've been in conversations where the words "may", "maybe", "perhaps", and "might" dominate the discussion. These discussions are never productive, and make a leader or expert appear indecisive and unconfident.

From Hacknot:

A Technical Lead lacking in self-confidence can be a major frustration to their team. They may find themselves waiting on the Lead to make decisions that significantly effect their work, but find that there is some reticence or unwillingness to make a firm decision. Particularly when new in the role, some Technical Leads find it difficult to make decisions in a timely manner, for they are paralyzed by the fear of making that decision incorrectly. Troubled that a bad decision will make them look foolish, they vacillate endlessly between the alternatives, while their team mates are standing by wondering when they are going to be able to move forward.

You could substitute "domain expert", "product manager", or "stakeholder" for "technical lead" and the paragraph still makes sense. Many times the problem isn't timely decision making but ineffective communication. Maybe that's just the individual's personality. Perhaps they are just being politically correct or may be timid.

What the stakeholder says: The last change we might want to possibly make is to change this screen to maybe make the buttons stand out a little more.

What the developers hear: We are done! Ship party!

It's perfectly fine to be an expert and say "I don't know", or "this requires some research", but when possible you need to paint the world in shades of black and white to keep a team moving towards the goal.

You must make decisions.

You must clearly communicate those decisions.

Silverlight Event Tokens

Thursday, September 27, 2007 by scott

Events are easy to add and remove when using the CLR and C#. Just sprinkle some += and -= in the right places and the runtime does the rest. Silverlight programming with JavaScript is a bit different, however, and although the addEventListener and removeEventListener appear similar to a DOM element's event registration APIs, these two methods have a twist.

As an example, let's say we wanted to listen to the MediaElement's BufferingProgressChanged event, but we want to stop listening once buffering has exceeded 50%. The following code does work:

function onLoad(rootElement)
{
    
var mediaElement = rootElement.findName("_media");
    mediaElement.addEventListener(
"BufferingProgressChanged",
                                  
"onBufferProgress");
}

function onBufferProgress(sender, eventArgs)
{      
    
// .. do something

    if(sender.BufferingProgress > 0.50)
    {
        sender.removeEventListener(
"BufferingProgressChanged",
                                    
"onBufferProgress");
    }
}

.. but this code will never unsubscribe from the event:

function onLoad(rootElement)
{
    
var mediaElement = rootElement.findName("_media");
    mediaElement.addEventListener(
"BufferingProgressChanged",
                                   onBufferProgress);
}

function onBufferProgress(sender, eventArgs)
{      
    
// .. do something

    if(sender.BufferingProgress > 0.50)
    {
        sender.removeEventListener(
"BufferingProgressChanged",
                                    onBufferProgress);
    }
}

When not using a quoted string to specify the event handler, you have to save the value returned from addEventListener. The return value is a token that is "just an integer value to track the order in which handlers were added for each object-event combination" (read MSDN for other subtleties in the event registration methods).

A proper unsubscribe looks like the following:

var token;

function onLoad(rootElement)
{
    
var mediaElement = rootElement.findName("_media");
    token = mediaElement.addEventListener(
                          
"BufferingProgressChanged",
                           onBufferProgress);
}

function onBufferProgress(sender, eventArgs)
{      
    
// .. do something

    if(sender.BufferingProgress > 0.50)
    {
        sender.removeEventListener(
"BufferingProgressChanged",
                                    token);
    }
}