Критика кода — создаю ли я машину Руба Голдберга?

Я делаю достаточное количество обращений к таблицам базы данных через ADO. В духе того, чтобы все было СУХИМ, я написал следующие функции для возврата массива значений из набора записей. У этого зайца есть мозги? Я использую его в основном для получения набора значений комбинированного списка и т.п., а не для огромных значений. Пример использования (обработка ошибок удалена для краткости):

Function getEmployeeList()
    getEmployeeList= Array()
    strSQL =  "SELECT emp_id, emp_name from employees"
    getEmployeeList = getSQLArray( strSQL, "|" )
End Function

Затем я просто делаю с возвращенным массивом все, что хочу.

Function getSQLArray( SQL, delimiter )
'*************************************************************************************
' Input a SQL statement and an optional delimiter, and this function
' will return an array of strings delimited by whatever (pipe defaults)
' You can perform a Split to extract the appropriate values. 
' Additionally, this function will return error messages as well; check for 
' a return of error & delimiter & errNum & delimiter & errDescription
'*************************************************************************************
    getSQLArray = Array()
    Err.Number = 0
    Set objCon = Server.CreateObject("ADODB.Connection") 


    objCon.Open oracleDSN


    Set objRS = objCon.Execute(SQL)

    if objRS.BOF = false and objRS.EOF = false then
        Do While Not objRS.EOF
            for fieldIndex=0 to (objRS.Fields.Count - 1)
                    If ( fieldIndex <> 0 ) Then
                        fieldValue = testEmpty(objRS.Fields.Item(fieldIndex))
                        recordString = recordString & delimiter & fieldValue
                    Else 
                        recordString = CStr(objRS.Fields.Item(fieldIndex))
                    End If
            Next 
            Call myPush( recordString, getSQLArray )
            objRS.MoveNext
        Loop
    End If
    Set objRS = Nothing
  objCon.Close
  Set objCon = Nothing
End Function

Sub myPush(newElement, inputArray)
    Dim i
    i = UBound(inputArray) + 1
    ReDim Preserve inputArray(i)
    inputArray(i) = newElement                                          
End Sub


Function testEmpty( inputValue )
    If (trim( inputValue ) = "") OR (IsNull( inputValue )) Then 
      testEmpty = ""
    Else
        testEmpty = inputValue 
    End If
End Function

У меня возникнут следующие вопросы: имеет ли смысл абстрагировать все создание/открытие/обработку ошибок объекта набора записей в собственный вызов функции, подобный этому? Я создаю машину Руба Голдберга, где любой, поддерживающий этот код, будет проклинать мое имя?

Должен ли я просто смириться с этим и написать несколько макросов, чтобы выдать код подключения ADO, а не пытаться сделать это в функции?

Я очень новичок в asp, поэтому у меня есть пробелы в его возможностях/лучших практиках, поэтому любой вклад будет оценен.


person GoingTharn    schedule 07.02.2009    source источник


Ответы (3)


Интересно, почему вы не используете GetRows? Он возвращает массив, более подробную информацию вы найдете здесь: http://www.w3schools.com/ado/met_rs_getrows.asp

Несколько замечаний по GetRows:

Set objRS = Server.CreateObject ("ADODB.Recordset")
objRS.Open cmd, , adOpenForwardOnly, adLockReadOnly

If Not objRS.EOF Then
   astrEmployees = objRS.GetRows()
   intRecFirst   = LBound(astrEmployees, 2)
   intRecLast    = UBound(astrEmployees, 2)

   FirstField  = 0
   SecondField = 1
End If

'2nd field of the fourth row (record) '
Response.Write (SecondField, 3)
person Fionnuala    schedule 08.02.2009

Нет ничего плохого в том, чтобы сделать это по-своему. Библиотеки ADO на самом деле были не очень хорошо спроектированы, и их непосредственное использование занимает слишком много строк кода, поэтому у меня всегда есть несколько служебных функций, облегчающих выполнение обычных задач. Например, очень полезно создать себе функцию «ExecuteScalar», которая запускает SQL и возвращает ровно одно значение для всех тех SELECT COUNT(*), которые вы можете выполнить.

НО - ваша функция myPush крайне неэффективна. ReDim Preserve занимает ДОЛГОЕ время, потому что ему приходится перераспределять память и все копировать. Это приводит к производительности O(n2), или тому, что я называю Алгоритм Шлемиэля-художника. Рекомендуется начинать с затемнения, скажем, массива с местом для 16 значений и удваивать его размер всякий раз, когда вы его заполняете. Таким образом, вам не придется вызывать ReDim Preserve больше, чем Lg2n раз.

person Joel Spolsky    schedule 07.02.2009
comment
Ааа, спасибо. Я думаю, что лучше всего на самом деле создать экземпляр массива после вызова набора записей и создать его с помощью getSQLArray = Array(objRS.RecordCount) Таким образом, мне вообще не нужно переделывать. - person GoingTharn; 09.02.2009

Да, общие задачи имеет смысл вынести за скобки. Не вижу ничего плохого в общей идее. Мне интересно, почему вы возвращаете массив строк, разделенных разделителем; вы также можете вернуть массив массивов.

person Morendil    schedule 07.02.2009
comment
Потому что он вставляет в выпадающий список. Обычная практика Windows. Если это то, что делает функция, зачем снова обрабатывать цикл вне функции. - person jmucchiello; 07.02.2009