tag:blogger.com,1999:blog-1702873441071265539.post7398994965120801469..comments2023-05-29T19:02:20.570+03:00Comments on Блог GunSmoker-а: 98/97: Отделяйте интерфейс пользователя от кодаGunSmokerhttp://www.blogger.com/profile/15611696588191431330noreply@blogger.comBlogger39125tag:blogger.com,1999:blog-1702873441071265539.post-15218645394196339582011-09-03T00:18:27.482+04:002011-09-03T00:18:27.482+04:00procedure GetHtml(HTTP: TIdHTTP; const URL: string...procedure GetHtml(HTTP: TIdHTTP; const URL: string);<br /><br />Кому надо - сам передаст. Может с формы, а может - создаст сам, динамически.<br /><br />Но бред какой-то получается. В чём смысл существования процедуры GetHtml, если по своей сути она является методом к объекту, только что вынесенному отдельно в виде процедуры? Так и делать её надо методом, а не процедурой.<br /><br />А так получается, что постановка задачи не корректна: вы изначально делаете "неправильное" действие (вынос метода объекта в автономную процедуру), а потом спрашиваете: а правильно-то как? А правильно-то было этого не делать.<br /><br /><i> >>> вот не хочется мне создавать объект динамически и настраивать его свойства при создании</i><br /><br />Если вопрос про лень - то тут или-или. Если ленимся - то передаём IdHTTP извне. Если делать правильно - то делаем наследника IdHTTP или декоратор. В промежутке между этими вариантами - создание IdHTTP в GetHtml (кстати, можно же не IdHTTP, можно WinInet).<br /><br /><i> >>> И ещё вопрос, когда необходимо определять свои процедуры и функции в классе формы, а когда это запрещается?</i><br /><br />Ответ на вопрос зависит от: кем запрещается?<br /><br />Если это был вопрос про создание хорошего кода, то тут так просто не ответить. Могу посоветовать взять в руки GoF или Макконнела.<br /><br />Если кратко:<br />- Форма должна быть единым объётом, чёрным ящиком<br />- Манипулирование компонентами формы должно производиться самой формой (её внутренними методами)<br />- Наружу должна выставлять методы по манипулированию собой<br />- Каждый метод должен выполнять одну задачу. Если метод выполняет две задачи, его нужно разбить на два<br />- Логика программы не должна содержаться в форме<br /><br />Как-то так.GunSmokerhttps://www.blogger.com/profile/15611696588191431330noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-59903256950449392392011-09-02T22:36:52.076+04:002011-09-02T22:36:52.076+04:00Допустим я использую процедурный подход, как мне в...Допустим я использую процедурный подход, как мне в реализации процедуры не ссылаться на объект Form1 чтобы добраться до свойств и методов объектов расположенных на форме, скажем тотже clHttp1 расположенный на форме:<br /><br />procedure GetHtml(URL: string);<br />var<br /> html: TStrings;<br />begin<br /> html := TStringList.Create;<br /> try<br /> Form1.clhttp1.Get(URL, html);<br /> finally<br /> html.Free;<br /> end;<br />end;<br /><br />вот не хочется мне создавать объект динамически и настраивать его свойства при создании, есть ли выход?<br /><br />И ещё вопрос, когда необходимо определять свои процедуры и функции в классе формы, а когда это запрещается?Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-30810486736522599492010-10-21T21:42:48.767+04:002010-10-21T21:42:48.767+04:00>>Не могу даже представить себе, что дельфя ...>>Не могу даже представить себе, что дельфя в таком случае перестанет компилировать (Delphi7). <br />Так прикол в том что если есть ссылки на "Form1" в модулях проекта то перестанет. Эта переменная нужна для Application.CreateForm, не более. А я у многих видел обращение к главной форме из глобальных подпрограмм и других классов через эту переменную. И это как раз признак привязки к интерфейсу. Так что, это можно считать маленьким тестом архитектуры =)G-Hosthttps://www.blogger.com/profile/06089610261947160462noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-67588667976620504582010-10-21T15:55:31.870+04:002010-10-21T15:55:31.870+04:00перенести глобальную переменную формы(var Form1: T...<i> перенести глобальную переменную формы(var Form1: TForm1) в dpr? </i><br /><br />Не могу даже представить себе, что дельфя в таком случае перестанет компилировать (Delphi7).Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-47055248346563502742010-10-21T01:15:01.294+04:002010-10-21T01:15:01.294+04:00Интересно, у какого процента дельфи-программистов ...Интересно, у какого процента дельфи-программистов проект перестанет компилироваться если перенести дефолтную глобальную переменную класса формы(var Form1: TForm1) в dpr?G-Hosthttps://www.blogger.com/profile/06089610261947160462noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-35109624758188425902010-10-15T15:01:16.559+04:002010-10-15T15:01:16.559+04:00>>> Забавно, но стоит заменить TForm на T...<i> >>> Забавно, но стоит заменить TForm на TObject(а еще лучше - просто дописать IWorker к TForm) в объявлении формы и, после удаления ненужных полей, готов чистый TWorker.</i><br /><br />В таком простом примере - да. Но это всего лишь пример. <br /><br />А в реальном проекте, написанном на принципе волшебной кнопки, сделать так будет очень сложно, потому что UI и рабочий код перемешаны в нём страшнейшим образом. В особо запущенных случаях будет проще переписать код заново.GunSmokerhttps://www.blogger.com/profile/15611696588191431330noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-21337974269107763652010-10-15T14:53:55.251+04:002010-10-15T14:53:55.251+04:00Вызов Sleep в UI-потоке - это диагноз.
Это просто...<i>Вызов Sleep в UI-потоке - это диагноз. </i><br />Это простой способ наглядно показать, почему надо разносить код формы и полезный код. К сожалению, взят из практики.<br /><br />Забавно, но стоит заменить TForm на TObject(а еще лучше - просто дописать IWorker к TForm) в объявлении формы и, после удаления ненужных полей, готов чистый TWorker. Это несколько умаляет значимость доводов о требованиях начальника. <br /><br />Я не хочу ввязываться в дискуссию что хорошо а что плохо, просто размышлял на досуге над Вашим постом.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-12084437484564587702010-10-14T19:24:46.986+04:002010-10-14T19:24:46.986+04:00Странный комментарий. А VCL тут при чём? Вызов Sle...Странный комментарий. А VCL тут при чём? Вызов Sleep в UI-потоке - это диагноз.GunSmokerhttps://www.blogger.com/profile/15611696588191431330noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-69795721264507784362010-10-14T17:45:48.176+04:002010-10-14T17:45:48.176+04:00VCL однопоточна? Вот теперь я понимаю, почему у пр...VCL однопоточна? Вот теперь я понимаю, почему у приверженцев одной кнопки программа виснет почти всегда, когда используется sleep...Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-35256526068942159982010-10-01T23:57:05.756+04:002010-10-01T23:57:05.756+04:00Насколько я понимаю, исходя из темы топика и жажды...Насколько я понимаю, исходя из темы топика и жажды знаний про ORM, можно направить в сторону MDA (есть книжка на русском!) и Bold for Delphi (на английском точно что-то есть). Была еще одна штука (попроще, чем MDA), но название я уже не помню.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-20534486223541440912010-10-01T01:22:09.837+04:002010-10-01T01:22:09.837+04:00Эээээээ..... ну напишите.
Какое я имею отношение ...Эээээээ..... ну напишите.<br /><br />Какое я имею отношение к, скажем, ORM? Никакого.GunSmokerhttps://www.blogger.com/profile/15611696588191431330noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-76442963360559820772010-09-30T23:51:15.229+04:002010-09-30T23:51:15.229+04:00Еще неплохо бы было написать пост с описанием и ср...Еще неплохо бы было написать пост с описанием и сравнением существующих фреймворков ORM, DAO (Data Access Object), Repository, Аналога LINK, аспектов и пр. для Delphi.<br /><br />Информации в сети крайне мало, по крайней мере на русском языке. Или я просто искать не умею :)Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-69580122072960952352010-09-30T17:37:57.187+04:002010-09-30T17:37:57.187+04:00Ээээ... ну извиняюсь :)Ээээ... ну извиняюсь :)GunSmokerhttps://www.blogger.com/profile/15611696588191431330noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-57236147355961944882010-09-30T17:36:22.969+04:002010-09-30T17:36:22.969+04:00Вы слишком суровы. Комментарии к посту постом не я...Вы слишком суровы. Комментарии к посту постом не являются. Это уже дискуссия по проблеме, которая вполне может открыть "приверженцам" глаза еще шире, т.к. в одном месте смогут увидеть несколько разных подходов. От себя добавлю, то поскольку VCL - библиотека компонентов, то обозначенную проблему можно решать при помощи компонентов, при этом GUI-решениях (на основе TForm) нет необходимости описывать инициализацию объекта (ну в определенном смысле, ведь, например, при использовании таймера его конструктор не прописывается в коде, а инициализация осуществляется при помощи свойств, правда обработчик OnTimer страдает болезнью, описываемой в посте), и связывать компоненты можно будет при помощи инспектора объектов...<br />Об этом давным давно писал дятька Рэй Конопка.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-22041144380842411842010-09-27T22:54:27.538+04:002010-09-27T22:54:27.538+04:00Я напомню, что этот пост написан "открыть гла...Я напомню, что этот пост написан "открыть глаза приверженцам <a href="http://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D0%B3%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D0%B0" rel="nofollow">Магической Кнопки</a>". Вы слишком многого хотите от простой заметки.GunSmokerhttps://www.blogger.com/profile/15611696588191431330noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-51268067599313460612010-09-27T22:48:30.332+04:002010-09-27T22:48:30.332+04:00К сожалению в посте, да и в его обсуждении, практи...К сожалению в посте, да и в его обсуждении, практически не упоминаются интерфейсы (IInterface), а между тем это очень мощный инструмент при проектировании приложений.<br />Лично я вообще стараюсь придерживаться следующих принципов (грубо):<br /> 1. Со всеми более или менее значимыми объектами в системе работаем только через соответствующий интерфейс.<br /> 2. Объект реализющий тот или иной интерфейс создается только посредством фабрик.<br /> Например:<br /> CoMyObject = class<br /> class function Create(const AParam: IMyParam): IMyObject;<br /> end;<br /> 3. Четко разделять бизнес-модель (т.е. объектную модель) и дополнительные функции типа аутентификации, авторизации, логирования и пр.<br /> <br />Таким образом для реализации сущности предметной области создаются 4 модуля:<br /> 1. untMyObjectInterface - объявление интерфейса<br /> 2. untMyObjectClass - объявление класса реализующего интерфейс<br /> 3. untMyObjectCoClass - описание фабрик (см. паттерн "Фабрика"), создающих экземпляр класса реализующего интерфейс<br /> 4. untMyObjectHelper - описание сервисов (т.е. вспомогательных процедур, классов и пр.) для работы с этим интерфейсом<br /> <br />Выгоды:<br /> - Описание бизнес-модели четко отделено от ее реализации;<br /> - При помощи фабрик легко меняем реализацию интерфейса (путем создания экземпляра другого класса);<br /> - Весь служебный код оформлен отдельно и не "захламляет" реализацию объектной модели;<br /> - Громадный простор для рефакторинга не только отдельных методов, но и целых классов;<br /> - Маcштабируемость. Создаем в фабрике другой класс и вот мы уже работаем не с Oracle, а с MS SQL Server (или вообще с WEB-сервисом);<br /> - Модульное тестирование;<br /> - Ну и как дополнительный плюс - это сборщик мусора;Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-45163704921053419602010-08-11T10:03:48.402+04:002010-08-11T10:03:48.402+04:00>> Имеет смысл разобрать конкретную ситуацию...>> Имеет смысл разобрать конкретную ситуацию использования классовых методов и указать - какие альтернативные подходы лучше использовать и почему.<br />По мне у чисто классовых методов множество приемлемых применений пустое. Дело в том, что они, как и хелперы, вносят явные ограничения, устранение которых требует крупных переделок. Но в отличие от хелперов, методы классов нельзя использовать с немодифицируемым чужим кодом. В результате все преимущество методов классов перед объектами в отсутствии явных инициализации-финализации. Это экономит пару строк кода на стороне "клиента", но делает громоздким код "исполнителя" (инициализацию-финализацию вместо конструктора и деструктора приходится размещать прямо в методе класса). Полагаю это недостаточной компенсацией за отсутствие своих данных.Leo Bonarthttps://www.blogger.com/profile/07929105702896168924noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-72558689252580507882010-08-10T15:07:28.124+04:002010-08-10T15:07:28.124+04:00совсем не понимаю предмета разгоревшегося спора!))...совсем не понимаю предмета разгоревшегося спора!))<br /><br />есть классовые методы, которые можно использовать в определенных ситуациях. Какой смысл спорить с тем, что они не нужны? Да, решение не расширяемое в плане добавления локальных данных для класса - прийдется создавать объект. Но не во всех случаях нужно иметь расширяемое решение - чтобы не наступить на грабли переинжиниринга. <br /><br />Имеет смысл разобрать конкретную ситуацию использования классовых методов и указать - какие альтернативные подходы лучше использовать и почему.deksdenhttps://www.blogger.com/profile/14875114625608323641noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-60981579899669082202010-08-10T14:31:29.324+04:002010-08-10T14:31:29.324+04:00>>> Разве не проще передать этот другой о...<i> >>> Разве не проще передать этот другой объект один раз как параметр конструктора?</i><br /><br />От ситуации зависит. Вы же не создаёте классовый хэлпер перед использованием - а просто используете его. Так же и тут.GunSmokerhttps://www.blogger.com/profile/15611696588191431330noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-45529305563011319662010-08-10T14:28:20.400+04:002010-08-10T14:28:20.400+04:00Если возникают сложности со временем жизни объекта...Если возникают сложности со временем жизни объекта - значит настала пора использовать заменить прямую ссылку на него интерфейсной.<br />Класс как эрзац-пространство имен использовать не люблю - нечитабельно и нерасширяемо.<br /><br />>классовые методы в объекте-заглушке, принимающие параметром другой объект - это что-то вроде класс-хэлперов для этого второго объекта.<br /><br />Разве не проще передать этот другой объект один раз как параметр конструктора?Leo Bonarthttps://www.blogger.com/profile/07929105702896168924noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-55661436032158734522010-08-10T13:33:03.567+04:002010-08-10T13:33:03.567+04:00Я бы развил защиту классовых функций. Во первых, у...Я бы развил защиту классовых функций. Во первых, у них есть возможность стать виртуальными. Во вторых, они объединяются единым классом-это важно, например, для описания скина. То есть классовые функции не просто объединены в класс, а при этом связаны некоей общей концепцией - например, отрисовать управляющий элемент в определенном стиле. Или сюда могут подойти классы, описывающие API (directX/d2d). <br /><br />Важное замечание про то, почему сложно создать объект. Основная сложность при создании объектов-это определение времени его жизни и своевременное удаление. В этом и есть сложности. Поэтому классовые методы в этом случае упрощают ситуацию.deksdenhttps://www.blogger.com/profile/14875114625608323641noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-64228589265641669262010-08-10T12:52:33.131+04:002010-08-10T12:52:33.131+04:00Я решил вступиться за классовые методы.
Думаю, чт...Я решил вступиться за классовые методы. <br />Думаю, что у многих бывают проблемы с классификацией утилитарных функций. Вот надо тебе спец. функцию. А она ну никак не подходит целиком в какой-то класс. Безусловно, ее можно побить на несколько простых функций. Но это так удобно - одна непонятная функция используется 1000 раз в программе и экономит много строк кода. Куда ее девать? Как ее называть? Куда помещать?<br /><br />У меня подход на это дело такой. Создаю класса с статическими классовыми функциями. В них реализую требуемый специфический функционал. Называю класс примерно так (это пример) - TStrUtilsEx. Кидаю туда все, что есть хоть косвенно относящиеся к строкам. В ходе работы периодически пересматриваю код. Иногда из TStrUtilsEx выделяю что-то в общие функции.<br /><br />Т.е. статические классовые методы - хорошее средство для временных утилитарных функций, которые не знаешь куда деть сейчас, но надеешься, что придумаешь им место потом.Дмитрий Тимоховhttps://www.blogger.com/profile/11993493223285214259noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-41027705764283426752010-08-10T12:22:45.617+04:002010-08-10T12:22:45.617+04:00В общем, можно сойтись на том, что классовые метод...В общем, можно сойтись на том, что классовые методы в объекте-заглушке, принимающие параметром другой объект - это <i>что-то вроде класс-хэлперов</i> для этого второго объекта.<br /><br />Да, это могут быть и процедуры, но классовые методы могут быть виртуальными и наследоваться.GunSmokerhttps://www.blogger.com/profile/15611696588191431330noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-41375506405374454482010-08-10T11:07:26.323+04:002010-08-10T11:07:26.323+04:00До ВСЕХ имеющихся данных рисовальщику вообще не до...До ВСЕХ имеющихся данных рисовальщику вообще не добраться - только до публичных. <br />Вязать пучком процедуры в псевдоклассы не нужно - слава богу не Ява. А использование класса вместо объекта во-первых хуже читается, во-вторых не дает использовать данные экземпляра, в-третьих, не имеет никаких преимуществ, кроме мизерного - минус одно создание-уничтожение объекта.Leo Bonarthttps://www.blogger.com/profile/07929105702896168924noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-85915429568844987262010-08-10T10:56:16.398+04:002010-08-10T10:56:16.398+04:00@bonart: ну - не совсем представляю, зачем рисовал...@bonart: ну - не совсем представляю, зачем рисовальщику могут потребоваться собственные данные кроме всех имеющихся у отскиненого объекта данных. Впрочем, никто же не говорил, что наличие классовых методов убивает необходимость создавать объекты. Просто можно принять к сведению, что набор логически связанных процедур и функций можно связать пучком в классе и обозвать классовыми методами - и применять по необходимости, в дополнение, а не вместо объектов.deksdenhttps://www.blogger.com/profile/14875114625608323641noreply@blogger.com