Kamafeel

求其上,得其中;求其中,得其下,求其下,必败


  • 首页

  • 归档

设计模式-管道

发表于 2021-12-01 | 分类于 设计模式

使用场景

处理步骤组合,存在灵活多变

类似

责任链

招式

定义context上下文,
处理context的handler接口

定义一个Executor执行一个List顺序的责任链

参考

https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&mid=2650413430&idx=1&sn=32c89ea3222d341bf3014854f69fd239&chksm=8396d16eb4e1587838f99a6859668a3588b0762155c1a13872d3f419efa3f75c5a532d7d38fe&scene=21#wechat_redirect

好代码编写原则

发表于 2021-11-23 | 分类于 架构 , 基础

单一性原则SRP(Single Responsibility Principle)

单一性原则要求一个对象/类应该只有一个变更的原因。但是在这个案例里,代码可能会因为任意一个外部依赖或计算逻辑的改变而改变。

依赖反转原则DIP(Dependency Inversion Principle)

依赖反转原则要求在代码中依赖抽象,而不是具体的实现。在这个案例里外部依赖都是具体的实现,比如YahooForexService虽然是一个接口类,但是它对应的是依赖了Yahoo提供的具体服务,所以也算是依赖了实现。同样的KafkaTemplate、MyBatis的DAO实现都属于具体实现。

开放封闭原则OCP(Open Closed Principle)

开放封闭原则指开放扩展,但是封闭修改。在这个案例里的金额计算属于可能会被修改的代码,这个时候该逻辑应该需要被包装成为不可修改的计算类,新功能通过计算类的拓展实现。
多使用策略模式扩展

DDD持久化

发表于 2021-11-17 | 分类于 微服务 , DDD

领域对象和仓储对象

领域只关心核心业务

仓储对象偏数据存储

注意一些:create_time,update_time,create_user_id之类的信息,属于极弱的领域属性,尽量放到仓储层

存储库选择

如果是使用文档数据库 mongodb, 不需要考虑映射。

如果使用关系数据库,需要考虑,ORM框架中间加上,领域对象和仓储对象的转换

仓储库的接口

本身属于领域的服务能力,一般包含save(add,update),delete,find/builder

DDD工程落地辅助

发表于 2021-11-17 | 更新于 2022-08-13 | 分类于 微服务 , DDD

架构选择

COLA框架,搭建分层模型

核心思路

业务内聚,分而治之
APP层可先厚,再做薄

领域层抽象

1)实体
唯一标识,具备生命周期,包含业务关键行为
包含实体相关的方法,实体对象可以包含接口(接口可注入),实体建议使用工厂模式创建

2)值对象
只关系属性,没生命周期。
避免大量对象为实体,从而需要唯一标识,唯一标识会带来数据库主键之间关系网庞大。

3)领域服务
属于领域业务,但非实体对象本身的逻辑。
多领域对象计算,业务动作,领域对象转换等均可定义为领域服务。

4)聚合
将实体和值对象进行聚合
形成业务内聚。

聚合根设计

如何聚合根:
1)生命周期一致
2)问题域一致性
3)场景频率一致性
4)聚合内的元素尽可能少

控制边界

如何割断值对象
1)引入Id值对象
2)使用ORM框架的LazyFetch机制(注意生命周期范围)
3)引入Supplier的get延迟机制

实体和值对象的创建,查询

实体的创建最好走工厂模式/builder模式

实体的变更需要走唯一gateway/Repository模式

实体的查询走CQRS模式,注重效率即可

值对象的变更,查询随意,不受约束。

实体对象的持久化

使用mongodb文档型数据库
使用聚合根快照概念
https://github.com/meixuesong/aggregate-persistence

关系数据库,实体持久化可以灵活,一个实体多表(值对象占表),或者一实体一表

各层对象转换

利用 mapstruct

参考

https://blog.csdn.net/significantfrank/ COLA框架
https://developer.aliyun.com/article/713097?spm=a2c6h.13262185.profile.12.1ea36c7btzXxqf DDD落地
https://zhuanlan.zhihu.com/p/436465508 DDD落地
https://blog.csdn.net/qq_33589510/category_10734882.html DDD系列

https://blog.csdn.net/qq_42046105/article/details/125013100?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-125013100-blog-120566859.pc_relevant_multi_platform_whitelistv3&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-125013100-blog-120566859.pc_relevant_multi_platform_whitelistv3&utm_relevant_index=1

