|
Программирование >> Программный интерфейс приложений
профаммах или в нескольких местах одной профаммы Предыдущий абзац объясняет одну причину, почему это так. Вот два примера, которые обеспечат дополнительное обоснование этому. Пример 1. В версиях СУБД MySQL, предшествующих 3.22, вызов функции mysql real connect {) производится не совсем так. Как в последней версии. Отсутствует параметр с именем базы данных. И если попробовать применить процедуру doconnect {) со старой клиентской библиотекой СУБД MySQL, она не заработает. Но процедуру do connect () можно исправить так, чтобы она работала и с более ранними версиями. Это значит, что, изменяя процедуру do cor.nect (), мы можем увеличить переносимость всех профамм, которые ее используют. Если программный код включать непосредственно в каждый клиент, придется вносить изменения во все профаммы. Для того чтобы процедура do connect () могла работать с более ранними версиями функции mysqlrealconnect {), нужно воспользоваться макросом MYSQL VERSI0N ID, который содержит номер текущей версии. Модифицированный do connect {) проверяет значение MYSQL VERSI0N ID, и в зависимости от этого обращается к соответствующей версии функции mysql real connect (): MYSQL * do connect (char *-hobt name, char *user name, char *password, char *db name, unsigned mt port num, char *socket name, unsigned int flags) { MYSQL *conn; /* указатель на дескриптор соединения */ conn = mysql init (NULL); /* размещение и инициализация дескриптора соединения */ if (conn == NULL) { fprintf (stderr, сбой mysql init()\n ); return (NULL); #if defined(MYSQL VERSION ID) && MYSQL VERSION ID >= 32200 /* 3.22 и выше */ if {mysql real connect (conn, host name, user name, password, db name, portnum, socket name, flags) == NULL) fprintf (stderr, сбой mysql real connect0: \nError %u (%s)\n , mysql errno (conn), mysql error (conn)); return (NULL); #else /* до версии 3.22 */ if (mysql real connect (conn, host name, user name, password, portnum, socket name, flags) == NULL) fprintf (stderr, сбой mysql real connect0 : \nError %u (%s)\n . mysql errno (conn), mysql error (conn)) ; return (NULL); if (db name = NULL)/*имитация действия параметра dbname*/ { If (mysql select db (conn, dbname) != 0) { fprintf (stderr, сбой mysql select db{): \nError %u (%s)\n , mysql errno (conn), mysql error (conn)); mysql close (conn); return (NULL); #endif return (conn); /* соединение установлено */ Модифицированная версия процедуры do connect () аналогична предыдущей версии за исключением двух моментов. Она не передает параметр db narae старой версии функции raysql real connect О потому, что эта версия не имеет такого параметра. Если имя базы данных непустое, процедура do connect () вызывает функцию raysql select db () ДЛЯ того, чтобы сделать указанную базу данных текущей. (Это имитирует реакцию на отсутствие параметра db narae.) Если база данных не находится, процедура do connect () вьщает сообщение об ощибке, заверщает соединение и возвращает значение null как свидетельство об ощибке Пример 2. Этот пример базируется на изменениях, внесенных в процедуру do connect О, по сравнению с первым примером. В результате этих изменений появилось три вызова диагностических функций mysql errno() и raysql error (). Действительно утомительно программировать детальное сообщение о возникающих ошибках. Номер ошибки тоже трудночитаем. Значительно проще прочитать что-то наподобие: print error (conn, сбой raysql real connectО ) . Так что соберем диагностику ошибок в процедуру pnnterror (). Ею можно воспользоваться для того, чтобы выполнить какие-то осмысленные действия, даже если переменная conn будет равняться null . Таким же образом можно воспользоваться процедурой print error (), если функция mysql init () возвращает ошибку. Таким образом мы избежим путаницы вызовов (одни fprintf () и другие print error ()). Глава 6, Программный интерфейс MySQL С API 289 101724 Кто-то может возразить, что при этом программный код делается нечитаемым только потому, что надо показать, что модульный стиль программирования лучше. Ведь совсем не обязательно писать весь программный код обработки ошибочных ситуаций каждый раз, когда это необходимо. Достаточно просто скопировать его. Все это правильно, но у меня есть возражения. Даже если использовать копирование, значительно проще копировать короткие блоки исходного текста. Независимо от того, предпочитаете вы или нет вызывать обе функции каждый раз, когда необходимо диагностировать ошибки, постоянная запись диагностирующего кода может привести к внесению изменений и порождает неуверенность при диагностировании ошибок. Заключение диагностирующего кода в отдельную функцию уменьшает этот соблазн и повышает однозначность программного кода. При необходимости изменить формат сообщений об ошибках, это проще сделать в одном месте. Или если принято решение выводить сообщение об ошибках в регистрационный журнал, а не на устройство stderr (или в дополнение к нему), это проще сделать только в процедуре printerror {). Этот подход позволяет уменьшить количество ошибок и увеличивает уверенность в положительных результатах своего труда. Если при тестировании программы используется отладчик, то можно порекомендовать один очень удобный прием: поместить точку останова внутри функции диагностики ошибок. Вот текст диагностирующей функции printerror (): void print error (MYSQL *conn, char *message) { fprintf (stderr, %s\n , message); if (conn != NULL) fprintf (stderr, Error %u (%s)\n , mysql errno (conn), mysql error (conn)); Процедура print error() находится в common, с, поэтому добавим ее прототип в common.h: void print error (MYSQL *conn, char *message); Теперь внесем изменения в do connect () и добавим вызов процедуры print error(): MYSQL * do connect (char *host name, char ♦user name, char *password, char *db name,
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |