Как вы организуете свои небольшие повторные работы?

Я реорганизую свои структуры каталогов ColdFusion, и мне интересно, как опытные разработчики CF организуют библиотеки меньших cffunctions.

Мне не так интересно узнать о сложных компонентах (объектах), поскольку я имею в виду десятки небольших функций полезности, которые мы все нарастаем с течением времени.

  • Используете ли вы большой одиночный файл с cffunctions и cfinclude?
  • Используете ли вы большой одиночный файл как cfcomponent и вызываете creatobject/cfinvoke?
  • Вы помещаете каждую полезную функцию в свой собственный cfc и вызываете createobject/cfinvoke?
  • Вы используете синтаксис cfimport taglib?
  • Используете ли вы CustomTags или cfmodule?
  • У вас есть лучший способ?

Поскольку мне не нравится подробный синтаксис, я просто использовал lib.cfm, в котором есть куча общих cffunctions. Я могу реорганизовать их для группировки cfcs. Я могу создать объект, чтобы иметь лучшую изоляцию по областям переменных.

Есть ли лучший способ сделать это?

Ответы

Ответ 1

Это перепечатка сообщения

После того, как у вас будут все UDF, которые приложение будет использовать в вашем компоненте, вам нужно будет сделать UDF доступными для вашего приложения. Почти каждый, кого я видел, выполняет эту загрузку компонента в область приложения. Следующая строка помещается в onApplicationStart(), если вы используете Application.cfc или просто добавляете его в Application.cfm, если вы используете это:

<cfset application.functions = CreateObject("component", "udfs").init()>

Какой бы вы ни использовали, Application.cfc или Application.cfm, результаты одинаковы; все ваши UDF доступны для вашего приложения, и вы можете использовать их свободно во всем. Единственное различие заключается в том, какое имя переменной вы используете. Я использую application.functions, некоторые используют application.utils или application.udfs; не имеет значения, опять же, результаты одинаковы.

Есть одна проблема, которая у меня есть с этим подходом, но она громоздка и компонент UDFs станет огромным. Проблема с тем, что такой огромный файл компонента редактируется, становится кошмаром, так как прокрутка тысяч строк кода не очень забавная, и я заметил, что CFEclipse пугает огромные файлы. Конечно, коллапс кода дает некоторое облегчение, но должен быть лучший способ.

Я хотел только иметь один файл для каждого используемого UDF и способ загрузки приложения автоматически. Причина в том, что если мне нужно было отредактировать myUDF1, я мог бы просто открыть файл myUDF1.cfm и отредактировать то, что мне нужно. Я также хотел иметь возможность захватить UDF из и просто отбросить их в мое приложение, не редактируя ничего. Если мне когда-либо понадобилось удалить UDF из моего приложения, было бы так же легко, как удалить файл UDF и повторно инициализировать мое приложение.

Чтобы выполнить то, что я хотел, я изменил свой UDFs.cfc на 11 строк кода:

<!--- UDFs.cfc --->
<cfcomponent output="false">

  <cfset variables.udfdir = GetDirectoryFromPath(GetCurrentTemplatePath()) & "udfs">
  <cfset variables.q = "">

  <cffunction name="init" access="public" returntype="Any" output="false">
    <cfreturn this>
  </cffunction>

  <cfdirectory action="list" directory="#variables.udfdir#" filter="*.cfm" name="variables.q">

  <cfoutput query="variables.q">
    <cfinclude template="udfs\#name#">
  </cfoutput>

</cfcomponent>

Итак, что именно происходит?

Вкратце, вот что происходит: у меня есть каталог под названием udfs в том же каталоге, что и у меня UDFs.cfc. Это каталог, в который я поместил все файлы UDF CFM. Что делает UDFs.cfc, это сканировать этот каталог, когда он вызывается, и автоматически включает каждый найденный файл CFM. Таким образом, он автоматически загружает любые UDF в папку UDFs в себя (обычно называется "mixin" ).

Итак, моя цель достигнута! У меня есть каждый UDF в собственном файле, поэтому мне не нужно прокручивать огромный файл компонента, чтобы найти его. Теперь я могу легко его открыть и отредактировать. Просто просматривая каталог, я знаю, что использует UDF, используемое моим приложением. Я могу автоматически добавлять UDF из CFLib.org, просто сохраняя текст из браузера в файл в каталоге. Плюс, если мне больше не нужно использовать UDF в моем приложении, я просто удаляю файл из каталога и удаляю его из моего приложения во время следующего перезапуска. Все это делается без необходимости касаться основного файла UDFs.cfc.

Ниже приведен пример того, как выглядит один из файлов CFM UDF. Файл называется fullLeft.cfm и находится в каталоге UDF.

<!--- fullLeft --->
<cffunction name="fullLeft" access="public" displayname="fullLeft" returntype="string" output="false">
  <cfargument name="str" type="string" required="true">
  <cfargument name="count" type="numeric" required="true">
  <cfif not refind("[[:space:]]", arguments.str) or (arguments.count gte len(arguments.str))>
    <cfreturn Left(arguments.str, arguments.count)>
  <cfelseif reFind("[[:space:]]",mid(arguments.str,arguments.count+1,1))>
    <cfreturn left(arguments.str,arguments.count)>
  <cfelse>
    <cfif count-refind("[[:space:]]", reverse(mid(arguments.str,1,arguments.count)))>
      <cfreturn Left(arguments.str, (arguments.count-refind("[[:space:]]", reverse(mid(str,1,arguments.count)))))>
    <cfelse>
      <cfreturn left(arguments.str,1)>
    </cfif>
  </cfif>
</cffunction>

Ответ 2

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

<cfif not isDefined("application.utilities")>
    <cfset application.utilities = createObject("component", "Utilities")>
</cfif>

Теперь вы можете вызывать методы в application.utitlies из любого места. Обратите внимание, что если вы вносите изменения в свой cfcomponent, вам нужно обновить вашу переменную приложения новым экземпляром Utilities.

Ответ 3

если вы используете Application.cfc(если вы этого не сделаете, я настоятельно рекомендую вам перенести его из Application.cfm - его очень легко сделать), вы можете создать baseComponent.cfc со всеми вашими методами UDF и иметь приложение. cfc наследуется от baseComponent. то в методе onRequestStart задается переменная, называемая request.app = this;

для запроса entyure, вы можете использовать request.app.methodname() для доступа к UDF. его очень хороший и простой способ обработки UDF

также, если вам нравится, вы можете наследовать все свои cfcs из одного базового компонента, чтобы все ваши cfcs использовали эти функции как собственные методы. делает модульное тестирование cfcs очень простым, потому что cfcs не должны отвечать на переданную (введенную) ссылку на компонент UDf, это их дедукты!

одна проблема с этим подходом заключается в том, что атрибут extends cfc не может быть выражением... так что в зависимости от того, как вы упаковываете свои компоненты, это может быть трудно реализовать. самый простой способ справиться с этим - с отображением coldfusion.

НТН Джон

Ответ 4

Мы используем файлы .cfm для библиотек функций и вызываем соответствующий файл с помощью cfinclude. Некоторые из файлов .cfm были загружены с сайта cflib.org, а другие написаны нами. Файлы находятся в каталоге с именем UDF, который является подкаталогом другого каталога, который отображается на символ косой черты. Оператор cfinclude просто:

<cfinclude template="/UDF/filename.cfm">

Этот подход делает эти функции доступными для всех приложений на сервере.

Мы также предпочитаем несколько небольших библиотечных подходов. Каждая библиотека является специфичной для темы (математика, строка, список-массив и т.д.)

Ответ 5

Опция: вы используете большой одиночный файл с cffunctions и cfinclude?

A: Я сделал это, но делаю это все меньше и меньше. Мне нравится использовать наследование и cfcexplorer

Опция: вы используете большой одиночный файл как cfcomponent и вызываете creatobject/cfinvoke?

A: Да, я часто это делаю

Опция: вы помещаете каждую полезную функцию в свой собственный cfc и вызываете createobject/cfinvoke?

A: Я могу сделать это, если ожидаю добавления дополнительных функций позже

Опция: используется ли синтаксис taglib cfimport?

A: Я делаю это так.

Опция: используете ли вы CustomTags

A: Не за долгое время. cfc лучше в этом

Опция: или cfmodule?

A: Не за долгое время. cfc лучше в этом. вызывающий. * область действия может затруднить отладку

Ответ 6

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

Утилита Функция/Синглтонный подход с "Инъекцией"

