Wednesday, December 14, 2011

Mixed Variable Types

Some languages like VB and VBScript allow for what is commonly referred to as "evil coercion" meaning that the system will do it's best to do automatic type conversion between two variable types.

This can be helpful in situations like this:
Dim x As Integer
Dim s As String

s = "7"

x = s 'No need to call Convert functions

But this can also cause major problems, especially in VBScript where variables aren't explicitly typed and everything is a "Variant", meaning a variable that can dynamically change it's internal type.

In these cases if you don't explicitly stick to rules of variable handling, initialization and comparison, you can run into serious logical errors, as well as confuse anyone trying to troubleshoot your code.

Sad Code:
'Variable is prefixed with "int"
'and value is initialized to a number
'but in quotes so it's treated as a string
Dim intNew : intNew = "0" 

'The database bit field is a Boolean,
'so the variant intNew should change to act like a Boolean
intNew = objRSLeadStage("bNew") 

'What's going to happen here?
'Is intNew a string, boolean or number?
If (intNew = "True") Then

Oddly enough, the above Sad Code works, in the sense that the comparison between the string value "True" coerces to the Boolean value True for the If statement.

The intNew variable here clearly has an identity crisis, and anyone trying to debug this code amongst a thousand other lines is most likely going to end up pulling there hair out asking WHY?

So remember that when you're working with dynamic variable types like Variants or Objects, and languages that perform evil coercion you should be VERY strict with how you handle your data types and variable names to avoid confusion.

Happy Code:
Dim bNew : bNew = False

bNew = CBool(objRSLeadStage("bNew"))

If (bNew) Then

As you can see here, there is no confusion in any area as to the behavior of your variable.

Wednesday, November 16, 2011

Documentation

I'm a big fan of what they call "Self Documenting Code" meaning code that is so straightforward and simple that just about any programmer could understand based on variable names, function names, context etc.

But of course there are times when you may have to write complex algorithms, or you're working in a module that's very large and you have to put in documentation to help make it easier for you or someone else to troubleshoot your code in the future.

Just make sure that your documentation is accurate and correct and belongs where it is in the code!

The only thing worse than NO documentation is INCORRECT documentation.

Trying to troubleshoot a function assuming that the comments are accurate only to find out later they are out of date or just copied and pasted from a different non applicable section can really drive you crazy!

Wednesday, October 12, 2011

Boolean Variables

Don't use non-Boolean data types for Boolean type operations.

i.e. Don't create a string variable and then check if it's equal to "Yes", "True", "On", or an integer variable and check for 1.

If the your flag is contained in a session variable or textbox, just declare a Boolean variable and use it going forward.

Sad Code:
If (sAccess = "Yes") Then
 'Go ahead

Happy Code:
Dim bAccess: bAccess = False

If (sAccess = "Yes") Then bAccess = True

If (bAccess) Then
 'Go ahead

Wednesday, September 14, 2011

Variable Declarations

1. Declare your variables outside of Try / Catch blocks

- AND -

2. Don't initialize your variables in the declaration block.

1 - If you declare your variables inside your Try Catch block you won't be able to access them at exception time.

Sad Code:
Try
 Dim MyString As String

 MyString = "Hey"

Catch ex As Exception
 'Can't view value of MyString here
End Try

Happy Code:
Dim MyString As String

Try
 MyString = "Hey"
Catch ex As Exception
 Response.Write(MyString) 'Yay!
End Try

2 - If you initialize your variables when you declare them, there are two issues.
A - You are creating objects that may never get used
B - Since your declarations are outside the try / catch blocks, you could throw an unhandled exception

Sad Code:
Dim MyObj As New CustomObject() 'Oops, this could cause an error!
Dim MyString As String

Try
 MyString = CInt("Hey") 
'Or it could get thrown out because
'this error happened before it was used

Catch ex As Exception
 'Stuff
End Try

Happy Code:
Dim MyObj As CustomObject 
Dim MyString As String

Try
 MyString = CInt("Hey")
'Now if we get an error here,
'we haven't wasted valuable resources!

 MyObj = New CustomObject()
'Yay! We waited until we needed the object to create it!

Catch ex As Exception
 'Stuff
End Try

Wednesday, August 17, 2011

HTML Tags

Don't leave HTML tags open, or close HTML tags that aren't there.

