高度可定制化的方案_如何开发高度可定制的产品

高度可定制化的方案

您是否听说过:“我们非常喜欢您的产品……除了一些小细节。”? 然后,CIO推出了一系列其他“必备”要求的清单,其中有数百个要添加到您的惊人产品中。 您是否听说过,甚至说过:“团队,我们即将签署一份利润丰厚的合同,但是……”? 然后,客户对附加功能的愿望清单使开发人员感到头疼。

木制拼图 那么,如何使产品远离客户的潜在危险想法,同时又让他们满意呢? 对于专门设计为以特定方式运行但现在具有大量附加组件的产品,如何保持最高性能水平呢? 为已开发的解决方案提供不间断且出色的支持的基本需求将带来多少挑战?

在商业世界中,产品定制已成为越来越令人期望的要求,并且响应于这种客户需求,已经发展了许多通用实践。 您可以在下面找到典型方法的概述。 如果您已经熟悉它们,那么欢迎您直接滚动至“ 扩展方法 ”部分,并了解我们如何以我们认为更有效的方式解决这些挑战。

一体

定制的最直接,最明显的解决方案是在一个核心产品中实现所有要求,然后采用“ 功能切换 ”技术来满足每个特定客户的需求。

多合一方法的主要优点是保持整体产品,这似乎是某些类型的产品的好方法,这些产品通常可以满足业务需求,而无需进行广泛的定制。

这种方法的自然局限性隐藏在“不需要太多定制”的假设中。 通常,产品开发就是从这种信念开始的,但是经过多次交付,您才真正意识到需要多少特定于客户的功能。 陷入困境的情况并不少见。 拒绝定制开发并可能失去客户,或者将源代码变成具有针对单个客户的功能的垃圾箱 ,这些功能对于大多数最终用户而言可能是无用的。

您会选择哪个选项? 显然,在艰难和艰难的地方之间进行选择并不是成功的方法。

简介:仅当您确定需要罕见且有限的定制时,“多合一”方法才是合适的选择。 否则,您将面临可管理和可支持产品与客户满意度之间的选择。 让我引用杰里·加西亚(Jerry Garcia)的话:“不断选择两种邪恶中的较小者仍然是选择邪恶”。

分枝

如果重大定制是交付的“必不可少”部分,则不能采用多合一技术。 还有另一种简单的方法- 分支 。 您只需分支产品代码库,然后单独进行更改即可。

分支“多合一”进行比较,最大的优势是没有适用于定制范围的限制。 您使用单独的分支来满足不同客户的特定要求,并避免在同一代码库中混合使用所有功能。

但是,它的另一面可能会在产品发展方面变成死胡同。 显然,产品分支是主要的开发空间:大多数错误修正,改进和新功能都首先被应用到产品中。 因此,需要频繁合并以使所有定制分支与核心产品保持同步。 只要原始产品源代码不受定制分支的影响,合并是一项简单的操作,否则,合并将变得非常耗时,并可能导致不可避免的回归错误。

如果您仅限于很少的自定义分支,则此方法仍然可以使用。 但是,随着交付实例数量的增加,面临“通过合并实施酷刑”的可能性迫在眉睫。

简介: 分支方法无疑是非常灵活和直接的-产品的任何部分都可以修改。 但是,交付后阶段可能非常费力,随着时间的推移变得越来越困难,并且不太可能导致交付大量可管理的定制分支。

实体-属性-价值模型

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

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

与以往一样,还有一个缺点:

  • 有限的适用性–仅通过允许向实体添加属性来限制EAV模型,然后根据预编程的逻辑将其自动嵌入到UI中。
  • 额外的数据库服务器负载–垂直数据库设计通常成为企业应用程序的瓶颈,企业应用程序通常使用大量与它们相关的实体和属性进行操作。
  • 最后,如果没有复杂的报告引擎,就无法想象企业系统。 EAV模型具有“垂直”数据库结构,因此有可能带来许多麻烦。

