最近收到这样的问题:
领域服务做业务逻辑校验时应该返回错误码还是抛出业务异常?
这其实不算是领域服务的问题,而是Java异常处理问题。
之前总结过一次如何处理异常
上面的文章基本上就解决异常相关问题了。
这儿再回顾总结一下:
CQRS全称Command Query Responsibility Segregation
在CQRS中,来自客户端的命令通过单独的路径抵达命令模型,而查询操作则采用不同的数据源,这样的好处在于可以优化对查询数据的获取,比如用于展现、用于接口或报告的数据。
CQRS这些年火起来了,常被人挂在嘴边提起。为什么?因为DDD提倡富模型,但从资源库查找所有需要显示的数据是困难的,特别是在需要显示来自不同聚合类型与实例的数据时。领域越复杂,这种困难程度越大。
有没有一种完全不同的方法可以将领域数据映射到界面显示中呢?答案正是CQRS。
在From CRUD to CQRS文章中,作者比对了CRUD模式与CQRS模式
Twitter上有人发了一个推,说他之前问过一个问题:“你最好的一条职业建议是什么?”,他得到了1300多个答案,最后他整理了12条最好的建议。
🔗 twitter、com/chrishlad/status/1502650707274608644
1、 尽可能为别人减少不确定性
2、 公司比职位更重要
3、 一旦接受了一个任务,无论多小或者多么不起眼,要把它做的特别好,超出别人的预期。这样你就能建立起一个良好的声誉,让别人知道你总能高质量的完成工作。当你建立了这种声誉,你就能得到更多的机会,更大的知名度,以及更大的成功。
4、 如果我不能信任你,你再聪明都没用。
5、 在你的职业生涯中,陪你走到最后的只有你自己。不是你的公司,不是你的经理,不是你的团队,只有你自己。
在做你所有职业生涯的决定时,优先考虑你自己。
6、 影响你职业生涯的三件事:
如果你热爱你的工作、客户和团队,你会非常非常幸运。
7、 和一个聪明的能激励你走向伟大的人结婚。
8、 要么能学东西,要么能赚钱。
否则果断离职,去找一个这两者至少占一样的工作。
9、 如果一个问题你不问,那么答案一定是“不”。
10、 选择你的老板。
你有权选择谁当你的老板,而在找工作的过程中很多人没有考虑到这一点。
一个优秀的老板可以为你的职业发展提供极大的助力。
11、 学会阐明你所做的事情的商业价值,而不仅仅是你的工作头衔或者项目。
不好的例子:“我是一个数据科学家。我创建了3个自服务数据应用”
更好的例子:“我帮助管理层发现了一个可以节约2300万美元成本的机会”
12、 “职业”,本质是一个营销名词,是由那些经营特定类别的梦想的人卖给你的,而他们在贩卖这个梦想时赚了很多钱。
赚钱,承担风险,有冒险精神。
但不要让“职业”来限制自己
在做程序测试时,常会用到测试替身来协助我们快速完成测试。
有时候被测试系统(system under test(SUT))很难测试,因为在测试环境下依赖的组件不能正常使用。如外部系统。
当在一个不能使用真实依赖组件(depended-on component(DOC))的地方写test时,我们可以使用Test Double。
几乎在每个团队,都至少有一份代码规范,或者代码的check list。然也就仅仅是一份清单。
每次团队复盘时,都会有一条,我们要写好代码,然“好代码”是什么样子,什么标准,全取决于各人的水平。
每个程序员也都知道code review的重要性,然排期很紧张,难得做一次。宁可花时间追查问题,也不做防御性准备。
这些现象,是不是特别平常,虽然很想改变,但又是无力感呢。
程序员对代码的追求态度决定了职业生涯的高度,代码的质量决定了生活质量。
为什么会有上面提到的现象,大概有这两方面的原因:
1、每个人对“好代码”的观念不一样
2、对于“坏味道”缺乏明确的表象判断,也就很难提出明确的改进措施
先看一段简单的代码:
1 | package com.zhuxingsheng.adapter |
从代码中,可以明显看出这是一段处理登陆请求的方法。在大多数项目中,这种代码很常见。
它有什么坏味道呢?
分层穿透了,LoginRequest类本应该属于入口层,结果穿透到了service层。
细细追究,需要明确的问题:
1、LoginRequest到底属于哪一层,是resource层,还是service层?
2、没有达到DDD防腐层的意义,resource是隔离外部与核心业务的,但却变成了透传。
“学而优则仕”的传统文化渗透在各行各业。
那么”码而优则仕”则是这种文化的延伸,自然而然的结果。
当然很多程序员对做管理不感兴趣,想很纯粹的研究技术,成为一名技术专家。人各有志,但客观讲,技术专家与技术管理相比较,成为技术专家比技术管理难度大得多,只有做到在一个区域,一个行业屈指可数的顶尖专家,才有更加广阔的前景。尤其在国内的环境大多数都是业务型公司,技术本身没有直接价值,没有太高的壁垒,有太多能取代你位置的人。
当然,技术管理也有难度,尤其对于程序员群体。但只要做到一个团队内的最佳,则拿到了敲门砖,随时准备幸运之神的降临。跨越技术纯粹性的舒适性,技术管理之路就开启了。
使用缓存来加速应用程序的访问速度,是几乎所有高性能系统都会采用的方法。
但缓存真的那么好吗?架构师在构建高性能系统时,是不是必须增加缓存组件?缓存是不是多多益善?
《一代宗师》里本山大叔说过这样的一段话:
“一门里,有人当面子,就得有人当里子。面子不能沾一点儿灰尘。流了血,里子得收着,收不住,漏到了面子上,就是毁派灭门的大事。”
如果缓存是里面的角色,那么绝对是面子。
虽然缓存带来了性能的提升,但给系统带来的多少复杂性。缓存穿透,缓存击穿,缓存雪崩,缓存污染这些问题不绝于耳。这些问题不是操作系统兜着,就是程序员。所以缓存是24K纯金的面子。人人都好面子,还得有个能轻松应对的里子。
微服务架构已经很流行了,并且有大量文章描述相对单体架构,微服务架构带来的众多优点。
怎么从单体架构更优雅地转化为微服务架构呢?
有一种被实践证明有效的方法论:The Twelve-Factor App
一份基准代码,多份部署
尽管每个应用只对应一份基准代码,但可以同时存在多份部署。每份 部署 相当于运行了一个应用的实例。通常会有一个生产环境,一个或多个预发布环境。此外,每个开发人员都会在自己本地环境运行一个应用实例,这些都相当于一份部署
显式声明依赖关系
12-Factor规则下的应用程序不会隐式依赖系统级的类库。 它一定通过依赖清单 ,确切地声明所有依赖项
在环境变量中存储配置
通常,应用的配置在不同部署 (预发布、生产环境、开发环境等等)间会有很大差异。这其中包括:
有些应用在代码中使用常量保存配置,这与12-Factor所要求的代码和配置严格分离显然大相径庭。配置文件在各部署间存在大幅差异,代码却完全一致。
把后端服务(backing services)当作附加资源
后端服务是指程序运行所需要的通过网络调用的各种服务,如数据库(MySQL,CouchDB),消息/队列系统(RabbitMQ,Beanstalkd),SMTP 邮件发送服务(Postfix),以及缓存系统(Memcached)。
每个不同的后端服务是一份 资源 。例如,一个 MySQL 数据库是一个资源,两个 MySQL 数据库(用来数据分区)就被当作是 2 个不同的资源。12-Factor 应用将这些数据库都视作 附加资源 ,这些资源和它们附属的部署保持松耦合。
基准代码 转化为一份部署(非开发环境)需要以下三个阶段:
12-factor 应用严格区分构建,发布,运行这三个步骤。 举例来说,直接修改处于运行状态的代码是非常不可取的做法,因为这些修改很难再同步回构建步骤。
以一个或多个无状态进程运行应用
运行环境中,应用程序通常是以一个和多个进程运行的。
12-Factor 应用的进程必须无状态且无共享。 任何需要持久化的数据都要存储在后端服务内,比如数据库。
通过端口绑定(Port binding)来提供服务
互联网应用有时会运行于服务器的容器之中。例如 PHP 经常作为 Apache HTTPD 的一个模块来运行,正如 Java 运行于 Tomcat 。
12-Factor 应用完全自我加载 而不依赖于任何网络服务器就可以创建一个面向网络的服务。互联网应用 通过端口绑定来提供服务 ,并监听发送至该端口的请求。
通过进程模型进行扩展
任何计算机程序,一旦启动,就会生成一个或多个进程。互联网应用采用多种进程运行方式。例如,PHP 进程作为 Apache 的子进程存在,随请求按需启动。Java进程则采取了相反的方式,在程序启动之初 JVM 就提供了一个超级进程储备了大量的系统资源(CPU和内存),并通过多线程实现内部的并发管理。上述2个例子中,进程是开发人员可以操作的最小单位。
快速启动和优雅终止可最大化健壮性
应用程序的进程应该是一次性的,以便它们可以快速启动、停止和重新部署,而不会丢失数据。这有助于快速弹性扩展、代码和配置更改的快速部署以及生产部署的稳健性。
尽可能的保持开发,预发布,线上环境相同
从以往经验来看,开发环境(即开发人员的本地 部署)和线上环境(外部用户访问的真实部署)之间存在着很多差异。这些差异表现在以下三个方面:
12-Factor 应用想要做到 持续部署 就必须缩小本地与线上差异。 再回头看上面所描述的三个差异:
把日志当作事件流
将日志流式传输到选定的位置,而不是将它们转储到日志文件中。日志可以定向到任何地方。例如,它们可以被定向到 NoSQL 中的数据库、另一个服务、存储库中的文件、日志索引和分析系统或数据仓库系统。
后台管理任务当作一次性进程运行
将管理任务与应用程序的其余部分分开,以防止一次性任务导致正在运行的应用程序出现问题。容器使这很容易,因为可以启动容器只是为了运行任务然后将其关闭。