SoftwareDesign
首席IT民工
编程才是真爱^_^
展开
-
Month1 Month2
Month 1Month 2类型EventDimensiondeletehidedisable恢复re createenable业务id编号名字editdelete&createcorrecteditid可以变id不可变edit不联动联动下拉框不作为入参可作为入参原创 2023-07-18 12:25:01 · 309 阅读 · 0 评论 -
权限管理系统(Security)
本系统设计的一个重要目标就是将权限的管理从业务系统中完全抽离出来。对于后端服务而言,他接受到的请求就一定是合法的,不单操作是合法的,包括操作中间的参数,也应该是符合权限管控的要求。权限相关的配置,例如角色配置,用户与角色的绑定都由权限管理系统完成。业务服务与权限系统尽可能少的交互仅限于用户添加租户添加的少数情况。原创 2023-03-20 13:40:19 · 2082 阅读 · 0 评论 -
领域驱动设计思考(领域变更)
一些场景下,编辑功能改变类型会导致一个实体从一个领域转换到另一个领域原创 2022-08-05 16:29:15 · 153 阅读 · 0 评论 -
多个环境的配置文件
分析各种配置文件的区别原创 2022-08-05 14:30:21 · 221 阅读 · 0 评论 -
架构检查表
业务架构服务之间不应当存在循环依赖服务之间避免跨层调用服务之间避免同层调用技术架构原创 2022-04-22 15:25:14 · 219 阅读 · 0 评论 -
系统重构的思考
衡量被重构的优先级有两个维度:1.重构带来的价值高2.坏味道多一般来说前者的重构更容易得到外部的认可,而开发人员更容易发现后者,因为深受其害.同样是坏代码,如果修改越多则越多的开发人员痛恨,同时它也会变得越坏.如果一个地方会经常改并且业务价值不高,说明大家用了很多的精力在低业务价值上.但是从另一个方面来看,如果核心业务都还在频繁变动,那也是有问题.如果这样悲观的来看,当我们做一件事时,往往是不得不做的时候.恐怕这也是最难而非最适宜的时候.毕竟,最佳时机啊是昨天....原创 2021-11-02 10:21:47 · 607 阅读 · 0 评论 -
数据库设计的思考
1 视图随着重构的进行,所有的表都将变成视图,那么使用视图查询就没有什么问题,而继承提供了一种不用视图的方案.由于Mybatis的sql嵌入功能,加上with语法,那么可以不创建数据库的视图,而是使用with创建临时视图,这样在新老版本更替的时候就不会出现代码和数据库不一样的情况...原创 2021-07-13 09:25:38 · 199 阅读 · 0 评论 -
软件设计的点滴思考
1 对资源的操作是否要加锁从业务上来看,如果操作是减少资源则必须要加锁,如果是增加,则可能没有冲突(如果这里的增加是以另一个的减少为代价,也就是在一个事务中,那么也应该是减少的资源加锁).但是这是要求增加资源是原子的,例如update some_table set some_value=some_value+? where id=?.如果采用了DDD,先select,再通过DDD计算值,然后再执行update some_table set some_value=? where id=?的形式写入终值,那原创 2021-07-13 09:24:51 · 157 阅读 · 0 评论 -
DDD中的一些疑问与思考
1 domain新增计算逻辑如何处理a 推,则需要刷所有系统,而这个新增字段并不一定是所有系统所需要的b 不推 b1 修改本地记录 b2 不修改 无论是哪种情况,别人只能通过GET请求来初始化,如果乐观的来看,往往是新系统才需要这些新字段(因为老系统没有这些字段也顺利的运行),所有要求新系统来GET初始化自己似乎也没什么问题结论:不推,让新系统GET请求过来从而初始化2 domain修改计算逻辑如何处理这里要分成两种情况,是否需要对历史数据进行修改是:那么所有老系统也需要修改,那么最原创 2021-07-13 09:24:27 · 180 阅读 · 0 评论 -
关于“禁用“操作的思考
1 能否和启用共享同一个URL不行,因为权限可能不一样2 能否在Domain共享同一个方法,通过入参true和false来区分不行,因为背后的业务逻辑不一样,如果启用和禁用的业务逻辑是单纯的update some_table set enabled=true/false where id=?的话说明这个业务逻辑是偏简单的,和DDD专门解决复杂业务场景的用途不相符.如果业务是复杂的(启用和禁用不仅仅是一个update)那么就需要在领域方法内做if判断,这显然是重复的.另外如果入参不一样的话就更原创 2021-07-13 09:02:18 · 122 阅读 · 0 评论 -
一个计费系统的研究
文章目录需求外部约束思考计费时机服务前服务后服务中预扣费计费与业务的分离与一致职责分离monolithChoreographyOrchestration总结事务设计balanceChargeEventFlowchartbeforeafter补充需求一个ToB的SaaS系统,企业先充值,然后用户在使用服务的时候从企业账户上扣钱。服务分为三类:免费服务,按次计费,按时长计费。当一个服务同时服务多个人时服务费用可能按人数增长。用户的一个操作可能触发多个服务。按时长计费的服务使用先计划再服务的模式,即用户先原创 2020-11-17 13:59:48 · 666 阅读 · 1 评论 -
Restful中传输对象DTO的研究
文章目录DataTransferObjectValueObject vs DTOgetter的名字和返回值int vs Integerboolean vs BooleanStream vs Listenum vs (String or DTO)总结DTO vs POViewObject vs DTOAllArgumentConstructorextendsDataTransferObject根据Restful风格,对于资源操作后需要返回当前资源(即使是DELETE操作),也就意味着对于一个资源的多种业务原创 2020-07-16 14:58:19 · 1692 阅读 · 1 评论 -
UML与模式应用读书笔记八(文档)
文章目录Software Architecture DocumentSAD动机架构视图常见的视图动机Software Architecture DocumentSADSAD描述了有关架构的总体想法,包含架构分析的关键决策.在实践中,SAD可以帮助开发人员理解系统的基本概念动机当某人加入开发团队时,如果项目的导师对他说…阅读10页SAD文档…这对他会有很大帮助因此,撰写SAD文档时应该将下述目标和潜在读者时刻放在心中:如果需要帮助某人快速理解系统的主要概念,我应该写什么(或者在UML图中原创 2020-06-17 09:39:53 · 211 阅读 · 0 评论 -
UML和模式应用读书笔记七(GoF)
文章目录AdapterFactorySingletonStrategyCompositeFacadeObserver/Publish-SubscribeDo It MyselfAdapter问题:如何解决不相容的接口问题,或者如何为具有不同接口的类似构件提供稳定的接口建议:通过中介适配器对象,将构件的原有接口转换为其他接口类型名称中包含了模式名称Adapter.这是相对常见的风格,这使得其他人在阅读代码或图形时能够很容易理解其中使用了哪些模式.Factory如果是某个领域对象来创建这些原创 2020-06-16 16:37:02 · 262 阅读 · 0 评论 -
UML和模式应用读书笔记六(迭代中)
文章目录CodeTDDRefactorUML蓝图继续编码架构分析质量factor table艺术post-compiler & aspect-oriented引导架构决策的优先级Code类的实现(理想情况下,还包括完整的单元测试)要按照从耦合度最低到耦合度最高的顺序来完成.TDD逻辑就是让人充满信心地得出错误结论的方法TDD的有点使程序员获得满足感从而更始终如一的坚持编写测试如果先编写测试,我们会感觉在面前存在具有价值的挑战和问题有助于澄清接口和行为的细节如果你在测试原创 2020-06-16 15:57:03 · 288 阅读 · 0 评论 -
UML和模式应用读书笔记五(UML)
文章目录interaction diagram顺序图常见图框操作符refmetaclass多态active object通信图消息实例的创建编号互斥&循环静态方法 & 多态 & 同步异步活动图DFD活动图准则state machine diagram对状态依赖对象建模转换动作与监护嵌套状态interaction diagram文中提到了两种交互图sequence diagram和communication diagram,前者相对于后者更好(Craig Larman也承认这一点)原创 2020-06-16 15:55:58 · 444 阅读 · 0 评论 -
UML和模式应用读书笔记四(领域模型与类图)
文章目录领域模型association vs attributeIDnumber attribute示例概念分类列表将概念类划分为子类的动机简化继承树abstract conceptual class状态继承association classaggregation & composite时间间隔作为概念的角色 & 关联中的角色导出元素受限关联类图属性三种方法属性文本格式关联性集合composition限定关联关联类方法格式creategetter关键字单实例类主动类领域模型associa原创 2020-06-16 15:55:08 · 1522 阅读 · 0 评论 -
UML和模式应用读书笔记三(GRASP)
文章目录GRASPCreatorInformation ExpertLow CouplingControllerHigh Cohesion反例Pure FabricationIndirectionPolymorphismProtected Variations初始化和*启动*用例可见性GRASPCreator十分有趣!这反映了一种"直觉",OO软件开发者常常想让容器创建被容纳的事物,就像Board创建Square一样建议如果以下条件之一为真时(越多越好),将创建类A实例的职责分配给类B:原创 2020-06-12 16:28:59 · 745 阅读 · 0 评论 -
UML和模式应用读书笔记二(包&层)
文章目录包层内部嵌套包的表示分包最底层敏捷建模CRC卡interaction diagram顺序图常见图框操作符refmetaclass多态active object通信图消息实例的创建编号互斥&循环静态方法 & 多态 & 同步异步类图属性三种方法属性文本格式关联性集合composition限定关联关联类方法格式creategetter关键字单实例类主动类GRASP对象职责模式里程碑这是从原书中第12章到后面的读书笔记,对于前面的读书笔记及思考参见UML和模式应用读书笔记二(做正确原创 2020-06-11 16:48:39 · 235 阅读 · 0 评论 -
UML和模式应用读书笔记一(做正确的事)
文章目录绪论初始阶段用例用例的几个部分的具体含义UI vs Essential黑盒系统边界有效性用例图特性列表除了用例词汇表业务规则领域模型association vs attributeIDnumber attribute示例System Sequence DiagramSSD与其他UP制品的关系为系统事件和操作命名UP阶段操作契约后置条件系统操作对领域模型的修改UP阶段绪论不要单独建模…小组成员要轮流画草图,以使每个人都参与其中并行地创建模型.例如在一块白板勾勒UML动态视图的交互图,同时在原创 2020-06-10 15:50:38 · 706 阅读 · 0 评论 -
Restful风格api设计(HttpMethod)
文章目录写操作修改禁用这篇文章主要是讨论对于各种业务需求如何选择HttpMethod,一般来说HttpMethod的选择应该和URL一起考虑,所以这里也有涉及,但是主要是讨论HttpMethod写操作对于某些记录用户操作的系统(特别是还提供了对操作记录的查看)而言,有些应该是读的操作变成了写操作,例如电商中的搜索,也许有人说应该从这个操作的原意或者业务含义来考虑这个操作是否是写,但是如何判断原意又变成了见仁见智的问题,一般来说程序员之间很难在业务上达成一致,我这里提供一个更加精确的定义:如果一个接口的原创 2020-06-08 14:11:36 · 1071 阅读 · 0 评论 -
微服务设计读书笔记
文章目录微服务划分聚合多版本APIpendingsnapshot其他事件微服务划分把verifyOrderDetail放到了restaurant service因为那里有数据让整个企业对全局单一建模是困难的,这个单一的业务实体过于复杂超出了他们的要求.组织内部有些团队对不同的概念使用相同的术语,有些团队对同一个概念使用不同的术语,DDD通过多个领域模型来解决.聚合采用API聚合时如果调用其他方法除了问题:使用原先的数据使用nullsaga:协同式:choreography编原创 2020-06-03 11:01:58 · 123 阅读 · 0 评论 -
交易类型Transaction
文章目录TransactionDebitTransactionReceiveTransactionDepositPaycenterCollectionEditableCollectionInternalDebitTransactionCreditTransactionInternalCreditTransactionAccountantRefundTransaction交易DebitTran...原创 2020-03-18 14:51:29 · 844 阅读 · 0 评论 -
Restful接口中的POST
新增不解释继承父类到子类这种情况是从外部同步过来的信息(这个时候需要展示),然后经过信息完善后补充划分到子类。这个时候可以摆脱子类和父类的集成关系。把Child集成Parent改成Parent和某个NewType绑定。只是Parent和NewType的id是一致的子类到子类上述方案无法解决的问题是子类到子类,特别是一个Object1从ChildOne移动到ChildTwo时,这时往往伴...原创 2020-03-18 14:36:11 · 1166 阅读 · 0 评论 -
Backend For Frontend 实践心得
Controller为每个页面单独写一个Controller,完全不必遵循Restful风格。为每一个请求单独写一个方法,放弃后端接口复用。这样做有以下几点原因业务上无法保证各个下拉框的取值范围一致。例如班级类型,也许在新增订单时班级类型有【普通班】和【寒假班】,但是作为查询条件时有【普通班】,【寒假班】和【暑假班】。另外作为转班时,可能下拉框有除了现在班级外其他班级,这个需要根据当前id...原创 2019-12-20 09:27:21 · 1118 阅读 · 0 评论 -
微服务设计(消息)
MQ重复消息的处理幂等性把insert和业务操作放入一个事务MQ乱序的处理分片有序,由id来hash事务性发件箱将要发送的消息写入DB,然后由另一个线程来读取并发送(可以轮询或者读DB日志)...原创 2019-09-18 19:06:39 · 329 阅读 · 0 评论 -
DDD中数据的校验
入参校验Controller校验可以更友好的返给前端信息可以在一开始就检查完毕,特别是一个Controller方法对应两个Domain方法的情况下Domain校验可以处理不同Domain之间的差异数据库中数据校验Repository校验作为数据存储方提供数据的完整性,domain只解决业务问题可以对id不存在的进行进行处理可以处理冗余字段的一致性Domain.re...原创 2019-06-10 16:52:22 · 2296 阅读 · 0 评论 -
网状关联下Restful返回对象
网状对象的返回双向引用Repository的cache双向引用在编程中会碰到以下情况A.b=BB.a=A如果像DDD中进行仔细分析避免上面的情况当然好。但是有时无法避免时整个ValueObject就会变成网状关联。但是作为restful接口返回的时候应该是树状,当接收方收到后又可能倾向网状。如果考虑到对象的循环引用,应该有Repository来负责处理并cache。class Rep...原创 2019-01-24 09:25:39 · 238 阅读 · 0 评论 -
领域驱动设计思考(Service与Domain分工)
POST事件由谁来处理如果domain之间有调用不通过service,那么service无法感知到所有时间,这些消息通知只能有domain来处理。但这个通知要在持久化之后么?这样又和持久化谁处理相影响权限本着简单处理事务一致性的原因,操作一旦开始就不能中止。权限的检查应当由controller里作为入口的方法在调用domain和其他service方法之前检查(包括状态等其他业务上先决条...原创 2018-12-26 10:27:56 · 2188 阅读 · 0 评论 -
微服务设计思考(伴随创建)
有的时候一个操作涉及到两个微服务都要创建一个对应的Entity信息,这里分为两种情况讨论,这里先讨论第一种情况,就是现实世界中的一个实体有不同的侧面,而微服务的划分将不同侧面交给了不同微服务来处理,各自专注于处理相关的一些信息.例如当新增一个客户时那么就生成了该客户的一个钱包信息,以及积分信息等等.按照传统的关系型数据库的设计范式,这些一对一的关系用一张表就可以解决.这个表既有性别,生日这样的...原创 2018-12-26 10:12:56 · 333 阅读 · 0 评论 -
领域驱动设计思考(锁)
谁来锁由Service来锁还是有domain的内部方法来锁,或可以通过拦截器读取url上的id来锁。URL这种方案看上去最简单也最可靠,但是不够灵活。特别是一个操作会影响多个业务对象(如果只是通知也许简单点)。并且所谓的业务逻辑往往是这些关联性,而不仅仅是按照前端数据来updateDOMAIN这种做法的问题是没法批量锁,无法保证事务。既不能满足多个不同domain之间的大锁,也...原创 2018-12-26 10:04:05 · 298 阅读 · 0 评论 -
Restful风格api设计(domain转跳)
关于跳到另一个domain的url一般是要操作的,所以这里有GET和PUT两个请求方案一不用调用GET请求,数据少则直接显示。缺点,字段权限不好控制。适用于前端弹窗方案二2.1只给GET请求如果能PUT则给GET请求,否则不给。优点:点击弹窗的数据新。缺点:URL的语义变了2.2两个URL都给Get请求时又会给一个PUT请求,语义重复且前一个给的PUT请求会过时...原创 2018-12-24 14:23:28 · 432 阅读 · 0 评论 -
业务中继承关系研究(命名)
重构在开发的过程中,有些概念会不断扩张从而成为一个父类。这个时候只能通过改名来实现。但对之前的兼容怎样解决?可能相关调用方要做出调整(特别是两个调用方调用同一个接口的同一个字段的时候,难以兼容)页面显示有时父类的同一个字段在不同子类有不同叫法1 如果同时出现在一行,自然分别有一个字段2 如果同时出现在一列,表头用‘/’来分割3 如果非列表,建议注...原创 2018-12-24 14:09:25 · 185 阅读 · 0 评论 -
数据库设计
业务逻辑应该是写的逻辑,而不是读的逻辑(特别是通过表而不是接口来读数据的情况)时间相关的逻辑可能要靠读来解决(但性能是不是问题)两个业务业务间依赖可能要靠读来解决...原创 2018-12-27 10:01:26 · 135 阅读 · 0 评论 -
Restful风格api设计(倒置)
批量操作的倒置往往有这样一种情况,用户需要对列表页的多行记录进行批量操作,如果要求前端逐个向后端请求既不能保证操作的一致性(虽然批量操作时后端也未必能保证事务),也在查看操作日志时产生困惑。所以尽量一次请求,那么api怎么设计呢,下面以给多个学员分配一个老师为例(一个学员只能有一个老师,而一个老师可以有多个学生)soap一种容易设计出来的方式是soap风格{"teacherId...原创 2018-12-05 10:51:29 · 175 阅读 · 0 评论 -
业务中继承关系研究(微服务)
上面的问题貌似通过postgresql来解决了,但其实问题在微服务中依旧存在.只不过数据库专注于读而服务专注于写.还是上面的问题,当后请员工的各项操作和老师领域的相关操作分到两个微服务的时候怎么办.毕竟老师很多时候是和教学等等紧密相关的.这样的话数据库的问题就变成了微服务的问题.微服务也可以分为一个微服务(方案一),两个微服务(方案二),三个微服务(方案三).就算是多个微服务使用同一个数据库,...原创 2018-08-26 15:57:02 · 442 阅读 · 0 评论 -
DDD思考(数据保存)
如果不考虑数据库的具体实现,只考虑代码中执行的保存操作,大致可以分为以下几种情况1有Repository由repository.save(entity)来完成持久化操作2无Repository,由entity.save()来完成保存3无repository,无entity.save(),在调用业务方法后自动保存到数据库按照DDD书上的介绍推荐的是第一种,理由是把持久化的责任...原创 2018-08-18 15:11:54 · 1028 阅读 · 0 评论 -
入参等数据校验的思考
在进行真正的业务操作之前,为了确定数据都是合法可靠地,需要对数据进行检查。数据一般有以下几个来源外部调用– 前端– 第三方服务– 另一个可信服务数据库显而易见,数据的校验越早越好,这样后面被调用的方法就不用再校验。如此看来public方法一般需要校验而private方法可以不校验。为了方便阅读,private还是可以加上annotation。外部调用对于外部调用时的检查又可以分...原创 2019-06-23 13:18:25 · 452 阅读 · 0 评论 -
审批流加入对原业务的影响
对调用方影响如果是想减少对调用方的影响,可以不更改URL但是更改返回的状态码对domain的影响domain可以拆分成三个个方法,一个是用来处理请求,那么就是检查入参和状态。并且把当前状态改成审批中从而拒绝其他所有请求,另两个方法处理审批结果,因为审批结果有通过和未通过两种情况。这两种情况的处理可以合成一个方法也可以分成两个方法,分成两个方法时入参更加明确。...原创 2019-06-23 14:02:51 · 251 阅读 · 0 评论 -
Set与distinct的选择
对于查询出来非重复数据是应该使用select distinct还是使用java.util.Set来作为接收对象来去重?如果是返回id这一列的话貌似两个都能满足要求,但是distinct更好因为这样应该传输数据少,虽然这样加大了DB的一些负担。如果返回多列,则毫无疑问要distinct,否则还要重写equals...原创 2019-09-18 19:01:33 · 1068 阅读 · 0 评论