简介: 实体-属性-价值模型在某些情况下具有很大的价值,例如,当需要提供通过具有其他信息性数据而获得的灵活性时,该信息性数据未在业务逻辑中明确使用。 换句话说,EAV具有良好的适度性,例如,除了标准的关系模型和插件体系结构之外

插件架构

插件体系结构是最流行且功能最强大的方法之一,其中功能逻辑作为单独的工件(称为插件)保存。 要覆盖现有的开箱即用行为并运行插件,必须在产品源代码中定义“定制点”(即扩展点)。 “定制点”是源代码中的某个位置,应用程序在该位置上浏览附加的插件,以检查插件是否包含要在此处运行的替代实现。 插件体系结构的一种变化是外部脚本。 在实现功能实现并将其作为脚本存储在外部时。 脚本调用也由预定义的“定制点”控制。

使用这种插件方法,可以使产品“清洁”特定的客户需求,“按原样”交付核心产品,并根据插件或脚本的要求自定义行为。 这种方法的另一个优点是管理完善的更新过程。 产品和插件功能的完全分离使彼此之间可以独立更新。

当然,存在限制:主要限制是不可能完全知道将来可能会提出哪些自定义要求。 因此,只能猜测应该在何处嵌入“定制点”。 当然,这些可以作为缓解“防万一”计划的零星散布在各处,但这将导致代码可读性差,硬调试以及复杂的支持。

简介:如果易于预测“定制点”,那么插件架构确实可以工作,但是请注意,“定制点”之间的定制是不可能的。

扩展方法

我们在企业软件开发平台CUBA中实施了独特的方法。 正如我们上一篇文章所述 ,CUBA是一种非常实用的活生物体,它是通过开发人员驱动的演变过程创建的。 因此,根据我们在现成产品上的丰富经验,我们提出了两个最终要求:

  • 客户特定的代码应与核心产品代码完全分开
  • 产品代码的每个部分都应该可以修改

我们设法满足了这些要求,并通过我们的“扩展”机制实现了更多目标。

CUBA扩展

扩展是一个单独的CUBA项目,它继承基础项目(即您的核心产品)的所有功能,并将其用作库。 显然,这使开发人员可以实现全新的功能而不会影响父项目,但是由于使用了“ 继承继承”模式和特殊的CUBA工具,您还可以覆盖父项目的任何部分。 总之,扩展是实现本文开头讨论的数百个“少量次要细节”的地方。

实际上,每个CUBA项目都是CUBA平台本身的扩展-因此它可以覆盖任何平台功能。 我们自己采用了这种方法,以从核心平台中分离出一些现成的功能(全文搜索,报告,图表等)。 因此,如果您在项目中需要它们,则只需将它们添加为父项目–就是这样,是多重继承!

以相同的方式,您可以构建分层的定制模型 。 这听起来可能很复杂,但是完全有道理。 让我举一个真实的例子: Sherlock –是Haulmont完整的出租车管理解决方案,支持从预定,派遣到应用程序和计费的出租车业务的各个方面。 该解决方案涵盖了客户业务的许多不同方面,其中许多与位置相关。 例如,所有英国出租车公司都具有相同的法律法规,但其中许多不适用于美国,反之亦然。 显然,我们不想在核心产品中实施所有这些规定,因为:

  • 这是“特定于操作区域”的功能
  • 当地法规可能会对不同国家的出租车队运营产生完全不同的影响
  • 一些客户根本不需要监管

因此,我们组织了多级扩展层次结构:

  1. 核心产品包含出租车业务的通用功能
  2. 定制的第一层实现了区域特性
  3. 第二层定制涵盖了客户的愿望清单(如果有的话!)

古巴平台_产品方案

整洁明了。

如您所见,通过使用扩展,您既不需要分支也不需要在核心产品中集成所有需求 ,因此代码保持简洁且易于管理。 听起来真是太好了,所以让我们看看它是如何工作的!

向现有实体添加新属性

假设我们具有用户实体的产品定义,该定义由两个字段组成:登录名和密码:

@Entity(name = "product$User")
@Table(name = "PRODUCT_USER")
public class User extends StandardEntity {@Column(name = "LOGIN")protected String login;@Column(name = "PASSWORD")protected String password;//getters and setters
}

现在,我们的一些客户提出了一项附加要求,即向用户添加“家庭住址”字段。 为此,我们在扩展中扩展User实体:

@Entity(name = "ext$User")
@Extends(User.class)
public class ExtUser extends User {@Column(name = "ADDRESS", length = 100)private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}

您可能已经注意到,除@Extends以外的所有注释都是通用的JPA注释。 @Extends属性是CUBA引擎的一部分,它甚至在整个产品功能上都将User实体全局替换为ExtUser

使用@Extends属性,我们强制平台执行以下操作:

  1. 始终创建“最新子级”类型的实体
User user = metadata.create(User.class); //ExtUser entity will be created
  1. 在执行之前转换所有JPQL查询,以便它们始终返回“最新子集”
select u from product$User u where u.name = :name //returns a list of ExtUsers
  1. 始终在关联实体中使用“最新子项”
userSession.getUser(); //returns an instance of ExtUser type

换句话说,如果声明了扩展实体,则基础实体在整个解决方案(产品和扩展)中都将被放弃,并且被扩展实体全局覆盖。

屏幕定制

因此,我们通过添加地址属性扩展了User实体,现在希望更改能够反映在用户界面中。 首先,让我们看一下原始(产品)屏幕声明:

<windowdatasource="userDs"caption="msg://caption"class="com.haulmont.cuba.gui.app.security.user.edit.UserEditor"messagesPack="com.haulmont.cuba.gui.app.security.user.edit"><dsContext><datasourceid="userDs"class="com.haulmont.cuba.security.entity.User"view="user.edit"></datasource></dsContext><layout><fieldGroup id="fieldGroup" datasource="userDs"><column><field id="login"/><field id="password"/></column></fieldGroup><iframe id="windowActions" screen="editWindowActions"/></layout></window>

如您所见,CUBA屏幕描述符表示为普通XML。 显然,我们可以简单地在扩展名中重新声明整个屏幕描述符,但这意味着要复制粘贴其中的大部分内容。 因此,如果将来产品屏幕中发生某些更改,我们将必须手动将这些更改复制到扩展屏幕中。 为避免这种情况,CUBA引入了屏幕继承机制,您所需要的只是描述对屏幕的更改:

<window extends="/com/haulmont/cuba/gui/app/security/user/edit/user-edit.xml"><layout><fieldGroup id="fieldGroup"><column><field id="address"/></column></fieldGroup></layout></window>

您可以使用extends属性定义祖先屏幕,并且仅描述要更改的主题。

这个给你! 最后,让我们看一下结果:

cuba-platform_admin

修改业务逻辑

为了启用业务逻辑修改,CUBA平台使用Spring框架,该框架构成了平台基础结构的核心部分。

例如,您有一个中间件组件来执行价格计算过程:

@ManagedBean("product_PriceCalculator")
public class PriceCalculator {public void BigDecimal calculatePrice() { //price calculation}
}

要覆盖价格计算实现,我们只需要执行两个简单的操作。

首先,扩展产品类并覆盖相应的过程:

public class ExtPriceCalculator extends PriceCalcuator {@Overridepublic void BigDecimal calculatePrice() { //modified logic goes here}
}

最后,使用产品Bean标识符在Spring配置中注册新类:

<bean id="product_PriceCalculator" class="com.sample.extension.core.ExtPriceCalculator"/>

现在, PriceCalculator注入将始终返回扩展类实例。 因此,修改后的实现将在整个产品中使用。

扩展基础产品版本

随着核心产品的发展和新版本的发布,您最终将决定将扩展程序升级到最新的产品版本。 这个过程非常简单:

  1. 在扩展名中指定基础产品的新版本。
  2. 重建扩展名:
    1. 如果扩展是基于产品API的稳定部分构建的,则可以运行它。
    2. 如果对产品API进行了一些重大修改,并且这些修改与扩展中实现的自定义重叠,则有必要在扩展中支持新的产品API。

在大多数情况下,产品API在每次更新之间都不会发生重大变化,尤其是在次要版本中。 但是,即使API发生了“大爆炸”,产品通常也至少保持几个未来版本的向下兼容性,并且旧的实现被标记为“已弃用”,从而允许将所有扩展迁移到最新的API。

结论

作为一个简短的摘要,我想以表格形式说明比较分析的结果:

一体 分枝 电动汽车 外挂程式 CUBA扩展
独立于架构 + +
动态定制 + +/-
业务逻辑定制 + + +/- +
数据模型定制 + + + +/- +
用户界面定制 + + +/- +/- +
代码质量和可读性 +/- +/- +/- +
不影响性能 + + + +
软件回归的风险
长期支持的复杂性 极端的 极端的
可扩展性

如您所见,扩展方法功能强大,但是它缺少的一件事就是能够动态地微调系统(动态定制)。 为了克服这个问题,CUBA还提供了对实体属性值模型和插件/脚本方法的全面支持。

我希望您会发现此概述很有用,当然您的反馈意见也将受到赞赏。

翻译自: https://www.javacodegeeks.com/2015/07/how-to-develop-a-highly-customizable-product.html

高度可定制化的方案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337168.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文言文编程?厉害了程序员!

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删你能看出来&#xff0c;这首诗妙在哪里吗&#xff1f;来源&#xff1a;量子位&#xff08;ID&#xff1a;QbitAI&#xff09;&#xff0c;梦晨 萧…

sublime快捷键代码对齐_Python配置sublime运行环境

1、下载安装python和sublime&#xff0c;不再赘述&#xff0c;官网即可下载&#xff1b;2、打开subilme&#xff0c;打开Tools > Build System > New Build System..3、点击New Build System后&#xff0c;会生成一个空配置文件&#xff0c;在这个配置文件内覆盖配置信息…

C语言贪心算法

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删01基本概念贪心算法是指在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;…

C++最佳实践 | 可维护性

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删C最佳实践:1. 工具2. 代码风格3. 安全性4. 可维护性&#xff08;本文&#xff09;5. 可移植性及多线程6. 性能7. 正确性和脚本可维护性避免使用编…

springboot启动自动关闭_App自动化测试用例格式和App的启动与关闭

【一】基本的用例格式这里使用unittest测试框架来编写用例。注&#xff1a;unittest可以提供用例的组织和管理、预期结果验证、批量化运行、产生测试报告等功能。新建一个calculator的python package&#xff0c;新建一个calculator_test.py&#xff0c;导入以下包。按照标准的…

C++最佳实践 | 可移植性及多线程

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删C最佳实践:1. 工具2. 代码风格3. 安全性4. 可维护性5. 可移植性及多线程&#xff08;本文&#xff09;6. 性能7. 正确性和脚本可移植性明确使用的…

eap aka_使用API​​密钥(aka身份验证令牌)部署到Maven Central

eap aka如何在不使用未加密本地密码的情况下与Maven Central / Nexus通信&#xff08;尤其是使用Gradle&#xff0c;但不仅限于此&#xff09;。 基本原理 不幸的是&#xff0c;Gradle&#xff08;和许多其他构建工具&#xff09;没有提供任何机制来本地加密密码&#xff08;或…

万维网发布服务 w3svc 已停止 除非万维_万维网和互联网的区别

常见的一个误解是&#xff0c;人们认为互联网(Internet,也叫因特网)和万维网(World Wide Web)是同样的事物。一些词语如“互联网”、“万维网”&#xff0c;“网”和“网络”经常可以交替使用。但是&#xff0c;从技术的角度来说&#xff0c;“互联网”和“万维网”是两个独立的…

C/C++项目开发:通讯录管理系统源码,C语言链表实现

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删hello&#xff0c;各位小伙伴们大家好&#xff01;你们今天有敲代码嘛&#xff1f;如果有熟悉的小伙伴看到我&#xff0c;就知道又可以来学习源码…

javafx窗体程序_JavaFX真实世界应用程序:欧洲电视网广播联盟

javafx窗体程序我荣幸地与今年在德累斯顿Saxonia 系统公司工作的Alexander Casall一起在JavaOne上展示了多个JavaFX Real-World应用程序。 在准备本次演讲时&#xff0c;我们向客户和合作伙伴发送了一份调查表&#xff0c;并向他们询问了一些与他们的项目&#xff0c;他们的应用…

spring 数据库 链接db2_Druid,Java语言中最好的数据库连接池

Druid是Java语言中最好的数据库连接池&#xff0c;这话不是我说的&#xff0c;是Druid官方文档自己这样描述的&#xff0c;这是何等的自信&#xff01;连接池的作用&#xff0c;跟线程池的作用大同小异&#xff0c;都是为了减少频繁的创建销毁连接IO&#xff0c;提升性能。drui…

编程知识:既然已经有数组了,为什么还要链表?

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删对于不少开发者而言&#xff0c;链表(linked list)这种数据结构既熟悉又陌生&#xff0c;熟悉是因为它确实是非常基础的数据结构&#xff0c;陌生…

jcache_随机JCache内容:多个提供程序和JMX Bean

jcacheJCache&#xff08;JSR 107&#xff09;是用于缓存的Java标准…足够了。 没有更多介绍性的东西。 这是一则速成文章&#xff0c;内容涉及 多个JCache提供程序配置&#xff0c;以及 功能&#xff1a;通过JMX Mbeans的JCache统计信息 管理多个JCache提供程序 如果您只使…

python webbrowser点击_用 Python 实现手机自动答题,这下百万答题游戏谁也玩不过我!...

引言如果谈到这几年手机上各平台最常见的引流福利&#xff0c;必然是答题赢大奖系列小游戏了。像什么头号英雄&#xff0c;百万玩家之类的&#xff0c;充斥在我们生活中&#xff0c;同时也成为了我们生活中常见的娱乐方式。但是有时候就会想&#xff0c;能不能实现手机自动答题…

程序员的年终总结,各种版本各种残

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删朱自清版这几天心里颇不宁静了&#xff0c;眼看上线的日子越来越临近&#xff0c;而项目Bug之多&#xff0c;密密的交叉着&#xff0c;却无从改起…

securecrt哪个版本好用_电脑跑分测试软件哪个好?好用的电脑跑分软件推荐

想要直观的了解自己电脑状况&#xff0c;那么一款好用的电脑跑分软件无疑是必不可少的&#xff0c;毕竟他能够将测试结果用跑分的形式计算出来。那么&#xff0c;电脑跑分软件哪个比较好呢&#xff1f;下面是小编分享的好用的电脑跑分软件推荐&#xff0c;游戏玩家们可不要错过…

C语言,单片机绕不过的坎,你对C语言内存分配了解多少呢

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删一、static在C语言里面可以用来修饰变量&#xff0c;也可以用来修饰函数。1、 先看用来修饰变量的时候。变量在C语言里面可分为存在全局数据区、…

内存 增量数据持久_内存中数据模型和大数据持久性

内存 增量数据持久ORM框架在需要与关系数据库进行交互时可以帮助开发人员。 对于关系数据库&#xff0c;有许多出色的ORM框架&#xff0c;例如Hibernate和Apache OpenJPA&#xff0c;其中一些确实很棒。 如今&#xff0c;大数据正在涌现&#xff0c;越来越多的人开发在大数据上…

自学编程的6个技巧总结

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删有一天&#xff0c;我的一个在学编程的朋友问我&#xff1a;“我想快速学习编程&#xff0c;你有什么好的推荐吗&#xff1f;”我曾在上大学的时…

C语言如何知自身函数的实际地址与大小

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删事情的起因大概是这样……在很久很久以前&#xff0c;我最早用的是MASM&#xff08;Win32ASM&#xff09;写程序&#xff0c;从平台兼容性、开发…