Лучший подход к модульному программированию в Delphi

Это продолжение дискуссии, которую я начал здесь. Я хотел бы найти лучший способ для модуляции исходного кода Delphi, так как я не разбираюсь в этой области. Буду благодарен за все ваши предложения.

Позвольте мне опубликовать то, что я уже написал там.

Программное обеспечение, разработанное компанией, для которой я работаю, состоит из более чем 100 модулей (большинство из которых представляют собой драйверы для различных устройств). Большинство из них используют один и тот же код - в большинстве случаев это классы. Проблема в том, что эти классы не всегда помещаются в отдельные, автономные модули PAS. Я имею в виду, что общий код часто помещается в блоки, содержащие код, специфичный для модуля. Это означает, что когда вы исправляете ошибку в совместно используемом классе, недостаточно скопировать модуль PAS, в котором он определен, во все программные модули и перекомпилировать их. К сожалению, вы должны скопировать и вставить фиксированные фрагменты кода в каждый модуль, один за другим, в соответствующий модуль и класс. Это занимает много времени, и это то, что я хотел бы устранить в ближайшем будущем, выбрав правильный подход - пожалуйста, помогите мне.

Я подумал, что использование BPL, распространяемых с EXE, было бы хорошим решением, но у него есть некоторые недостатки, как некоторые упоминали в предыдущем обсуждении. Худшая проблема заключается в том, что если каждому EXE-файлу требуется несколько BPL, специалистам нашей службы технической поддержки нужно будет знать, каким EXE-файлам нужны BPL-файлы, а затем предоставить конечным пользователям нужные файлы. Пока у нас нет средства обновления программного обеспечения, это будет очень полезно как для наших технических специалистов, так и для конечных пользователей. Они наверняка заблудятся и разозлятся.

Также могут возникнуть проблемы совместимости - если один BPL используется многими EXE-файлами, модификация этого BPL может быть полезной для одного EXE-файла и плохой для некоторых других.

Что мне делать, чтобы быстрее исправлять ошибки во многих проектах? Я думаю об одном из следующих подходов. Если у вас есть идеи получше, пожалуйста, дайте мне знать.

  • Разместите общий код в отдельные и автономные модули PAS, поэтому, когда в одном из них есть исправление ошибки, достаточно скопировать его во все проекты (перезаписать старые файлы) и перекомпилировать все из них. Это означает, что каждый блок копируется столько раз, сколько проектов он использует.

Это решение кажется приемлемым, если речь идет о редко измененном коде. Но у нас также есть блоки с общими функциями и процедурами, которые часто подвергаются изменениям. Было бы невозможно выполнить одну и ту же процедуру (копировать и перекомпилировать так много проектов) каждый раз, когда кто-то добавляет новую функцию в этот файл.

  • Создайте BPL для всего общего кода, но свяжите их с EXE-файлами, чтобы EXE-файлы были автономными.

Для меня это кажется лучшим решением сейчас, но есть некоторые минусы. Если я исправлю ошибку в BPL, каждый программист должен будет обновить BPL на своем компьютере. Что если они забудут это сделать? Тем не менее, я думаю, что это небольшая проблема. Если мы позаботимся о том, чтобы информировать друг друга об изменениях, все должно быть хорошо. Как вы думаете?

  • И последняя идея, предложенная CodeInChaos (я не знаю, правильно ли я ее понял). Обмен файлами PAS между проектами. Это, вероятно, означает, что нам придется хранить общий код в отдельной папке и заставить все проекты искать этот код там, верно? И всякий раз, когда необходимо изменить проект, он должен быть загружен из SVN вместе с папкой общих файлов, я думаю. Каждое изменение в общем коде должно было бы вызывать перекомпиляцию каждого проекта, который использует этот код.

Пожалуйста, помогите мне выбрать хорошее решение. Я просто не хочу, чтобы компания теряла гораздо больше времени и денег, чем необходимо, на исправления ошибок, просто из-за глупого подхода к разработке программного обеспечения. До сих пор никто не заботился об этом, и вы можете себе представить, сколько проблем это вызывает.

Большое спасибо.

2 ответа

Решение

Ты говоришь:

  • Создайте BPL для всего общего кода, но свяжите их с EXE-файлами, чтобы EXE-файлы были автономными.

