针对非业务通用框架开发,需要做到尽量通用,适合百变的场景,做到良好的扩展。 需求分析 功能性需求分析 满足使用者的需求,尽量通用。 借助设计产品线框图工具来罗列需求点。 把最终的数据显示样式画出来,一目了然。 非功能性需求分析 一个通用系统,需要做好良好的兼容性。 易用性 框架是否易集成,易插拔,跟业务代码是否松耦合,提供的接口是否够灵活。 性能 当集成到业务系统的框架里,不会影响业务性能。 做到低延时,内存消耗低。 扩展性 做到不修改框架源码进行扩展。 做到给框架开发插件一样扩展。 容错性 非常重要,不能因为框架本身异常导致接口请求错误。 对外暴露的接口抛出的所有运行时,非运行时异常都要进行捕获处理。 通用性 能够灵活应用到各种场景中。 多思考一下,除了当前需求场景,还适合其它哪些场景中。 框架设计 借鉴TDD(测试驱动开发)和 Prototype (最小原型)的思想 先聚集一个简单的应用场景。 设计实现一个简单的原型。 尽管功能不完善,但它能够看得见,摸得着,比较具体,不抽象,能够很有效地帮助自己缕清更复杂的设计思路,是迭代设计的基础。 在原型系统的代码实现中,我们可以把所有代码都塞到一个类中,暂时不用考虑任何代码质量,线程安全,性能,扩展性等等问题,怎么简单怎么来就行。 最小原型的代码实现虽然简陋,但它帮我们将思路理顺很多。 我们现在就基于它做最终的框架设计。 关于我 我的博客:https://yezihack.github.io 欢迎关注我的微信公众号【空树之空】,共同学习,一起进步~
纲要 完整的系统流程包括: 前期的需求沟通分析 中期的代码设计实现 后期的系统上线维护 需求分析 做为技术人员不仅仅是等着产品设计文档,线框图,照着实现就可以。应该参与到产品设计中。具有产品思维,前期应该去市场上调研,参考,借鉴已成熟的产品。充分了解自己公司的产品后,然后再将其糅合到自己的产品中,并做适当的微创新。 调研产品 充分了解自家产品 微创新 tip: 技术人也要有一些产品思维 系统设计 合理地将功能划分到不同模块 合理地划分代码可以实现代码的高内聚,低耦合,类与类之间的交互简单清晰,代码整体结构一目了然。 设计模块与模块之间的交互关系 同步接口调用 适合上下层之间的关系 异步接口调用 适合同级间的关系 设计模块的接口,数据库,业务模型 代码实现 前提 数据库和接口设计非常重要,一旦设计好并投入使用之后,这两部门都不能轻易改动。 改动数据库表结构,需要涉及数据的迁移和适配。 改动接口,需要推动接口的使用都作相应的代码修改。 一定要多花点心思和时间,切不可过于随意。 业务逻辑代码侧重内部实现,不涉及外部依赖的接口,也不包括持久化的数据,所以对改动的容忍性更大。 MVC Controller 层负责接口暴露 Repository 层负责数据读写 Service 层负责核心业务逻辑 两种开发模式 充血 DDD 开发模式 贫血 OOP 开发模式 为什么使用MVC开发 分层能起到代码复用的作用 同一个 Repository 可能会被多个 Service 来调用。 同一个 Service 可能会被多个 Controller 调用。 分层能起到隔离变化的作用 Repository 层封装了对数据库访问的操作,提供了抽象的数据访问接口。 基于接口而非实现编程的设计思想,Service 层使用 Repository 层提供的接口,并不关心底层依赖是哪种具体的数据库。 如果需要替换不同的数据库,只需要修改 Repository 层,Service 层的代码完全不需要修改。 三层的稳定程序也不同。越底层越应该稳定。 分层能起到隔离关注点的作用 Repository 层只关注数据的读写。 Service 层只关注业务逻辑,不关注数据的来源。 Controller 层只关注与外界打交道,数据校验,封装,格式转换,并不关心业务逻辑。 三层之间的关注点不同,分层之后,职责分明,更加符合单一职责原则,代码的内聚性更好。 分层能提高代码可测试性 使用依赖注入方式,采用 mock 数据替代真实数据。 分层能应对系统的复杂性 水平方向基于业务来做拆分,就是模块化。 垂直方向基于流程来做拆分,就是分层。 tip: 对于工作不满意,应该我花点时间在技术上;对于当前工作很满意则多花时间在业务上。