Я создаю cfc 'core' или 'utility'. В нем я собираю все мои функции типа утилиты, которые:

  • Часто используется все время повсюду (например, общая viewRecord() dao и функция ядра checkSecurity() и т.д.)
  • Являются базовыми функциями, которые imho должны быть ядром в CF (например, lpad(), capitalize() и др.)
  • Являются оболочками некоторых тегов, которые позволяют мне использовать cfscript повсеместно (например, exit(), который обертывает <cfexit>)

В onApplicationStart() я создаю экземпляр этого объекта и присваиваю его области Application, создавая при этом статический одноэлементный тип.

Затем вместо того, чтобы расширять или повторно включать это в почти все мои cfc, что позволяет мне использовать расширение для более традиционного типа наследования, я затем вставляю эти методы в конструктор (init) для всех моих сборщиков cfc. Я делаю это, вызывая метод на самом объекте утилиты, так что:

public/remote any function init() {
  structAppend( Variables, Application.MyApp.Objects.oCore.injectCoreMethods() ); 
  return this; // Return instance of this object
}

Метод injectCoreMethods() выборочно возвращает структуру функций утилиты, которые я хочу фактически расширить до всех моих объектов. Он не обязательно вводит все полезные утилиты. Менее часто используемые, в том числе injectCoreMethods(), по-прежнему должны быть решены с помощью полного указателя приложения singleton, так что Application.MyApp.Objects.oCore.infrequentMethod().

Вводя в область Variables, которая защищена, эти методы будут эффективными частными методами. Таким образом, любые дампы объектов не будут показывать эти служебные функции, но полностью доступны в cfc всеми его прямыми методами.

Организация файла:

Я вообще попал в шаблон наличия одного cfc на папку. В каждой папке у меня есть один файл cfc для компонента и init. Все другие методы я выхожу в cfm файлы и вступаю в это cfc. Я делаю это, чтобы:

  • Избегайте гигантских файлов cfc с 1000 + строк, которые могут замедлить работу моей IDE (я использую aptana/cfeclipse)
  • Позволяет записывать/отслеживать изменения в зависимости от файла на каждый файл и, таким образом, записывать в мое программное обеспечение управления SCM/версией.
  • Позволить более чем одному человеку работать с данным объектом с отсутствием кода перебора друг друга.

Итак, объект dao, который содержит 4 метода crud, будет выглядеть примерно так:

/code/dao/dao.cfc
/code/dao/_removeRecord.cfm
/code/dao/_addRecord.cfm
/code/dao/_viewRecord.cfm
/code/dao/_editRecord.cfm

cfc просто содержит init() и самодокументирующие комментарии, а в области псевдоконструктора я включаю четыре метода. Это также позволяет мне захватить любую cfc по ее папке и переместить ее где-нибудь.

То же самое для утилиты cfc. Он находится в своей собственной папке и имеет около 30 нечетных функций среди 10 или около того cfm файлов (некоторые простые функции я оставляю в том же файле, что и _string.cfm, который фактически содержит lpad(), rpad() и т.д. Все связанные строки. получите идею.)

Модули и пользовательские теги

Я избегаю их любой ценой, потому что они должны быть зарегистрированы и препятствовать легкому перемещению/развертыванию. Мне не нравятся вещи, которые не просто настраиваются на перетаскивание из одной среды в другую. CF5 - вам приходилось так много делать. Но так как CF6 и возможность использовать объекты в реальном шаблоне ООП, зачем вам это нужно? Очень мало случаев, когда вам нужно/нужно, если они есть.

Другое

Я использовал функции ядра в base.cfc, который автоматически расширяется во все cfc, сгенерированные CF (ищите его, добавляйте функцию и вуаля!). Как-то вроде добавления вещей к прототипу в js). Мне это действительно нравилось, но это было проблемой для развертывания/обслуживания.

В какой-то степени я использую подход Factory. Я часто ставил в приложение довольно много статического cfc в качестве основного. Контроллер считывает общую таблицу управления и устанавливает все объекты в цикле вместе с кучей других вещей при запуске приложения, таких как переменные приложения. Но некоторые объекты создаются по мере необходимости, очевидно, что тяжелые объекты и объекты, содержащие манипулируемые [полу] постоянные данные, попадают в эту категорию

Я, в некотором роде, делал это с CF7. С CF9 + он становится довольно простым, зрелым и гладким.