Gra*_*ler 10 architecture tfs dependency-injection visual-studio-2010 asp.net-mvc-3
我正在寻找一些关于如何允许基于每个客户端轻松定制和扩展核心产品的建议.我知道这可能是个大问题.然而,我们真的需要得到一些想法,好像我们得到了这个错误的设置,它可能会导致我们多年来的问题.我在定制和扩展现有产品方面没有太多经验.
我们有一个核心产品,我们通常在每个客户的基础上定制.我们最近使用MVC3前端在C#4中重写了该产品.我们已经重构,现在有3个项目组成了解决方案:
此解决方案可作为独立产品使用.我们的问题是在每个客户的基础上扩展和定制产品.我们的客户通常希望通过品牌CSS和样式很快(通常在签订合同后的几天内)向他们提供核心产品版本.但是,70%的客户希望通过自定义来改变其运行方式.一些自定义很小,例如域模型,视图模型和视图等的附加属性.其他更重要,需要全新的域模型和控制器等.
某些自定义似乎对所有客户端都有用,因此我们会定期将其更改为自定义并将其添加到核心.
我们目前将源代码存储在TFS中.要启动项目,我们通常会手动将源复制到新的Team Project中.更改命名空间以反映客户端名称并开始自定义基本部件,然后部署到Azure.这显然会导致完全重复的代码库,我确信这不是正确的方法.我认为我们可能应该提供一些能够提供核心功能并在需要时扩展/覆盖的东西.但是我真的不知道该怎么做.
所以我正在寻找有关最佳项目配置的任何建议,以允许:
非常感谢任何帮助/建议.很高兴添加任何人认为有用的信息.
我可能不会完全回答这个问题,但这里有一些建议:
为你开发目标正确的分支是最重要的事情,你没有必要定义一些"在哪个场合做什么"的硬规则,但试着保持一致.
我参与了一个超过75个版本的10年大项目,我们通常做的是:
这是我的看法,其他可能有不同的观点,我在工作项上依赖于代码的可追溯性,这对代码的交付和报告有很大帮助.
编辑
好的,我添加一些关于分支的想法/反馈:
在软件配置管理(SCM)中,您有两个功能可以帮助您进行版本控制:分支和标签.每一个都不比另一个好,也不差,这取决于你需要什么:
因此,仅使用分支取决于您希望能够做什么.如果你必须同时处理多个不同版本(比如说每个客户端一个版本):没有其他方法可以处理它而不是使用分支.
要限制分支数量,您必须决定新分支的内容或标签将标记的内容:客户端特定版本,主要版本,次要版本,Service Pack等.
使用客户端版本的分支看起来并不是一件容易的事.为每个主要版本使用一个分支可能是您做出的最艰难的选择.如果您选择仅对所有主要版本使用一个分支,那么您将无法灵活地同时处理不同的主要版本,但您的分支数量将尽可能低.
最后,Jemery Thompson有一个很好的观点,他说并非所有代码都应该依赖于客户端,有些库(通常是最低级别的代码库)不应该按客户端进行自定义.我们通常使用的是分离的分支树(不是每个客户端)用于框架,交叉,低级服务库.然后在每个客户端版本项目中引用这些项目.
我的建议是将Nuget用于这些库并为它们创建nuget包,因为这是定义版本化依赖项的最佳方法.定义Nuget包非常简单,并且设置本地Nuget服务器.
I just worried that with 30 or 40 versions (most of which aren't that different) branching was adding complexity.
我是否想要一个整洁的代码库,可以轻松维护,并且可以快速向所有客户推出功能和修复
或者我是否想要将一个代码库的大量实例分开,每个实例都进行一些微小的调整,这是很难的(编辑:除非你是一个可以“取消品牌”的东西的 ALM MVP)合并到一个主干中。
我同意 @Nockawa 提到的几乎所有内容,除了恕我直言,不要用分支来替代扩展代码架构。
绝对使用分支/主干策略,但正如您所提到的,太多分支使得quickly推出站点范围的功能变得更加困难,并阻碍项目范围的持续集成。如果您希望防止复制/粘贴,请限制分支数量。
就编码解决方案而言,我相信您正在寻找以下内容:
模块/插件点的一个很好的例子是 CMS,例如DotNetNuke 或 Kentico。其他想法可以通过查看 Facebook 的插件架构、用于音频和视频编辑的插件、3D 建模应用程序(如 3DMax)以及可让您构建自己的关卡的游戏来获得。
理想的解决方案是一个管理应用程序,您可以选择模块 (DLL)、定制 CSS(皮肤)、编写 DB 脚本并将解决方案自动部署到 Azure。为了实现这个目标,插件会更有意义,代码库不会被分割。此外,当对模块进行增强时,您可以将其推广给所有客户。
您可以轻松地进行小型定制,例如使用用户控件、派生类和函数覆盖在域模型、视图模型和视图等上添加附加属性。
真正做到这一点,假设客户说我想要一个标签来统计系统中每个人的年龄,创建一个名为的函数int SumOfField(string dBFieldName, string whereClause),然后为该客户站点提供一个绑定到该函数的标签。然后假设另一个客户想要一个函数来统计客户购买的产品数量,您可以重复使用它:SumOfField("product.itemCount","CustomerID=1")。
需要全新的域模型和控制器等的更重大的变化将适合插件架构。一个例子可能是客户需要第二个地址字段,您可以将当前的地址用户控件调整为任何页面的插件,它将具有设置以了解可以实现其 CRUD 操作接口的 dB 表和字段。
如果功能是在 30-40 个分支中为每个客户端定制的,那么可维护性将变得非常困难,因为我感觉您将无法(轻松)将它们合并在一起。如果有可能这会变得非常大,您不会想管理 275 个分支机构。然而,如果它是专业的,你必须深入到每个客户端的用户控制级别,并且“用户无法设计自己的页面”,那么使用 Nockawa 的前端分支策略是完全合理的。