Sure you can write Sad Code like this:
<%
If (HasAccess) Then
%>
      <a href="Secure.asp">
<%
End If
%>
      Secure Link</a>

and it will most likely still show a link, but look at the messy source!

-- If HasAccess = True:
Secure Link

Source:
<a href="Secure.asp">Secure Link</a>

-- If HasAccess = False:
Secure Link

Source:
Secure Link</a>

That little closing anchor tag is not a happy tag!

Wednesday, July 13, 2011

Wasted Objects

Don't create objects unless you need them

Sad Code:
Dim MyTable As New DataTable 'Creates 1st data table

MyTable = MyFunction.GetDataTable()  'Destroys 1st data table and creates another

Happy Code:
Dim MyTable As DataTable

MyTable = MyFunction.GetDataTable()

Or if you prefer the quickie version:
Dim MyTable As DataTable = MyFunction.GetDataTable()

Wednesday, June 15, 2011

Naming Conventions

Do not name your local variables or subroutine arguments the same as your module level variables.

i.e.

Sad Code:

Private MyVar As Integer
Public Sub MySub(ByVal MyVar As Integer) Also Sad Code: Public Sub MySub() Dim MyVar As Integer


Tip: Use a character prefix to define the scope and type of your variables.

Happy Code:

Private mnVar As Integer

Public Sub MySub(ByVal vnVar As Integer)
 Dim nVar As Integer

Wednesday, May 11, 2011

Process map for upgrading from Classic ASP to ASP.Net

When Microsoft published ASP.Net they made a very large architecture change from their old product of Classic ASP.

Unfortunately when they made this change, they didn't provide a very good upgrade path from the old code to the new, so many programmers still support Classic ASP pages as upgrading them can be very time consuming without a lot of return on investment.

There is no silver bullet for upgrading Classic ASP pages, but I've come up with a standard method that I follow when I have to upgrade pages that seems to work well.

Process map for upgrading from Classic ASP to ASP.Net

1 - Upgrade the majority of your SQL queries to stored procedures

Having your SQL queries as simple calls to stored procedures makes your upgrade easier because when you are trying to debug problems during the transition phase you can rule out syntax problems with your queries.
It also helps if you are trying to migrate from include files to business logic libraries.

This is also something you can do while your Classic ASP site is running, so you can go through the testing and debugging phase with the existing site and rule out any problems that may come about after converting to stored procedures.

2 - Turn your page headers, navigation and footers into a master page

If you have common page headers, tabs along the top, links on the side, copyright links on the bottom, style sheets, javascript libraries or any other common elements that are used across all of your ASP pages, set up a master page to handle as much of it as you can.

3 - Create a base page class

A lot of ASP pages will start out with validation for a user login, initialization of session variables, and loading some database values into memory for later use.
You can create separate business object class libraries to handle all of this, but it helps if you create a simple base page class for all of your .aspx pages to inherit from.
That way you can have your base page's "Page_Load" routine handle any initialization you would normally have to do, as well as declare any variables that will be used across your codebehind page.

4 - Turn include files with HTML output into user controls

If you use include files to spit out large chunks of HTML either through code breaks <% or calls to response.write, create a user control (.ascx file) so that you can have the same functionality through your .aspx page

5 - Turn include files with functions into classes

If you have include files that you use across your application to make database calls or crunch some code, the best place for those is in class files.
If you have common routines that are just used for parsing inputs or just generic functionality, you can create shared classes.
Otherwise you can create specific classes to handle each section of your application.

6 - Turn page functions into functions in your codebehind

If you have functions that you use for crunching code for your .asp page, you should be able to convert them easily to functions in your codebehind for .aspx page.
If it is a function mostly used for outputting HTML to the page, it may not be worth converting.

7 - Grab the HTML from your browser

Load up your current Classic ASP page in the browser, view source and grab the HTML as it is presented.
Paste that into the content placeholder in your .aspx page, cut out the common areas covered by your master page and you have a pretty good starting point.
From there you can paste in your user controls where necessary, and start adding data grids, drop down lists or other server controls that you can bind from your codebehind.

8 - Rewrite the rest

Unfortunately since Classic ASP and ASP.Net are such different animals, you're pretty much guaranteed to lose a lot of code that can't really be migrated very well.
In most cases once you've done all the previous steps it's time to just throw out whatever code hasn't been migrated of the page and put all the pieces together in .Net.