我在寻找如何允许在每个客户端的基础上很容易定制和核心产品的延伸一些建议。 我知道这可能是太大的问题。 然而,我们真的需要一些想法,如果我们得到这个错误的设置可能会导致我们的问题多年。 我没有很多的经验,定制和扩展现有的产品。
我们有一个核心产品,我们通常在每个客户端的基础上显出。 我们最近与MVC3前端改写了该产品在C#4。 我们重构,现在有3个项目组成该解决方案:
- 核心域项目(命名空间 - projectname.domain。*) - 由域模型(供EF),域名服务接口等(库接口)
- 域基础设施项目(命名空间-projectname.infrastructure。*) - 实现域名服务EF上下文,仓库实现,文件上传/下载接口实现等。
- MVC3(命名空间 - projectname.web。*) - 项目,包括控制器,的ViewModels,CSS,内容,脚本等,它也有项目IOC(Ninject)处理DI。
该解决方案正常工作作为一个独立的产品。 我们的问题是扩大并在每个客户端的基础上定制的产品。 我们的客户通常要与品牌的CSS和造型给了他们非常快(通常在一对夫妇签订合同的天)的核心产品版本。 不过70的客户端%,那么要的定制改变它的功能的方式。 一些的定制是小如域模型,视图模型和视图等其他属性另外一些则更为显著,需要全新的领域模型和控制器等。
一些的定制似乎是有用的所有客户,所以定期我们希望他们成为的定制更改,并将它们添加到核心。
目前,我们正在存储TFS的源代码。 要启动一个项目,我们通常是手工源复制到新的团队项目。 更改命名空间,以反映客户的名字和开始定制的基本组成部分,然后部署到Azure上。 这显然会导致一个完全复制的代码库,我敢肯定不是去了解它的正确方法。 我想我们可能应该具有的东西,它提供核心功能和扩展/覆盖在需要。 但是我真的不知道如何去了解这一点。
所以我找上最好的项目配置,将允许任何意见:
- 代码的快速部署 - 很容易开始新的客户端,允许品牌/细微的变化
- 防止复制和代码粘贴的需要
- 尽可能多的DI尽可能使用,以保持它的松耦合
- 允许每个客户端的基础上的代码bespoking
- 延长在一个地方的核心产品,并拥有所有的客户获得这些功能,如果我们获得最新版本的核心和重新部署的能力
任何帮助/意见是极大的赞赏。 快乐添加更多的信息有人认为会有所帮助。
I just worried that with 30 or 40 versions (most of which aren't that different) branching was adding complexity.
+1大问题,它更多的是商业决定,你将不得不作出:
做我想做一个整洁的代码库,其中维护方便,功能和修复得到迅速推广到我们所有的客户
或者我想一个代码库的情况下,过多化整为零,每个微小的调整,是很难(编辑:除非你的一个ALM MVP谁可以“unbrand”的东西),以合并到主干。
我几乎寄托都只是恕我直言@Nockawa提到同意不设有分支机构扩展你的代码架构的替代品。
绝对使用分支/主干的策略,但你所说的分支太多使得难以quickly
转出网站广泛的功能和阻碍项目范围内的持续集成。 如果你想防止复制/粘贴限制分支机构的数量。
在这里编码解决方案方面是什么,我相信你正在寻找:
- 模块/插件,界面和DI是正确的目标!
- 导出关闭基地那些自定义类(每延伸客户DSL,Assembly.Load())
- 自定义报表解决方案(而不是新的网页很多定制的请求可能会报告)
- 使用电子表格页面(呵呵,我知道 - 但有趣的是它的工作原理!)
模块/插件点的很好的例子是CMS的如DotNetNuke的或Kentico。 其他想法的可以通过查看Facebook的插件架构,插件用于音频和视频编辑,3D建模应用程序(如3DMAX)和游戏,让你建立自己的水平的获得。
理想的解决方案将是一个管理应用程序,你可以选择你的模块(DLL的),裁缝的CSS(皮肤),脚本的分贝和自动部署高达Azure的解决方案。 要达致这目标插件的会让这么多的意义,基本代码不会被分拆。 同样,当完成增强到一个模块 - 你可以滚出来给所有的客户端。
你可以轻松地做小的定制,如域模型,视图模型和视图等与用户控件,派生类和功能覆盖的附加属性。
难道它真的一般,说一个客户说我要一个标签,理货的每个人的年龄在系统中,创建一个名为函数int SumOfField(string dBFieldName, string whereClause)
然后客户现场有结合功能的标签。 然后说另一个客户想要一个函数来计算购买产品的顾客的数量,就可以重新使用它:SumOfField(“product.itemCount”,“客户ID = 1”)。
需要全新的领域模型和控制器等更多显著的变化会适合进入插件架构。 一个例子可能是客户需要第二地址字段,你会调整你的当前地址的用户控制是一个插件到任何页面,就必须设置,以了解哪些数据库表和字段就可以实现它的接口CRUD操作。
如果功能是根据客户定制的30-40分行可维护性将变得很难,因为我得到的感觉,你将无法把它们合并起来(容易)。 如果有机会的话,这将得到非常大的,你不想管理275枝。 但是,如果它是专门你必须深入到用户的控制级别为每个客户端和“用户不能设计自己的网页”,则具有前端Nockawa的分支策略是完全合理的。
我可以不回答这个完全地,但这里一些建议:
- 不要复制你的代码,永远,不管是什么原因是。
- 不要重命名的命名空间,以确定一个给定的客户端版本。 使用该树枝和持续集成。
- 选择一个分支模型如下所示:根分支被称为“主”,然后创建从每个产品的主要版本主要一个分支,然后每个客户端一个分支。 当你开发的东西,目标从一开始就在哪个分支,你会取决于你在做什么开发(客户特定的功能会在客户端的分支,全球版的版本分支或客户分行,如果你想原型它在第一等)
- 尝试最好的依靠工作项跟踪您开发知道在哪个分支它的实施,以缓解整个分支合并功能。
瞄准分支,在右侧为您dev的是最关键的事情,你没有必要界定“做什么,其中一次”一些硬规则,但是尽量洽。
我在10大年的项目曾与超过75个版本和我们平时所做的是:
- 下一个主要版本:创建主一个新的分支,dev的内部
- 接下来次要版本:开发在目前的大分支,使用标签来标记每个小版本的分支内。
- 一些复杂的功能functionnal是developped在要求它的客户端的分支,然后逆转集成在版本分支时,我们成功地将“无品牌”吧。
- 在客户端分支Bug修复,那么其他部门在需要时报告。 (您必须使用工作项目,否则,你会得到很容易丢失)。
这是我对这项,其他可以有不同的观点,我靠了很多工作项目的代码,它帮助了很多的代码交付和报告的可追溯性。
编辑
好吧,我加入约分支的一些想法/反馈:
在软件配置管理(SCM),你有两个功能,可以帮助您versionning:分支和标签。 每个人并不比其他更好的,也没有最差,这取决于你所需要的:
- 标签被用于标记的时间点,用一个标签,让你以后还可以,如果需要返回到这一点。
- 一个分支是用来“复制”你的代码,能够在同一时间在两个版本一起使用。
因此,使用仅分支取决于你希望能够做什么。 如果你有工作的一个很多不同的版本(就是每一个客户端)在同一时间:有没有其他办法来解决它比使用分支机构。
为了限制你必须决定这将是一个新的分支或者是什么将一个标签标明分支的数量:客户特定版本,主要版本,次要版本,服务包等。
使用分支机构的客户端版本看起来是没有道理的。 使用一个分支每个重大版本可能会为您作出最艰难的选择。 如果您选择只使用一个分支的所有主要版本,那么你将无法灵活地在同一时间不同的主要版本,但你的分支数量将是最低的。
最后,Jemery汤普森有一个好点的时候,他说,并非所有的代码应该是客户依赖的,也有一些库(通常是最低级的)应该不是每个客户进行定制。 我们通常做的是使用框架,交叉,低水平服务库分离叉树(这是不是每个客户端)。 然后在每个客户端版本项目中引用这些项目。
我对你的建议是使用的NuGet这些库,并创建NuGet包对他们来说,因为它的定义versionned依赖关系的最佳途径。 定义NuGet包是很容易的,以及建立一个本地的NuGet服务器。
文章来源: What is a good solution structure to allow easy customisation of a product on a per client basis?