Как управлять CFC (подсистемой), которая является общей для нескольких сайтов?

#svn #coldfusion #cfc #subsystem

#svn #coldfusion #cfc #подсистема

Вопрос:

Как вы можете управлять чем-то подобным? Я изо всех сил старался сделать подсистему многоразовой, но есть только определенные вещи, уникальные для сайта, которые необходимо настроить (например, поля в сущности Account или cfc =»» в аннотации orm).

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

Итак… Каков наилучший способ справиться с этой ситуацией? Просто клонировать набор кода в новый элемент управления версиями и исправлять ошибки в обоих / всех элементах управления версиями?

Комментарии:

1. Что вы подразумеваете под подсистемой?

2. хм … сложно описать. Давайте просто скажем, что у меня есть несколько версий подобной вещи, но есть просто что-то отличное от них?

3. что-то вроде того, что логика / бизнес-правила одинаковы, но входные данные и собранные данные не совпадают

4. Эти сайты работают на одном сервере?

5. Изучите шаблон разработки стратегии: en.wikipedia.org/wiki/Strategy_pattern

Ответ №1:

Предполагая, что вы не используете какой-либо MVC-фреймворк … пока…

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

В зависимости от того, что кажется разным и одинаковым между CFC, вы можете:

1) используйте наследование

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

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

2) используйте mix-ins

Если кажется, что вы каждый раз дублируете функциональность / логику, попробуйте преобразовать эту логику в фрагменты кода, которые вы включаете в любые cfc, которые этого требуют. Смотрите эксперименты Бена с mixins и комментарии Шона к mixins.

К сожалению, механизмы для эффективной работы в CF слабы, в отличие от модулей Ruby.

Если ваши потребности соответствуют тому, что вы описали в своем комментарии, «что-то вроде, логика / бизнес-правила одинаковы, но входные данные и собранные данные не совпадают», я бы посоветовал взглянуть на Rails или Django для вдохновения.

В моей ситуации я закончил разработкой фреймворка, который позволил мне при определении модели расширить базовый класс модели и просто заполнить его набором тегов cfproperty с пользовательскими свойствами, которые определяли мою модель и использовались базовым классом модели и набором сервисов, которые обрабатывали большую часть бизнес-логики. Это работало в 95% случаев, и в любой ситуации, когда мне нужно было отклониться от логики фреймворка, я бы либо добавил дополнительные функции в свою модель cfc, либо даже переопределил функцию базовой модели.

В итоге мои модели выглядели следующим образом:

     <cfcomponent output="false" persistentLayer="GAE" persistentClass="asana" extends="com.bespokelogic.framework.BaseModel">
        <cfproperty name="id" type="string" persistentDatatype="string" settable="true" gettable="true" required="true">
        <cfproperty name="deckSet" type="string" persistentDatatype="string" settable="true" gettable="true" default="basic">
        <cfproperty name="englishName" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="traditionalName" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="pronunciation" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="pronunciationNotes" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="description" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="type" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="anatomicalFocus" type="array" persistentDatatype="array" settable="true" gettable="true" default="#arrayNew(1)#">
        <cfproperty name="therapeuticFocus" type="array" persistentDatatype="array" settable="true" gettable="true" default="#arrayNew(1)#">
        <cfproperty name="benefits" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="variations" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="contraindications" type="array" persistentDatatype="array" settable="true" gettable="true" default="#arrayNew(1)#">
        <cfproperty name="skill" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="instructions" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="skill" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="prelimAsana" type="asana" persistentDatatype="Key[]" settable="true" gettable="true" default="#arrayNew(1)#">
        <cfproperty name="followupAsana" type="asana" persistentDatatype="Key[]" settable="true" gettable="true" default="#arrayNew(1)#">
        <cfproperty name="thumbnailImage" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="primaryImage" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="images" type="array" persistentDatatype="array" settable="true" gettable="true" default="#arrayNew(1)#">
        <cfproperty name="primaryVideo" type="string" persistentDatatype="string" settable="true" gettable="true">
        <cfproperty name="videos" type="array" persistentDatatype="array" settable="true" gettable="true" default="#arrayNew(1)#">
    </cfcomponent>
  

Комментарии:

1. Я уже использую MVC. Тем не менее, я начал планировать повторное использование этой подсистемы, но во время разработки произошли некоторые утечки логики / данных, специфичных для конкретного проекта, в подсистему, и было нелегко поддерживать подсистему в «чистоте», а аннотации ORM привязаны к CFC, а не к интерфейсу, к сожалению… Теперь, когда пришло время повторно использовать подсистему, я беспокоюсь о том, как я могу поддерживать обе версии в будущем…

2. Или мы должны сделать это следующим образом.. система сборки Java? каждый раз извлекать последнюю версию подсистемы из соответствующего SVN? Непрерывная интеграция с Hudson?

3. Я прекратил кодировать CF сразу после выхода 9, поэтому у меня нет большого опыта работы с CF ORM. Это действительно бизнес-логика, от которой вы пытаетесь избавиться, верно? Я думаю, что вполне нормально дублировать определения модели / orm, поскольку на самом деле там нечего тестировать, и это все более или менее сгенерированный код. Итак, сосредоточив внимание на том, как сократить значительную бизнес-логику, у вас есть небольшой пример, который мы могли бы рассмотреть?

4. Что касается развертывания (повторной сборки системы), да. Вы можете использовать систему управления зависимостями (мы использовали Ivy), чтобы указать и включить конкретные версии необходимых вам базовых библиотек. Вы можете либо использовать соглашение для своих сопоставлений, либо какой-нибудь изящный Ant-скрипт может переписать ваши сопоставления App.cfc во время сборки WAR.

Ответ №2:

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

Затем вы можете настроить некоторые сопоставления CF. Затем у вас может быть набор CFC для обоих сайтов под com.common.model , другой под com.mysite.model и еще один под com.myothersite.model .

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

Надеюсь, это поможет.