我们的产品是基于Web的课程管理系统。我们有10多个客户,未来我们可能会有更多的客户。 (Asp.net,SQL Server)
目前,如果我们的客户需要额外的功能或自定义业务逻辑,我们将更改数据库架构和代码以满足需求。
(我们只有一个分支代码库和一个数据库架构)
为了使更改不会影响彼此的路由,我们使用客户端标志,该标志在Web配置文件中定义,因此这些额外的字段和业务逻辑仅应用于特定客户的系统。
if(ClientId = 'ABC')
{
//DO ABC Stuff
}
else
{
//Normal Route
}
我们的一位高级同事说,通过这种方式,像我们这样的小公司可以节省资源来支持多种资源。
但我觉得,这种策略使我们的代码和数据库更难维护。
有没有人遇到类似的情况?你是如何处理的?
更新:如果这不是SO的正确问题,是否有人可以将此问题移至正确的stackexchange站点?
UPDATE2 : 你是对的。代码现在变得很臭,我肯定迟早会成为一场噩梦。我们公司正在做产品并省力,其他客户的后期产品都是基于前一个。我知道理想的方法是将@ e-j-brennan开发团队分成两部分。一个团队致力于核心产品,并使其高度可定制,团队两个团队致力于为特定客户定制。但是,如果我们公司这么小,那真是一个两难的局面。 :(
答案 0 :(得分:6)
我认为您需要决定是否销售自定义软件,为每个客户量身定制,或者是“现成的”软件,这是一种通用的(并且可能通过您提供的功能进行定制)。
如果你现在只有少数像你这样的客户,你就可以逃避你正在做的事情,但我几乎可以保证,如果你继续走这条路,你的客户群增加,客户数量增加 - 特定的定制也会增加,你手边会有一场噩梦;对于多个客户,我已经多次这样做了,它总是以同样的方式结束。这一切都是可以控制的,直到它不是,然后它是一个皇家的痛苦,可能会让你的生活非常困难。
如果您认为自己是一家定制公司,并希望拥有该软件和数据库的多个版本,那就没问题,只需确保您收取全部费用 - 即您可能需要维持多个级别的因素由于您需要测试每个客户端的代码库,因此源代码和数据库以及升级因素将需要花费很多倍才能推出。
如果您决定要成为“现成”类型的产品,那么您最好的选择是为每个客户提供定制体验的能力,而无需更改代码 - 即内置于定制中功能通过配置屏幕和表来控制事物的工作方式 - 但每个人仍将使用相同的底层代码和数据库。提前完成更多的工作,但为您节省了大量的时间。
答案 1 :(得分:4)
我也一直在你的位置,我同意这是一个困难的问题。就我而言,我正在为客户构建自定义单一产品站点。虽然每个站点都遵循类似的布局和工作流程,但每个站点都必须具有足够的灵活性,以便拥有完全自定义的设计,关于运输和优惠券的自定义规则,以及不同的商家网关和配置。
几年后,我们最终得到了可维护的东西。首先,我们创建了库来存放所有公共代码,并将这些库放入一个简称为Common的TFS项目中。然后,我们为每个站点创建了一个新的TFS项目(不是客户端,因为许多客户端有多个产品/站点),并从Common分支了适用的项目。接下来,我们创建了一个VS模板项目,其中包含站点的框架,包括“无设计”视图,控制器及其操作方法(请记住,每个站点具有相同的基本流程)。此外,每个站点都在自己的数据库上运行,该数据库是从一个未使用且大部分为空的模板数据库中克隆的。
每个站点在其自己的分支和数据库上运行时,可以对模板安装的原始流和设计进行修改(永远不需要将其合并回来),而不会影响任何其他站点。对于自定义业务方法(如运输计算),我们可以创建公共类的子类并在需要时覆盖。启用此功能的部分原因是将所有代码转换为使用依赖注入。具体来说,每个Controller都注入了Services,每个Service都注入了Repositories。商家处理也被编码为接口并注入。另外值得一提的是,这使我们能够对每个站点的所有上传逻辑进行硬编码(您购买了产品X,因此我们建议使用Y),与在旧的追加销售中定义复杂的配置规则相比,这更容易创建和维护规则引擎。我不知道你有没有这样的......
有时我们希望对Common代码本身进行更改,这通常是由特定站点的特定需求引起的。在这种情况下,我们在该分支上进行更改,将其合并到Common,然后在方便的时候将其合并到其他站点(非常适合“破坏”更改或更改,这也需要更改DB)。类似地,对于数据库更改,我们将更新模板数据库,然后编写一个小脚本来更新具有相同模式更改的其他站点数据库(仍然必须聪明且小心)。
另一个好处是我们还创建了Mock存储库,这些存储库将在“设计”构建配置中使用/注入,这使得设计人员可以跳转应用程序并在屏幕上工作,而无需将自己提交到工作流程。它还允许他们在后端做任何事情之前开始在网站上工作,这对于那些需要“看到某些东西”的焦虑客户来说非常重要。
10个以上的客户绝对不是您所谈论的一个小数目。三个对我来说足够痛苦。我们一次有30多个站点在运行,由三位开发人员和两位设计师维护。
最后,我知道这超出了你的问题的范围并且有点冒昧,但在设计师实际执行它之前(以及在开发者做了他们的事情之前)让“最终”客户签署设计也节省了我们很多昂贵的返工。我知道没有设计是最终的,但提高实施效率会让客户更少时间改变他们对他们批准的设计的看法。
我希望至少能给你一些思考方法。
答案 2 :(得分:3)
使用必须更改或定制的系统的人已经开发出处理此类问题的模式。
你一定要从阅读一本关于控制反转的好书开始。简而言之,您可以通过定义构建块(契约,表示为接口)并提供多个实现来构建系统。这种方法有多种好处,但仅举两个: - 您可以通过提供相同接口的不同实现来处理自定义 - 您可以静态或动态地重新配置应用程序,但这两种方法都比“if”
更加干净说到数据层,请研究存储库模式。它有助于以可以在不同提供程序之间切换的方式组织数据访问。它非常适合ioc。
只是技术提示 - nhibernate支持动态属性。您只需在映射中提供其他列,并且能够从相同的代码库中支持它。这样,您可以使用稍微不同的数据库模式来定位不同的数据库。