Friday, September 02, 2011

Raising Our J-Score

I follow Joel Spolsky's Blog, which I find very useful and pithy.  Joel is a former Microsoft programmer, now CEO and programmer.  Joel published a blog way back in the Halcyon Days of 2000 entitled "The Joel Test: 12 Steps to Better Code"

So how do we stack up?


The Joel Test
1.  Do you use source control?
     Not yet.  We make file-system copies.  Our score:  0
2.  Can you make a build in one step?
     Depends.  My code is usually a yes, others, not a chance. Our score is a generous  .5
3.  Do you make daily builds?
     Not really.  Our score:  0
4.  Do you have a bug database?
     Nope  Our score: 0
5.  Do you fix bugs before writing new code?
     We try, but without a bug database, it's often hard to tell. I'm going to be very generous and say yes.  Our score 1.
6.  Do you have an up-to-date schedule?
      What's a schedule?  Our score:  0
7.  Do you have a spec?
     Real programmers don't need no stinkin' specs! That's a no, by the way.  Our score: 0
8.  Do programmers have quiet working conditions?
     What did you say?  It's too noisy in here!  Our score: 0
9   Do you use the best tools money can buy?
     Mostly.  Being a state agency, buying anything is challenging.   I'll say "yes".  Our score: 1
10 Do you have testers?
     Do programmers and users count?  No?  Then no.  The only thing harder than buying stuff is hiring people.  Our score:  0
11.  Do new candidates write code during their interview?
      Nope.  Our score: 0 
12.  Do you do hallway usability testing?
       No.  Our score:  0

Joel says "A score of 12 is perfect, 11 is tolerable, but 10 or lower and you've got serious problems. The truth is that most software organizations are running with a score of 2 or 3, and they need serious help, because companies like Microsoft run at 12 full-time. "

We scored a pathetic 2.5.  But there's hope!  I spend some time today investigating source control, and am confident that we will, kinda, sorta, start using it soon.  We're going with Mercurial , an open source distributed source control management tool.

If you've not looked at it, it is a command-line code repository.  If you are not using source control at all, look at this tutorialthis blog post, and this tutorial.  These sites will bring you up to speed.

Next in my sites, bug tracking!

That's Generic!

So you are creating a small config file and think "Gee, it would be nice to use the auto-serialization feature of  dot net"

