Home

t3knomanser's Fustian Deposits

More drek than you can pull from an elephant's arse.

How Random Babbling Becomes Corporate Policy

IOCCC Original Winner

Mad science gone horribly, horribly wrong(or right).

October 13th, 2009

"Breathtaking" code

Add to Memories Tell a Friend
IOCCC Original Winner
Words like "breathtaking", "stunning", "astounding", "amazing", and "incredible" are not positive words. Oh, they're often used in a positive context, but in reality, they only convey a sense of wonder and disbelief. They can be applied to something horrifying just as easily as something delightful.

Such has been my experience over the past few days.

Once upon a time, some fragment of the giant behemoth I work for needed an application to manage some inventory tracking and similar tasks. They found an external contractor that would make it for them. In that era, the app was built in VB6 with an MS Access back end. Horrible, yes, but hey, it was the 90s.

Well, now it's time to upgrade. So they go back to the same contractor. "Hey, we want it to be .NET and use SQL Server. Here's a check."

Well, it wasn't that easy, of course. There are policies. Checkpoints. Oversight. I was part of the oversight, and my job was to get the application through our "gates". Since this was a purchased application, we didn't care if it was terribly well designed, so long as it worked. We weren't going to have to maintain it. So we got some design diagrams from the contractor, sanity checked them, and then called it a day.

More fool I.

Last week, I hear, "Hey, that application- they're not satisfied with the support from the vendor. They want to bring it internal. Hey, Remy, find out what you need to do to make it fit with our standards."

Now, when we develop an app internally, or have a contractor develop an app that we intend to support, the auditing requirements are much stricter. We don't care if an outside vendor has to suffer under horrible support issues, but if we're wasting time on stupid support work, we're unhappy.

So, the first step then, would be to audit the application via a code review. I sat down in a room with three other developers, we pulled up the code, and we started skimming through it.

It was breathtaking.

The first, most glaring thing, was that the actual design and the provided diagram had no relationship to each other. That didn't bode well. And it was all downhill from there. As a sampling of some of the amazing things we saw:
  • One window in the application has all of the business and data access code bundled up in it. It's like they took all the functions and dumped them into a bucket.
  • But not all functions. For example, when that main window wants to log an error message, it calls out to a class called "Utility". When it does that, the Utility class makes a call against the main window. Not only is the code just a disorganized pile in a big bucket, but sometimes the bucket says, "Hey, you gotta go look in another bucket to find that!" and when you do, the other bucket says, "Nope, it's actually back out in the original bucket."
  • All of the database access stuff is hard coded strings. With no SQL injection protections.
  • It stores passwords in plaintext
  • The most stunning thing, however, is what the application does every time it launches. Every time the application launches, it attempts to add columns to a bunch of tables. If those columns already exist, this would cause an error, so it just ignores the errors. Since, once the app has run once, the columns will exist, that means every time a user runs the app, it's trying to add columns to tables for no damn reason.
There's more, but I won't bore you with the details. I wrote a 2,200 word code review document. Normally, these documents follow this form: "File X, Line 128, variable strFoo should be named foo, we don't use Hungarian Notation." For even large projects, they don't tend to get that long, just because they're so terse. This, this was a 5 page essay. I couldn't even call out flaws by line numbers, just because the developer was so clearly incompetent. I've dealt with some bad code in my day, but this is just special.

There's a punchline. They started development using .NET 1.x, and then partway through switched to .NET 2.0. In .NET 1.x, there was no built in FTP functionality. If you wanted to do FTP, you needed to write your own class to do it, or steal some. Microsoft's developer documentation site, MSDN, had an MSFTP code sample, which demonstrated how one could implement their own FTP code. The developer copypasted this- despite the fact that .NET 2.0 had all the functions he needed- and included a class called "MSFTP" in his project.

He couldn't just use the class as it was, however. There were some quirks in our FTP server it didn't handle. And while he was at it, he added a "Dispose" method to handle cleanup, replacing Microsoft's use of the "Finalize" method. This is actually a good .NET technique for technical reasons that are irrelevant here, so he obviously read a book. He didn't read it closely enough, because his Dispose is actually implemented wrong, but that's neither here nor there.

In the comment above his "Dispose" method, he had the gall to include this:
'M$ should have implemented this. Man, this code is sloppy.

