Posted on January 3, 2012
ASP and VBS, how do I love thee, let me count the ways
Over the past year I have had to work on a large legacy ASP code base spanning millions of lines of code. Not surprisingly, I have developed a deep and passionate hatred of VB Script as a result. This angry rant is the culmination of months of hate, pain, and tears. Now, I don’t want to come off as too negative, so before I begin I will say that vb script does have a few positives: It is positively a great case study in how not to design a scripting language, and it positively inspires developers (myself included) to think of creative ways to migrate and port the code base over to the a language that doesn’t suck.
So without further ado, here is a list, in no particular order, of why VB Script is garbage.
- If statements don’t short circuit – In most languages, each of the conditionals in an if statement is evaluated in order from left to right. If any of them evaluate to false, none of the other conditionals to the right are evaluated. This makes sense. One common usage of an if statement is to first check if an object is null, and if its not, to then check the value of one of its members. For example in C#:
if (someObject != null && someObject.memberValue == 5)
This of course is not possible in VB Script. The second conditional would cause a null reference exception if someObject were null. This forces the developer to write two separate if statements where one would suffice. Words cannot describe how mind numbingly stupid this is. I’m scratching my head trying to figure out the rationale behind this design decision. Perhaps the designers felt that developers might want to write conditionals that had side-effects. For example, perhaps the conditional would call a function that would update some global variable, and that this needed to happen every time the if statement ran. Needless to say, this is a terrible coding practice. Evaluating an if statement should never have side effects, as this causes a testing and maintenance nightmare that is a ripe breeding ground for bugs.
- Subroutines and functions are redundant – A sub in VB Script is just a function that doesn’t have a return value. In other words, it simply returns void. There is really no need for this distinction. I understand that subs and functions derive from BASIC, VB Script’s ancient predecessor, but BASIC is decades old. Perhaps there was a good reason for this architecture back then. If I had to hazard a guess, I’d suspect that there were performance optimizations back then that the BASIC compiler was able to perform based on whether a sub or a function was called. Decades later, there is simply no excuse to not trim the fat. Its sloppy and its lazy. This design decision makes even less sense because you can declare functions that have no return value, making the existence of subroutines about as useful as those phonebooks that they keep delivering to my door.
- Calling a subroutine is ugly – Let’s say you have a FooBar subroutine that takes in two parameters. There are two ways of invoking this subroutine, but both of them are ugly:
Call FooBar(1, 2) FooBar 1,2
Why the hell can’t you just call like you would a function?
Oh that’s right, because then subs would be even more indistinguishable from functions, and we wouldn’t want that! Then we might have to get rid of subs altogether. That’d make far too much sense.
WEND – Yes, there is actually a statement called WEND in VB Script. Let that sink in for a moment. It is used to indicate the end of a block of code in a while loop. In addition to being a hideously ugly statement, it is inconsistent with the rest of the language. For loops use “Next”. If statements use “End If”. “End Sub” and “End Function” are used to denote the end of a subroutine and a function, respectively. If I may paraphrase Frederick P Brooks in his excellent book, Design of Design, the key hallmark of a well designed product is conceptual integrity.1 Conceptual integrity gives the product a consistent and easily comprehensible design, which in turn allows users to easily and intuitively learn and use the product, and more importantly, remember how to use the product years later.
VB Script does not achieve any semblance of conceptual integrity at all. Instead, it takes exactly the opposite approach by using a widely divergent syntax in its statement block syntax Again, this syntax is taken directly from BASIC, but the designers had a chance to make a clean break from its predecessor. It’s a terrible excuse that spawned a terrible language.
- & is used to concatenate strings – This is not a good choice for a string concatenation operator. Am I being petty and subjective? No. & is almost universally used in all languages to denote some kind of logical AND. It looks awkward when used to concatenate strings.
- ‘ is used to denote comments – Again, ‘ is almost universally used in all languages to denote some kind of string or character. The designers could have picked a semantically better choice.
- Multi line string concatenation cannot handle comments – To denote a multi line string in vb script, you use &_ to do so. Ignoring the fact that this is hideously ugly, VB Script chokes when you try to add comments.Take a look at the following code:
dim foobarFoobar = “hello” &_ ‘this is a comment “world” ‘this is another comment
“this is a comment” causes a syntax error. The equivalent C# code compiles and runs just fine. Typically, you’d want to break up a string into multiple lines to help with readability. To further assist in elucidation, its conceivable that you’d want to add a comment next to each line. I’m not sure if this is disallowed in VB Script because the comment parsing code is awful, or if this was an intentional design decision. I’m also not sure which of those two is worse.
- Variables are not case sensitive – When VB Script first appeared in 96, most languages were already case sensitive. There are a number of naming conventions that are based on capitalization. Not having a case sensitive language means that not only are these naming conventions not possible, different programmers will capitalize variables differently, often in the exact same function, making for code that makes your eyes bleed.
- Option explicit is off by default – Option explicit forces all variables to be defined before they can be used. By default, this is OFF in VB Script. You have to manually set this in your code in order for it to take effect. VB Script came out in 1996. By that time, requiring variables to be declared before being used was the default for the most languages. It was just common sense. Not making this the default makes it possible to introduce a large number of easily preventable bugs. Part of good design is setting sensible defaults and encouraging best practices. Allowing programmers to make typos and then waste hours trying to track down the resulting bugs is asinine. Of course, no good programmer would ever not use option explicit in the first place. Actually, a good programmer would probably be using a better scripting language altogether.
- Empty, Null, Nothing – Why are three separate keywords needed to indicate a variable does not have a value? A good design is achieved not when nothing more can be added, but when nothing more can be taken away. Having all these useless and un-necessary distinctions causes lots of useless and un-necessary bugs when a developer confuses the difference between Empty and Null.Languages that came out before VB Script such as C and Java get away with just using NULL and have not been any worse off as a result. Perhaps you have heard of these moderately successful languages before.
- IsNumeric(Empty) evaluates to true – VB Script is a scripting language, which means its not very strongly typed. Scripting languages in general tend to play fast and loose with types, to facilitate rapid prototyping and easy to write code. However, they typically provide GOOD type checking functions so that strong type checking CAN be done if necessary. A GOOD type checking function would not return true when checking if empty is numeric. What the hell were the designers even thinking? Did they even stop to think about the use cases for IsNumeric? In what use case scenario would a programmer trying to validate data want IsNumeric(empty) to evaluate to true? In every situation I can think of, I would never want empty to be considered a number. This terrible design decision forces programmers to do two separate checks, one for IsEmpty, then another for IsNumeric, instead of using just one.
- Functions can be called without parentheses – No big deal right? Not quite. This makes the following innocuous looking line of code completely ambiguous.
“y” could either be a function or a variable. Who knows? I guess the VB Script designers wanted to keep programmers on their toes.
- Setting the return value in a function does not terminate the function. You must call “End Function” to do so – In every other language, there is typically a one line “Return x” statement that causes a function to return the value and stop execution of the function. Not so in VB Script. They decided one line wasn’t good enough. You have to set the return value, and then manually exit the function. For example, if you have a function FooBar and you want to return the value “x”, you’d need two statements: “FooBar =x” followed by “Exit Function”. Its as if the VB Script designers wanted to add useless filler to their language to make it even uglier. Mission accomplished. Talk about a pyrrhic victory.
- You cannot declaring a variable and set its value in the same line – This is something I think every language in the planet supports. You’d think the syntax would look something like this:
Dim foobar = 5
Nope! Syntax error. I guess the designers were looking for more ways to differentiate VB Script. Not satisfied with requiring two lines of code to return a value in a function, they decided declaring and setting a variable in one line would be disallowed as well. To be fair, you can get around this limitation by using the colon, which allows you to execute multiple statements on the same line. You could for example write
Dim foobar : foobar = 5
But that’s not quite the same thing as having built in support, and its also ugly as hell.
- VB Script Regex does not support lookahead/lookbehind – Ok, this is a nitpick, since a lot of other languages don’t support this either. But given that this is a rant, I decided to include this one in the list for completeness. Cartharsis can not be achieved otherwise.
If I may digress for a moment, this is no excuse for developers not to use inheritance in VB Script. To quote Steve McConell from his book, Code Complete:3
"Programmers who program in a language limit their thoughts to constructs that the language directly supports. If the language tools are primitive, the programmer's thoughts will also be primitive.... Programmers who program into a language first decide what thoughts they want to express, and then they determine how to express those thoughts using the tools provided by their specific language."
So yes, technically you can do inheritance in VB Script, but you have to be put in the effort to hack it in. Of course, why not put in the extra effort and just rewrite all the code from scratch using any of the other languages out there which are all vastly superior? You know its inevitable anyway.
- Dim Array(3) creates an array of size 4 – Again, this is not intuitive. You’d expect Dim Array(3) to create an array that holds 3 objects. Instead, the 3 denotes the largest index value of the array. This flies in the face of normal convention. I’m not sure if the designers were looking for ways to be intentionally defiant or looking for ways to make VB Script different. Whatever the case, this syntax is completely boneheaded.
Because VB Script and ASP go together like peanut butter and jelly, no rant against VB Script would be complete without an obligatory rant against ASP. Most developers who have ever worked on an ASP code base know the horror that is include file hell. Languages that support include files typically provide a way of checking if a file is already included. In C, you put all your code inside a #ifndef directive, and #define an identifier to prevent the code from being included elsewhere. Not providing such a mechanic makes code a nightmare to maintain as you navigate the maze of include dependencies. Most companies (that still use ASP) have simply resorted to using one giant include file that includes everything, which defeats the whole purpose of include files in the first place.
Also, ASP implements include files in such a way that encourages abuse. Include statements can be included anywhere, allowing for truly unreadable code to exist. Witness the following (note I had to add in a space for the include files otherwise WordPress would treat it as an actual HTML comment. Despite downloading various Raw HTML plugins for WordPress I have not yet found a workaround for this. Just remember to remove the extra space should you want to try this for yourself):
<% Dim X : X = True %>
< !-- #include file="inc_if.asp" -->
< !-- #include file="inc_else.asp" -->
< !-- #include file="inc_endif.asp" -->
<% If x = true then %>
<% Else %>
<% Endif %>
Sure enough, this code results in “One” being printed out in the response. Sure, only the most sick and depraved person who had already given his two weeks notice would write code like this intentionally, but allowing unreadable code such as this to exist in a language is inexcusable. If you had the safety on in a loaded gun, would you keep it in a room with an unattended baby? Hell no. In the case of ASP, the “safety” is nothing more than relying on programmers to know better.
In this long and rambling diatribe, I have repeatedly used the word ugly. Why do I make such a big deal out of this? Sure, ugly code can be written in any language. This can not be argued. However, a clean and elegantly designed language will by its very nature help encourage clean and elegant code. An ugly language such as VB Script however, encourages ugly code. In fact, sometimes it even demands it. I noted quite a few examples of VB Script requiring multiple lines of code to do the same task that in other languages would require one. Clean code can be written in VB Script, but it requires far more discipline and effort. Most developers won’t even bother or will have long ago given up. The moral of this story is: don’t use ugly languages unless you absolutely have to (regular expressions for example, are hideously ugly, but compensate for this by offering powerful functionality and expressiveness. VB Script however, has no real redeeming qualities whatsoever).
1 From the essay “Esthetics and Style in Technical Design” in The Design of Design by Frederick P Brooks.
3 McConnell, Steven C. 2004. Code Complete Second Edition. P. 68