6

我们的产品是一个基于网络的课程管理系统。我们有 10 多个客户,未来我们可能会获得更多客户。(ASP.NET、SQL Server)

目前,如果我们的一位客户需要额外的功能或定制的业务逻辑,我们将更改数据库架构和代码以满足需求。

(我们只有一个分支代码库和一个数据库模式)

为了使更改不会影响彼此的路由,我们使用了一个客户端标志,该标志在 Web 配置文件中定义,因此这些额外的字段和业务逻辑仅适用于特定客户的系统。

if(ClientId = 'ABC')
{
   //DO ABC Stuff
}
else
{
   //Normal Route
}

我们的一位资深同事说,这样一来,像我们这样的小公司可以在支持多种资源上节省资源。

但我的感觉是,这种策略使我们的代码和数据库更难维护。

有没有人遇到过类似的情况?你怎么处理?

更新:如果这不是 SO 的正确问题,有人可以将此问题移至适当的 stackexchange 站点吗?

更新2:你是对的。代码现在变得很臭,我敢肯定迟早会成为一场噩梦。我公司在做产品,为了省力,后面给其他客户的产品都是在前一个的基础上做的。我知道理想的方法是将@ej-brennan 开发团队分成两部分。一个团队致力于核心产品并使其高度可定制,而第二个团队致力于为特定客户进行定制。但是,既然我们公司这么小,那真是一个两难的境地。:(

4

3 回答 3

6

我认为您需要决定是销售为每个客户量身定制的定制软件,还是一刀切的“现成”软件(也许可以通过您提供的功能进行定制)。

当您像现在这样只有少数客户时,您可以摆脱您正在做的事情,但我几乎可以保证,如果您继续沿着这条路走下去,您的客户群会增加,客户特定定制的数量也会增加同样,您将做噩梦;我已经为多个客户经历了很多次,它总是以同样的方式结束。这一切都是可以控制的,直到它无法控制,然后它是一个皇家的颈部疼痛,可能会让你的生活变得非常困难。

如果您决定自己是一家定制公司,并且想要拥有多个版本的软件和数据库,那很好,只需确保您收取全部费用 - 即考虑到您可能需要维护多个级别的源代码和数据库以及升级的因素将需要许多倍的努力才能推出,因为您需要测试每个客户的代码库。

如果您决定要成为“现成”类型的产品,那么您最好的选择是让每个客户能够自定义他们的体验,而无需更改代码 - 即通过配置内置自定义功能控制事物如何工作的屏幕和表格 - 但每个人仍将使用相同的底层代码和数据库。前期工作要多得多,但可以为您节省大量时间。

于 2012-09-04T15:52:18.257 回答
4

我也处于你的位置,我同意这是一个困难的位置。就我而言,我正在为客户构建定制的单一产品网站。虽然每个站点都遵循类似的布局和工作流程,但每个站点都必须有足够的灵活性才能拥有完全定制的设计、围绕运输和优惠券的定制规则以及不同的商家网关和配置。

几年后,我们确实得到了一些可维护的东西。首先,我们创建了库来存放我们所有的公共代码,并将这些库放入一个简单称为 Common 的 TFS 项目中。然后,我们为每个站点(不是客户,因为许多客户有多个产品/站点)创建了一个新的 TFS 项目,并将适用的项目从 Common 分支到它们中。接下来,我们创建了一个包含站点骨架的 VS 模板项目,包括“无设计”视图、控制器及其操作方法(请记住,每个站点都有相同的基本流程)。此外,每个站点都在自己的数据库上运行,该数据库是从一个其他未使用且大部分为空的模板数据库中克隆的。

由于每个站点都在自己的分支和数据库上运行,因此可以对模板安装的原始流程和设计进行修改(无需重新合并),而不会影响任何其他站点。对于自定义业务方法,例如运输计算,我们可以创建公共类的子类并在需要时覆盖。实现这一点的部分原因是将我们所有的代码转换为使用依赖注入。具体来说,每个 Controller 都注入了​​ Services,每个 Service 都注入了​​ Repositories。商户处理也被编码到一个接口并注入。另外值得一提的是,这允许我们对每个站点的所有加售逻辑进行硬编码(您购买了产品 X,所以我们推荐 Y),与在我们旧的追加销售规则引擎中定义复杂的配置规则相比,这更容易创建和维护。不知道你有没有这样的...

有时我们希望对公共代码本身进行更改,这通常是由对特定站点的特定需求引起的。在这种情况下,我们将在该分支上进行更改,将其合并到 Common,然后在方便时将其合并到其他站点(非常适合“破坏”更改或还需要更改数据库的更改)。同样对于数据库更改,我们将更新模板数据库,然后编写一个小脚本来更新具有相同架构更改的其他站点数据库(仍然必须聪明并小心)。

另一个好处是我们还创建了 Mock 存储库,这些存储库将在“设计”构建配置中使用/注入,这使设计人员能够在应用程序中跳转并在屏幕上工作,而无需将自己真正提交给工作流。它还允许他们在后端完成任何操作之前开始在站点上工作,这对于那些需要“看到一些东西”的焦虑客户来说非常重要。

10+ 客户绝对不是你所说的小数目。三对我来说已经足够痛苦了。我们同时运行了 30 多个站点,由三位开发人员和两位设计师维护。

Finally, I know it's outside the scope of your question and a bit presumptuous, but getting "final" client sign-off on design before the designers actually went about implementing it (and before devs did their thing) also saved us a lot of costly rework. I know no design is final, but increasing efficiency on the implementation end gave the clients less time to change their minds about the design they approved.

I hope that at least gives you some approaches to think about.

于 2012-09-04T18:27:59.623 回答
3

使用必须更改或定制的系统的人们已经开发出处理这些问题的模式。

你绝对应该从阅读一本关于控制反转的好书开始。简而言之,您可以通过定义构建块(合同,表示为接口)来构建系统并提供多种实现。这种方法有很多好处,但只提两个: - 您可以通过提供相同接口的不同实现来处理自定义 - 您可以静态或动态重新配置您的应用程序,但这两种方法都比您的“如果”干净得多

当涉及到数据层时,请研究存储库模式。它有助于以您可以在不同提供者之间切换的方式组织数据访问。它非常适合ioc。

并且只是一个技术提示 - nhibernate 支持动态属性。您只需在映射中提供额外的列,nh 就可以从相同的代码库中支持它。通过这种方式,您可以针对具有稍微不同的数据库架构的不同数据库。

于 2012-09-04T15:54:27.643 回答