Вы не можете связать BPL в исполняемый файл. Вы просто связываете в отдельных единицах, которые также находятся в BPL. Таким образом, вы фактически не используете или даже не нуждаетесь в BPL.

BPL предназначены для использования в качестве общего кода, то есть вы помещаете код, который является общим, в один или несколько BPL и используете его из каждого из.exes,.dll или других.bpls. Исправления (если они не изменяют открытый интерфейс BPL) просто требуют перераспределения этого фиксированного BPL.

Как я уже сказал, определитесь с открытым интерфейсом DLL, а затем не меняйте его. Вы можете добавить подпрограммы, типы и классы, но вы не должны изменять общедоступные интерфейсы любых существующих классов, типов, интерфейсов, констант, глобальных переменных и т. Д., Которые уже используются. Таким образом, фиксированная версия BPL может быть легко распространена.

Но обратите внимание, что BPL сильно зависят от версии компилятора. Если вы используете новую версию компилятора, вам также придется перекомпилировать BPL. Вот почему имеет смысл давать суффиксы BPL, такие как 100, 110 и т. Д., В зависимости от версии компилятора. Затем исполняемый файл, скомпилированный с версией компилятора 15.0, будет использовать BPL с суффиксом 150, а исполняемый файл, скомпилированный с версией 14.0, будет использовать BPL с суффиксом 140. Таким образом, разные версии BPL могут мирно сосуществовать. Суффикс может быть установлен в настройках проекта.

Как вы управляете разными версиями? Создайте каталог со структурой, подобной моей, для моего BPL ComponentInstaller (это эксперт, которого вы можете увидеть в Delphi/C++Builder/RAD Studio XE IDE в меню Компоненты -> Установить компонент):

Projects
  ComponentInstaller
    Common
    D2007
    D2009
    D2010
    DXE

Каталог Common содержит файлы.pas и ресурсы (точечные рисунки и т. Д.), Совместно используемые каждой версией, а каждый из каталогов Dxxxx содержит.dpk, .dproj и т. Д. Для этой конкретной версии BPL. Каждый из пакетов использует файлы в общем каталоге. Конечно, это можно сделать для нескольких BPL одновременно.

Кстати, система управления версиями может сделать это намного проще. Просто убедитесь, что у каждой версии BPL свой суффикс.

Если вам действительно нужны автономные исполняемые файлы, вы не используете BPL, а просто ссылаетесь на отдельные модули. Опция "компилировать с BPL" управляет этим.

С моей точки зрения, пытаясь управлять такими артефактами, как модули Delphi, библиотеки и исполняемые файлы, вы выполняете поиск в неправильном месте. Я предлагаю вам развернуться и начать с рефакторинга кода, основанного на реализации шаблонов проектирования.

Например, все общие функции могут быть помещены в один класс Singleton, экземпляры общих классов могут быть построены с помощью абстрактной фабрики, классы могут взаимодействовать посредством нативной реализации интерфейсов Delphi вместо прямого использования и так далее. Даже вы можете выбрать внедрение Фасада для всех общих частей проектов.

Конечно, конкретный выбор шаблонов и деталей реализации зависит от конкретного проекта, и только вы можете решить, что применимо в вашем случае. Я полагаю, что, взглянув на проект в этом ключе, вы сможете найти более естественные способы организации кода и решения ваших проблем.

Некоторые другие вещи:

  1. Конечно, вы должны следовать предложению @CodeInChaos и делиться одной копией исходного файла между всеми проектами, а не копировать ее в каждый проект вручную. Это может быть полезно, если вы примете какой-то стандарт для среды разработки, который будет обязательным для всех разработчиков (одинаковая структура папок, расположение библиотек, настройки среды).
  2. Попробуйте проанализировать процесс сборки и развертывания: для меня это выглядит ненормально, когда решение не построено с последней версией кода и не протестировано перед развертыванием. (это для вашей фразы "Если я исправлю ошибку в BPL, каждый программист...").
  3. Вариант с автономными исполняемыми файлами выглядит лучше, поскольку значительно упрощает организацию среды тестирования и развертывание проекта. Просто выберите подходящие соглашения для управления версиями.
Другие вопросы по тегам