When I read that, I just started cracking up.

Until I saw how much my company paid for this. And then I started crying.

April 25th, 2009

I love functional programming. I'm going to present on doing FP in VB.Net in August- this is a feature new to .NET 3.5. I was very excited about the ability to do functional programming in VB.Net. And some of the key features I really wanted, currying and closures, are there.

But the limitations... they almost make it not worth the trouble. Most obviously, VB.Net doesn't support true lambdas. In a true lambda environment, I could do something like this:
f = Function(x as integer) if (x % 2 = 0) then return x / 2 else ... some other code ...
In true lambdas, you can put any code you like inside of your function. C# and F# allow this. VB.Net does not- VB.Net only allows expressions (you can't do ifs or loops or anything like that).

Still, there's a lot you can do with expressions, so that's not too bad. Since you get closures, you can work around that without too much trouble.

But then you start running into the bizarre things. I wanted to do a patterned call. In many functional languages, you can create functions like this: f(1) = 1; f(2) = 2; f(x) = f(x - 1) + f(x - 2);. Calling f(13) will print out the 13th number it the Fibonacci sequence.

Now, I accept that VB.Net wouldn't have an architecture like that built in- it's a somewhat obscure functional trick. But I was hoping I could roll my own. My first attempt at it was to come up with a compiler macro- oops! VB.Net doesn't support pre-proccesor macros. C# does, of course.

Well, okay, what about Attributes? .NET has the ability to define metadata on code, that you can "reflect" on to change runtime behavior. I could do something like this:
Module 1
  '"fib" is the function name, the second parameter is the pattern- if it returns true, execute this
  'operation, otherwise, go find another operation named "fib" to execute.
  <PatternedFunction("fib",function(x as Integer) x = 1 or x = 2)> Function f1(x as Integer)
    Return x
  End Function

  <PatternedFunction("fib",function(x as Integer) true)> Function f2(x as Integer)
    Return PatternedCall("fib")(x - 1) + PatternedCall("fib")(x - 2)
  End Function
End Module


Not as concise as I would like, but hey, it works, right? Wrong. Turns out, since Attributes are evaluated at compile time, you can only pass constant expressions into them. Since a function may possibly contain a closure (even though this one does not), you can't ever treat a function like a constant.

I'm being an FP snob, and I know it. My reason for wanting to do this is less because I have a specific need and more because I want to. I get frustrated when a language implements a potentially awesome feature in a half assed way, but as I think about it, "Potentially awesome, practically useless" describes VB.Net to a "T". If I had my druthers, we'd be a C# shop if we were doing Microsoft at all- I think a big portion of our business would be streamlined by a real RAD language, like Ruby or Python.

All of my complaints would be patched if VB.Net supported compiler macros. I'm stunned that it doesn't- it's not exactly the hardest thing on earth to implement; your average C compiler has had a macro pre-processor since before I was born. C# has one. And here's the real kick in the teeth: most macro engines are language agnostic, so there's no reason they couldn't have wired the C# engine onto VB.Net.

Basically, this is an exercise in driving home the flaws of the language that pays my bills.

June 10th, 2008

The Joys of Offshore

Add to Memories Tell a Friend
johnny cash
I designed an application recently. It's a really simple application, as such things go: Read a record from a database, send the record to the mainframe, and flip a flag on the record to mark it done. Tack on a little logging and error handling, and you've got a very basic project. So basic, in fact, that my boss decides that it's a waste of my time. I'll put the design together and we'll ship it to an offshore contractor.

Now, I've seen the way offshore fucks up projects. So I sit down, and try and figure out how best to prevent this sort of blow up. My solution? I write the program myself, mostly. I supplied design diagrams, documentation, and about 40% of the code, already implemented so that it matches the design. There are a bunch of blanks in the code marked with "TODO: Open the connection to the database and fetch the next record. Map the column values according to the tech spec, a la: 'rec.sMfgCode = dbrecord("sMfgCode")'*".

Now, it's entirely possible that the developer might screw up filling in those blanks. Mind you, this stuff is (theoretically) basic knowledge for a contractor, but hey- it could happen? But I was surprised by the scope of the offshore fuckup. The developer completely ignored the sample code I gave him. I did most of his job for him and he just pissed it down his leg and reimplemented the application. He ignored my design diagram, didn't create the classes I told him to, and generally fucked the entire thing up.

