Link to home
Start Free TrialLog in
Avatar of Dave_Greene
Dave_Greene

asked on

Get / Set / Let ... is there a problem with using them?

I recently heard that the use of G/S/L should be forbidden when writing code for the web.  I personally do not see how that could be true.  But on the other hand, I am not a web guru.

I am looking for definative proof that the use of G/S/L is not a good idea in ASP programming.

I have used them before with great success, example to follow.  But if there is a major problem with thier use, I would like to know about it.

<Example ASP>
<!--#include file=incUtils.asp-->  

<%
'---LOGINCONFIRM.asp

Session.Timeout = 60
 
Dim user, pwd

User = Request.Form("username")
PWD = Request.Form("password")
Remember = Request.Form("cbRemember")

If user <> "" AND pwd <> "" Then

  Dim oInfo
  Dim GUID

  set oInfo = Server.CreateObject("JDUser.Info")
 
  If NOT oInfo Is Nothing THEN
     oInfo.UserName = user
     oInfo.Password = pwd

     If oInfo.ValidateLogin() = True Then
        With oInfo
           Session("ID") = .ID
           Session("FName") = .FName
           Session("LName") = .LName
           Session("UserName") = .UserName
           Session("Address") = .Address
           Session("Phone") = .Phone
           Session("Fax") = .Fax
           Session("Email") = .Email
           GUID = oInfo.BuildGUID(Session("ID"))
        End With
       
        IF Remember = "YES" THEN
             BuildCookie(GUID)
        END IF

        Response.Redirect "result.asp?from=login&status=ok"

     Else

        Session("ErrDesc") = oInfo.ErrDesc
        Session("ErrNo") = oInfo.ErrNo
        Session("ErrLoc") = oInfo.ErrLoc

        Response.Redirect "result.asp?from=login&status=err"

     End If
   
     Set oInfo = Nothing        

   Else  

     Session("ErrDesc") = "Unable to Create Server Object"
     Session("ErrNo") = "404"
     Session("ErrLoc") = "LoginConfirm.asp"

     Response.Redirect "result.asp?from=login&status=err"
   
   End IF

End IF

%>

<Example COM+ Function>
Option Explicit

'Data Members
Private m_sID           As String
Private m_sUserName     As String
Private m_sFName        As String
Private m_sLName        As String
Private m_sAddress      As String
Private m_sPhone        As String
Private m_sFax          As String
Private m_sEmail        As String
Private m_sPassword     As String

'Error Properties
Private m_ErrNo         As Long
Private m_ErrDesc       As String
Private m_ErrLoc        As String

Public Function ValidateLogin() As Boolean
   
    On Error GoTo EH

    ValidateLogin = FAIL
   
    m_ErrLoc = "JDUser::ValidateLogin"
   
    If ConnectDB = SUCCESS Then
       
        Set RS = New ADODB.Recordset
       
        SQL = "Select * from tblUsers where UserName = '" & m_sUserName & "' AND Password = '" & m_sPassword & "'"
       
        RS.Open SQL, Conn
       
        If Not RS.EOF Then
         
            m_sID = RS.Fields("ID")
            m_sUserName = RS.Fields("UserName")
            m_sFName = RS.Fields("FName")
            m_sLName = RS.Fields("LName")
            m_sAddress = RS.Fields("Address") & vbNullString
            m_sPhone = RS.Fields("Phone") & vbNullString
            m_sFax = RS.Fields("Fax") & vbNullString
            m_sEmail = RS.Fields("Email")
            m_sPassword = RS.Fields("Password")
           
            ValidateLogin = SUCCESS
               
        Else
         
            m_ErrNo = 404
            m_ErrDesc = "Login Credentials are Incorrect. Please Try Again"
       
        End If
       
        CloseDB
         
    Else
         
        m_ErrNo = 101
        m_ErrDesc = "Unable to make Database Connection"
         
    End If
       
    Exit Function

EH:
    m_ErrNo = Err.Number
    m_ErrDesc = Err.Description
    CloseDB
    Err.Clear
End Function


I would love to hear from the web guru's on this topic.  Thanks in advance!

-Dave
Avatar of John844
John844

One of the major drawbacks of using properties in components for the web is that it forces the object to maintain state.  Web components should be built to allow complete statelessness.  If you are going to need a poece of information in two function calls, you are better off passing the piece of data both times instead of creating a property, setting it and using the property value in your component.  Each function should be written to get all of its needed information in the parameters collection, perform its processes, and return info if needed.  This methodology makes for much more robust and scalable solution.

John
from MSDN...

In practice, accessing COM properties or methods can be deceptively expensive. Here is an example, showing some fairly common code (syntactically speaking):

