A Portion of Buff

Everybody else had one, so...

April 2003 - Posts

What's that, Skip?

Someone needs XP

(OK, so that's a little glib, but reading through Brad's description of where it hurts, the voices in my head were screaming "Agile! Agile!").

Macro-economics

After seeing this macro for VB.Net, I thought I'd be clever and adapt it for C#. Then I saw this, so I needn't have bothered, but my version handles a slightly different format, so if you write your private fields like so:

SomeType foo; //_foo is OK as well - it will strip the leading underscore for the public name

it will create properties of the form:

public TypeName Foo 
{
get { return foo; }
set { foo = value; }
}
It's a bit buggy (it will try to create properties from public fields and output invalid code, and doesn't match the indentation of the private fields), but someone might find it useful:

Imports EnvDTE
Imports System.Diagnostics
Imports System.Text.RegularExpressions
Public Module ConvertToProperties
    Sub Run()

        DTE.UndoContext.Open("ConvertToProperties")

        Try
            Dim text As TextSelection = DTE.ActiveDocument.Selection
            Dim line As String
            Dim lines() As String = Split(text.Text, vbLf)
            Dim match As Match

            Dim r As Regex = New Regex("\s*(?(private|protected)*)\s*(?\S*)\s*(?\S*)", RegexOptions.IgnoreCase Or RegexOptions.IgnoreCase.ExplicitCapture)

            text.Insert(vbCrLf, vsInsertFlags.vsInsertFlagsInsertAtEnd)

            For Each line In lines
                line = line.Trim
                If Not line = "" Then
                    match = r.Match(line)
                    If match.Success Then
                        CreateProperty(text, line, match)
                    End If
                End If
            Next

            text.SmartFormat()

        Catch ex As System.Exception

            MsgBox("There was an error while constructing Property code: " & ex.ToString & ".", MsgBoxStyle.Critical, "ConvertProperties")

        End Try

        DTE.UndoContext.Close()

    End Sub
    Sub CreateProperty(ByVal text As TextSelection, ByVal line As String, ByVal match As Match)

        Dim fieldName As String
        Dim strippedVariableName As String
        Dim publicName As String
        Dim typeName As String
        Dim startChars As Char = ("_")
        Dim endChars As Char = (";")

        fieldName = match.Groups("fieldName").Value.Trim
        fieldName = fieldName.TrimEnd(endChars)

        strippedVariableName = fieldName.TrimStart(startChars)

        typeName = match.Groups("typeName").Value.Trim
        publicName = strippedVariableName.Substring(0, 1).ToUpper & strippedVariableName.Substring(1)

        WriteProperty(text, fieldName, typeName, publicName)

    End Sub
    Sub WriteProperty(ByVal text As TextSelection, ByVal fieldName As String, ByVal typeName As String, ByVal publicName As String)

        Dim propertyText As String = String.Format("public {0} {1}" _
                                                        & "{3}{{{3}" _
                                                        & "    get {{ return {2}; }}{3}" _
                                                        & "    set {{ {2} = value; }}{3}" _
                                                        & "}}{3}", _
                                                        typeName, _
                                                        publicName, _
                                                        fieldName, _
                                                        vbCrLf)

        text.Insert(vbCrLf & propertyText, vsInsertFlags.vsInsertFlagsInsertAtEnd)

    End Sub
End Module

Do, or do not. There is no try

Keith writes:

"I believe that it is not possible to ‘Do your best’ when it comes to developing an application. I think this because as developers we are constantly evolving in our skill sets. Even within the scope of a small, say 4-6 week project; we have learned things by the end of the 6 weeks that make us better than when we started. Thus, to do our best we would need to re-code the things done at the project outset and then at the end of the re-write we would once again be in the same boat."

 

Some random thoughts in response:

I think "your best" is the wrong metric by which to judge performance.  You don't need to do your best, you need to get your code accepted by the customer.  As long as refactoring your code helps you pass their tests more quickly, with less effort, and more reliably, then keep refactoring it, but when you reach a point where the changes to your code have little or no impact on your application's ability to pass its tests, stop.

Also, why wait until the end of the project to rewrite your software?  Continuous refactoring (test, code, refactor, test, code, refactor...) allows you to instantly apply the things you have learned as you code, not six weeks later.  It's not as if you'll get to the end of the project and suddenly become aware of all the things you have learned, so why not (with the above caveat) apply that knowledge immediately?

And if your customer is judging the quality of your software solely on the effort put into it, or your skill as a developer, well...I don't have an answer for that :-)

Cheers.

Losing my precision

A colleague of mine ran into an issue with NUnit today.  He was comparing a decimal value returned from a database query with the expected value, and couldn't figure out why his assertion kept failing, even though he was sure both values were equal.  We looked a bit closer and saw that the expected value was 20, but the returned value was 20.0000.  If you call Decimal.Equals() on those two values, it will return true, because it ignores trailing zeros.  NUnit, however, calls ToString() on numeric types before it compares them, so the comparison obviously fails.

This brought up another question: why is there no method on Decimal to compare both the value and the precision of two decimal numbers?  In Java, the BigDecimal class provides for it with the CompareTo() method, but Decimal.CompareTo() in .Net behaves pretty much the same as Equals().  Surely in some cases 20 should not be considered equal to 20.0000?

The only way I can see to compare value and precision is by calling Decimal.GetBits() with both values, and stepping through the two arrays.

Interesting, n'est-ce pas?

Think outside the box

Greg writes:

"Standard, out of the box .NET collections store references of type System.Object. We have a structure that we add to a collection. We add approx 2500 structure types to this collection.

Well, duh, if we are adding a structure, which is a value type, to a collection, which stores a reference type, the structure will get boxed and allocated on the heap 2500+ times! Its like creating a reference type 2500+ times!

Solution: use a reference type (class) vs. a structure in this case."

No no no!!  Changing your struct into a class is a cop-out.  You'll still be creating 2,500 references, and losing the benefits of value types (of course, that's assuming you really want a value type in this case).

The solution to the boxing/collection issue is to create a strongly-typed collection using an underlying store of the same type as the objects you are storing.  If you want a vector-type collection for storing Int32's, you would base it on an Int32[] array, for example.  There are several tools that can help you with this, including Collection Gen and whatever this thing's called.

Roll on generics.

CruiseControl.Net

CruiseControl.Net is now on SourceForge. Documentation is still a bit lacking, and there are a few problems building it on VS.Net 2003 (oh God, I'm a VS.Net user - now I'll have to take this back...), but at least the source is out there now. I know there are a few people on this site looking at continuous integration and build tools, so I thought I'd give you a heads up. (For those who don't know what Cruise Control or continuous integration is, look here and here).

 

More Posts