https://mp.weixin.qq.com/s?__biz=MzIzOTU0NTQ0MA==&mid=2247503833&idx=1&sn=d103844943ef2ce81eadd77664a6ac84&chksm=e92af2d6de5d7bc072a16f04d2eb15afd9f3d9d085818901345901bc6f67841747071c78889e&mpshare=1&scene=1&srcid=1117apoiUxlPQGYsMhAjB3L6&sharer_sharetime=1637114884293&sharer_shareid=21878bc7924c790b0c0f03ef06b36d15&key=bcca9004de07f2d9ea0029f6d4fd7e4e2cd15ecfca135628ce2815e910f6e0e5c815a0d2c05d4448da0f537d30c3f741e07d4bb0c2bc020274fe69689036c678b1a67c3c8c00da2342d4df4d835ef555c43129ef4d3c62deffce7fed0460cbd6b08f60f16155a9d9fe369415441773ddeca39927a93a1202ee64380edca719b2&ascene=1&uin=OTM4NTY4MzU%3D&devicetype=Windows+10&version=62060844&lang=zh_CN&exportkey=Abg59yCBS4dVa7lUHHEySnQ%3D&pass_ticket=mxk%2FEa9Sff76MaFalsSx5JYeiSimROUbxBnC7%2FOvQGvs6cXCIB%2B9jRjSm5%2B70Biz&wx_header=0 ##

spring骚操作-1-FactoryBean

发表于 2021-11-11 | 更新于 2021-11-17 | 分类于 Spring , 开发

##用途##

创建复杂对象:
1.需要根据配置文件。

2.spring运行环节期间创建对象。

3.符合spring设计理念

##例子##
EhCacheFactoryBean

MybatisSqlSessionFactoryBean

Java Immutable and mutable

发表于 2021-11-04 | 分类于 JAVA , 开发

不可变对象 用途

1.在实例化时存在校验,不希望后续属性再次被修改(逃避校验)
2.存在多线程使用场景,不希望此代码运行对对象进行修改(事件对象,HTTPclient参数)

可变对象 用途

DTO类,被快速GC

使用技巧

1
2
3
4
5
6
7
8
9
10
@SuperBuilder
@Builder
@Getter

/** 此处只能避免不被修改引用,但是还是可以修改引用对象的值 **/
比如 Date
private final

Guava Collection之Immutable类

参考

https://juejin.cn/post/6844903586661400590
https://www.cnblogs.com/shoshana-kong/p/10822759.html
https://www.codenong.com/32989562/

Java泛型

发表于 2021-11-02 | 分类于 JAVA , 开发

何时用

无论何时,只要你能做到,就应该尽量使用泛型方法

使用场景

1.把容器类泛型化
2.接口实现泛型
3.方法参数泛型

何为泛型

各类方法,类的参数的类型,参数化,不再是具体类型,而是一个泛化的类型

类使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{
//key这个成员变量的类型为T,T的类型由外部指定
private T key;

public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
this.key = key;
}

public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
return key;
}
}

接口使用

1
2
3
4
5
6
7
8
9
10
11
/**
* 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
* 即:class FruitGenerator<T> implements Generator<T>{
* 如果不声明泛型,如:class FruitGenerator implements Generator<T>,编译器会报错:"Unknown class"
*/
class FruitGenerator<T> implements Generator<T>{
@Override
public T next() {
return null;
}
}

泛型方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 泛型方法的基本介绍
* @param tClass 传入的泛型实参
* @return T 返回值为T类型
* 说明:
* 1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
* 2)只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
* 3)<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
* 4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
*/
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
IllegalAccessException{
T instance = tClass.newInstance();
return instance;
}

default <T, E extends T> MetaObjectHandler strictUpdateFill(MetaObject metaObject, String fieldName, Supplier<E> fieldVal, Class<T> fieldType) {
return this.strictUpdateFill(this.findTableInfo(metaObject), metaObject, Collections.singletonList(StrictFill.of(fieldName, fieldVal, fieldType)));
}

kafka安装部署

发表于 2021-10-13 | 更新于 2022-03-03 | 分类于 中间件 , Kafka

2.8版本前

kafka:2.13-2.6.3 前面为scala版本后面为kafka版本

