ASP patarimų liūnas

Buvęs C/C++ programuotoju dabar įklimpau į ASP (su VBScript) liūną. Ir nustebau, su kiek daug naujo tipo netikėtumų susiduriama. Kai kurie jų kartojasi daugelyje ASP taikymų. Šie patarimai skirti tiems, kurie nori rečiau suklupti lygioje vietoje.

1. Visada aprašykite kintamuosius, vardus suteikdami pagal nusistovėjusius susitarimus.
Option Explicit įjungia režimą, kurio metu būtina aprašyti visus programoje naudojamus kintamuosius. VBScript teturi tik vieno tipo (Variant) kintamuosius, tad tenka atidžiai sekti, kokio tipo reikšmę jam priskyrėte. Norint rečiau susipainioti reikia stengtis tvarkingai parinkti vardus. Rekomenduojama naudoti "vengriškąją" sistemą kai kintamojo vardo pradžia nusako jo tipą, pvz.,

Option Explicit
Dim iRow, sVardas, oCon
iRow = 1
sVardas = Request.Form("Vardas")
Set oCon = Server.CreateObject("ADODB.Connection")

2. VBScript programą aprašykite kaip Main procedūrą.
Globalieji kintamieji (ypač kai nenaudojamas jų aprašas, t.y. Dim) gali sukelti klaidas, kurias sunku derinti, pvz., funkcijoje panaudojus globalųjį kintamąjį K manant, kad jis yra lokalus. Šias problemas pašalina visos programos pertvarkymas į Main procedūrą paliekant tik kelis (ir tikrai būtinus) globaliuosius kintamuosius. Pvz.,

Main
'
Sub Main
'
' visi veiksmai
'
End Sub

3. Apimtį sumažinkite naudodami SSI (Server Side Includes)
Į ASP puslapius galima įtraukti kitus failus. Į atskirus failus iškelkite kodo fragmentus, kurie yra bendri keliems puslapiams, pvz., ryšio su DB nustatymą ar navigacijos meniu. Pvz.,

<BODY>
<!--#include FILE="/common/connect.inc" -->
<!--#include FILE="/common/menunav.inc" -->

4. Atsargiai naudokite On Error režimą.
On Error Resume Next yra vienintelė galimybė "gaudyti" programos vykdymo metu aptinkamas klaidas. Tačiau panaudota globaliai ji gali sukelti sunkiai aptinkamas klaidas., pvz.,

Option Explicit
On Error Resume Next
Dim sVardas, ilgid
sVard = Request.Form("Name")
ilgis = Len (sVardas)

Suklydome nurodydami kintamojo vardą ir sVardas niekada neįgaus reikšmės. Tačiau klaidos pranešimo šiuo atveju negausite. Tad On Error naudokite tik funkcijų viduje - ir tik ten, kur to tikrai reikia.

5. Du skirtingi laukų masyvų formose sukūrimo būdai.
Dinamiškai generuojamose lentelėse laukų masyvus galime sukurti dviem būdais:

a) visiems laukams priskiriant tą patį vardą, pvz.,

<%
  Const icTotalRows = 3
  For iRow = 1 To icTotalRows
%>
    <TR><TD><INPUT SIZE=3 NAME="numeris"
                   VALUE="N<%=iRow%>"></TD></TR>
<% Next %>

Naršyklėje šis kodas sugeneruos tris lentelės eilutes su įvedimo laukais. Kaip paimti šių laukų reikšmes parodoma šiame fragmente:

For Each sItem In Request.Form("numeris")
  ' Veiksmai su sItem
  Response.Write "<BR>" & sItem
Next

b) Tačiau galima generuoti lentelės laukus kiekvienam jų priskiriant unikalų vardą (ir sukuriant paslėptą lauką jų kiekio reikšmei saugoti), pvz.

<%
  Const icTotalRows = 3
  For iRow = 1 To icTotalRows
%>
    <TR><TD><INPUT SIZE=3 NAME="numeris<%=iRow%>"
                   VALUE="N<%=iRow%>"></TD></TR>
<% Next %>
<INPUT TYPE="hidden" NAME="kiekis" VALUE="<%icTotalRows%>">

