如何开发高度可定制的产品

原文:how-to-develop-a-highly-customizable-product

翻译:CUBA China

CUBA-Platform: https://cuba-platform.com

CUBA-China:http://cuba-platform.cn

欢迎转载, 转载请注明来源。

        本文探讨了几种开发高度可定制项目的方案,包括CUBA平台。

做为开发人员肯定听客户说过:“你们的产品还不错,但是还有些细节需要完善”, 然后收到一份有数百个需求的“待完善细节”清单。 做为项目经理肯定也跟团队说过:"公司即将拿到一个大单,但是需要咱们先。。。。。。" ,结果往往变成开发人员头疼不已地去满足客户的各项愿望清单。

那么,如何既能满足客户的需求,又能使核心产品远离客户潜在的危险想法? 以特定技术方式设计的产品,如何既支持更多功能插件又能持续保证最高性能? 为解决方案提供可靠和出色的支持,需要面对多大的挑战?

随着商业世界对定制产品的需求越来越强烈,软件开发行业发展出了许多通用方法来满足客户的定制需求。下面我们会介绍一些典型的方案,如果您对这些方案已经很熟悉,那么欢迎您直接向下滚动到“扩展方案”段落,了解我们如何以更有效的方式解决这些具有挑战性的问题。

"全家桶"方案(All In One)


最直接,最显而易见的解决方案就是在一个核心产品里实现所有的功能,然后为了满足不同客户的需求,再给各个功能加个“开关”。

这个方案的主要优点就是“大”而“全”,对于某些类型的产品适用,这样的产品通常涵盖该行业所有业务需求所以无需大量定制。

