The aim of this tutorial is to save burgeoning self taught developers some of the early pitfalls that lurk on the road to programming enlightenment. It will attempt to do this by distilling the last 50 years of software engineering philosophy into a relatively short single tutorial, applying the concepts along the way in the medium that is in most need of its principals: web development.
Several assumptions have been made about your level of knowledge, such as having an understanding of the Visual Basic Scripting syntax for Active Server Pages (ASP) and the ability to create and ADO connection and recordset objects for example. If you don’t have a clue what is meant by looping through your recordset to make an HTML Table or List Control then, to be honest, you are probably not quite ready for this tutorial.
If you are still reading then you are probably wondering why ASP when it has been superseded by ASP.NET? The truth is that ASP is far from dead and anyway, the stuff covered here will make the move to ASP.NET from ASP that much easier anyway, if and when you should find yourself in that position.
Building a web application from the snippets garnered from a ‘learn ASP in 24 hours’ tutorial is all well and good, and can be done. But be warned that further down the road you may face headaches maintaining that system. So let’s look at how you should be thinking of applying the syntax you have already learnt in order to avoid those headaches.
Let us start by introducing Object Oriented Programming (OOP), the natural step onward from structured programming. Computing hardware was become cheaper and more powerful, the problems that needed to be solved and therefore the software requirements were becoming ever more complex. What was needed was a better way to model the real world problems that were to be solved with our software. In order to do it quicker; to make the software easily maintainable; to make it more future proof required new languages and syntax to enable the programmer to group his or her variables, subroutines and functions into abstract items called classes. Classes are a blue print for an object, you use that blueprint to create an instance of your class, an object, in your program and then you can set its variables and call its methods. This can be demonstrated by way of using the most famous example in programming: the hello world program.
Create a new asp file, call it Greeting.asp, if you’re using an IDE like Interdev, get rid of any code or HTML the template bungs into your new page e.g. the <%@ Language = VBScript %> and any HTML tags. Put the following code in exactly as shown:
<% Public Class Greeting ‘Private member variable accessible only ‘to the class Private m_sGreeting ‘Accessor method, controlled aliased ‘READ access to your class variable Public Property Get Message() Message = m_sGreeting End Property ‘Accessor method, controlled aliased ‘WRITE access to your class variable Public Property Set Message(sMsg) m_sGreeting = sMsg End Property ‘The constructor, initialization for ‘your object Private Sub Class_Initialize() m_sGreeting = “Hello world!�? End Sub ‘Public class method, something this ‘class can do for you. Public Sub Greet() Response.Write m_sGreeting End Sub ‘Cleaning up. ‘Unhand that RAM you hog ! ‘There’s nothing to clean up in this ‘small class, so this is here for ‘demonstration only Private Sub Class_Terminate() End Sub End Class %>
Now you should create another ASP page, call it index.asp and place the following code within it:
<%@ Language=VBScript %> <%Option Explicit ‘This next bit is an SSI (server Side Include) It means put here ‘the contents of Greeting.asp as if it were part of the code ‘in this page.%> <!-- #include file="Greeting.asp" --> <% Dim oGreeting 'Instantiate an object of type Greeting Set oGreeting = New Greeting %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <P> <% 'Call the Greet method oGreeting.Greet 'Destroy our object Set oGreeting = nothing %> </P> </BODY> </HTML>
Now this may seem an excessive amount of code just to display the string “HelloWorld!" and you would be right, but ignore that for a minute and look at what you have actually achieved. Firstly you have hidden the nitty gritty of making a dynamic greeting on your ASP page using the response object, and replaced it with something much more intuitive. You needed a greeting, so you created an instance of a greeting and asked it to greet by calling the greet method. This is called encapsulation or data hiding, should a new and better way of writing strings be released for ASP you could change the greet method in your class without effecting any of the code in your index.asp page, which will still work just as before.
Secondly, that extra effort spent now has saved you effort in the future because you have separated out the responsibility of providing a greeting on an ASP page: it has become a black box. You don’t need to know how it works, you just need to know how to use it. It is also in a separate file, next time you need a greeting in another project, there it is ready and waiting. This is known as code reuse.
Thirdly you have avoided duplication. Imagine a project where you had to have a greeting on several pages within it, deadlines were tight so you used single line Response.Write statements throughout and went home early for tea. Suddenly the following morning you need any greeting to now include the users name. If you have been developing for any amount of time you will know there are three certainties in life, not two. Death, Taxes, and changes to the requirements. As you had used single line Response.Write statements everywhere, you now have to hunt them down and recode them. With the greeting class implementation you merely open Greeting.asp and amend the Greet method accordingly in one place. Any pages making use of the class will display the new behavior with no change to their code what-so-ever. Imagine applying these principals to those repetitive tasks such as connecting to your database, filling a recordset, concatenating the HTML string and so on. Using classes you can: do it once and do it well.
Now it is time to go into the class syntax in more detail, explaining member variables and accessor methods and how it all works as well as attempting to create a more useful class that makes an HTML list box control. If you were lucky enough to study computing at a good college you will have learnt about things like Orthogonal systems, the DRY principal (Don’t Repeat Yourself), encapsulation, code reuse, and possibly even newer terms such as Unit testing and Iterative development. If however, you came into programming from nothing and have taught yourself pretty much everything by reading getting started type books then they will be new terms for you, or terms you have heard but don’t understand. But these terms are very important and you are going to learn them one at a time and then repeat each time you find yourself facing a new challenge requiring a solution.
The first concept you are going to tackle is best described as 'damn the details.' If you are lucky as a developer you find yourself facing lots of problems that require your software solutions. How you go about designing and creating that software is much more important than the actual code you will end up implementing. If your early encounters with programming were VBScript and ASP, your immediate response when faced with a problem that needs a software solution may be to start writing down some [search]pseudocode[/search].
Your thought process might go along the lines of something like: “Hmmm, I’ll need to store customer details, so I’ll need a form with some text boxes…" But it’s actually far too early to be thinking at that low level in your solution, leave the details out for as long as possible. The trick is to force yourself to stay high level, to look down from a birds eye view. You should be aiming to glide into your deadline from on high, not nose dive to ground level and get lost in the terrain. By start high you should be thinking of something like:
INPUT ? PROCESS ? OUTPUT
High enough? Well it does no harm to make this a mantra, making things habit embeds them in your mind and also sets it in the right frame. Every sprinter knows 99% of the race is how you exit the starting blocks. Before you get to the code for a listbox control making class, you should look back at the class we created earlier and examine its parts to understand what it really means. Only then can you apply that knowledge and make a new one. Firstly a class in VBScript is declared simply with the keyword Class; then a valid identifier to name it; some valid syntax; and finally the keyword End Class.
Class MyClass ‘Properties and methods here End Class
Implementing classes varies widely amongst languages, but the concept of classes is universal. There are many analogies for describing classes. Most often a book or article will talk about real world objects like a car or bike, and go on to describe the difference between the idea of a bike and the physical bike itself, but this does not quite capture fully what they are, or how they can empower you as a developer. Think of them instead as super variables with ‘supervariable’ powers. They not only store data like variables can, but they store LOTS of data; they have responsibility; and they have knowledge; finally they have an interface.
The essential components of a class are as follows:
- Private and or public member variables (your current state)
- A Constructor (we are all born)
- Accessor methods (your eyes and ears)
- Private and or Public functions or subroutines (your ability and knowledge)
- A Destructor (we all die one day)
Our Greeting class had all of these. Next there is a single member variable:
‘Private member variable accessible only ‘to the class Private m_sGreeting
This variables’ scope is the bounds of the class, you can not affect it from any code outside of the class. If you had declared it as Public:
‘Private member variable accessible only ‘to the class Public m_sGreeting
you could access it from code outside the class like this:
Dim oGreeting Set oGreeting = New Greeting oGreeting.m_sGreeting = “Hi!�?
But this is seldom advisable as class variables should ideally be accessed via an accessor method or methods, depending whether you want the value to be read only, or updateable.
‘Accessor method, controlled aliased ‘READ access to your class variable Public Property Get Message() Message = m_sGreeting End Property ‘Accessor method, controlled aliased ‘WRITE access to your class variable Public Property Set Message(sMsg) m_sGreeting = sMsg End Property
You use the same dot notation to use these methods:
Dim oGreeting Set oGreeting = New Greeting ‘Set the message value oGreeting.Message = “Hi!�? ‘Read the message value Response.Write oGreeting.Message
The important issue here is that because they are methods you get additional opportunity. You can validate the value trying to be set, and should you need to change the implementation of your class the interface stays the same. So any ‘User’ of your class doesn’t need to know about it. They call the same method and pass the same data, what the class does with it once received is up to the class. The constructor is where we initialize things, if necessary. If you omit the constructor a blank one is inserted by the compiler automatically. In VBScript this is a special subroutine Class_Initialize() (careful of the spelling of initialize with a z if you spell it with an s you wont get a syntax error, just a hard to locate bug!) In your Greeting example you set the class variable m_sGreeting to the string value “Hello World!" so that if the user of your class does not set a message with the Message accessor method, you have a default value already set.
‘The constructor, initialization for ‘your object Private Sub Class_Initialize() m_sGreeting = “Hello world!�? End Sub
Next comes the meat of the class, it doesn’t look so much in your example, but in the real world these are likely to be the most sophisticated elements of your classes:
‘Public class method, something this ‘class can do for you. Public Sub Greet() Response.Write m_sGreeting End Sub
In this case you have a subroutine, but it could be a function. The difference being a function returns a value, where as a subroutine just does some work. Actually a subroutine is a function that returns void or nothing. Finally all good things come to an end at some point; this is the responsibility of the destructor. In VBScript (like the constructor) a special subroutine Class_Terminate() is called, when you set your object to nothing explicitly, or when VB’s garbage collector kills it off. So this is where you put any code needed to tidy up.
So that’s classes, for now at least. It is time now to put what you have learnt so far to good use. Create a new asp file ‘Controls.asp’ and place the following code into it, remembering again to remove anything the template puts in for you if you are using an IDE such as Interdev.
<% Class Combo 'Member Variables Private m_bIsData Private m_aOptionElements Private m_sName Private m_iRowIndex Private m_iRowCount Private m_sSelectItem 'Accessor methods Private Sub Class_Initialize() m_bIsData = False m_sName = "combo1" m_sSelectItem = "" End Sub Public Property Let Name(sName) m_sName = sName End Property Public Property Let SelectItem(sItem) m_sSelectItem = sItem End Property Public Property Get SelectItem() SelectItem = m_sSelectItem End Property 'Public methods Public Sub FillCombo(ByRef rs) 'Takes reference to recordset 'and puts data into a 2 dimensional 'array If rs.EOF and rs.BOF Then m_bIsData = False Else m_bIsData = True m_aOptionElements = rs.GetRows m_iRowCount = Ubound(m_aOptionElements,2) End If End Sub Public Sub WriteCombo() 'loops through an array to 'create dynamic HTML Response.Write "<select name='" & m_sName & "'>" & vbCrLf If m_bIsData Then For m_iRowIndex = 0 to m_iRowCount Response.Write "<option " If m_aOptionElements(0,m_iRowIndex) = m_sSelectItem Then Response.Write "selected " Response.Write "value=""" & m_aOptionElements(0,m_iRowIndex) & """>" & m_aOptionElements(1,m_iRowIndex) & "</option>" & vbCrLf Next Else Response.Write "<option value=''></option>" & vbCrLf End If Response.Write "</select>" & vbCrLf End Sub End Class %>
Now to implement your class, put the following code in another file called UserForm1.asp. This example assumes you have SQL Server developer edition installed. You can download it from Microsoft http://msdn2.microsoft.com/en-us/sql/default.aspx if you don’t have it.
<%@ Language=VBScript %> <%Option Explicit%> <!-- #include file="Controls.asp" --> <% 'Declare our variables Dim oCon, oRst, oCombo1 Dim sCon, sSQL 'Initialise our variables and objects sCon = "Provider=SQLOLEDB;Integrated Security=SSPI;Data Source=localhost;Initial Catalog=Pubs" sSQL = "Select au_id, au_fname+' '+au_lname from authors" Set oCon = Server.CreateObject("ADODB.Connection") Set oRst = Server.CreateObject("ADODB.Recordset") Set oCombo1 = New Combo 'Set some properties oRst.CursorLocation = adUseClient 'Connect to database and fill the recordset oCon.Open sCon oRst.Open sSQL, oCon Set oRst.ActiveConnection = Nothing oCon.Close Set oCon = Nothing 'Pass the data to our combo class oCombo1.FillCombo oRst 'Ditch the recordset no longer required Set oRst = Nothing %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% 'Display our Combo as HTML Listbox control oCombo1.WriteCombo Set oCombo1 = Nothing %> </BODY> </HTML>
If you have typed the code correctly, and have SQL server set up correctly (you may have to add the local account IUSR_<machine_name> to SQL Server logins) you should get a Listbox of author names when you browse UserForm1.asp. So next time you need a Listbox in a form, you won’t have to write all that loop code ever again.
<% While Not Rst.EOF Response.Write “<select blah ….. Wend %>
You’ve done it once, and you’ve done it well in your Controls.asp page, so that you can now use in any project with an SSI <!-- #include file=“Controls.asp" -->