So you wrap the serialization and deserialization routines as shared (static for you c# guys) functions, and throw a  _ in front of your class, and viola!

But, what if you are doing two, three, 48, 72 small serializable objects?  Ah, the power of object orientation!  Yes folks, object orientation makes this cake.  I created an abstract base class which contains the code I need to repeat for each small class.


Imports System.IO
Imports System.Xml.Serialization

Public Class AbstractSerialzationClass(Of t)
    Private Shared _ErrorOccured As Boolean = False
    Private Shared _ErrorText As String = ""
    Shared Function Deserialize(ByRef anObject As t, _
ByVal FileNameString As String) As Boolean

        _ErrorOccured = False
        If File.Exists(FileNameString) Then
            Try
                Dim aStreamReader As New StreamReader(FileNameString)
                Dim x As New XmlSerializer(anObject.GetType)
                anObject = CType(x.Deserialize(aStreamReader), t)
                aStreamReader.Close()
            Catch ex As Exception
                _ErrorOccured = True
                _ErrorText = "Unable to deserialze '" & FileNameString & "'." & ex.Message
            End Try
        Else
            _ErrorOccured = True
            _ErrorText = "XML File -'" & FileNameString & "' was not found"
        End If
        Return _ErrorOccured
    End Function
    Shared Sub Serialize(ByVal FileNameString As String, ByVal InObject As t)
        _ErrorOccured = False
        If File.Exists(FileNameString) Then
            If File.Exists(FileNameString & ".old") Then
                File.Delete(FileNameString & ".old")
            End If
            File.Copy(FileNameString, FileNameString & ".old")
            File.Delete(FileNameString)
        End If
        Try
            Dim aStreamWriter As New StreamWriter(FileNameString)
            Dim x As New XmlSerializer(InObject.GetType)
            x.Serialize(aStreamWriter, InObject)
            aStreamWriter.Close()
        Catch ex As Exception
            _ErrorText = "Unable to Serialze Annotation object to file named '" & FileNameString & "'.  " & ex.ToString
            _ErrorOccured = True
        End Try
    End Sub
    Public ReadOnly Property ErrorOccured() As Boolean
        Get
            Return _ErrorOccured
        End Get
    End Property
    Public ReadOnly Property ErrorText() As String
        Get
            Return _ErrorText
        End Get
    End Property
End Class


Now to use this in a class, all I've got to do is this

 Public Class foo
    Inherits AbstractSerialzationClass(Of foo)
end Class


Much neater!

Thursday, August 11, 2011

What's Different?

What's Different?

Remember the kids puzzles which asked you to spot the differences?  They were fun but also frustrating. I remember straring at a picture saying "WHAT'S DIFFERENT!"

How does this pertain to development? Well, we don't use an automated source code versioning system here at work (I know, we should). Instead, we make copies of each version of the program. So I will have a folder for each version of the code.  Sometimes, we accidentally use the wrong folder, and that makes my life resembles these puzzles.  I am puzzling  out what changed, when and why.

We have some command-line tools to compare folders, but that only reveals files that have changed.  We then have to load the files and do a file comparison with them.  Can we say tedious and time consuming?

That tedium was ended the day I found K-diff.  K-Diff is a really useful tool that can compare two folders and display all of the differences for you.  It highlights the files which have change, and double-clicking them brings up the files side-by-side for easy comparison.  It makes comparing differences easier and quicker.  It has made my life much easier.

You can find K-Diff here at http://kdiff3.sourceforge.net/  It's open source and is available for Windows, Linux, Unix, Mac and anything (in theory) that supports the qt libraries.

Wednesday, August 03, 2011

Saturday, July 09, 2011

Too Cool no really it is

     Most of my posts are very code-specific.  This one isn't.  This one is more on development philosophy.

     I ordered a pizza from Papa Johns online.  Being the geek I am, I have an established account in which I have specified my address, phone number, and which store is my local store.  I design the perfect pizza, and click order, and WAM.  The too-cool technology of IP address geo-location kicks in and bites my butt.

     It seems that in an effort to better serve their customers, Papa Johns looked at the physical location of my IP address and.determined the city from which  I was accessing the web page  Problem is that my ISP is out of Hurricane, about twenty minutes away from here on the Interstate, and that is where Papa Johns thought I was located.

They HAD my address on file.  THEY KNEW WHAT STORE I ALWAYS ORDER FROM.  But they were" helpful" and placed the order with the store a half-an-hour away, instead the store which is located less than two minutes from my house.

I had to call the distant store and cancel the order.  While the pizzas where in the oven, The manager was very nice, the order was canceled and everyone is happy.


I'll give you another example.  I automated order entry for certain preprinted applications which print with the birth certificate.  The application has an ID number which links it to our master birth file. 

The automation saves staff time and makes us more efficient.  My probelm was that the address mom gave on the birth certificate may or may not be the one included on the application.  She may have moved since the birth occurred and our staff wasn't double checking the address.  A significant number of orders were returned to us as undelivered.  This was bad customer service and consumed additional staff time to corret the mistakes.

One last example.  On my phone, I have a feature that auto-corrects words that are misspelled when typing a text message with the on-screen keyboard.  More than one of my Facebook updates didn't make much sense because the software 'helped' me when it didn't need to.
 
Microsoft is bad for this type of problem.  Every try to put a asterisk in a Microsoft Word document?  Auto-changes it to a bullet.


These stories illiterate a design principle that programmers should consider. Sometimes, you don't know what you think you know.  Automated data capture/data entry can save time but there are gotcha's you have to keep in mind.  Just remember, just because it's possible to automate something it doesn't mean that it is a wise idea to do so.


  • The data you think you know, you may not know.  It may be stale, or just wrong.
  • .The data may be correct, but you're measuring the wrong thing.  The location of my IP was correct, but the location was the location of my ISP, not my home.
  • The time you save by automation may be consumed quickly by the mistakes such automation breeds.


Sometimes in our rush to make software easier to use, we actually make it less useful by making the user have to fight our programs.

Saturday, June 18, 2011

Windows Event Log by Visual Basic 2008

We've been experiencing Delayed Write Errors, which result in a loss of data.  In an effort to provide enough data points for our IT section to determine the problem, I needed to extract from the Window's Event Log all logged events.


For those who may not know, the Event Log is a system managed place in which the system logs certain events that users may use to diagnose problems.  It only took a few minutes on Google to pick up enough pieces to do what I needed.


Everything we need is found in the System.Diagnostics namespace.


Imports System.Diagnostics


Module Module1


    Sub Main()
        'Here we create an EventLog object
        Dim a As New EventLog
        Dim z As Long
        'This creates a streamwriter through which we will
        'write the log data.
        Dim myOut As New System.IO.StreamWriter("delayed.txt")
        'This is which of the EventLogs we are accessing 
        a.Log = "System"
        'We have to specify the machine name
        a.MachineName = My.Computer.Name

       '----------------------------------------
       '       the good stuff
       '       We iterate through each event log entry,
       '       looking for the word "delayed".  If we
       '       find it, we write out the entry.
       '------------------------------------------
        For Each entry As EventLogEntry In a.Entries
            z += 1
           
            If entry.Message.ToLower.Contains("delayed") Then
                myOut.WriteLine(entry.TimeGenerated & "," & entry.Message & "," & entry.MachineName)
                Console.WriteLine(entry.Message)
            Else
                If z Mod 100 = 0 Then
                    Console.Write(".")
                End If
            End If


        Next
        myOut.Close()


    End Sub


End Module

Friday, June 17, 2011

more RegEx

The more I use Regular Expressions, the more I rely upon the ease of use they provide in pattern matching in real, everyday work.
Want to match a date at the start of a line?  try

^\d*/\d*/\d* \d*:\d*:\d* [A|P]M
The ^ means the start of a line.
The \d matches all numbers
The [A|P] matches to either "A" or "P" as in AM/PM.
The rest are just string literals.

I was needing to clean a log file I extracted from the Windows Event log to report a problem to our IT support staff.
I had several hundred line s like
The description for Event ID '1073741850' in Source 'Application Popup' cannot be found.  The local computer may not have the necessary registry information or message DLL files to display the message, or you may not have permission to access them.
Where each ID was different.  Solution?  RegEx and Repetition!
I used this as my search query.
The description for Event ID '\d*' in Source 'Application Popup' cannot be found.  The local computer may not have the necessary registry information or message DLL files to display the message, or you may not have permission to access them.  The following information is part of the event:
The \d is, of course, the shorthand meaning "numeric information."  this is the same as the expression [0-9$.,]
* says "repeat the last search term 0 or more times.