<% ASP на блюдечке %>. Часть 13
Формализация подхода разработки Web-интерфейсов к базам данных
Полезные советы, или Прежде чем приступать
Правила компоновки (написания) функционального модуля
Проверка правильности заполнения полей формы
Введение
Рассмотренные нами в предыдущих частях настоящей статьи множественные примеры, по сути, в той или иной степени представляли разнообразные интерфейсы к базам данных. Однако ни разу нами не была предпринята попытка формализации подхода к созданию произвольных Web-интерфейсов. В настоящей статье мы попробуем это сделать, рассмотрев наиболее полный набор логических компонентов, составляющих Web-интерфейс, с функциональной точки зрения и определив последовательность шагов, ведущих к скорейшему и оптимальному способу разработки Web-интерфейса к базе данных.
Целью настоящей статьи является формализация подхода к созданию наиболее типичного и полнофункционального Web-интерфейса к базам данных. Согласитесь, что задача весьма актуальна, тем более, что она требует знаний в самых различных областях Web-программирования. Статья будет крайне полезна начинающим Web-программистам, а также тем, кто уже свободно ориентируется в программировании баз данных, но хотел бы упорядочить свое представление о порядке решения задач по разработке Web-интерфейсов и ознакомиться с приемами, значительно облегчающими и ускоряющими этот процесс.
Из чего состоит Web-интерфейс
Разумеется, речь идет о наиболее типичном Web-интерфейсе. Прежде всего это, как правило, система идентификации пользователей, призванная недопустить несанкционированный доступ к данным. Понятно, что само приложение должно содержать некую главную часть, предоставляющую пользователям доступ к данным с целью их просмотра и содержащую ссылки на остальной функционал системы. Под остальным функционалом подразумеваются система добавления и редактирования записей в базе данных, система удаления данных, система сортировки данных и поисковая система. Согласитесь, что данный функционал по работе с базами данных, пожалуй, нельзя назвать неполным.
Давайте теперь остановимся на функциональном элементе поподробнее, приведем экземпляр кода, реализующего наиболее типичную его форму, и рассмотрим последовательность выполняемых действий. При этом мы не будем подробно останавливаться на самом коде и на всех компонентах Web-интерфейса, а попробуем описать порядок его разработки, компоновки и взаимодействия отдельных его частей.
Полезные советы, или Прежде чем приступать
Практически идеальным решением, ведущим к скорейшей реализации проекта, является соблюдение следующих правил при разработке Web-интерфейсов:
- Называйте поля базы данных, строго придерживаясь определенной нотации, например поля-счетчики можно называть IDPackage или IDFirm, поля, содержащие логические переменные, — IsChecked, поля с целочисленными значениями — PackageNum или PackageQuant. Это необходимо, чтобы и вы сами, и программисты, которые впоследствии будут работать с проектом, сумели разобраться что к чему. То же самое относится и к правилам определения заглавий таблиц, хранимых процедур и других объектов баз данных.
- Разбейте проектируемое приложение на логические модули, максимально отвечающие функциональным компонентам поставленной задачи. Например, если необходимо решить задачу проектирования компонентов добавления записей в базу данных и задачу поиска записей в базе данных, то рекомендуется разбить приложение на два модуля и назвать их add.asp и search.asp соответственно.
- Выведите все основные переменные и функции, служащие для манипуляций с данными,
в отдельный файл и озаглавьте его соответствующим образом, например так:
<% option explicit response.buffer=true response.write "<meta charset='visual'>" dim line line = "<img src='images/line.gif' width=600 height=1><br><br>" Sub Header() Response.Write "<head><meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'>" Response.Write "</HEAD><body bgcolor='#D7D5C0' text='#000000' link='#000000' vlink='#FFFFFF' alink='#FFFFFF'>" Response.Write "<table border=0 cellpadding=0 cellspacing=0>" End Sub Response.Buffer = true dim dsn,conn,rs,sql dsn = "DSN=WBOMS; UID=sa;PWD=;database=WBOMS" Sub Connect() set conn = server.createobject("adodb.connection") set rs = server.createobject("adodb.recordset") conn.open dsn End Sub Sub Close() rs.close set rs = nothing conn.close set conn = nothing End Sub Sub Footer() Response.Write "<tr><td><br>" Response.Write "</body></html>" End Sub Sub maxRec() set rs_maxid=server.createobject("adodb.recordset") sql_maxid = "select max(id) as maxid from MessagesTable" Set rs_maxid = Conn.Execute(sql_maxid) maxid = rs_maxid("maxid")'new id rs_maxid.close set rs_maxid=nothing End Sub Function changeColor() If flag = 0 Then flag = 1 color = "#FCFBE8" Else flag = 0 color = "#C1C0AB" End if End Function Sub secure_general() If session("status") <> "admin" Then Response.Redirect "error.htm" End If End Sub %>
- Далее следуйте основным правилам компоновки модуля Web-приложения (см. ниже).
На первый взгляд некоторые из этих советов могут показаться очевидными, однако, как показывает практика, далеко не все разработчики и не всегда придерживаются этих правил.
Правила компоновки (написания) функционального модуля
Прежде чем приступать к созданию того или иного модуля, решающего конкретную задачу в пределах Web-приложения, настоятельно рекомендую ознакомиться с материалом настоящего параграфа.
Для начала составьте все необходимые активные компоненты интерфейсной части с помощью одного из HTML-редакторов (рекомендуется использовать не Microsoft Frontpage, а Macromedia Dreamweaver). Набросав все формы, назовите все их компоненты именно так, как называются соответствующие им поля базы данных. Это позволит избежать путаницы при проектировании больших приложений с множественными наборами данных или приложений, в которых осуществляется обработка больших форм (с большим количеством полей), как, к примеру:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Placing the order</title> </head> <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#000000" alink="#FFFFFF"> <p Style="font: 12pt 'Verdana';"><b>Placing the order:</b></p> <table border=2 width=700> <tr> <td Style="font: 10pt 'Verdana';" colspan=2>To place new order, enter the order details/information:</td> </tr> <form name="AddEditForm" action="add.asp?action=add" method="post" onSubmit="return checkMe();"> <tr Style="font: 10pt 'Verdana';" align=left> <td>Customer Salutation: (*)</td> <td> <select id="CustomerSalutation" name="CustomerSalutation" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 150px"> <option value="Mr." Selected>Mr.</option> <option value="Mrs.">Mrs.</option> <option value="Ms.">Ms.</option> <option value="Dr.">Dr.</option> </select> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Customer First Name: (*)</td> <td><input type="text" name="CustomerFirstName" size="40" maxlength="50" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"></td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Customer Last Name: (*)</td> <td><input type="text" name="CustomerLastName" size="40" maxlength="50" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"></td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Quantity, Product title and pages info: (*)</td> <td> <input type="text" value="1" name="ProdQuantity" size="4" maxlength="5" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> <select id="ProductID" name="ProductID" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 150px;"> </select> <input type="text" value="" name="OtherProduct" size="30" maxlength="31" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> <select id="PagesNum" name="PagesNum" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 150px;"> <option value="1" Selected>1 page</option> <option value="2">2 pages</option> <option value="4">4 pages</option> </select> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Payment method:</td> <td> <select id="PaymentMethod" name="PaymentMethod" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 150px"> <option value="Visa" Selected>Visa</option> <option value="Master Card">Master Card</option> <option value="American Express">American Express</option> </select> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>CardHolder Name (First, MI, Last):</td> <td> <input type="text" name="CardHolderFName" size="15" maxlength="15" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> <input type="text" name="CardHolderMI" size="3" maxlength="4" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> <input type="text" name="CardHolderLName" size="20" maxlength="20" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Card Number:</td> <td><input type="text" name="CardNum" size="40" maxlength="40" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"></td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Card Expiration Date: (D:M:Y)</td> <td> <input type="text" name="CardExpDate" size="1" maxlength="2" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> <select id="CardExpMonth" name="CardExpMonth" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 42px"> <option value="1" Selected>1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> <option value="8">8</option> <option value="9">9</option> <option value="10">10</option> <option value="11">11</option> <option value="12">12</option> </select> <select id="CardExpYear" name="CardExpYear" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 55px"> <option value="2001" Selected>2001</option> <option value="2002">2002</option> <option value="2003">2003</option> <option value="2004">2004</option> <option value="2005">2005</option> <option value="2006">2006</option> <option value="2007">2007</option> </select> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td valign="top">Billing Address:</td> <td> 1:<input type="text" name="BillingAdr1" size="40" maxlength="40" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> 2:<input type="text" name="BillingAdr2" size="40" maxlength="40" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> <table Style="font: 10pt 'Verdana';"> <tr> <td>Type:</td> <td> <select id="BillingAdrType" name="BillingAdrType" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 55px"> <option value="Apt." Selected>Apt.</option> <option value="Ste.">Ste.</option> <option value="Flr.">Flr.</option> </select> #: <input type="text" name="BillingAdrNum" size="3" maxlength="4" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> Gift: <input type="checkbox" Style="font: 10pt 'Verdana';" name="IsGift" value="off"> </td> </tr> <tr> <td>City:</td> <td> <input type="text" name="BillingCity" size="20" maxlength="20" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr> <td>State:</td> <td> <input type="text" name="BillingState" size="20" maxlength="20" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr> <td>Zip Code:</td> <td> <input type="text" name="BillingZip5" size="4" maxlength="5" Style="font: 10pt 'Verdana';background-color: #FCFBE8;">- <input type="text" name="BillingZip4" size="3" maxlength="4" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr> <td>Country:</td> <td> <input type="text" name="BillingCountry" size="20" maxlength="20" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> <input Style="Width: 200px; font: 10pt 'Verdana';" type="button" name="CopyToSAdr" value="Copy to Shipping Address"></td> </tr> </table> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td valign="top">Shipping Address:</td> <td> 1:<input type="text" name="ShipAdr1" size="40" maxlength="40" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> 2:<input type="text" name="ShipAdr2" size="40" maxlength="40" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> <table Style="font: 10pt 'Verdana';"> <tr> <td>Type:</td> <td> <select id="ShipAdrType" name="ShipAdrType" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 55px"> <option value="Apt." Selected>Apt.</option> <option value="Ste.">Ste.</option> <option value="Flr.">Flr.</option> </select> #: <input type="text" name="ShipAdrNum" size="3" maxlength="4" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr> <td>City:</td> <td> <input type="text" name="ShipCity" size="20" maxlength="20" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr> <td>State:</td> <td> <input type="text" name="ShipState" size="20" maxlength="20" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr> <td>Zip Code:</td> <td> <input type="text" name="ShipZip5" size="4" maxlength="5" Style="font: 10pt 'Verdana';background-color: #FCFBE8;">- <input type="text" name="ShipZip4" size="3" maxlength="4" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr> <td>Country:</td> <td> <input type="text" name="ShipCountry" size="20" maxlength="20" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> <input Style="Width: 200px; font: 10pt 'Verdana';" type="button" name="CopyToBAdr" value="Copy to Billing Address"></td> </td> </tr> </table> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Gift Recipient Name:</td> <td> First: <input type="text" name="GRFirstName" size="20" maxlength="20" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> Last: <input type="text" name="GRLastName" size="20" maxlength="20" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Phone: (*)</td> <td> Area Code:(<input type="text" name="PhoneAC" size="2" maxlength="3" Style="font: 10pt 'Verdana';background-color: #FCFBE8;">) Number:<input type="text" name="Phone" size="7" maxlength="7" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Fax:</td> <td> Area Code:(<input type="text" name="FaxAC" size="2" maxlength="3" Style="font: 10pt 'Verdana';background-color: #FCFBE8;">) Number:<input type="text" name="Fax" size="7" maxlength="7" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>E-mail:</td> <td><input type="text" name="Email" size="40" maxlength="40" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"></td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Payment status: (*)</td> <td> <select id="PaymentStatus" name="PaymentStatus" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 150px"> <option value="Pending" Selected>Pending</option> <option value="Paid">Paid</option> </select> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Shipment status: (*)</td> <td> <select id="ShipStatus" name="ShipStatus" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 150px"> <option value="Pending" Selected>Pending</option> <option value="Shipped">Shipped</option> </select> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Tracking Number: (*)</td> <td> <input type="text" name="TrackNum" size="40" maxlength="40" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"> </td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Rush Charge(USD):</td> <td>$<input type="text" name="RushCharge" size="6" maxlength="7" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"></td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Sub-total(USD):</td> <td>$<input type="text" name="Cost" size="6" maxlength="7" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"></td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Sales Tax(USD):</td> <td>$<input type="text" name="SalesTax" size="6" maxlength="7" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"></td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td>Total(USD):</td> <td>$<input type="text" name="Total" size="6" maxlength="7" Style="font: 10pt 'Verdana';background-color: #FCFBE8;"></td> </tr> <tr Style="font: 10pt 'Verdana';" align=left> <td colspan=2 align=center> <input type="submit" name="submit" value="Place the order" Style="font: 10pt 'Verdana';"> <input type="Reset" value="Reset form" Style="font: 10pt 'Verdana';"> </td> </tr> </form> </table> <br> <a Style="font: 10pt 'Verdana';" href="main.asp">Back to Order Manager</a> </body> </html>
Как видите, разобраться во всех компонентах такой формы, не придерживаясь вышеупомянутых нотаций по ее составлению, будет крайне затруднительно.
В ряде случаев для реализации некоторых элементов формы придется извлекать данные из базы данных, формируя соответствующие тэги HTML. Наиболее типичен случай представления полей списка выбора (ComboBox-а) записями базы данных, например:
<select id="ShipType" name="ShipType" Style="font: 10pt 'Verdana';background-color: #FCFBE8;WIDTH: 150px"> <% Call Connect() Sql = "Select * From ShipType Order By ShipType" rs.open Sql, conn Do While NOT rs.EOF Response.Write "<option value=" & rs("ID") & ">" & rs("ShipType") & "</option>" rs.MoveNext Loop Call Close() %> </select>
Далее следует замкнуть форму на себе, то есть определить в качестве обработчика формы сам модуль формы и определить скрипт-функцию проверки корректности заполнения полей формы, например:
<form name="AddEditForm" action="add.asp?action=add" method="post" onSubmit="return checkMe();">
В данном случае страничкой (модулем), инициирующей при приеме данных из текущей формы (модуля Add.asp), является сам модуль Add.asp, которому в качестве параметра передается код выполняемого действия (в данном случае — add). Функцией же обработки правильности введенных значений является функция, вызываемая по событию OnSubmit, которое отрабатывает в пределах окна браузера и до момента передачи данных непосредственно на сервер, а следовательно, предотвращает посылку на сервер некорректной информации и таким образом сокращает количество возможных неудачных попыток передачи данных вследствие опечаток или некорректных действий оператора. Иногда применяется проверка правильности введенных значений и на стороне сервера, в этом случае скрипт-функция в объявлении формы отсутствует и вся проверка осуществляется на соответствующей страничке (если придерживаться данной нами нотации, то на той же самой страничке) проектируемого приложения.
После этого можно приступать к написанию самой составляющей обработки введенных значений и их последующей посылки в базу данных.