Тема открыта по просьбе жителей Королевства и посвящена обсуждению вопросов оптимизации кода. Выставляйте свои лучшие и худшие тексты и не стесняйтесь их обсуждать. В споре рождается истина. Или, по крайней мере, оптимизация.
Всего в теме 737 сообщений
Добавить свое сообщение
Отслеживать это обсуждение
- Тестирование проекта. Отладка.
- Подводные камни
- Централизованная обработка ошибок
- Бета-тестирование
- Давайте учиться на ошибках.
- Почему программисты допускают ошибки?
- Автоматизированные тесты для GUI
- О системах контроля ошибок
№ 407 24-02-2007 13:18 | |
Ответ на »сообщение 400« (Бел Амор)
___________________________
>>> Если отвлечься от конкретного чекбокса, то в общем случае с таким утверждением я не согласен.
Общие утверждения редко бывают истинными, если их применять ко всем без исключения частным случаям ;-)
>>> вопрос: какие косяки во внешнем виде и поведении сможет заметить ваш острый глаз и какие потенциальные проблемы могут возникнуть впоследствии?
Автор все вылизал, так что комар носа не подточит. Но поставили программу на другой компьютер, а там шрифт немного другой. И... бабах! ... текст уже опутсился на пару пикселов ниже. А потом поставили на другую ОС, где радиобуттон организован совсем по-другому. И тут наше сочетание стандартного компонента (который является надстройкой надо объектом ОС) и нестандартного текста к нему превращается в полную кашу.
Скорость обработки -- это вообще отдельная песня. Слепили мы что-то нестанартное из трех различных компонентов. При перерисовке компоненты будут перерисовываться по очереди, реагируя на WM_PAINT, в то время как единый компонент будет перерисовываться сразу целиком.
№ 406 24-02-2007 04:45 | |
Ответ на »сообщение 405« (Антон Григорьев)
___________________________
>>> Сам эту процедуру не видел, но из вашего описания получается следующие косяки:
Виноват... Не очень ясно объяснил. Вы немного не так поняли.
Итак, у обычной радиогруппы присутствует:
1. Рамка
2. Надпись на рамке (это и есть TRadioGroup.Caption)
3. Несколько радиокнопок с надписями (задаются через TRadioGroup.Items)
Задача: не изменяя ничего внутри рамки, сделать надпись вверху слева на рамке жирной.
Проблема в том, что шрифт задается один на всех и отдельно установить Bold для TRadioGroup.Caption не получится. Поэтому мы на место этой надписи просто сажаем новую TLabel и для нее и задаем нужный шрифт.
Ни с какими событиями это не связано, это чисто внешнее украшательство. В сухом остатке, если убрать все лишнее (там есть еще несколько нюансов, не имеющих отношения к делу в данном случае), то все это безобразие выглядит примерно так:
procedure BoldCaption(RadioGroup: TRadioGroup);
begin
with TLabel.Create(RadioGroup) do
begin
Parent := RadioGroup;
Top := 0;
Left := 8;
AutoSize := True;
Caption := RadioGroup.Caption;
Font.Style := [fsBold];
RadioGroup.Caption := '';
end;
end;
И вы всё время забываете, что подобные решения кажутся простыми и понятными только сразу после написания этого кода. Пройдёт год-два, вы вернётесь к нему и будете с удивлением смотреть, что это такое, зачем нужно и как правильно пользоваться, чтобы ничего не поломать.
Приведу пример реального использования (изменены фамилии и убрано 4 строки):
constructor TSomeForm.Create;
begin
inherited Create(Application);
...
SomeDoc := TSomeDoc.Create;
...
...
PageControl.ActivePage := tsCommon;
...
WindowState := wsMaximized;
BoldCaption(rgSome1);
BoldCaption(rgSome2);
BoldCaption(rgSome3);
BoldCaption(rgSome4);
pnlSome.BevelOuter := bvNone;
end;
destructor TSomeForm.Destroy;
begin
SomeDoc.Free;
inherited Destroy;
end;
Все ясно, четко и понятно (замечу, что форма очень навороченная). Ошибиться или запутаться можно, но это надо очень постараться.
№ 405 23-02-2007 23:52 | |
Ответ на »сообщение 400« (Бел Амор)
___________________________
Если отвлечься от конкретного чекбокса, то в общем случае с таким утверждением я не согласен. В качестве примера приведу поцедуру BoldCaption из того-же модуля FormUtil, которая создает метку, сажает ее на RadioGroup в нужное место, делает ее Bold, копирует себе Caption радиогруппы и обнуляет ее. Получается радиогруппа с жирным заголовком. Внимание, вопрос: какие косяки во внешнем виде и поведении сможет заметить ваш острый глаз и какие потенциальные проблемы могут возникнуть впоследствии? При условии, что эта процедура вызывается один раз в конструкторе формы и не планируется устанавливать Enabled = False, а также менять Caption.
Сам эту процедуру не видел, но из вашего описания получается следующие косяки:
1. У нормальной радиокнопки, когда она в фокусе, название обводится пунктирным прямоугольником, чего у вашей метки нет.
2. У нормальной радиокнопки для выбора можно щёлкать мышью не только по кружку, но и по тексту.
И если второй пункт реализуется относительно просто с помощью TLabel.OnClick, то первый требует переписывания TLabel. Так не проще ли сразу переписать тот компонент, который нужен?
И вы всё время забываете, что подобные решения кажутся простыми и понятными только сразу после написания этого кода. Пройдёт год-два, вы вернётесь к нему и будете с удивлением смотреть, что это такое, зачем нужно и как правильно пользоваться, чтобы ничего не поломать.
№ 404 23-02-2007 15:41 | |
Ответ на »сообщение 403« (Cepгей Poщин)
___________________________
А я с трудом представляю зачем нужно делать запрещенный компонент без внешних проявлений, но это так, к слову...
Ну, судя по написанному вами далее, фантазия у вас развита неплохо, так что не скромничайте... А в качестве примера: неужели никогда не возникало желания, чтобы какой-нибудь хорошо акцентированный TDBEdit что-то отображал, но при этом был не только ReadOnly, но еще и не мог принимать фокус? И при этом не был блеклым? Что, писать наследника? Ужоз... Ж8D
Где в описании написано, что её нужно вызывать только в конструкторе и не более одного раза?
Сэр... Вы зануда...
Предлагаю вполне реальный сценарий:
1.В конструкторе есть некий участок кода, который занимается инициализацией каких-то данных, среди него завалялся вызов этой процедуры.
2.Потом его решили вызывать не только при создании формы, но и после отображения формы из скрытого состояния.
3.Потом его решили вызывать при нажатии на кнопочку Refresh, чтобы отображать изменения в БД.
4.Потом обленились и решили вызывать по таймеру каждые 30 мин.
5.Потом на круглом столе появляются копросы типа: "как бы мне cделать так, чтобы в полночь/в обед/во время перекура программа сама себя закрывала, а потом откывала?"
(задумчиво) Про фантазию я, кажется, уже говорил...
Сэр... Мои аплодисменты...
№ 403 23-02-2007 14:48 | |
Ответ на »сообщение 401« (Бел Амор)
___________________________
Я с трудом представляю себе неоходимость перебирать разномастные компоненты, лежащие на конкретной форме А я с трудом представляю зачем нужно делать запрещенный компонент без внешних проявлений, но это так, к слову...
т.к. процедура вызывается один раз в конструкторе формы Где в описании написано, что её нужно вызывать только в конструкторе и не более одного раза? Ладно, допустим когда в приложении одна форма и одна такая процедура (пусть две) можно по быстрому посмотреть на её код, прочитать описание, проанализировать, но если их переваливает за сотню, такой стиль программирования крайне осложнит любые попытки что-либо изменить в проекте. Особено если над ним предварительно уже поработало несколько поколений, каждое из которых плодило свои наборы подобных вспомогательных процедур.
Он споткнулся, упал, поднялся, опять упал и так поднимался и падал Вы на льду ни когда не стояли? Предлагаю вполне реальный сценарий:
1.В конструкторе есть некий участок кода, который занимается инициализацией каких-то данных, среди него завалялся вызов этой процедуры.
2.Потом его решили вызывать не только при создании формы, но и после отображения формы из скрытого состояния.
3.Потом его решили вызывать при нажатии на кнопочку Refresh, чтобы отображать изменения в БД.
4.Потом обленились и решили вызывать по таймеру каждые 30 мин.
5.Потом на круглом столе появляются копросы типа: " как бы мне cделать так, чтобы в полночь/в обед/во время перекура программа сама себя закрывала, а потом откывала?"
Сэр... Признайтесь... Ведь вы немножко преувеличили? :) Если на эту программу посмотрит профессионал, то он скажет "лучше всё взять да переписать!", а "студень" и месяц может провозиться.
Короче, по моему, заменять свойства такими процедурами — плохо, а методы допустимо. Например: нет большой разницы procedure SaveCheckboxToIni и procedure TCheckboxEx.SaveToIni.
P. S. В общем правильно делаете, что ни кому не даёте смотреть свои исходники ;o)
№ 402 23-02-2007 13:57 | |
Ответ на »сообщение 401« (Бел Амор)
___________________________
>>> А как это повлияет на последовательность перехода по tab?
Никак. Панель имеет тот-же TabOrder, что имел раньше пересаженный на нее компонент, а внутри панели действует свой порядок обхода, но там один компонент, а сама панель фокус не принимает (смотрим код), как и вся стопка из панелей, если вдруг она появится.
Прошу извинить, проглотил пару фраз.
Панель запрещена, поэтому находящийся на ней компонент фокуса не принимает. Но в качестве перестаховки панель имеет тот-же TabOrder, что раньше имел находящийся теперь на ней компонент. И если вдруг кто-то доберется до этой панели и поставит ей Enabled = True, то порядок обхода по Tab останется таким-же, каким он был до вызова процедуры.
№ 401 23-02-2007 13:21 | |
Ответ на »сообщение 394« (Cepгей Poщин)
___________________________
В-четвертых: допустим некто в будущем захочет перебрать все контролы на форме, после DisableCtrl это будет сделать гораздо сложнее.
Руки оборвать этому "некту"...
В большом проекте неделя будет затрачена только на поиски и определение смысла этой самой процедуры.
Сэр... Признайтесь... Ведь вы немножко преувеличили? :)
Кроме того, я уже говорил, что это совершенно реальный кусок кода. И комментарии - тоже реальны. Так что нет необходимости даже читать код.
В результате тревиальная конструкция
For i := 0 to ControlCount - 1 do
...
на написание которой уходит секунд 15 превратится в сложную задачу.
Я с трудом представляю себе неоходимость перебирать разномастные компоненты, лежащие на конкретной форме. Кроме того, если мы там чего-то ищем, то, наверное, знаем что... И это "что-то" - вряд-ли запрещенный таким образом компонент.
Потом, что будет если DisableCtrl вызвать несколько раз (по ошибке)?
Стопка будет. Из панелей. Без каких-либо проявлений во внешнем виде и поведении.
Но это скорее из области фантастики, т.к. процедура вызывается один раз в конструкторе формы и описанная вами ситуация скорее напоминает анекдот "он споткнулся, упал, и так семь раз подряд".
А если это происходит где-то в цыкле?
Хорошо: "Он споткнулся, упал, поднялся, опять упал и так поднимался и падал, пока его не схватили за руки, за ноги и за голову пять человек, после чего он отбился чудом и убежал..."
А как это повлияет на последовательность перехода по tab?
Никак. Панель имеет тот-же TabOrder, что имел раньше пересаженный на нее компонент, а внутри панели действует свой порядок обхода, но там один компонент, а сама панель фокус не принимает (смотрим код), как и вся стопка из панелей, если вдруг она появится.
№ 400 23-02-2007 13:18 | |
Ответ на »сообщение 393« (Geo)
___________________________
>>>>>> Часть участников обсуждения считает, что при недостатке функционала стандартного компонента следует строго писать наследника, в котором этот самый функционал и добавляется.
>>>Не знаю, кто так считает. Но только не я ;-)
Блин, почудится-же иногда... Пора налаживать режим сна и питания...
Я восстал против другого. Типа, у CheckBox'а убираем Caption, рядом кладем TStaticText и т.д. По-моему, создавать видимость компонента с нестандартными свойствами путем слепления в кучу нескольких стандартных компонент -- это не есть гут.
Тут скорее соглашусь. В данном конкретном случае наблюдается некоторый перебор...
Во-первых, обработка такого "составного компонента" ухудшается (скорость проприсовки, реакция на события и т.п.), во-вторых, зачастую остаеются мелкие "косячки", которые лично мне сильно режут глаз, в-третьих, проблемы могут возникнуть при переходе на другую тему (компьютер, версию ОС).
А тут скорее не соглашусь. Если отвлечься от конкретного чекбокса, то в общем случае с таким утверждением я не согласен. В качестве примера приведу поцедуру BoldCaption из того-же модуля FormUtil, которая создает метку, сажает ее на RadioGroup в нужное место, делает ее Bold, копирует себе Caption радиогруппы и обнуляет ее. Получается радиогруппа с жирным заголовком. Внимание, вопрос: какие косяки во внешнем виде и поведении сможет заметить ваш острый глаз и какие потенциальные проблемы могут возникнуть впоследствии? При условии, что эта процедура вызывается один раз в конструкторе формы и не планируется устанавливать Enabled = False, а также менять Caption.
Да, в этом случае просто напрашивается обычный нормальный наследник, помещенный в палитру. Но...
Допустим, есть старый проект, в котором мы хотим во всех радиогруппах сделать жирный заголовок. Внимание, вопрос номер два: что проще и безопаснее сделать:
1. Удалить старую радиогруппу, вставить новую радиогруппу, восстановить имя, Caption, Items, размеры, положение, события... Я ничего не забыл? А таких групп -много...
2. В конструкторе формы добавить по одной строчке на каждую радиогруппу. Если что и забыл - максимум - заголовок останется обычным.
Так что наследника радиогруппы, конечно, желательно написать и использовать во вновь создаваемых формах, а в старых - лучше все-таки использовать старую добрую BoldCaption. И каких-либо потенциальных проблем здесь я не вижу.
Так что такой прием я признаю только для одного случая: когда нужно срочно заткнуть дыру, обнаруженную за 5 минут до демонстрации программы Заказчику ;-)
Соглашусь на 30% и то только в отношении конкретного чекбокса :)
№ 399 21-02-2007 03:13 | |
Ответ на »сообщение 398« (Cepгей Poщин)
___________________________
Ответ на »сообщение 397« (panda)
___________________________
но не проходит
for Control in Controls do
if (Control is TCheckBox) then Memo1.Lines.Add(Control.Name);
т.к. Controls не коллекция и не список а свойство типа TControl.
А fControls недоступно.
Зато, если Controls относится к форме, можно дописать что вроде:
TForm1 = class(TForm)
...
public
function GetEnumerator: TControlEnumerator;
end;
и тогда можно будет так:
for Control in self do
if (Control is TCheckBox) then Memo1.Lines.Add(Control.Name);
не так выразительно, конечно, но...
№ 398 20-02-2007 08:19 | |
Ответ на »сообщение 397« (panda)
___________________________
Что характерно в дельфе проходит:
for S In List do
if S <> '' then Memo1.Lines.Add(S);
но не проходит
for Control in Controls do
if (Control is TCheckBox) then Memo1.Lines.Add(Control.Name);
т.к. Controls не коллекция и не список а свойство типа TControl.
А fControls недоступно.
Добавить свое сообщение
Отслеживать это обсуждение
Дополнительная навигация: |
|