Comments 76
А теперь, персонально для делфи-разработчиков!!!
Я к тому, что несмотря на некоторые моменты специфичные для Delphi, большинство рекомендаций актуальны для всех языков :)
Я к тому, что несмотря на некоторые моменты специфичные для Delphi, большинство рекомендаций актуальны для всех языков :)
+1
Потому и разместил здесь, а не в блоге Delphi.
-1
Спасибо! Отличный материал. Для молодых кадров, почти руководство к выполнению, чуток подкрасить и подредактировать и можно вручать при приёме на работу программиста.
-1
UFO just landed and posted this here
> И чего это вам не понравилось хранение данных в классе и запись в БД ну и некоторые другие функции?
Тем, что мешают читать, использовать, тестировать и модифицировать класс без физической реализации «этих других функций».
> Соответственно и все поведение мы и должны в один класс записать.
Это будет известный антипаттерн «божественный класс» — сложный для чтения, отладки, модификации и повторного использования.
> Допустим у нас есть класс tDoc мы должны описать его сохранение в БД, загрузку из базы, проверку на валидность, объект этого класса — единственное достоверное хранилище данных.
Не должны — для сохранения есть сериализаторы, для проверки — валидаторы и т.п. На собственно документ ложится хранение данных. Остальное вполне реально выделить в отдельные классы.
>Опять же не совсем понятно требование на приватность полей — да в подавляющем большинстве случаев это действительно важное требование, но бывают и исключения…
В Delphi таких исключений не бывает. Хочешь показать снаружи — опиши свойство. С тривиальными геттером и сеттером оно даже по скорости исполнения полю не проиграет.
Тем, что мешают читать, использовать, тестировать и модифицировать класс без физической реализации «этих других функций».
> Соответственно и все поведение мы и должны в один класс записать.
Это будет известный антипаттерн «божественный класс» — сложный для чтения, отладки, модификации и повторного использования.
> Допустим у нас есть класс tDoc мы должны описать его сохранение в БД, загрузку из базы, проверку на валидность, объект этого класса — единственное достоверное хранилище данных.
Не должны — для сохранения есть сериализаторы, для проверки — валидаторы и т.п. На собственно документ ложится хранение данных. Остальное вполне реально выделить в отдельные классы.
>Опять же не совсем понятно требование на приватность полей — да в подавляющем большинстве случаев это действительно важное требование, но бывают и исключения…
В Delphi таких исключений не бывает. Хочешь показать снаружи — опиши свойство. С тривиальными геттером и сеттером оно даже по скорости исполнения полю не проиграет.
-1
UFO just landed and posted this here
Я до разбора полетов предпочитаю не доводить в принципе.
Именно для этого сделано двойное рецензирование: неформальное — решения задачи перед кодированием (отвергается только явно косячное по дизайну) и формальное — ревью кода после (отвергается опять-таки только явно косячное и неправильно оформленное).
На молодых работает отлично.
Именно для этого сделано двойное рецензирование: неформальное — решения задачи перед кодированием (отвергается только явно косячное по дизайну) и формальное — ревью кода после (отвергается опять-таки только явно косячное и неправильно оформленное).
На молодых работает отлично.
0
Я тоже против жесткого запрета на strict protected поля.
Одно дело показывать наружу (не в коем случае), а другое — парочке наследников, доступность поля которым не ломает инкапсуляцию в широких масштабах.
Одно дело показывать наружу (не в коем случае), а другое — парочке наследников, доступность поля которым не ломает инкапсуляцию в широких масштабах.
0
Хорошо, кратко и по сути. А чтобы всё это ушло в подкорку — практика, еще раз практика и Макконнелл.
+1
UFO just landed and posted this here
Тема написания конструкторов раскрыта не полностью (возможность реинициализирующего вызова)
+1
Можно подробнее? Полностью тему в таком формате все равно раскрыть нереально, но что бы вы сказали про реинициализирующие вызовы молодым разработчикам?
0
Сказал бы, что в конструкторе нельзя считать что объект заполнен нулями, и необъодимо обрабатывать ситуацию когда часть полей (или все) уже инициализированны ранее. В этом случае наверное нужно освободить старые ресурсы, занулить содержащие их поля и тогда действовать по ранее утвержденному плану. Ну для вложенных объектов можно просо вызывать FreeAndNil перед инициализацией.
+1
Полагаю такую ситуацию ошибкой программиста и предпочитаю тратить силы на ее предотвращение, а не пытаться минимизировать вред после ее возникновения.
0
Что нельзя считать что в начале конструктора объект всегда заполнен нулями, и перед инициализацией нужно освободить то что там было раньше (для объектов — хотябы просто вызвать FreeAndNil(FObjectField) перед присваиванием)
Ну вобщем как то, что у вас написано про деструктор
Ну вобщем как то, что у вас написано про деструктор
0
И да, первый коммент почему-то сразу не появился
0
4.Приделать doxygen или javadoc и не сношать другим мозги.
5.Выкинуть эту венгерскую нотацию на помойку, НИКАКИХ T ПЕРЕД НАЗВАНИЕМ КЛАССА: ОНИ НЕ НУЖНЫ.
И вообще не начинать новые проекты на Дельфи
5.Выкинуть эту венгерскую нотацию на помойку, НИКАКИХ T ПЕРЕД НАЗВАНИЕМ КЛАССА: ОНИ НЕ НУЖНЫ.
И вообще не начинать новые проекты на Дельфи
+7
Префикс Т в начале класса не имеет отношения к венгерской нотации
-1
Можете не тратить напрасно свое время и силы — вы отвечали человеку, для которого Delphi как красная тряпка для бычка.
0
Хорошо, нафига он нужен? Понимаю еще если так исторически сложилось, понимаю когда это первая буква из названия библиотеки и при этом она вполне красиво вписывается. Но блин в остальных то случаях зачем? Чем namespace'ы не угодили?
0
Она отличает типы от нетипов. Поля — F, аргументы сеттеров — А, интерфейсы I
Венгерская нотация же про другое.
Венгерская нотация же про другое.
0
По-моему как раз оно самое и было одним из принципов венгерки.
0
Нет, там информация о типе в именах переменных
-1
Но суть то та же самая, просто теперь буквами обозначаем семантику, мне это кажется излишним. Всё прекрасно и без букв лишних просматривается в любом нормальном IDE.
-1
Нет, суть совершенно разная.
Пойдите лучше повоюйте с сишниками по поводу капслока в идентификаторах типов и знаков подчеркивания в макросах, а мне пожалуй хватит.
И да, IDE женского рода.
Пойдите лучше повоюйте с сишниками по поводу капслока в идентификаторах типов и знаков подчеркивания в макросах, а мне пожалуй хватит.
И да, IDE женского рода.
0
Когда я начинал программировать под Windows, пользовался продуктами борланда: delphi, builder, c++. меня тоже это как-то коробило, точнее, я не понимал, зачем нужны эти префиксы, хотя против T ничего не имел, но вот названия аргументов в VCL с этими F, A меня раздражали :)
В то же время, в MFC все классы имели префикс С, о чем у меня была дискуссия с другом, который ею пользовался. Он мне объяснял, что это — правильная концепция, потому что CWnd — это класс, а вот у борланда как раз ничего непонятно с этими Т :)
Кроме того, теория того времени утверждала, что префиксы — это правильно, об этом писалось во всех книгах, что по Дельфи, что Билдеру, и, наверное, в туториалах микрософта.
И только когда начал изучать джаву по двухтомнику Хорстмана все наконец встало на свои места — наконец-то префиксы были признаны ненужными и нарушающими «концепцию» :)
Кстати говоря, Макконнелл так же пишет, что префиксы — это хорошо
В то же время, в MFC все классы имели префикс С, о чем у меня была дискуссия с другом, который ею пользовался. Он мне объяснял, что это — правильная концепция, потому что CWnd — это класс, а вот у борланда как раз ничего непонятно с этими Т :)
Кроме того, теория того времени утверждала, что префиксы — это правильно, об этом писалось во всех книгах, что по Дельфи, что Билдеру, и, наверное, в туториалах микрософта.
И только когда начал изучать джаву по двухтомнику Хорстмана все наконец встало на свои места — наконец-то префиксы были признаны ненужными и нарушающими «концепцию» :)
Кстати говоря, Макконнелл так же пишет, что префиксы — это хорошо
-1
Т — это type, все понятно же.
F и А жизненно необходимы, когда у вас есть свйство, поле для его хранения и аргумент в сеттере. Когда в в контексте метода SetOwner, то очень удобно иметь свойство Owner, поле FOwner и аргкмент AOwner
F и А жизненно необходимы, когда у вас есть свйство, поле для его хранения и аргумент в сеттере. Когда в в контексте метода SetOwner, то очень удобно иметь свойство Owner, поле FOwner и аргкмент AOwner
0
да я это все понимаю, я же говорю, сам очень много программировал на дельфи и билдере. и также использовал Т :)
я просто привел в пример MFC-шника, у которого концепции несколько отличаются. Видимо, в микрософте решили, что класс — это не тип, следовательно, ему нужно свой префикс :)
я просто привел в пример MFC-шника, у которого концепции несколько отличаются. Видимо, в микрософте решили, что класс — это не тип, следовательно, ему нужно свой префикс :)
0
>AOwner FOwner
как же это ужасно выглядит, особенно две гласные буквы подряд. Лучше уж методы и поля класса писать с маленькой буквы, а private поля или прятать в приватный класс или же слова разделять через нижнее подчеркивание и добавлять префикс m_
как же это ужасно выглядит, особенно две гласные буквы подряд. Лучше уж методы и поля класса писать с маленькой буквы, а private поля или прятать в приватный класс или же слова разделять через нижнее подчеркивание и добавлять префикс m_
-2
А мне вот нравится первая буква, отвечающая за тип
+1
Так исторически сложилось. Это стандартный стиль.
0
Да, я даже могу понять из за чего это так сложилось, но всё же это не отменяет устарелость этого стиля и то, что есть более современные и удобные в нынешнее время. Так зачем предлагать в качестве советов то, что осталось нам в наследство и нынче уже не подкрепляется необходимостью?
0
Т.е. из-за одной буквы вы готовы горы свернуть и привнести в программу смешение стилей?
0
Почему же? В собственных программах у меня никаких буков T и в помине нету, есть только вот префикс V в модуле для работы со вконтакте, с ним что ли названия классов красивее смотрятся, но мне лично не нравятся любые излишние соглашения в стиле. Буква T явно излишняя.
0
А вот тут как раз — место для неймспейсов.
0
Это в хаскеле раздельные пространства имен для функций с параметрами, конструкторов данных, типов данных, переменных типов данных. Ни в дельфи, ни в плюсах, ни в яве, ни в сишарпе такой роскоши нет, приходится использовать те или иные соглашения для улучшения читаемости кода. Плюс в делфи еще нельзя полноценно использовать разный регистр. Отсюда и префиксы — уже по коду видно, где тип, где переменная, где поле, где параметр. С венгерской нотацией (что прикладной, что системной) это не имеет ничего общего.
0
Здесь для вас еды нет
-4
Я не знаток Delphi и мне интересны некоторые аспекты.
В Delphi есть библиотеки, которые позволяют делать модульное тестирование? Если есть, почему о нем не упомянуто?
И еще про зависимости. В разделе «15 Устранение лишних зависимостей» ничего не сказано про IoC-контейнеры. Вместо них много упоминаний про глобальные переменные. Есть ли в Delphi реализация IoC-контейнера?
В Delphi есть библиотеки, которые позволяют делать модульное тестирование? Если есть, почему о нем не упомянуто?
И еще про зависимости. В разделе «15 Устранение лишних зависимостей» ничего не сказано про IoC-контейнеры. Вместо них много упоминаний про глобальные переменные. Есть ли в Delphi реализация IoC-контейнера?
+2
> В Delphi есть библиотеки, которые позволяют делать модульное тестирование?
Да. DUnit идет в стандартной поставке.
> Если есть, почему о нем не упомянуто?
Конкретные вспомогательные инструменты не упоминаются специально.
> В разделе «15 Устранение лишних зависимостей» ничего не сказано про IoC-контейнеры. Вместо них много упоминаний про глобальные переменные.
Глобальные переменные и эквивалентные им паттерны (например, синглтон) есть типичная ошибка молодого разработчика.
> Есть ли в Delphi реализация IoC-контейнера?
Для версий от 2009 и выше есть как минимум OpenSource библиотеки. Для младших версий IoC нет ввиду наличия отсутсвия генериков и недостаточных возможностей интроспекции (RTTI есть, но неполная и неудобная для таких целей). Для проектов на Delphi 2007 у нас используется ServiceLocator. Конкретные паттерны и инструменты для устранения зависимостей не упоминаются сознательно — здесь нет однозначно лучшего решения и я не вижу смысла его навязывать.
Да. DUnit идет в стандартной поставке.
> Если есть, почему о нем не упомянуто?
Конкретные вспомогательные инструменты не упоминаются специально.
> В разделе «15 Устранение лишних зависимостей» ничего не сказано про IoC-контейнеры. Вместо них много упоминаний про глобальные переменные.
Глобальные переменные и эквивалентные им паттерны (например, синглтон) есть типичная ошибка молодого разработчика.
> Есть ли в Delphi реализация IoC-контейнера?
Для версий от 2009 и выше есть как минимум OpenSource библиотеки. Для младших версий IoC нет ввиду наличия отсутсвия генериков и недостаточных возможностей интроспекции (RTTI есть, но неполная и неудобная для таких целей). Для проектов на Delphi 2007 у нас используется ServiceLocator. Конкретные паттерны и инструменты для устранения зависимостей не упоминаются сознательно — здесь нет однозначно лучшего решения и я не вижу смысла его навязывать.
-1
> Да. DUnit идет в стандартной поставке
А вы пишете на нем тесты или на какой-то другой библиотеки? Думаю эта информация будет полезна для начинающих разработчиков.
> Конкретные вспомогательные инструменты не упоминаются специально
Вообще это не просто инструмент. Написание модульных тестов (желательно до кода), которые запускаются постоянно — это способ написание программ, который практически устраняет пункт «9 Отладка»
> Для проектов на Delphi 2007 у нас используется ServiceLocator
Т.е. есть реализация только «пассивного» внесения зависимостей?
А вы пишете на нем тесты или на какой-то другой библиотеки? Думаю эта информация будет полезна для начинающих разработчиков.
> Конкретные вспомогательные инструменты не упоминаются специально
Вообще это не просто инструмент. Написание модульных тестов (желательно до кода), которые запускаются постоянно — это способ написание программ, который практически устраняет пункт «9 Отладка»
> Для проектов на Delphi 2007 у нас используется ServiceLocator
Т.е. есть реализация только «пассивного» внесения зависимостей?
+1
>Вообще это не просто инструмент. Написание модульных тестов (желательно до кода), которые запускаются постоянно — это способ написание программ, который практически устраняет пункт «9 Отладка»
Ну не уверен. Скорее сильное сокращение отладки, но все ситуации тестами не отловишь.
Ну не уверен. Скорее сильное сокращение отладки, но все ситуации тестами не отловишь.
0
> Ну не уверен. Скорее сильное сокращение отладки, но все ситуации тестами не отловишь
Согласен, можно переформулировать «практически устраняет», а «сильно уменьшает» :)
Согласен, можно переформулировать «практически устраняет», а «сильно уменьшает» :)
0
Для реально сильного уменьшения меры должны быть комплексными:
1. Устранение зависимостей.
2. Рецензирование дизайна.
3. Рецензирование кода.
4. Модульные тесты.
5. Непрерывная сборка.
6. Логирование.
7. Автоматическое функциональное тестирование.
8. Ручное функциональное тестирование.
Попытка сэкономить на чем-то одном уменьшает эффективность всего остального.
1. Устранение зависимостей.
2. Рецензирование дизайна.
3. Рецензирование кода.
4. Модульные тесты.
5. Непрерывная сборка.
6. Логирование.
7. Автоматическое функциональное тестирование.
8. Ручное функциональное тестирование.
Попытка сэкономить на чем-то одном уменьшает эффективность всего остального.
0
> А вы пишете на нем тесты или на какой-то другой библиотеки? Думаю эта информация будет полезна для начинающих разработчиков.
Полагаю, что не будет — в команде у молодых выбора инструмента нет. Тем кто работает один — нужны не краткие рекомендации, а толстые книжки и много чужого кода.
> Написание модульных тестов (желательно до кода), которые запускаются постоянно — это способ написание программ, который практически устраняет пункт «9 Отладка»
Модульные тесты являются серебряной пулей только для некоторого класса задач и никоим образом не избавляют от отладки. ЕМНИП по Макконнеллу формальное рецензирование кода ловит больший процент ошибок. Плюс использование способа (TDD) априори важнее выбора инструмента. Но согласен: наличие отдельного пункта про модульные тесты логично и обоснованно.
> Т.е. есть реализация только «пассивного» внесения зависимостей?
Ну изнутри сервиса это наоборот «активное», но увы, в дельфи до 2009 IoC контейнеры слишком сложны в реализации. И у локатора свои плюсы при межязыковом взаимодействии — под Win32 на единую объектную платформу рассчитывать не приходится.
Полагаю, что не будет — в команде у молодых выбора инструмента нет. Тем кто работает один — нужны не краткие рекомендации, а толстые книжки и много чужого кода.
> Написание модульных тестов (желательно до кода), которые запускаются постоянно — это способ написание программ, который практически устраняет пункт «9 Отладка»
Модульные тесты являются серебряной пулей только для некоторого класса задач и никоим образом не избавляют от отладки. ЕМНИП по Макконнеллу формальное рецензирование кода ловит больший процент ошибок. Плюс использование способа (TDD) априори важнее выбора инструмента. Но согласен: наличие отдельного пункта про модульные тесты логично и обоснованно.
> Т.е. есть реализация только «пассивного» внесения зависимостей?
Ну изнутри сервиса это наоборот «активное», но увы, в дельфи до 2009 IoC контейнеры слишком сложны в реализации. И у локатора свои плюсы при межязыковом взаимодействии — под Win32 на единую объектную платформу рассчитывать не приходится.
+1
молодой разработчик Delphi — звучит как приговор…
+1
«Все методы, реализующие интерфейс — обязательно protected и невиртуальные»
Это почему так важно?
Выходит этот код опасен чем-то? Не пойму, где могут от этого неприятности быть.
Это почему так важно?
Выходит этот код опасен чем-то? Не пойму, где могут от этого неприятности быть.
TCommand = class(TInterfacedObject, ICommand, IInfoCommand)
private
FInfo: TInfo;
protected
procedure DoExecute; virtual; abstract;
function GetName: WideString; virtual; abstract;
function GetPriority: TCommandPriority; virtual; abstract;
public
constructor Create(const AШтащ: TInfo);
destructor Destroy; override;
procedure Execute;
function GetMux: TMuxInfo;
end;
0
Спасибо, хороший пост, много о чем сказано в кратком лаконичном виде.
0
Sign up to leave a comment.
Заповеди молодого разработчика Delphi