Foo.bar.blah.baz = Foo.bar.blah.qaz(1)
If Foo.bar.blah.zaq = Foo.bar.blah.abc Then ' ...

When this code runs, here?s what happens:

The variable Foo is resolved as a global object.
The variable bar is resolved as a member of Foo. This turns out to be a COM method call.
The variable blah is resolved as a member of Foo.bar. This, too, turns out to be a COM method call.
The variable qaz is resolved as a member of foo.bar.blah. Yes, this turns out to be a COM method call.
Invoke Foo.bar.blah.quaz(1). One more COM method call. Get the picture?
Do steps 1 through 3 again to resolve baz. The system does not know if the call to qaz changed the object model, so steps 1 through 3 must be done again to resolve baz.
Resolve baz as a member of Foo.bar.blah. Do the property put.
Do steps 1 through 3 again and resolve zaq.
Do steps 1 through 3 yet another time and resolve abc.
As you can see, this is terribly inefficient (and slow). The fast way to write this code in VBScript is:

Set myobj = Foo.bar.blah ' do the resolution of blah ONCE
Myobj.baz = myobj.qaz(1)
If Myobj.zaq = Myobj.abc Then '...

also from MSDN

State Management
Recommendations
In general, use stateless components and stateless ASP pages where you can. Components should not require state from one method call to the next.  Store complex state in a database.  For simple data, leverage cookies, the QueryString, or hidden form fields to pass data across pages.

Why
Server resources are limited.  Maintaining state in your components means consuming valuable resources while exposing your application to resource contention and concurrency issues.  Stateless components help you avoid these issues.  Stateless components also provide more deployment options as well as enhance your ability to share resources across multiple clients.

Common Traps
A common pitfall that developers run into is designing or using components that need to maintain state.  Watch out for this desktop mentality.  Typically, developers coming from a desktop development background will design components that rely on state.

shall I keep going???
Avatar of Dave_Greene

ASKER

So by my example above, would you say I was maintaining state?
How is using a property Get/Let different from simply declaring the variable as Public within the component?  They are, in fact, both storing that data in memory are they not?  By using properties, is it any different?

Are you suggesting that properties not be used at all within a component?  i.e., No property get/let procedures AND no public variables?  In essence, arent most components, unless they are being pooled, stateless in the sense that they are destroyed and recreated with every call to the page in which they are used?

Listening...
For AZ,

<<How is using a property Get/Let different from simply declaring the variable as Public within the component?>>

You can regulate what data comes in and what data is visible to the outside world.  When they are public they are completely exposed and are corruptable.  You can GET a data element but choose not to LET anyone have access to it, and vice versa...  why do I think you already know this and somehow I've missed your point...
Yeah, I guess I wasnt very clear...
I understand the use of Property Get/Let procedures.  My question was directed towards, John, really, and whether this performance issue applies ONLY to Property Get/Let procedures, or if this idea of maintaining state applies to both that AND if you had just declared your variables as Public within the class module.  I understand the performance hit if you have a hierarchy of objects, but if thats how you have things set up, I dont think it will make that big of a difference.  Look at the FSO, ADO, MSXML Object, etc., used extensively in ASP.  Each of this represents a hierarchy of objects, possess properties, etc.
I am not sure if it is just my past experience or not.  I try to avoid using the properties in my components.  If you choose to use them that is totaly your call.  I have just read and been told by others to avoid them if at all possible.  In one of my posts from msdn, it explaines the additional overhead of using the properties.  

As far as properties maintaining state, I guess that is a point of debate.  If I create an object, set a property,  process 5 minutes of data, and then use the something dependent on the property, then yes the state is maintained the entire time the object is referenced.  State is not maintained across multiple pages if used in this manner.

When it is all said and done, there are many ways to solve the same problem.  What works for me might not be best suited for yours.  Stress testing in your particular scenario will be the only absolute answer for your exact set of needs.

No offense intended towards anyone.  Just trying to pass info on, not trying to force anyone to listen or use it.  I am not the definative reference by any means.

John
Thanks John,

With that being said.  Anyone have an opinion on passing on the information to a COM+ component using the response object instead of the way I have coded the above example.  

Pro's or Con's to using the response object?
ASKER CERTIFIED SOLUTION
Avatar of AzraSound
AzraSound
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>>Anyone have an opinion on passing on the information to a COM+ component using the response object instead of the way I have coded the above example

Not sure what you mean?  What information do you hope to pass with the Response object?  Or do you mean using the built-in ASP objects such as Request, Response, etc. from directly within your component in general?
Azra,
I am still unsure about this.  If I have a string property in my component, is it really consuming that
many more resources than if I had to have a string variable in my ASP page instead that I later passed
to a function within my component?  Not sure about that one...