Proxy

设置GIT代理 // 查看当前代理设置 git config --global http.proxy git config --global https.proxy // 设置当前代理为 http://127.0.0.1:1080 或 socket5://127.0.0.1:1080 git config --global http.proxy 'http://127.0.0.1:1080' git config --global https.proxy 'http://127.0.0.1:1080' git config --global http.proxy 'socks5://127.0.0.1:1080' git config --global https.proxy 'socks5://127.0.0.1:1080' // 删除 proxy git config --global --unset http.proxy git config --global --unset https.proxy
纲要 KISS原则 Keep It Simple and Stupid 尽量保持简单 代码行数越少就越“简单”吗? 答案是否定的,实现逻辑需要简单,易维护,不过度优化 代码逻辑复杂就违背 Kiss 原则吗? ​ 答案也是否定的,需要考虑逻辑复杂度,实现难度,可代码的可读性。 总结 不要使用很另类的技术实现代码 不要重复造轮子,善于使用已有的工具类库 不要过度优化 一句话:KISS原则讲”如何做“的问题(尽量保持简单) tip: 在开发中不要过度设计,越是能用简单的方法解决复杂的问题,越能体现一个人的能力。 YAGNI原则 You Ain’t Gonna Need It 你不会需要它 核心思想:不要做过度设计。 一句话:YAGNI原则讲”要不要做“的问题(当前不需要的就不要做) DRY原则 Don’t Repeat Yourself 不要重复自己,即不要写重复的代码。 三种典型的代码重复情况: 实现逻辑重复 实现逻辑重复,但功能语义不重复的代码,并不违反DRY原则。 功能语义重复 实现逻辑不重复,但功能语义重复的代码,也算是违反DRY原则。 代码执行重复 重复执行相同的代码也是违反DRY原则。 代码复用性 三个不同的概念: 代码复用性(Code Reusability) 表示一段代码可被复用的特性或能力 代码复用(Code Resue) 尽量复用已经存在的代码 DRY原则(Don’t Repeat Yourself) 不要写重复的代码 复用和可复用性关注角度不同 “可复用性”是从代码开发者的角度出发的。 “复用”是从代码使用者的角度出发的。 实际上目的是一样的,都是为了减少代码量,提高代码可读性,可维护性。 提高复用性方法 减少代码耦合 高度耦合的代码,往往是牵一发而动全身。 尽量减少代码耦合,提高代码的复用性。 满足单一职责原则 模块,类,函数尽量职责单一。 越细粒度的代码,代码的通用性会越好,越容易被复用。 模块化 类, 函数要尽量将独立的功能封装成模块。 独立的模块像一块一块积木,更加容易复用,可以直接拿来搭建更加复杂的系统。 业务与非业务逻辑分离 越是跟业务无关的代码越是容易复用。 越是针对特定业务的代码越难复用。 为了复用跟业务无关的代码,将业务与非业务逻辑代码分离,抽取成一些通用的框架,类库,组件等 通用代码下沉 从分层的角度来看,越底层的代码越通用,会被越多模块调用,越应该设计得足够可复用。 避免交叉调用导致关系混乱 只允许上层代码调用下层代码及同层代码之间调用。 杜绝下层代码调用上层代码。 通用的代码尽量下沉到更下层。 继承,多态,抽象,封装 利用继承:可以将公共的代码抽取到父类,子类复用父类的属性和方法。 利用多态:动态地替换一段代码的部分逻辑,让这段代码可复用。 利用抽象:越抽象,越不依赖具体实现,越容易复用。 利用封装:代码封装模块,隐藏可变的细节,暴露不变的接口,就越容易复用。 应用模板等设计模式 使用设计模式,提高代码复用性。 其它 泛型编程,也是提高代码复用性。 复用意识非常重要,时常要多去思考一下,这部分代码是否可以抽取出来,作为一个独立的模块,类或函数供多处使用。 设计每个模块,类,函数的时候,要像设计一个外部API一样,去思考它的复用性。 LOD原则 Low of Demeter
控制反转(IOC) Inversion Of Control “控制”是指对程序执行流程的控制 ”反转“ 指没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程可以通过框架来控制。流程的控制权从程序员”反转“到了框架。 tip: 控制反转是指对程序执行流程的控制权交给框架完成。 Go代码实现 package main import ( "fmt" "sync" "time" ) // 控制反转 ioc // 定义一个发送接口 type Sender interface { Send() // 发送函数 } // 定义一个发送 app 结构体,实现控制反转操作 type SendIoc struct { list chan Sender // 使用 chan 的发送接口 } var ( // 定义一个全局的 Ioc 对象,保证全局唯一 __sendApp *SendIoc __sendAppOnce sync.Once ) func NewSendIoc() *SendIoc { __sendAppOnce.Do(func() { __sendApp = &SendIoc{ list: make(chan Sender, 10), } go __sendApp.
依赖注入(DI) Dependency Injection 不通过 new() 的方式在类内部创建依赖类对象,而是将依赖的类对象在外部创建好之后,通过构造函数,函数参数等方式传递(或注入)给类使用。 tip: 基于接口而非实现编程 Go代码实现 package main import "fmt" // DI 依赖注入:Dependency Injection // 定义一个发送接口类 type ManagerSender interface { // 发送类 Send(phone, message string) } // 定义短信发送结构体,实现 ManagerSender 接口 type SmsSender struct { } func (s *SmsSender) Send(phone, message string) { fmt.Printf("正在使用短信发送消息,手机号:%s,消息内容:%s\n", phone, message) } // 定义站内发送结构体,实现 ManagerSender 接口 type InboxSender struct { } func (s *InboxSender) Send(phone, message string) { fmt.Printf("正在使用站内发送消息,手机号:%s,消息内容:%s\n", phone, message) } // ----------------- 实现注入的代码 -------------------- // 定义一个发消息结构体 type Notification struct { ms ManagerSender } // 将接口赋值给 Notification func NewNotification(m ManagerSender) *Notification { return &Notification{ms: m} } // 实现发消息,使用接口的对象 Send func (n *Notification) SendMessage(phone, message string) { n.
开发项目涉及到 MySQL时就需要MySQL管理工具, phpmyadmin 是一款网页功能强大的免费软件。 安装 MySQL 命令方式: docker run -itd --name dev_mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql docker-compose.yml 方式: version: '3' services: mysql: image: "mysql" restart: always container_name: "mysqld" environment: MYSQL_ROOT_PASSWORD: "123456" ports: - "3306:3306" 安装 phpmyadmin 管理 MySQL 的软件 修改 MySQL 配置 docker exec -it <dockerID> /bin/bash # 进入容器 mysql -u root -p # 进入 mysql # 将root账号(可替换成其他)的host修改为% update mysql.user set host = '%' where user = 'root'; # 查看修改结果 select host, user from user; # 刷新加密方式 flush privileges; 安装 phpmyadmin 命令行方式:
以 golang 构建项目为例。 新建任务 输入一个任务名称 选择:构建一个自由风格的软件项目 可选:也可以复制已创建的任务 确定提交 配置 再次编辑刚创建的任务 描述 对你的项目进行描述,可以写如下信息。 项目名称 部署的IP地址 部署远程的目录 日志路径 配置目录及文件名称 启动服务 停止服务 重启服务 等等 Job Notifications 参数化构建过程 构选: 参数化构建过程 GIT参数 选项参数 配置“构建” 和 “回滚” 参数。供构建时选择 字符参数 设置填写构建ID号。 源码管理 一般使用GIT,在 branches to build 指定分支使用变量 ${GIT_COMMIT},即参数化构建过程那一步使用的GIT参数名称 填写有效的 GIT 地址。并使用授权的用户帐号,保证可以访问仓库代码。 构建 会用到以下二个选项: 执行Shell Send files or execute commands over SSH 构建项目的SHELL 定义变量 删除或创建目录 判断用户是“构建”还是“回滚”进行区别操作 源码: set -x # 定义名称 program_name=go_test # 项目压缩名称 program_filename=${program_name}.tar.gz # 项目路径 target_path="${WORKSPACE}/target/" # 备份路径 back_path="${WORKSPACE}/bak/" if [ -f "${back_path}${program_filename}" ];then rm -f ${back_path}${program_filename} fi ls -l $back_path # 当前构建ID的路径 back_path_num="${back_path}${BUILD_NUMBER}" # 删除前必须判断是否存在 if [ -f "${target_path}${program_filename}" ]; then rm -rf "${target_path}${program_filename}" echo "${target_path}${program_filename} 删除成功" fi # 备份路径不存在则创建 if [ !
纲要 基础阅读 从一个孩童的视角切入。共四个阶段,循序渐进。 阅读准备阶段 身体方面的准备 良好的视力和听力。 起码的认知能力。 语言上的准备 口齿清晰。 个人的准备 与其它人一起学习时,保持注意力。 读一些简单的读物 看图识字。 字句的使用, 词名的含意,字句的发音等等。 快速建立词汇能力 阅读不同领域的书籍,像科学,社会学,语言艺术等等。 保持开放的心灵与好奇心,不断扩大自己的视野,增进阅读量。 精练与增进所学的技巧 此阶段为阅读的成熟阶段 开始消化阅读的经验 从一本书所提出来的一个观点转化到另一个观点。 在同一个主题上,对不同的作者所提出来的观点作比较。 检视阅读 检视阅读,才算是真正进入阅读的层次。 必须精通基础阅读,否则没法进入检视阅读层次。 略读的作用: 略读的目标是发现这本书值不值得花时间仔细阅读, 略读也能告诉你许多这本书有关的事。 略读的阅读 这是一种非常主动的阅读,需要集中精神来阅读。 先看书名页, 然后看序 特别注意副标题。 序囊括了这本书大部分的观点与内容。 在大脑里给这本书归个类。 研究目录页 对这本书的基本架构做概括性的理解。 检阅书中附有的索引 判断出这本书里的重要词汇,关系到作者的意图与态度。 了解下出版社和作者的背景 一个好的出版社会对他出版的图书背书的。 作者的背景与经历决定着这本书的高度。 挑几个看来跟主题息息相关的篇章来看 检阅这本书写得如何。 把书打开来,东翻翻西翻翻,念上一两段,有时候连续读几页,但不要太多 随时寻找主要论点的讯号,留意主题的基本脉动。 不要忽略最后的两三页,代表着一本书的收尾。 tip: 通过以上步骤有系统地略读过一本书,完成第一种型态的检视阅读。时间控制在一小时内完成。最后决定这本书是否值得继续投下时间与注意。 粗浅的阅读 对于一本难懂的书,阅读的规则: 头一次面对一本难讲的书的时候,从头到尾先读完一遍,碰到不懂的地方不要停下来查询或思索。 略过那些不懂的部分,直到读到你看得懂的地方,集中精神在这个部分,继续这样读下去。 将全书读完,不要被一个看不懂的章节,注解,评论或参考资料阻挠或泄气。 如果你让自己被困住了,如果你容许自己被某个顽固的段落绑住了,你就是被打败了。 在读第二遍的时候,你对那个地方的了解可能会多一些,但是在那之前,你必须至少将这本书先从头到尾读一遍才行。 从头到尾读一遍之后比你让自己在一碰上困难的地方就停止要好很多,后者让你对这本书真的一无所知。 阅读的速度: ​ 检视阅读是一种训练有素的快速阅读。懂得能快速读,也能用不同速度来阅读。 tip: 每一本书,不论是多么难读的书,在无关紧要的间隙部分就可以读快一点。而一本好书,总会包含一些比较困难的内容,应该慢慢阅读内容。 逗留与倒退: 许多人会从最初学会阅读之后,多年一直使用“半出声(sub-vocalize)”的方式来阅读。 此外还有些阅读者,在阅读一行字的时候会在五六个地方发生“逗留(fix-ate)”。 更糟的是,不熟练的阅读者在每看过两三行之后,眼睛就自然地“倒退”到先前读过的句子上去。 以上这些现象或习惯不但浪费时间而且降低阅读的速度。 我们的头脑跟眼睛不一样,并不需要一次只“读”一个字或一个句子。我们的头脑是个惊人的工具,可以在“一瞥”之间掌握住一个句子或段落。 矫正眼睛逗留的有效方法:
阅读的艺术 阅读是一件主动的事,而非被动。 阅读的误区 太多的资讯就如同太少的资讯一样, 都是一种对理解力的阻碍. 我们在这个互联网上接触的到的音频,视频及文章等等, 都是一些经过太精心的设计, 使得思考形同没有需要了, 长期接受这样的信息会对我们的理解力产生阻碍. tip: 远离二手信息, 直击源头知识. 主动的阅读 阅读越主动, 效果越好. 任务一种阅读都是一种活动, 那就必须要有一些主动的活力. 完全被动, 就阅读不了– 我们不可能在双眼停滞, 头脑昏睡的状况下阅读. 第一提醒读者: 阅读可以是一件主动的事. 第二提醒读者: 阅读越主动, 效果越好. 一个读者更主动一些, 在阅读的世界里探索能就更强一些, 收获更多一些, 因而也更高明一些. 读者对他自己, 以及面前的书籍, 要求的越多, 获得的就越多. 阅读的目标 以获得知识而读, 以及为求得理解而读. 一本书摆在你面前, 想要与你沟通一些想法. 你要能成功地阅读这本书, 完全看你能接获多少作者要要传达的讯息. 只有一种方式是真正地在阅读: 没有任何外力的帮助, 你就是要读这本书. 你什么都没有, 只凭着内心的力量, 玩味着眼前的字句, 慢慢地提升自己,从只有模糊的概念到更清楚地理解为止. 这样的一种提升, 是在阅读时的一种脑力活动, 也是更高的阅读技巧. 这种阅读就是让一本书向你即有的理解力做挑战。 两种不同意义的阅读: 第一种:阅读网文, 杂志, 公众号等, 凭我们的阅读技巧与聪明才智, 一下子便融会贯通. 这样的读物能增加我们的资讯, 却不能增进我们的理解力。 因为在开始阅读之前, 我们的理解力就已经与他们完全相当了。 否则我们一路读下去会被卡壳的。 第二种:试着读某样一开始并不怎么了解的东西。这个东西的水平就是比阅读的人高上一截。这个作者想要表达的东西, 能增进读者的理解力。 增进理解而阅读的两种状况: 第一是一开始时不相等的理解程度。 其次,阅读的人一定要把不相等的理解力克服到一定程度之内。一旦达到相同的理解程序,就完成了清楚的沟通。 tip: 我们只能从比我们"更高"的人身上学习。我们一定要知道他们是谁, 如何跟他们学习。