一定确定,kafka服务端版本和客户端版本,和zk的关系

参考:https://zhuanlan.zhihu.com/p/359573455

相对稳定版本:2.6.1 +

docker 部署脚本

强烈建议docker compose部署,非以下模式

ZK部署

1
2
3
4
5
6
7
8
docker run -d --name zookeeper-zq \
--restart always \
-p 2182:2181 -p 2888:2888 -p 3888:3888 \
-v /docker/zookeeper_zq/conf:/conf \
-v /docker/zookeeper_zq/data:/data \
-v /docker/zookeeper_zq/datalog:/datalog \
-v /etc/localtime:/etc/localtime \
zookeeper:3.6

kafka部署

1
2
3
4
5
6
docker run  -d --name kafka -p 9092:9092 -p 9094:9094 -e KAFKA_BROKER_ID=0 \
-e KAFKA_ZOOKEEPER_CONNECT=192.168.30.199:2182 -e KAFKA_ADVERTISED_LISTENERS=INSIDE://192.168.30.199:9092,OUTSIDE://192.168.30.199:9094 \
-e KAFKA_LISTENERS=INSIDE://0.0.0.0:9092,OUTSIDE://0.0.0.0:9094 -e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT \
-e KAFKA_INTER_BROKER_LISTENER_NAME=INSIDE -e KAFKA_LOG_DIRS=/kafka/logs -e TZ="Asia/Shanghai" \
-v /docker/kafka/logs:/kafka/logs -t wurstmeister/kafka:2.13-2.6.3

KAFKA_ZOOKEEPER_CONNECT 参数后面不要加路径,避免众多kafka工具不支持自定义路径。

配套观察工具

kafka-eagle

参考

https://www.codeleading.com/article/36874712175/

订单系统架构

发表于 2021-10-12 | 更新于 2021-11-18 | 分类于 架构 , 产品

订单核心2要素

下单
查询

订单核心领域

产品/服务
用户
商家
促销
支付
交付模式(物流,在线服务)
风控

下单

订单信息的获取
** 订单流程引擎,处理策略 (状态机)
订单状态的MQ异步通知
订单领域的DDD设计

能异步的地方最好异步,注意最终一致性事务,幂等性

查询

网关(Kong+ Konga ui,spring gateway)导流(根据参数,header信息等)

分库分表(mycat,Sharding-JDBC),需要考虑数据分布均匀,取模ID最好和用户相匹配

ES 提供全文检索查询(倒排索引),考虑ES的查询方式,非SQL模式

参考API

美团订单API
https://developer.waimai.meituan.com/home/doc/food/6

择偶的去伪存真

发表于 2021-10-11 | 更新于 2021-11-02 | 分类于 瞎扯蛋

女性对男性的诉求历程

1.力量的动画阶段(这个阶段表明很容易被强壮的男人吸引)

2.行为的动画阶段(这一阶段表明容易被行动能力强的男人吸引)

3.语言的动画阶段(这一阶段表明很容易被能很好使用语言的男人吸引)

4.有意义的动画阶段(这个阶段表明很容易被像精神领袖这样的男性形象所吸引)

物质的需求会同上面不同的阶段保持并驾齐驱。

男性对女性的诉求历程

1.生理需求
2.当全世界都抛弃他,而你会对他不离不舍的笃定(不需要真的发生,发生了他还会设身处地为你着想)

对家庭诉求历程

催产素的愿景,自己的子女的成长,家庭感。(不一定每个人都有这样的需求)

不合时宜的择偶

对方有强壮的身体,娇好的外貌,实则内在原驱力,这种显而易见的的优势,能提高下一代的基因。(如果不需要下一代,其实似乎也没那么重要)

一个人的自由两个人的快乐,如果鱼和熊掌不能同时兼得,考虑下顺序。

不谈物质条件都是不切实际的,太讲究条件对等,需要承担后期条件的置换变化
(比如男提供 房,车,豪华婚礼,女提供生育
后期女人老珠黄,男外遇,这种事情现代社会太多,是否属于条件随时间变化的不对等呢?
)

懂的37% 法则,如果你淘汰了太多选项,也学会接受现在这个不比之前好的现状

1…456…21

Kamafeel

204 日志
57 分类
129 标签
© 2022 Kamafeel
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Pisces v7.1.2