I agree with you you are not using more resources to store the string.  the only things that might affect speed is having to incur the additional round trips to verify the property exists, seting the property and then calling the method.  In most cases where the components are placed on the same machine, this is not even a major consideration.  When it would become move obvious is when the component is located on a seperate machine.

Dave,  I personally have seen no negatives in using the response object yet.  I have only used this methodology in a limited scope(6 current components).  We have fairly high exposure to these pages using the components and since the components are written inside the VB environment, the enhanced error handling allows more freedom than with ASP.

John
Firstly, I am not 100% sure about the terminology, so bear with me.

Currenly I have a Login.asp which does client side validation.  If processing is OK, I post the page to another asp page called ConfirmLogin.asp (The code of which is posted above)

I could simply post to an ASP page which only has the following code

<%
dim oObject
Set oObject = Server.CreateObject("wahh.haaa")
%>

Then from within my COM+ component, get the values of the Login.asp form.
I've seen the code to do it, but have never attempted it before.

Which method of processing is better?  Passing the parameters to the component or having the component parse out the parameters...





 
The only real overhead, I believe, is in getting the initial context of the page in your component, i.e., getting the references to the Response, Request, etc. objects.  Once you  have those, the performance should be the same had you been using those objects within the ASP page itself.  The benefit of writing it all within VB is that you get to use the stronger typed language, use better error handling as John mentioned, make use of API calls, use VB's native file I/O functions, and everything else that VB has over VBScript.
hi all --

dave, i don't think either method is better, though i can't say i've tested performance on both. components created under MTS seem to get access to the ASP objects very quickly, so i don't think you take a hit by using GetObjectContext("Request") inside your component. on the other hand, the more you rely on the built-in ASP objects, the more you commit your component to running only under ASP in its current incarnation; who knows what MS will come up with and switch around? or whether you'll want to integrate your components into a client-side app instead of ASP? though this isn't a strong argument, on balance im in favor of passing parameters to components unless there is a strong argument for using the built-in ASP objects inside.
Things to consider.  If you decide to use the request, response.... objects from inside the component, use them sparingly.  I would not build my page using 50 response.writes as this would cause 50 round trips(or more?) If you choose to use this methodology, I would build large strings and then do a few, or one response.write.

Getting or setting the session variables would be round trips that could not be avoided in this scenario.


One other option if you are just looking for different solutions would be something like

create a public function that accepted username and password.  The component pulls any data needed like name...  Component then returns a recordset.  An empty recordset would mean that no record was found for user.  Additional logic could be added for invalid password or errors appending an errorMessage field to the recordset.  This would allow one call to be made to the component without using properties.  No state is needed to be maintained in the component.  Component can be released immediately.

As much as I hate to admit it, I like the property usage in this case.  Kind of hypocritical isn't it?

John
hi all --

dave, i don't think either method is better, though i can't say i've tested performance on both. components created under MTS seem to get access to the ASP objects very quickly, so i don't think you take a hit by using GetObjectContext("Request") inside your component. on the other hand, the more you rely on the built-in ASP objects, the more you commit your component to running only under ASP in its current incarnation; who knows what MS will come up with and switch around? or whether you'll want to integrate your components into a client-side app instead of ASP? though this isn't a strong argument, on balance im in favor of passing parameters to components unless there is a strong argument for using the built-in ASP objects inside.
>If I have a string property in my component, is it really consuming that many more resources than if I had to have a string variable in my ASP page instead that I later passed
to a function within my component?  

I think what happens is that MTS tries to have components hanging about as little as possible. when you call

set obj=Server.CreateObject(".."), you're really telling MTS to get ready to create an object. but MTS is stingy, and it waits for you to call a method

obj.anything()

before it actually commits resources to the object. ideally, somewhere in Function Anything(), you call

GetObjectContext.SetComplete(),

which tells MTS to deallocate resources held by the object, and return to just holding a wrapper; MTS calls ObjectControl_Deactivate and forgets all property values. if you make another function call

obj.anythingElse(),

obj has forgotten everything it knew, and in fact MTS calls ObjectControl_Activate again as it revs up. so keeping a property around means that you have all the resources committed to the object, whereas if you waited and passed the ASP variable to the object later on in your logic, you would be saving resources up until the moment that you first made a call on the object.
A thing to remember though, is that ASP scripts are interpreted each time the page is called.  Your component is compiled, and for long scripts, placing the code into your component should prove to have better performance in the long run.
Here's additional info on how to "fine tune" your apps:

"Tips to Improve ASP Application Performance"
http://www.15seconds.com/issue/000106.htm
Well, I think we have hit all the bases on this one!  Thanks to everyone for their contribution!!!  I will leave points for everyone.  Keep your eyes open for your points!

Thanks Again!
-Dave