我继承了一个应用程序的怪物。这是一个被许多客户用于订单处理的网站。它很旧,过时了,需要一些认真的更新。最困难的部分是它最初是为一种类型的客户端创建的,然后,随着新客户端的添加,代码被数百个 IF 语句混为一谈,这些语句基本上打开或关闭每个客户端的功能。想象一下这样的事情(用 ColdFusion 编写):
<cfif clientId EQ "MIKE">
<a href="cart1.cfm">Shopping Cart</a>
<cfelseif clientId EQ "JOE">
<a href="cart2.cfm">Shopping Cart</a>
<cfelseif clientId EQ "BILL"
OR clientId EQ "JILL"
OR clientId EQ "RAY">
<a href="cart3.cfm">Shopping Cart</a>
<cfelse>
<a href="cart.cfm">Shopping Cart</a>
</cfif>
以上是我在整个网站上处理的内容的一个很好的 CLEAN 版本。
因此,我正在尝试重构网站以允许更轻松的特定于客户端的配置 - 基本上是为每个客户端提供或隐藏功能。
我从我认为是一个简单、干净的解决方案开始,但我担心它可能会变得难以维护。
基本上,我将为每个客户提供一个 Web 根目录之外的目录,用于存储他们的文件——可能是网站上使用的文档等。这个目录类似于C:\clients\MIKE\
. 在这个目录中,我存储了一个 xml 文件——我们称之为 config.xml。我创建的第一个 config.xml 文件具有以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<cart>
<url>cart1.cfm</url>
</cart>
</root>
因此,对于每个页面请求,我都会查找 xml。如果存在,我将每个值复制到Client
类实例的属性中:
<cfcomponent
hint="Represents configurable per-Client settings stored in a local Xml file">
<cfscript>
VARIABLES.CartLink = "";
</cfscript>
<cffunction name="init" return="Client" output="false">
<cfargument name="clientId" type="String" required="true" hint="i.e. 'MIKE'"/>
<cfscript>
var _clientXml = XmlNew();
THIS = setClientId(ARGUMENTS.clientId);
_clientXml = read();
if ( StructKeyExists(_clientXml.XmlRoot, "cart")
&& StructKeyExists(_clientXml.XmlRoot["cart"], "url")
)
setCartLink(_clientXml.XmlRoot["cart"]["url"].XmlText);
return THIS;
</cfscript>
</cffunction>
<cffunction name="getCartLink" returntype="String" output="false">
<cfreturn VARIABLES.CartLink />
</cffunction>
<cffunction name="setCartLink" returntype="Void" output="false">
<cfargument name="cartLink" type="String" required="true" />
<cfset VARIABLES.CartLink = Trim(ARGUMENTS.cartLink) />
</cffunction>
<cfscript>
function getXmlFilePath() {
return APPLICATION.ClientFilePath
& "\" & getClientId() & "\config.xml";
}
</cfscript>
<cffunction name="read" access="public" output="false" returntype="xml">
<cfscript>
var _clientXml = XmlNew();
var _fileContents = "";
_clientXml.XmlRoot = XmlElemNew(_clientXml, "root");
if (FileExists(getXmlFilePath()))
_fileContents = FileRead(getXmlFilePath());
if (IsXml(_fileContents))
_clientXml = XmlParse(_fileContents);
return _clientXml;
</cfscript>
</cffunction>
</cfcomponent>
使用上面的示例 xml,当用户在“MIKE”客户端下登录时,REQUEST 范围内的 Client 实例的属性值为“cart1.cfm” cartLink
。
现在我可以简单地查找该值并使用它来填充锚标记:
<a href="#REQUEST.Client.getCartLink()#">Shopping Cart</a>
我的目标是保持代码干净,避免在需要编辑的地方到处出现数百个 IF 语句。
但是,当我现在看到这个设计时,我意识到这可能更像是一场维护噩梦。该网站目前有大约 30-40 个客户。所以,现在,我需要维护 30-40 个 xml 文件,每个配置属性都有任意数量的节点。此外,每当添加新功能时,我都必须使用新属性的新 getter/setter 方法更新客户端类。
我不想让事情变得更糟。任何想法将不胜感激。