Вчера начал разбираться с чужим проектом на Delphi 7. Система весьма сложная – несколько взаимосвязанных АРМов по 20-50 форм (а может и больше, точно не считал). Усложняет все то, что она разрабатывается уже давно и пережила смену нескольких команд разработчиков. Каждая команда приносила в проект свои инновации. Например, одна из них перевела доступ к БД Oracle с BDE на ADO. При этом все старые объекты для работы с базами через BDE (TDatabase, TTable, TQuery и TStoredProc) продолжают лежать на формах рядом с их копиями для работы через ADO (TADOConnection, TADOTable, TADOQuery и TADOStoredProc). Они даже клонировали объекты TDataSource для ADODataSet'ов. Все замеченные беглым взглядом "интересные" моменты перечислять не буду, а вернусь к заголовку этой заметки. Одна из команд добавила в проект DBGridEh из EhLib 6.0 в компанию к стандартному DBGrid'у. Хороший выбор grid'а, одобряю ;-) Хочу поделится с вами их реализацией сортировки по клику на заготовке колонки. К каждому DBGridEh'у, подчеркиваю - к каждому DBGridEh'у, был написан обработчик OnSortMarkingChanged:
Еще, как зануда, отмечу, что вещи в стиле
Так, что господа, те кто считает себя программистом, дружите с Try...Finally...End и главное - ИЗУЧАЙТЕ ИСПОЛЬЗУЕМЫЙ ИНСТРУМЕНТАРИЙ!!!
...
dsXYZ: TDataSource;
gridXYZ: TDBGridEh;
...
procedure TfmMain.gridXYZSortMarkingChanged(Sender: TObject);
var
i: Integer;
s: String;
b: TBookmark;
begin
Screen.Cursor := crHourGlass;
b := dsXYZ.DataSet.GetBookmark;
s := '';
for i := 0 to gridXYZ.SortMarkedColumns.Count - 1 do
begin
s := s + gridXYZ.SortMarkedColumns[i].FieldName;
if (gridXYZ.SortMarkedColumns[i].Title.SortMarker = smDownEh) then
s := s + ' DESC';
s := s + ';';
end;
TADODataSet(dsXYZ.DataSet).IndexFieldNames := s;
dsXYZ.DataSet.GotoBookmark( b );
Screen.Cursor := crDefault;
end; В одном из АРМ'ов только на главной форме больше 20 DBGridEh'ов лежащих на страницах TNotebook. И на каждый был написан свой обработчик! Если говорить о Delphi, или о объектно-ориентированном программировании в целом, то почему бы все эти десятки одинаковых обработчиков не заменить на один, где вместо gridXYZ использовать TDBGridEh(Sender) (или (Sender as TDBGridEh)), а вместо dsXYZ.DataSet использовать TDBGridEh(Sender).DataSet? Но самое интересное, что для сортировки в DBGridEh и такого обработчика писать не надо. EhLib для автоматической сортировки данных в DataSet'е имеет набор специальных объектов и от программиста требуется только добавить в раздел "uses" любого модуля в проекте один из модулей EhLibXXX (EhLibBDE, EhLibADO, EhLibCDS... в зависимости от подключенного к grid'у DataSet'а). Таким образом, вместо написания и копипаста десятков обработчиков OnSortMarkingChanged нужно было всего лишь подключить к проекту небольшую юниту EhLibADO.Еще, как зануда, отмечу, что вещи в стиле
необходимо использовать совместно с конструкцией Try...Finally...End, т.к. если между этими строчками во время выполнения программы произойдет ошибка, то курсор не будет восстановлен. Т.е. нужно было написать так:Screen.Cursor := crHourGlass; ... Screen.Cursor := crDefault;
А еще к восстановлению курсора в блок Finally...End было бы неплохо, для высвобождения памяти распределенной при вызове GetBookmark, добавить DataSet.FreeBookmark(b). Это же элементарно – для всех изменяемых или создаваемых ресурсов, на случай ошибки, нужно гарантировать возвращение их к исходному состоянию или высвобождению занимаемой ими памяти.Screen.Cursor := crHourGlass; Try ... Finally Screen.Cursor := crDefault; End
Так, что господа, те кто считает себя программистом, дружите с Try...Finally...End и главное - ИЗУЧАЙТЕ ИСПОЛЬЗУЕМЫЙ ИНСТРУМЕНТАРИЙ!!!