这种方法的先天局限性隐藏在“无需大量定制”的假设中。通常,产品开发始于这一设想,但经过多次交付后,就会意识到客户定制化需求的真实规模。然后就是进退两难的局面:拒绝定制开发则可能失去客户,继续在核心产品上添加定制功能则导致源码成为一个“垃圾箱”,核心产品代码包含了多数用(户根本用不到的功能、臃肿、难以维护。

这种情况下你会如何选择?显然,不管怎么选都不是成功之道。

        总结:只有在你确定产品不会出现很多的个性化需求时,“All in One”方案才是合适的选择。 否则,你只能在产品的可维护性、可控性与客户满意度之间二选一。 对此,我们引用Jerry Garcia说过的一句话做出评价:Constantly choosing the lesser of two evils is still choosing evil(两害相权取其轻也是害)”。

如果确实有重量级的定制需求“必须”交付,又不能使用大而全的方案,另一种直截了当的方式就是使用代码分支 - 创建一个新的代码分支,然后在这个分支上独立修改。

分支方案与All in One比较,最大的优点是可以随心所欲的做定制化开发,不用担心一个分支的代码修改影响其它客户。 使用不同的分支来满足不同客户的特定需求,避免了在同一代码库中混合所有功能。

然而随着产品发展,这种方案将会面对另一种“死法”。 因为大多数bug修复,产品改进,新功能都应用到核心产品分支上,而定制化开发在客户分支上,因此,需要频繁地合并分支以使所有定制分支与核心产品保持同步。 原始产品代码没有受到客户分支的影响的话合并还算是一个简单的操作,否则的话代码合并会变得非常耗时并且无法避免地,回归测试时肯定有bug。

如果只需要少量客户分支,这个方案还是有效的。 然而,随着交付的增加,频繁地代码合并将会成为开发人员的噩梦。

        总结:分支方案无疑非常灵活和直接 - 产品的任何部分都可以修改。 然而,费力的部分发生在交付之后,并且随着时间的推移会越来越费力,并且客户分支太多的话就更加难以管理。


EAV:实体 - 属性 - 值模型  entity–attribute–value model


EAV,即实体 - 属性 - 值模型(又名对象 - 属性 - 值(object-attribute-value)模型,垂直数据库模型或开放模式)是众所周知且广泛使用的数据模型。 EAV支持动态实体属性,通常与标准关系模型并行使用。

从产品化的角度来看,使用EAV的主要优点是您可以“按原样”交付产品,然后通过在运行时添加所需的属性来调整数据模型,从而保持源代码的清洁。

但这个方案也有缺陷:

适用范围有限 - EAV模型受限于仅允许向实体添加属性,然后根据预先编写的逻辑将其自动嵌入到UI中。

额外的数据库服务器负载 - 垂直数据库设计经常成为企业应用程序的瓶颈,因为企业应用程序通常有大量实体,实体也可能具有很多属性。

最后,企业级应用往往需要成熟的报表引擎,EAV的“垂直”数据库结构会给报表引擎开发增加大量复杂度。

        总结:实体 - 属性 - 值模型在某些情况下具有很大的价值,例如通过增加额外的不会在业务逻辑中明确使用的信息数据来实现灵活性。换句话说,EAV是对标准的关系模型和插件架构的一个很好的补充。


插件架构方案


插件架构是最流行和最强大的方法之一 - 定制功能逻辑被发布为单独的制件,称为插件。这种方案需要在产品源代码中定义“定制点”(也称为扩展点),应用程序在定制点检查是否有插件要覆盖开箱功能。 插件的一个变体是外部脚本:所需功能采用外部脚本实现并在外部存储,通过预定义的“定制点”控制调用外部脚本实现插件功能。

使用插件方案,产品代码保持一直“干净”, 不会被不同的客户化影响。研发团队“按原样”交付核心产品,定制化功能做在插件或者脚本中。另一个优点是软件升级更新更易于管理,产品和插件的完全分离使得它们都可以彼此独立地更新而互不影响。

当然,这个方案也有限制:主要是不可能完全预测客户将来会提出哪些定制要求,只能先猜测应该嵌入“定制点”的位置。也许可以在各处都添加定制点以防万一,但结果就是代码可读性差、难以调试,技术支持复杂度提高。

        总结:如果“定制点”易于预测,插件架构方案确实有效,需要注意的就是“定制点”以外无法添加定制功能。


扩展方案


我们的企业级应用开发平台CUBA采取了一种独特的方法。CUBA是一个具有实践性、开发人员驱动演进的平台。 基于我们对现有产品的丰富经验,在定制化开发方面,我们提出了两个终极要求:

○ 客户定制化代码应与核心产品代码完全分离。

○ 产品代码的每个部分都应该支持可修改定制。

最终,通过CUBA的“扩展”机制,我们不但满足了以上需求而且做到了更多。


CUBA扩展


扩展是一个独立的CUBA项目(lib库),它继承了父项目(比如说核心产品)的所有功能。开发人员能够在扩展里开发新的功能而且不会影响到父项目,更厉害的是由于使用了Open Inheritance模式和CUBA的特别机制,开发人员可以在扩展里重写父项目的任何部分。总之,CUBA扩展就是开发团队实现本文开头提到的数百个“小细节”的地方。

实际上,每个CUBA项目都是CUBA平台本身的扩展 - 因此任何平台功能都可以被重写。我们自己也采用这种方法从核心平台中分离出一些开箱即用的功能(全文搜索,报表,图表等)。如果您在项目中需要它们,就把它们添加为父项目 - 就像多重继承!

用同样的方式还可以构建多级扩展结构。听上去有点复杂但是很实用。举一个现成的例子:Sherlock- 是Haulmont的出租车全周期管理解决方案,支持出租车业务从预订、派单到计费的方方面面。该解决方案满足了客户许多不同的业务,其中相当一部分与地域相关。例如,所有英国出租车公司都有相同的法律规定,但其中许多不适用于美国,反之亦然。显然,我们不希望在核心产品中实施所有这些规定,原因是:

○ 这是“特定运营区域”的功能

○ 不同国家当地的法规可能对出租车车队运营产生完全不同的影响

○ 一些客户根本不需要类似的法律规定

因此,我们这样组织多级扩展结构:

○ 核心产品包含出租车业务的通用功能

○ 第一级定制实现区域定制化功能

○ 第二级定制涵盖特定客户的定制需求(如果有的话)

显而易见,通过使用扩展,既不需要客户分支也不需要把客户需求都集成到核心产品中,代码还清晰可控。 看上去好得难以置信,接下来看看它是如何实现的:

向现有实体添加新属性(实体定制)


假设Product产品中有一个User实体,它包含两个字段:login和password:

然后根据客户要求需要向上述实体添加“家庭住址”字段,我们就需要在"扩展"中扩展User实体:

上述代码中除了@Extends之外的所有注解都是常见的JPA注解。 @Extends注解是CUBA引擎的一部分,它全局地将User实体替换为ExtUser,包括替换掉原Product产品里的User实体。

使用@Extends属性,我们在平台里强制做以下事情:

1. 始终创建“最新子类"的实体

User user = metadata.create(User.class); //ExtUser 实体将创建

2. 在JPQL执行之前做转换,以便它们始终返回“最新子类”的集合

select u from product$User u where u.name = :name //返回ExtUsers集合

3. 始终在关联实体中使用“最新子类”实体

userSession.getUser(); //返回 ExtUser 类型

换句话说,如果声明了扩展实体,整个解决方案(核心产品和扩展)中的基础实体都会被扩展实体替换。

  界面定制


以上我们通过添加地址属性扩展了用户实体,现在要反映到用户界面中。 原始产品(Product)界面声明是这样的:

如图所示,CUBA界面描述使用普通XML语法。 虽然我们可以简单地在扩展中重写整个界面的XML描述(先复制粘贴原XML的大部分内容),但是如果将来原界面某些内容发生变化就得手动将这些更改复制到扩展界面。为了避免这种情况,CUBA引入了界面继承机制,在扩展中只需要描述对界面的更改即可:

如图所示,使用extends属性定义要继承的界面,然后描述要更改的界面元素。

看看结果:

                

       修改业务逻辑

CUBA平台使用Spring Framework实现业务逻辑,Spring Framework构成了平台基础架构的核心部分。

举例,有一个bean用来做价格计算:

要重写价格计算逻辑,只需要简单的两步:

首先,扩展(继承)核心产品中的类并重写相应的方法:

其次,使用原有的bean标识符在Spring配置中注册新类:

然后对PriceCalculator的注入将始终返回扩展类实例,所以新逻辑将在整个产品范围内生效。

    在扩展中升级核心产品版本


随着核心产品的发展和新版本的发布,您很可能会打算将扩展升级到最新的核心产品版本。 这个过程也很简单:

   1. 在扩展中指定核心产品的新版本号

   2. 重新构建扩展:

○ 如果扩展是基于产品API的稳定部分构建的,则可以直接运行扩展。

○ 如果核心产品API进行了一些重大修改,并且这些修改与扩展中实现的定制化开发重复了,则有必要在扩展中支持新的核心产品API。

大多数情况下,产品API在更新时不会发生显著的变化,尤其是在小版本中。 但即使出现API“大爆炸”,产品通常会保持至少两个未来版本的向下兼容性,旧的实现标记为“已弃用”,允许将所有扩展迁移到最新的API。

总结

现在我们以表格形式对以上方案做一个简短的总结:

                                                                             

显而易见,扩展方案很强大,但它不支持运行时定制(动态定制)。为了弥补这方面,CUBA也支持Entity-Attribute-Value模型和Plugin/Scripting方案。

链接

CUBA-Platform 官方网站 : https://www.cuba-platform.com

CUBA China 官方网站 : http://cuba-platform.cn

原文地址:http://blog.51cto.com/13881728/2152315

时间: 2024-10-11 11:47:46

如何开发高度可定制的产品的相关文章

EAIntroView–高度可定制的iOS应用欢迎页通用解决方案

简介 高度可定制的应用欢迎页通用解决方案,可高度定制,不要仅限于现有的demo. 项目主页: EAIntroView 最新示例: 点击下载 入门 安装 安装后,引入" EAIntroView.h"并设置EAIntroDelegate代理即可. 使用CocoaPods安装 pod 'EAIntroView', '~> 2.7.0' 手动安装 添加EAIntroPage ,EAIntroView和EARestrictedScrollView 的.h和.m文件到你的工程即可. 可定制性

史上最全最完整的IOS 游戏开发 PDF电子书定制下载

<iOS 5游戏开发>作者:(新西兰)James·Sugrue著 页数:191 出版社:北京市:人民邮电出版社 出版日期:2012.08 简介:<iOS5游戏开发>是一本iOS5游戏开发的基础入门书.全书使用通俗易懂的简单实例,带领读者经历构建经典动作游戏的整个周期.读者在本书的阅读过程中,将经历从开发概念.规划设计一直到编写实际代码的全过过程.本书的每一章,都将演示游戏创建过程中的一个逻辑步骤,读者将在其中学习如何创建Sprite,用触摸屏.重力感应器和屏幕游戏棒控制玩家角色等-

如何开发AR增强现实应用与产品

2016年被称为VR元年,可见火爆程度,但是我要告诉你,其实还有一种技术AR(增强现实)技术,才是下一个真正的"风口"技术.可以预见的是,未来AR应用爆发之时,必将超越VR产业规模,开拓千亿级市场空间! AR技术需要硬件承载,最新的媒介以微软的HoloLens头显为代表,传统的则一般与手机或者Ipad结合.在目前市场(2016年)不是很成熟的情况下,让消费者为了体验AR而花钱买个新的硬件,消费者不一定买账. AR技术不仅在与VR技术相类似的应用领域,诸如尖端武器.飞行器的研制与开发.数

RBPlayer 教程:iOS 高度可定制的播放器

RBPlayer基于AVPlayer的高度可定制的播放器,要求iOS 7.0及以上版本. 特点: 完全可自定义UI 没有层级及位置大小等限制 支持全屏播放,支持忽略竖屏锁定 更多RBPlayer 教程:iOS 高度可定制的播放器,请查阅勤快学http://qkxue.net.

Android开发学习之 定制界面风格

统一的用户界面是可以使得应用程序更友好.要做到用户界面的统一,我们就必须用到风格(style)和主题(theme).OPhone系统提供了很多系统默认的风格和主题,但是很多情况下,这些不能满足我们的需要.例如我们不可能总是希望背景色是系统规定的,我们也不希望字体大小一成不变.当然我们可以在每个空间里面进行修改,但是如果放到风格里面去做,可以更容易的做到用户界面统一.如果有朋友还不清楚什么是风格什么是主题,你可以在Andoird的Dev Guide文档里面找到详细的解释,这篇文章要描述的是开发者怎

iOS 9应用开发教程之定制应用程序图标以及真机测试

iOS 9应用开发教程之定制应用程序图标以及真机测试 定制ios9应用程序图标 在图1.12中可以看到应用程序的图标是网状白色图像,它是iOS模拟器上的应用程序默认的图标.这个图标是可以进行改变的.以下就来实现在iOS模拟器上将HelloWorld应用程序的图标进行更改. (1)添加图像logo.png到创建的项目中,添加图像的具体步骤如下.首先右击项目文件夹中的任意位置,弹出快捷菜单,如图1.39所示. 图1.39  快捷菜单 然后,选择Add Files to "HelloWorld&quo

开放产品开发(OPD):产品负责人的工作原则和方法

产品backlog是如何从产品概念开始而形成的?产品负责人需要定义产品是什么.了解为什么要做,还需要决定何时交付.如何交付,敏捷开发中对产品负责人并没有明确的进行指导.去年在一些大会上分享过敏捷的本质,这是对敏捷团队所有成员的价值观指引.7月26日我将在2014 WOT全球软件技术峰会做相关的一个主题演讲[产品负责人的工作原则和方法],本次分享主要向大家介绍PO和业务需求人员工作中应该遵循的6个原则和相应的一些方法. 以下是本次分享内容: 完整版如下,如果你喜欢想下载的话,点击 http://t

B2C电商系统开发app平台定制详解

B2C电商系统开发从标品到非标品体现的是用户从追求功能价值到追求情感价值的变迁.在电商1.0时代,为用户习惯培养阶段,图书和3C等标品更利于降低用户的信 任成本.B2C电商app开发,同时,用户对标品的消费更多追求的是商品的功能价值,随着用户网购习性的培育和消费文化的升级,B2C电商平台开发,用户对情感价值和文化价值的追求逐渐引爆了非标品 市场,如食品.美妆.生鲜.本地生活服务等; 从低价到高价体现的是用户追求价格导向追求价值消费的升级.用户消费能力的升级,品牌电商的崛起,线下服务的完善,共同推

拉菲庄园系统开发330游戏定制app

330游戏定制(杨186.6508.4445电/微),拉菲庄园平台.拉菲庄园游戏定制.拉菲庄园理财系统.拉菲庄园源码定制.拉菲庄园app开发,拉菲庄园开发.拉菲庄园模式.拉菲庄园游戏.拉菲庄园理财.拉菲庄园渠道,但是我们今天谈的互联网+,最主要把互联网作为主语,是用互联网+上很多行业,本质上来说就是利用互联网这种思想,这种连接的思维,你在想如何在你做的产品里面,用互联网思维改造你的产品体验,从一个过去仅是卖给客户的商品,变成你跟客户的连接.同时利用互联网的商业模式,把这个一次性销售一个产品的模式