Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manage CFC's (subsystem) that's shared across multiple sites?

How can you manage something like that? I tried my best to design the subsystem to be reusable, but there are just certain things that are unique to the site that have to be customized (e.g. fields in Account entity, or cfc="" in orm annotation).

I thought of using SVN and branch out the customization, but we found it very cumbersome quick as the commit person has to decide an enhancement / bug fix belongs to the Truck or Branch every time and once something is missed, is not easy to undo.

So... What's the best way to handle this situation? Just clone the set of code into a new source control, and fix bugs on both/all source controls?

like image 745
Henry Avatar asked Oct 12 '22 07:10

Henry


1 Answers

Assuming you're not using some sort of MVC framework... yet...

I've used a couple of different methods for handling these sorts of situations.

Depending on what seems to be different and the same between CFC's, you can:

1) use inheritance

If the vast majority of your code is the same, but each project has just a few differences, then refactor the common code into a base CFC which you extend for each project. This allows you to maintain a single set of tests for most of the functionality, then just add further tests for code that deviates for each project.

The drawback to this is that it requires some planning and discipline to maintain forward compatibility when modifying the base classes. You are, in essence, defining an API, and doing that well is not an easy task.

2) use mix-ins

If what you seem to be duplicating each time is functionality/logic, then try refactoring that logic into chunks of code which you cfinclude into any cfc's that require it. See Ben's experiments with mixins and Sean's comments on mixins.

Sadly, the mechanisms for doing this well in CF are weak, unlike Ruby's modules.

If your needs are as you describe in your comment, "something like, the logic/business rules are the same, but the input and data collected are not the same", I would suggest taking a look at Rails or Django for inspiration.

In my situation, I ended up developing a framework that allowed me, when defining a model, to extend a base model class, and simply fill it with a bunch of cfproperty tags with custom properties that defined my model and were used by the base model class and a set of services which handled most of the business logic. This worked for 95% of the cases and in any situation where I needed to deviate from the framework logic, I would either add additional functions in my model cfc or even override the base model's function.

My models ended up looking like:

    <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>
like image 80
Edward M Smith Avatar answered Oct 14 '22 08:10

Edward M Smith