Also: no comments, bad coding practices, ignorance of key syntax elements, and a horrible horrible habit of doing lots of switching logic instead of using OOD and the config file to control app behavior.

I hate offshore.

*No, I didn't name the database columns. They really used Hungarian Notation. I hate Hungarian Notation

April 27th, 2007

Reflexive Reflection

Add to Memories Tell a Friend
IOCCC Original Winner
I've been prepping a lot lately at work (ie. not teaching). So I've been using that time to work on a .NET based plugin architecture, which I call NPlugin. The idea is that a developer can write a program that acts as a PluginHost. Another developer can write an assembly that contains a class that implements the IPlugin interface. With a few XML config files, the program can load the assembly and the plugin and leverage whatever functionality it contains.

This requires a very flexible design. There's a high demand for extensibility. So I've been using a lot of pattern based design. This has lead to some pretty interesting scenarios.

For example, I want the host to be capable of loading plugins from anywhere- the local filesystem, the web, a database, someplace I haven't yet thought of- which means I need to make the PluginLoader extensible. It would be great, for example, if I had some sort of... plugin architecture.

And that's the design I'm using- the plugin architecture uses itself to manage itself. The PluginLoader is a PluginHost. This is why programmers often refer to parts of software and operating systems as "bootstrappers"- your operating system, and my plugin architecture "lift themselves up by their own bootstraps". I've never worked with a bootstrapped design before, so this has been an incredibly educational experience for me.

I'm nowhere near done- I've got the core of the framework built, but I need to actually implement other PluginHost classes, as well as test the damn thing- oh, and a few GUI widgets would be smart for managing it all too. When I've got a working alpha, I'll throw it up on SourceForge and try and rope a few other .NET devs into it with me.

Oh, and (heresy of heresies), I'm writing it all in VB.NET. VB.NET is more flexible than C# when it comes to OOP and patterns- C# is more flexible for low level interactions which this library doesn't need.

April 11th, 2007

VB vs. C#

Add to Memories Tell a Friend
IOCCC Original Winner
Wow. Okay, so I come from the C/C++/Java school of languages. Visual Basic has always felt amateurish to me, especially old-school VB. The more modern version, VB.NET, has lots lots of that feeling- it's a truly Object Oriented language now, but it still uses big clunky keywords.

For example, VB.NET code might look something like this:
Public Class Circle
  Inherits Shape

  Private _Radius as Double;

  Public Property Radius() as Double
    Get
      Return _Radius;
    End Get
    Set (value as Double)
      _Radius = value;
    End Set
  End Property
End Class


Big, spelled out keywords. The original language was designed to be easy for non-programmers, so lots of spelled out words. The same thing, in C#, is generally more preferable to a programmer:
public class Circle : Shape
{
  private double _radius;

  public double Radius {
    get { return _radius; }
    set { _radius = value; }
  }
}


Way more concise, very trim. Thats the sort of thing programmers generally prefer. It's not hard to learn a syntax, regardless of how cryptic it is (inconsistency makes it very hard, however). Since I do most of my work in VB.NET, since that's what people want their classes in, that's what I know the best. C# has always been something I've been meaning to pick up more about, but never have. Until today.

Today, I discovered that VB.NET has things C# lacks. In fact, despite the chunkiness of the keywords (which are usually auto-completed for you anyway), there are several very prominent things VB.NET has that C# lacks.

The first is the ability to have multiple indexed properties. Maybe there is a trick to doing this in C#, but I can't find it. If I want to have a property that represents a list, I've gotta implement a property against "this". For the non-programmers, suffice to say, it's kinda annoying. To be fair, I'm spoiled- most languages don't have the same simple property syntax that C# and VB.NET share, but it's annoying to have to do things the "old fashioned way" in order to make them work.

Secondly, in VB.NET, interfaces are not tied to method names. For the non-programmers- an "interface" is a contract. I promise to expose methods to meet the contract. In VB.NET, the stuff my class has doesn't need to have the same method names as the contract requires- it can map between them. This is great, because I can add interfaces to a class without having to worry about naming conflicts. C# does it the Java way, where names matter.

Thirdly, setting up event handlers, while somewhat more concise in C# is cryptic. Why the hell do I use the "+=" operator for adding those?
Powered by LiveJournal.com