Tokių laukų reikšmių paėmimo būdas iliustruojamas šiame fragmente:

Dim nViso, iRow, sItem
nViso = CInt(Request.Form("kiekis"))
For iRow = 1 To nViso
  sItem = Request.Form("numeris" & iRow)
  ' Veiksmai su sItem
  Response.Write "
" & sItem Next

Koks skirtumas tarp šių dviejų būdų?
Aišku, kad pirmasis (tas pats vardas visiems laukams) paprastesnis programuojant serverio pusės kodą, tačiau kliento pusėje yra sunkiau tiesiogiai pasiekti konkretų atskirą lauką - tenka naudoti cikle For EachNext sakinį perrenkant Form.Elements rinkinį. Laukas neturi unikalaus vardo ir gali būti nelengva paskaičiuoti jo indeksą.

Logistikos (užsakymų įvykdymo sekimo) duomenų bazėje buvo pasirinktas antrasis būdas (galite pabandyti minėtos DB demonstracinį variantą).

6. Formų laukus konvertuokite į reikiamą formatą.
Laukų reikšmės yra perduodamos (ir priskiriamos kintamiesiems) kaip simbolių eilutės. Tad prieš atlikdami kokius nors veiksmus (pvz., aritmetinius) su lauko reikšme reikia ją konvertuoti į atitinkamą formatą. Kitaip galite gauti netikėtus rezultatus, pvz., sudėję du laukus, kurių reikšmės "2" ir "5" gausite "25", o ne 7. Tad reikia rašyti, pvz.,

iSuma = CInt(Request.Form("pirmas")) + CInt(Request.Form("antras"))

7. Naudokite ryšio seanso kintamuosius. Jei keliuose puslapiuose naudojami tie patys parametrai (pvz., vartotojo ID), galite naudotis Session kintamaisiais. Panašius sprendimus galima realizuoti naudojant paslėptus ("hidden") formų laukus ar "sausainiukus" (apie juos paskaitykite šiame puslapyje), tačiau ryšio seanso kintamieji yra daug efektyvesnis būdas (nes jie saugomi serveryje).

Tačiau ryšio seanso terpė turi savųjų niuansų. Pirma, jos kintamieji yra laikini ir automatiškai praranda reikšmė po tam tikro laiko (nustatyto serverio režimais, nutylint IIS'ui - 20 minučių). Šio laiko intervalo reikšmę galite valdyti ir patys priskirdami reikšmę Session.Timeout savybei (turite galimybę ir ištrinti visus ryšio seanso kintamuosius pasinaudoję Session.Abandon metodu). Įtai reikia atsižvelgti kuriant įmonių vidines sistemas, kai vartotojai, įkėlę dinaminį puslapį, gali nebūti aktyvūs ilgą laiko tarpą (išeiti pietauti ir t.t.). Pvz.,

Session("User")= Request.Form("Vartotojas")

Pradinės ryšio seanso kintamųjų reikšmės gali būti priskirtos GLOBAL.ASA failo (esančio pagrindiniame Internetinio taikymo puslapyje) "Session_onStart" procedūroje, pvz.,

Sub Session_onStart
  Session("User")="guest"
  Session("Aktyvumas")=0
  Session("PreviousPageVisited")=""
End Sub

Ryšio seanso kintamąjį "Aktyvumas" galima panaudoti skaitliukui, kiek puslapių aplankė šis vartotojas jo reikšmė padidinant kiekvieno puslapio pradžioje, pvz.,

Sesion("Aktyvumas")=CInt(Sesion("Aktyvumas")) + 1
ComeFrom=Session("PreviousPageVisited")
Session("PreviousPageVisited")="search.asp"

8. Formos laukų reikšmių korektiškumo patikrinimas.
Formos reikšmes patikrinti galite arba kliento pusėje (naršyklėje) arba serverio pusėje (ASP). Reikia gerai pagalvoti kada kurį variantą rinktis.

a) Tikrinimas kliento pusėje yra greitesnis, reakcija į klaidas staigesnė, nėra kreipinių į tinklą ir mažiau apkraunamas serveris. Atrodytų, visi pranašumai už šį variantą. Tačiau WWW svetainių lankytojai gali naudoti įvairias naršykles turinčias skirtingas galimybes. Tad tikrinimas kliento pusėje turėtų būti daromas naudojant kuo universalesnias funkcijas. Pvz.,

