skiminok: (Default)
[personal profile] skiminok
Мелочи из собственной практики ООП. Часть вторая.

Каждый уважающий себя инетчик хоть раз читал прикол про задачу "Как поймать льва в пустыне и посадить его в клетку?", адаптированную под различные категории пользователей ПК. В частности, там присутствовала следующая строчка:
Программист на Делфи - орёт по всем форумам и конференциям "Народ, как найти компонент, который ищет льва в пустыне и помещает его в клетку?
Как ни горько осознавать эту иронию, но под ней есть почва, и немалая. Десятилетия использования Delphi исключительно как простого и доступного средства разработки виндовых гуёвых приложений дали о себе знать. Теперь вся эта масса быдлокодеров привыкла работать с программой (даже скрытной) так: создали приложение, перетянули на форму парочку любимых компонент, первым делом написали Form1.Visible:=false и, довольные, чего-то там мастерят со своими компонентиками. Внимание, вопрос: ЗАЧЕМ?!

С подобной историей я столкнулся вчера. Мой знакомый Вова пишет свой очередной троян. Получается у него комбинация из пары батников и одного экзешника, который он решил забабахать на делфях. С приложения я просто фигею: VCL Forms Application, на форме гордо красуется единственный TServerSocket, в событии создания формы - одна строчка активации сервера, в событии уничтожения формы - одна строчка его деактивации. Всё остальное - код событий это самого сервера. И ещё немного кода добавлено непосредственно в саму программу. Когда это чудо инженерной мысли потребовалось перенести с Delphi 7 на Borland Developer Studio 2006, среда принялась ругаться. Оказывается, в последних версиях технологию сокетов (вполне заслуженно) признали устаревшей, компоненты, относящиеся к ней, с палитры убрали, но классы для совместимости в VCL оставили. И теперь Студия в упор не понимает, когда ей в .dfm-файле чёрным по белому написано, что форма содержит TServerSocket как компонент. Вова застопорился и выпал в осадок...
Хотя "проблема" на самом деле решается банально. Компонент я с формы стёр на фиг, зато одноимённое свойство того же типа засунул в приватные для TForm1. И код создания и уничтожения формы увеличился в сумме на четыре строчки.

procedure TForm1.OnCreate(Sender: TObject);
begin
  Form1.ServerSocket1:=TServerSocket.Create(Form1);
  Form1.ServerSocket1.OnClientRead:=Form1.ServerSocket1ClientRead;
  Form1.ServerSocket1.OnClientConnect:=Form1.ServerSocket1ClientConnect;

  Form1.ServerSocket1.Active:=true; //это было раньше
end;

procedure TForm1.OnDestroy(Sender: TObject);
begin
  Form1.ServerSocket1.Active:=false; //это было раньше

  Form1.ServerSocket1.Free;
end;


Вот скажите мне, это что, так архисложно, да? Ведь по факту компонент от класса совершенно ничем не отличается! Когда мы перетягиваем красивую иконку с палитры на форму, мы просто-напросто говорим среде совершить за нас следующие операции:
- назначить экземпляр класса свойством созданного наследника типа TForm;
- сделать форму ответственной за его создание и уничтожение, сняв с программиста необходимость следить за всеми конструкторами и деструкторами;
- обеспечить удобный менеджмент событиями и свойствами.
И получается быдлокодерство. Мы с упоённым лицом тыкаем мышкой в кнопочки и картиночки, забывая, что всё это - и свойства, и обработчики событий - можно и самому прописать в run-time, то бишь во время выполнения программы, и результат получится один и тот же! Нет. Результат ещё лучше, поскольку исчезают мелкие потери памяти и, кроме того, прогер сам знает и видит по коду, кто что у него делает. Но нет, нам лучше набросать на серое поле маленьких иконок и избежать лишних нагрузок на печень...
Я вообще не постигаю идею такого явления, как "невизуальный компонент". Зачем? С визуальными всё как раз понятно, если во время выполнения программы начать двигать по ней элементы оформления, то выйдет жестокая мозгодробилка - по собственному опыту знаю. Но смысл невизуального?! Это просто класс, не более того; будучи невизуальным, он никогда не имеет слишком много свойств (в среднем - не более десятка, максимум, виденный мною - штук 15-20), и всё это можно легко и просто определить по ходу дела. Вопрос ещё в другом. Если вы используете только невизуальные классы и окна ваше приложение иметь не должно - тогда зачем вам форма?!
Весь код Вова мог написать непосредственно в приложении, загнав свой TServerSocket в переменные и объявив процедуры ServerSocket1ClientRead и ServerSocket1ClientConnect как методы класса (procedure ... of object), убив модуль с формой подчистую и вставив в середину кода выполнение до бесконечности или до получения сообщения о закрытии. В итоге получил бы миниатюрное приложение в несколько килобайт - смесь структурного и объектно-ориентированного программирования. От первого здесь выполнение программы как алгоритма шаг за шагом, от второго - наличие делегатов (обработчиков событий). Учитывая, что троян обязан быть меньше некуда - это более чем необходимый шаг...

Мораль сей басни такова:не превращайтесь в быдлокодеров, не увлекайтесь компонентами, господа. Учите основы той среды, которую используете. В частности, работу с классами на уровне человека, разбирающегося в своей области деятельности, а не юзера - тупой овцы. А то так мы и приходим к строчкам ностальгической песенки. "И заказчик-дурак тычет мышкой в картиночки гордо..."

Date: Tuesday, 12 February 2008 18:33 (UTC)
From: (Anonymous)
На самом деле редактирование свойств компонентов в design-time это хорошо(и как и любой инструмент имеет свою сферу применения), но для невизуальных компонентов конечно форму создавать не имеет смысла, а вот data module - вполне(напимер в автоматизированных системах работающих с базами данных). Кстати Turbo Delphi Explorer хорошо поощряет создание объектов в ран-тайме, ибо регистрировать их нельзя.

P.S. При уничтожении родительского компонента необязательно уничтожать дочерние компоненты созданные в ран-тайме, достаточно присвоить им подходящего Owner'а при создании.

Date: Tuesday, 12 February 2008 18:59 (UTC)
From: [identity profile] skiminog.livejournal.com
> На самом деле редактирование свойств компонентов в design-time это хорошо(и как и любой инструмент имеет свою сферу применения)
Для дизайна, оформления, гуя, короче говоря - даже вопросов не возникает. Для того оно изначально и задумывалось. Для удобной композиции классов проекта и продумывания его идеи - UML есть просто панацея. Для первоначальной настройки коннекта с БД - BDS предлагает превосходный визуальный механизм. Но в случае невизуальных компонентов - просто несусветная глупость...

> При уничтожении родительского компонента необязательно уничтожать дочерние компоненты созданные в ран-тайме, достаточно присвоить им подходящего Owner'а при создании.
Согласен. В коде поэтому Owner'ом и указана форма, а не nil. Просто вбитая в мозг привычка... что сам заказал - сам и освобождай. Иначе худо будет...

Profile

skiminok: (Default)
skiminok

Most Popular Tags

Page Summary

July 2011

S M T W T F S
     12
3456789
10111213141516
17181920212223
242526272829 30
31