开源许可证
1. 开发流程 **说明:**此开发流程符合大部分需求场景,少数需求可能流程会有所增减。 2. 流程说明 2.1 需求评审 详细了解本次需求的背景和细节,并讨论需求的可行性。 比如: 当前需求是否明确? 新需求是什么? 需求背景及解决什么问题? 如果需求复杂程度大,提出是否需要分阶段实施? 需求完成的期望指标是什么? 如何评判? 如何交付? 技术能否实现、逻辑是否有问题? 进入开发阶段测试,遇到问题与谁对接,来协调解决问题? 如果需求复杂请让需求方拆解需求去描述要达到的目的。 如果需求未做到目的明确,清晰合理,请让需求方解决疑问点。 需求对接完,请邮件告知。 2.2 技术评审 阐述详细的技术实现方案,评估一下是否有不合理之处,比如表结构如何设计、接口怎么定义、有没有技术难点等。 2.3 开发 & 测试排期 评估具体的工作量,根据工作量安排各个步骤要完成的截止日期。 2.4 输出开发设计文档 此文档放在 confluence 上,大致包含需求背景、开发设计(技术方案)、排期计划、开发流程的具体内容、附录等。需求背景、开发设计(技术方案)、排期计划要在开发测试开始前书写完成,其他部分可以根据进度补充完善。 2.5 开发 & 测试 根据技术方案和排期,具体实现。 2.6 需求方验收 验收阶段,开发如有 bug 修改 bug,可以提前提供部分样例结果进行预验收。 2.7 生产部署 根据具体环境部署。 2.8 需求复盘总结 复盘一下问题主要出在哪里,以后如何规避,哪些优点可以以后借鉴等。 3. 其他注意事项 3.1 关于对接和验收阶段 首版需求已评审过的前提下,在此阶段如果不可避免出现需求变更频繁和很多不确定的时候,要明确告知需求方批量提供需求点或完善点,避免随时出现一个接一个,导致此需求一直完不成。 最好补充一次批量提完,如果第两个及以上批次,建议需求当需求变更处理。 开发要合理评估,尽量避免开发不合理需求。 4. 附件 Java 开发手册:!泰山版.pdf
关于技术债务的文章,尽管实践中会堆积技术债,但这个概念并不在我们的工作中频繁出现。这篇文章就系统性讲讲技术债,让大家避免知其然,不知其所以然。 一、技术债是什么 技术负债(英语:Technical debt),又译技术债,也称为设计负债(design debt)、代码负债(code debt),是编程及软件工程中的借鉴了财务债务的系统隐喻。指开发人员为了加速软件开发,在应该采用最佳方案时进行了妥协,改用了短期内能加速软件开发的方案,从而在未来给自己带来的额外开发负担。这种技术上的选择,就像一笔债务一样,虽然眼前看起来可以得到好处,但必须在未来偿还。软件工程师必须付出额外的时间和精力持续修复之前的妥协所造成的问题及副作用,或是进行重构,把架构改善为最佳实现方式。 1992 年,沃德 · 坎宁安首次将技术的复杂比作为负债。第一次发布代码,就好比借了一笔钱。只要通过不断重写来偿还债务,小额负债便可以加速开发。但久未偿还债务会引发危险。复用马马虎虎的代码,类似于负债的利息。整个部门有可能因为松散的实现,不完全的面向对象的设计或其他诸如此类的负债而陷入窘境。 二、技术债表现 技术债与其他债务本身一样,是一种透支行为,通过牺牲未来来满足当下的一些需求。也跟其他债务一样,技术债务也有利息,而且随着时间利滚利,会成为埋在项目里的定时炸弹。如果产品长期的可持续的发展,那么技术债的重要性是毋庸置疑的。 技术债务的本质是产品的结构阻碍了进步,表现出来的症状有:无法轻易重构产品以满足市场需求;组件之间的依赖性过多,体系结构不良;缺陷太多,结构不良;难以理解,难以改变。 技术债务的后果有偿还技术债务造成时间浪费,员工满意度降低带来士气低落,因解决遗留代码问题而错过优质项目造成人才流失,产品质量降低造成客户满意度下降,技术债务限制创新能力、扼杀创造性等诸多问题。 技术债不单单是技术债,它就像一个垃圾堆,久而久之不处理,慢慢周围就会产生更多的垃圾,因此产生的 “破窗效应” 更加是会对未来的项目环境造成很大的影响,大家也会逐渐丧失维护环境的信心。所以在讨论技术债的时候不仅仅是讨论技术债本身,技术债对团队追求质量的信心、对大家维护环境整洁的积极性都会造成很大的影响。 MartinFowler 把技术债分为四个象限,如下图所示: 三、技术债产生的原因 ●业务压力:为了满足业务的快速要求,在必要的修改并没有完成时就匆匆发布,这些未完成的修改就形成了技术负债。 ●缺少过程和理解:业务人员不清楚不理解技术负债的概念,在决策时就不会考虑到其带来的影响。 ●模块之间解耦不够:功能没有模块化,软件柔性不够,不足适应业务变化的要求。 ●缺少配套的自动化测试:导致鼓励快速而风险很大的 “创可贴” 式的 BUG 修复。 ●缺少必要文档:需求和代码都没有必要的支撑性文档或注释。 ●缺少协作:组织中的知识共享和业务效率较低,或者初级开发者缺少必要的指导。 ●重构延迟:在开发的过程中,某些部分的代码会变得难以控制,这时候就需要进行重构,以适应将来的需求变化。重构越是推迟,这些已有的代码被使用的越多,形成的技术负债就越多,直到重构完成。 ●不遵循标准或最佳实践:忽略了已有的业界标准、框架、技术和最佳实践。 ●缺少相关技能:开发人员有时候技能缺失,并不知道如何编写优雅的代码。 四、如何 “还债”? 技术债可视化 尽可能公开技术债,一开始就与团队,利益相关方一起权衡利弊,并明确告知影响与解决方案。平等沟通,相互理解。让技术债在业务层面、技术层面可见。 可以在组织资产负债表的财产债中新增两列:短期技术债和长期技术债。还可以用用跟踪开发速率的方式体现技术债对于产品的影响。 不同的债要对症下药 技术债的状态可以分类为偶然技术债、已知技术债和目标技术债。 偿还技术债时应遵循如下原则: 1)确定已知技术债必须还。 2)发现偶然技术债,立即还。 3)每个冲刺确定一定数量的已知技术债作为目标技术债,在当前冲刺中偿还。 4)无需偿还的技术债是行将就木的产品、一次性原型和短命产品。 五、如何避免 “欠债” 与其后期吭哧吭哧还债填坑,不如从一开始就尽量避免欠下技术债务。 避免使用过时的技术 遗留应用程序、过时的技术以及不同的平台和流程可能会使组织陷入沉重的技术债务,迫使其推迟基本的现代化计划。DNS 和流量管理技术提供商 NS1 的联合创始人兼首席执行官 Kris Beevers 说:“技术债务将大量金钱和宝贵的时间浪费在系统和应用程序上,而这些系统和应用程序并不是为现代企业所需的规模和速度而打造的。” 旧资产和老方法也往往充斥着安全漏洞,难以集成和自动化,并且很可能不再更新。 Beevers 指出:“寻找人才来管理基于复杂或过时的代码构建的遗留应用程序也是一个日益严峻的难题。坚持采用过时技术不仅会消耗宝贵的预算,而且还会阻碍公司创新和保持竞争力的能力。” 参考敏捷实践 有越来越多的组织渐渐接受敏捷软件开发,这是将方法交给协作、自行组织的团队和跨职能团队的一系列方法和实践。如果这种方法得到严格应用,敏捷开发使组织可以避免技术债务,其方法是快速且以迭代的方式创建和发布新产品。Dodd 说:“这一过程将新产品和新功能尽快并逐步地交到用户手中。” 随着新版本的交付,各种改进和问题都得到了解决,这使技术债务的积累不太可能产生。 敏捷方法认识到项目在生命周期中从未真正完成过,并且也从来都不是完美的。“同时,敏捷方法专注于…… 针对能力和质量的简化了的开发”,Dodd 说。重要功能往往要频繁地开发,测试并投入生产。敏捷团队可能不会发布软件的 “全面(Big Bang)” 方法,而是每年发布几次重大升级。Dodd 指出:“这可以使产品保持相当平稳的发展,还可以帮助用户避免重大的中断事件。” ...
把项目的配置文件按运行环境做一下区分,比如开发环境和线上环境使用的使用不同的配置文件,这里我们基于项目的 resoures/ 目录来实现: # resoures 目录 . ├── env │ ├── config.dev.properties │ └── config.prod.properties └── config.properties 我们创建了一个 config.properties 文件来配置项目的常用配置数据,如, kafaka 、 redis 等连接配置等。 然后创建一个 env 子目录,并创建两个环境对应的配置文件,我们希望不同的环境当中使用不同的配置。当然,光是创建这些文件,是无法让文件实现自动按照运行环境自动实现文件匹配的,我们还需要配置 pom.xml 文件: 首先,找到 <build> 配置字段,添加文件路径: <build> <!-- Loading all ${} --> <filters> <filter>src/main/resources/env/config.${env}.properties</filter> </filters> <!-- Map ${} into resources --> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>*.properties</include> </includes> </resource> </resources> <!-- 省略之后若干行 --> </build> 上述代码目的是告诉构建工具,在构建的时候需要加载 resoures 目录的配置文件参与构建,并且使用 ${env} 环境变量来决定具体加载的名称。 因此,我们还需要指定 ${env} 的环境变量配置,在 <profiles> 标签下,移除默认的 <profile> 配置内容,新建两份环境配置 dev 和 prod 的 profile 文件配置: ...
【策略模式】(Strategy Pattern) 其中的Context是一个所谓的“上下文”,不一定非得是个类,也可以只是一个函数/方法。最关键的是,我们其实根本不需要ConcreteStrategyX类,也不需要它们的对象。我们要的只是一个execute函数而已,我们甚至连execute这个函数名都不需要,只要能执行它就行。 看看函数式编程是怎么玩的(这里以大家都熟悉的JavaScript为例): function context(func) { // 做些什么... var result = func() // 有需要的话可以传参 // 再做些什么... } context(function() { // 做些什么... return 123 // 是否需要返回值看需求 }) 一个匿名函数参数func搞定。 Java能搞出这种类图来,全都是因为Java没有一等公民的函数,所以函数必须依附于类(静态方法)或者对象(非静态方法)。而玩静态方法又没法玩多态,而且类不能当成参数传递给其他函数/方法,所以只能用对象携带方法。而对象的方法必须有个名称,为了统一,就叫execute。由于需要多态,所以我们必须提一个接口出来,在接口里声明execute的方法签名。所有这一切说白了都是为了讨好Java编译器,否则它会给你颜色(red)看。 当然,自从Java有了函数式接口和lambda后一定程度上也能玩函数式编程了。 【观察者模式】(Observer Pattern) 这个在JS里大家已经熟悉到不能再熟悉了: someButton.onclick = function(event) { // 处理点击事件 } 又是一个匿名函数搞定!上图里的Subject#attach在这里就是直接赋值。Subject#detach就是赋空值。Subject#notify就是调用一下匿名函数而已。而Observer#update就是匿名函数本身。 【访问者模式】(Visitor Pattern) 能整成这样我也是服了。说白了不就是访问者需要判断一下元素类型嘛。直接套用策略模式,在匿名函数里if-else一下不就行了?(当然还有其他方式,比如引入一个工厂。有模式匹配的函数式编程语言如Haskell、Erlang、Elixir等玩起来更简单)。 【装饰器模式】(Decorator Pattern) 这才是函数式编程的魅力所在! function core1(arg1, arg2) { // 做些啥 return 123 } function core2(arg) { // 做些啥 return 456 } function decorate(core) { // 做些准备工作 return function() { // 做些啥,甚至可以改变参数 var ret = core(...arguments) // 做些啥,甚至可以改变返回值 return ret } } var decorated1 = decorate(core1) var decorated2 = decorate(core2) 酷吧?又是匿名函数搞定!只不过这次的匿名函数是返回值。 ...
命名风格 【强制】抽象类命名使用 Abstract 或 Base 开头; 异常类命名使用 Exception 结尾; 测试类 命名以它要测试的类的名称开始,以 Test 结尾。 【强制】POJO 类中布尔类型变量都不要加 is 前缀,否则部分框架解析会引起序列化错误。 【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使 用单数形式,但是类名如果有复数含义,类名可以使用复数形式。 正例: 应用工具类包名为 com.alibaba.ai.util、类名为 MessageUtils 【推荐】在常量与变量的命名时,表示类型的名词放在词尾,以提升辨识度。 正例: startTime / workQueue / nameList / TERMINATED_THREAD_COUNT 17.【参考】枚举类名带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。 B) 领域模型命名规约 数据对象: xxxDO,xxx 即为数据表名。 数据传输对象: xxxDTO,xxx 为业务领域相关的名称。 展示对象: xxxVO,xxx 一般为网页名称。 POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。 常量定义 【推荐】不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。 【推荐】如果变量值仅在一个固定范围内变化用 enum 类型来定义。 SPRING(1), SUMMER(2), AUTUMN(3), WINTER(4); 代码格式 【强制】采用 4 个空格缩进,禁止使用 tab 字符。 IDEA 设置 tab 为 4 个空格时,请勿勾选 Use tab character ...