<SCRIPT LANGUAGE="JavaScript">
<!--
function doSubmit(forma) {
  if ((forma.Vardas <>> "") && (forma.Slapt <> "")) return true;
  else {
    alert ("Būtina nurodyti tiek vartotoją, tiek jo slaptažodį!");
    if (forma.Vardas == "") forma.Vardas.focus();
    else                    forma.Slapt.focus();
    return false;
  }
} //--> </SCRIPT>

Vartotojas: <INPUT NAME="Vardas"><BR>
Slaptažodis: <INPUT NAME="Slapt" TYPE="Password"><BR>
<INPUT TYPE="Submit" VALUE="Įvesk" onSubmit="return doSubmit(this.form)">

b) serverio pusėje daroma visa parametrų kontrolė, kuriai reikalinga naudotis DB duomenimis. Pvz.,

<!--#include FILE="/common/connect.inc" -->
<%
sName=Request.Form("Vardas")
sPswd=Request.Form("Slapt")

bLogin = False
If (sName <> "") AND (sPswd <> "") Then
  sqlquery="SELECT ID FROM Vartotojai WHERE " & _
              User='" & sName & '" AND Pswd=' & sPswd & "'"
  oRset.Open sqlquery, oCon, 3
  bLogin = oRset.Recordcount > 0
  oRset.Close
End If
If Not bLogin Then
  Response.Write "<P>Neteisingi vartotojo registracijos duomenys. " & _
              "<A HREF=index.htm>Pakartokite...</A>" & _
               "</P></BODY></HTML>"
  Response.End
End If
%>
<!--#include FILE="/common/menunav.inc" -->

8. Sukurkite specialų klaidų pranešimų puslapį.
Klaidos gali atsirasti ne tik dėl klaidingai įvestų duomenų (jų patikrinimo galimybes aptarėm ankstesnėje skiltyje), bet ir dėl sistemos - pvz., nėra ryšio su DB, neteisinga suformuotos SQL užklausos sintaksė ir t.t. Geriau nepalikti šių vykdymo metu (runtime) susidarančių klaidų be dėmesio leidžiant programai "smigti" išvedant standartinį klaidos pranešimą. Supaprastinant klaidų apdorojimą rekomenduojama sukurti specialią paprogramę, kuri generuoja atitinkamus klaidų puslapius.

Function VykdykSQL (byval sqlQuery)
 On Error Resume Next
 oCon.Execute sqlQuery
 If (oCon.Errors.Count > 0) OR (Err.Number <> 0) Then
   KlaidaSQL (sqlquery) ' Paprogramė klaidos puslapio pateikimui
   VykdykSQL = False
 Else
   VykdykSQL = True
 End
End Function

insertSQL = "INSERT Vartotojai (User, Pswd) VALUES ('guest', 'guest')"
bOK = VykdykSQL(insertSQL)
If bOK Then
'  Tęsti kitus veiksmus
End If
AWK kalba - sena ir nuolat aktuali
Ruby on Rails
Sveikųjų skaičių žaidimai
JavaScript atspindžiai
Pelė uodega švystelėjo...
Programavimo kalbų istorija
Programavimas Unix aplinkoje
CGI.pm biblioteka: sausainiai
Ką delne mums neša HTML 4.0?
Lambda išraiškos – Java į naują lygį
Įvadas į Perl kalbą: Kas naudoja Perl?
Kaip valdyti piešinių pakrovimo tvarką
Kaip lankytoją nukreipti į kitą WWW puslapį
Įlįskite į lankytojų kailį
Kaip sužinoti ekrano charakteristikas?
Vaizdi rašysena - Visual Basic Script
Nutylimųjų savybių ieškant
Dygios JavaScript eilutės
Kaip Web'e atsiranda piešinukai?
Didelių duomenų analizės terminai
Programavimo kalbų klegesys
JavaScript pradmenys
Ateities kalbos?
Vartiklis