2019-09-13 17:27:26
摘要:持续集成、继续部署、继续交付
持续集成(Continuous integration)
是一种软件开发实践,即团队开发成员经常集成它们的工作, 通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。 每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。
持续部署(continuous deployment)
是通过自动化的构建、测试和部署循环来快速交付高质量的产品。 某种程度上代表了一个开发团队工程化的程度,毕竟快速运转的互联网公司人力成本会高于机器, 投资机器优化开发流程化相对也提高了人的效率,让 engineering productivity 最大化。
持续交付(英语:Continuous delivery,缩写为 CD)
是一种软件工程手法, 让软件产品的产出过程在一个短周期内完成,以保证软件可以稳定、 持续的保持在随时可以释出的状况。它的目标在于让软件的建置、 测试与释出变得更快以及更频繁。这种方式可以减少软件开发的成本与时间,减少风险。
DevOps
DevOps(Development和Operations的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。
它是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
它的出现是由于软件行业日益清晰地认识到:为了按时交付软件产品和服务,开发和运维工作必须紧密合作。
Jenkins
Jenkins是实现DevOps的工具
Jenkins是一款开源 CICD 软件,用于自动化各种任务,包括构建、测试和部署软件。
Jenkins 支持各种运行方式,可通过系统包、Docker 或者通过一个独立的 Java 程序。
特点: 易于安装,只要把jenkins.war部署到servlet容器 易于配置-所有配置都通过其提供的web界面实现。
集成RSS/E-mail通过RSS发布构建结果或当构件完成是通过e-mail通知。 生成JUnit/TestNG测试报告。
分布式构建支持Jenkins能够让多台计算机一起构建/测试。
文件识别:Jenkins能够跟……
阅读全文
2019-07-24 19:56:36
摘要:基于原始SQL查询创建LINQ查询,代替旧版的FromSql、SqlQuery
基本原生 SQL 查询
在版本.net core 2.0 中,我们引入了一种在依赖关系注入中注册自定义 DbContext 类型的新方法,即以透明形式引入可重用 DbContext 实例的池。 要使用 DbContext 池,请在服务注册期间使用 `AddDbContextPool` 而不是 `AddDbContext`:services.AddDbContextPool<BloggingContext>( options => options.UseSqlServer(connectionString));
如果使用此方法,那么在控制器请求 DbContext 实例时,我们会首先检查池中有无可用的实例。 请求处理完成后,实例的任何状态都将被重置,并且实例本身会返回池中。
从概念上讲,此方法类似于连接池在 ADO.NET 提供程序中的运行原理,并具有节约 DbContext 实例初始化成本的优势。
阅读全文
2019-05-26 18:36:57
摘要:
重构概述
重构的目的:为什么重构(why)?
对于项目来言,重构可以保持代码质量持续处于一个可控状态,不至于腐化到无可救药的地步。对于个人而言,重构非常锻炼一个人的代码能力,并且是一件非常有成就感的事情。它是我们学习的经典设计思想、原则、模式、编程规范等理论知识的练兵场。
重构的对象:重构什么(what)?
按照重构的规模,我们可以将重构大致分为大规模高层次的重构和小规模低层次的重构。大规模高层次重构包括对代码分层、模块化、解耦、梳理类之间的交互关系、抽象复用组件等等。这部分工作利用的更多的是比较抽象、比较顶层的设计思想、原则、模式。小规模低层次的重构包括规范命名、注释、修正函数参数过多、消除超大类、提取重复代码等等编程细节问题,主要是针对类、函数级别的重构。小规模低层次的重构更多的是利用编码规范这一理论知识。
重构的时机:什么时候重构(when)?
我们一定要建立持续重构意识,把重构作为开发必不可少的部分,融入到日常开发中,而不是等到代码出现很大问题的时候,再大刀阔斧地重构。
重构的方法:如何重构(how)?
大规模高层次的重构难度比较大,需要组织、有计划地进行,分阶段地小步快跑,时刻让代码处于一个可运行的状态。而小规模低层次的重构,因为影响范围小,改动耗时短,所以,只要你愿意并且有时间,随时随地都可以去做。
单元测试
什么是单元测试?
单元测试是代码层面的测试,由研发自己来编写,用于测试“自己”编写的代码的逻辑的正确性。单元测试顾名思义是测试一个“单元”,有别于集成测试,这个“单元”一般是类或函数,而不是模块或者系统。
为什么要写单元测试?
写单元测试的过程本身就是代码 Code Review 和重构的过程,能有效地发现代码中的 bug 和代码设计上的问题。除此之外,单元测试还是对集成测试的有力补充,还能帮助我们快速熟悉代码,是 TDD 可落地执行的改进方案。
如何编写单元测试?
写单元测试就是针对代码设计各种测试用例,以覆盖各种输入、异常、边界情况,并将其翻译成代码。我们可以利用一些测试框架来简化单元测试的编写。除此之外,对于单元测试,我们需要建立以下正确的认知:
编写单元测试尽管繁琐,但并不是太耗时;
我们可以稍微放低对单元测试代码质量的要求;
覆……
阅读全文
2019-05-19 16:35:32
摘要:
经典的设计原则,其中包括,SOLID、KISS、YAGNI、DRY、LOD 等。SOLID 原则,实际上,SOLID 原则并非单纯的 1 个原则,而是由 5 个设计原则组成的,它们分别是:单一职责原则、开闭原则、里式替换原则、接口隔离原则和依赖反转原则,依次对应 SOLID 中的 S、O、L、I、D 这 5 个英文字母。
单一职责原则(SRP)
如何理解单一职责原则(SRP)?
一个类只负责完成一个职责或者功能。不要设计大而全的类,要设计粒度小、功能单一的类。单一职责原则是为了实现代码高内聚、低耦合,提高代码的复用性、可读性、可维护性。
如何判断类的职责是否足够单一?
不同的应用场景、不同阶段的需求背景、不同的业务层面,对同一个类的职责是否单一,可能会有不同的判定结果。实际上,一些侧面的判断指标更具有指导意义和可执行性,比如,出现下面这些情况就有可能说明这类的设计不满足单一职责原则:类中的代码行数、函数或者属性过多;类依赖的其他类过多,或者依赖类的其他类过多;私有方法过多;比较难给类起一个合适的名字;类中大量的方法都是集中操作类中的某几个属性。
类的职责是否设计得越单一越好?
单一职责原则通过避免设计大而全的类,避免将不相关的功能耦合在一起,来提高类的内聚性。同时,类职责单一,类依赖的和被依赖的其他类也会变少,减少了代码的耦合性,以此来实现代码的高内聚、低耦合。但是,如果拆分得过细,实际上会适得其反,反倒会降低内聚性,也会影响代码的可维护性。
出现下面这些情况就有可能说明这类的设计不满足单一职责原则:
类中的代码行数、函数或者属性过多;
类依赖的其他类过多或者依赖类的其他类过多;
私有方法过多;
比较难给类起一个合适的名字;
类中大量的方法都是集中操作类中的某几个属性。
开闭原则(OCP)
如何理解“对扩展开放、对修改关闭”?
添加一个新的功能,应该是通过在已有代码基础上扩展代码(新增模块、类、方法、属性等),而非修改已有代码(修改模块、类、方法、属性等)的方式来完成。关于定义,我们有两点要注意。第一点是,开闭原则并不是说完全杜绝修改,而是以最小的修改代码的代价来完成新功能的开发。第二点是,同样的代码改动,在粗代码粒度下,可能被认定为“修改”;在细代码粒度下,可能又被认定……
阅读全文
2019-05-12 10:35:23
摘要:
面向对象概述
什么是面向对象编程?
面向对象编程是一种编程范式或编程风格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石 。
什么是面向对象编程语言?
面向对象编程语言是支持类或对象的语法机制,并有现成的语法机制,能方便地实现面向对象编程四大特性(封装、抽象、继承、多态)的编程语言。
如何判定一个编程语言是否是面向对象编程语言?
如果按照严格的的定义,需要有现成的语法支持类、对象、四大特性才能叫作面向对象编程语言。如果放宽要求的话,只要某种编程语言支持类、对象语法机制,那基本上就可以说这种编程语言是面向对象编程语言了,不一定非得要求具有所有的四大特性。
面向对象编程和面向对象编程语言之间有何关系?
面向对象编程一般使用面向对象编程语言来进行,但是,不用面向对象编程语言,我们照样可以进行面向对象编程。反过来讲,即便我们使用面向对象编程语言,写出来的代码也不一定是面向对象编程风格的,也有可能是面向过程编程风格的。
什么是面向对象分析和面向对象设计?
简单点讲,面向对象分析就是要搞清楚做什么,面向对象设计就是要搞清楚怎么做。两个阶段最终的产出是类的设计,包括程序被拆解为哪些类,每个类有哪些属性方法、类与类之间如何交互等等。
面向对象四大特性
关于封装特性
封装也叫作信息隐藏或者数据访问保护。类通过暴露有限的访问接口,授权外部仅能通过类提供的方式来访问内部信息或者数据。它需要编程语言提供权限访问控制语法来支持,例如 C# 中的 private、protected、public 关键字。封装特性存在的意义,一方面是保护数据不被随意修改,提高代码的可维护性;另一方面是仅暴露有限的必要接口,提高类的易用性。
关于抽象特性
封装主要讲如何隐藏信息、保护数据,那抽象就是讲如何隐藏方法的具体实现,让使用者只需要关心方法提供了哪些功能,不需要知道这些功能是如何实现的。抽象可以通过接口类或者抽象类来实现,但也并不需要特殊的语法机制来支持。抽象存在的意义,一方面是提高代码的可扩展性、维护性,修改实现不需要改变定义,减少代码的改动范围;另一方面,它也是处理复杂系统的有效手段,能有效地过滤掉不必要关注的信息。
关于继承特性
继承是用来……
阅读全文
2019-05-05 17:19:18
摘要:
一、引言:为什么关注代码质量?
“任何一个傻瓜都能写出计算机可以理解的代码,唯有能写出人类容易理解的代码的,才是优秀的程序员。” —— Martin Fowler
代码质量直接决定:
系统长期维护成本
缺陷修复效率
团队协作流畅度
技术债务积累速度
二、核心评价维度(思维导图模块解析)
1. 如何评价代码质量的高低?
核心矛盾:主观性 vs 客观标准
解决方案:多维度综合评估(如图所示)
graph LR
A[代码质量] -- B[技术维度]
A -- C[业务维度]
B -- D[可维护性]
B -- E[可读性]
B -- F[性能]
C -- G[需求契合度]
C -- H[变更响应速度]
2. 最常用的7大标准(优先级排序)
| 标准 | 重要性 | 关键表现 |
| :----------: | :----: | :--------------------------: |
| 可维护性 | ★★★ | 修改成本低,风险可控 |
| 可读性 | ★★★ | 命名清晰,结构直观,文档完备 |
| 可扩展性 | ★★☆ | 新功能添加无需重构核心逻辑 |
| 可测试性 | ★★☆ | 单元测试覆盖率80% |
| 灵活性 | ★★☆ | 支持多种使用场景 |
| 简洁性 | ★★☆ | 无过度设计,YAGNI原则 |
| 可复用性 | ★☆☆ | 模块化程度高,依赖清晰 |
💡 黄金三角:可维护性、可读性、可扩展性是质量基石(如图重点标注)
三、实践方法论
如何才能写出高质量代码?
具体实施建议:
设计四重奏
封装变化点(如用策略模式替代if-else)
依赖接口而非实现(DIP原则)
限界上下文划分(领域驱动设计)
代码可读性技巧
// Bad ❌
boolean f = (a 5) (b 10);
// Good ✅
boolean isWithinValidRa……
阅读全文
2019-03-20 11:26:30
摘要:什么是无服务器计算
“无服务器”是云计算中资源抽象的极致体现。从它的命名上你就可以看出,所谓“无服务器”就是想让用户感觉不到服务器的存在,这是因为有一朵巨大的云在底层进行着支撑。
如果说容器是给予了我们很大的定制空间,让你更加容易地按照自己的需要,来进行应用程序的拆分和封装;那么无服务器则是完全屏蔽了计算资源,它是在真正地引导你不再去关心底层环境,你只要遵循标准方式来直接编写业务代码就可以了。
而且在粒度上,无服务器会允许你拆分得更细致、更轻量。你甚至可以把每一个具有独立功能的函数,来作为一个单独的服务进行部署和运行。这也是为什么,在有些云计算的分类方法下,无服务器计算能够单独“开宗立派”,被称为函数即服务(Function-as-a-Service,FaaS)的原因。
各大云厂商现在都已经推出了各自的无服务器计算服务,比如 AWS 的 Lambda、阿里云的函数计算,和微软 Azure 的 Azure Functions。在国内的云厂商中,腾讯云的云函数也是在无服务器计算上投入较早、产品较为成熟的厂商。
无服务器计算是多面手
无服务器计算所能做的,可远远不止充当快速的 Web 开发工具。事件模型是无服务器的核心编程模型和运行逻辑,所以它非常适合相当广泛的事件驱动开发场景。
事件的起始,要依靠触发器。
云上 Serverless 服务一般都配套提供了多种多样的触发器,包括 API 触发器、对象存储触发器、队列触发器等等。比如上面的实验中,我们用的就是API 触发器,它的触发条件为 API 网关带来的外部 Web 请求。
较为常用的还有对象存储触发器。比如当用户上传了一个文件,后台程序把它保存到对象存储中,这时相应的无服务器函数会被这个新对象触发,你就能对这个新上传的文件进行必要的处理了。
此外,还值得了解相当实用的定时触发器,它可以按照设置的条件周期性触发。通过它和云函数的配合,可以在一定程度上代替操作系统中 crontab 类工具起到的作用,也许能帮你节省一台专门触发运行定时任务的虚拟机。
如果说触发器是无服务器计算的上游的话,那么各种各样的外部交互方式,也让无服务器计算能够对外访问,并向下游输出。云端的 Serverless 环境中,一般都能够提供一系列重要类库和 SDK,让你能够在函数内访问其他云服务,尤其是像数据库、消息队列这样的外部存储。
所以,在云端……
阅读全文
2019-03-17 11:04:16
摘要:什么是应用托管服务
在云计算发展的早期,就已经出现了“建站类服务”,这正是应用托管服务的雏形。当时的建站类服务,会自动为你分配好服务器,安装好相应语言的 Web 环境以供你使用。在部署层面,服务通常会开放 FTP 端口,以便你上传服务器端的代码、脚本和资源。这是应用服务的一种轻量形式。
应用服务的本质就是为你的应用提供一个隔离的独立运行环境。作为用户来讲,你可以只专注于业务逻辑,不需要来手动创建这个环境,更不需要运维这个环境。
应用托管的增值服务
成熟的应用服务还能够提供许多增值服务,来进一步地满足我们在实际开发运维 Web 应用时,产生的各个层面的需求。
第一项增值服务就是监控
尤其是针对 Web 应用的特点而进行的 HTTP 层面的应用监控。所以,你不仅能看到计算资源的占用率,如 CPU、内存使用率等,还能看到许多应用层指标,比如总请求数、错误响应数、并发连接数、响应时间等等。这些都是你在监控应用运行时非常有帮助的信息,而这一切都是 PaaS 服务自动提供、开箱即用的功能。
而且,基于这些监控的指标,你还能够在云上制定相应的报警规则,当某些指标达到你设定的阈值时,会及时发送警报。这同样是一个非常实用的功能。
第二个方面是扩展
也就是底层计算资源和流量需求的匹配。这里既包含了底层机器配置的垂直扩展,也包含了机器数量层面的水平扩展。一旦你有调整需求,只需要动动手指发出指令,就可以随时升级相应的机器配置,并无缝切换。
特别是水平扩展的存在,它相当于同时包含了负载均衡和弹性伸缩,把它们都一股脑儿集成到了托管服务中。这意味着应用托管服务不是只能对应一台机器,而是能够创建多台机器来承接请求,并会在前端均衡地分发到多个实例上去。这里你同样可以指定自动伸缩的规则,来让应用服务自动地调整实例数量。
第三个方面是集成
这里是指与其他 PaaS 的集成。这是所有 PaaS 服务的优势,各个服务间可以互相帮助、联合作战,应用托管类服务也不例外。比如在监控数据方面,它可以和云监控系统进行衔接;再比如,有些云允许 Web 应用以目录的形式,挂载对象存储中的文件等等。
其中,应用托管类服务还有一项非常重要的集成能力,就是应用服务与云上 DevOps 组件和流程的无缝对接。它意味着应用服务可以作为整个应用生命周期管理的一部分,嵌入到持续集成的流程中去。借助和源代码管理设施的联动,你的应用……
阅读全文
2019-03-15 22:01:47
摘要:云上的关系型数据库
关系型数据库的应用在业界是最普遍的,也是云数据库首先进入的领域。这里的先行者同样是 AWS,早在 2009 年就发布了 RDS(Relational Database Service),后来其他的厂商也纷纷开始跟进。
云数据库在外部交互的层面上,保持了和传统“原版”数据库几乎完全一致的编程接口和使用体验。
比如说,你针对 MySQL 编写的 SQL 代码和应用层连接代码,包括你很熟悉和经常会使用的连接管理工具,除了要更改连接字符串和参数之外,都能够几乎不经修改地在云数据库的 MySQL 服务上运行。
另外,针对某个数据库的某个具体版本,云厂商们会把它的功能、内部机制完整地保留下来,以求获得最大程度的兼容性。早期比较简单的云数据库实现原理,是充分利用云上已经提供的虚拟机、云磁盘等 IaaS 层面的资源,在隔离的环境下进行数据库镜像的安装。而后来技术实力比较强大的厂商,还能够做到对数据库源码和模块的深度定制,在保证兼容性的前提下,进行许多对用户透明的云端适配和优化。
所以,云数据库尽管是一个受限的 PaaS 环境(比如它通常无法让你直接访问底层的服务器),但在使用体验上和传统数据库是相当一致的。你大可放心,之前积累的 MySQL 和 PostgreSQL 的知识,在 RDS 上也大都可以适用。在云上,你也同样能够找到和安装一些数据库的常用插件,来增强 PaaS 数据库的功能。
云数据库和传统数据库又很大的区别,这是指在搭建、运维、管理层面,云数据库提升了一个层次,实现了相当程度的智能化和自动化,极大地提升了用户友好度,降低了使用门槛。比如灵活的性能等级调整、详尽的监控体系、攻击防护机制等等,这些许多在传统数据库中需要借助额外工具或产品的功能,在云数据库服务是默认内置,可以开箱即用的。
除了这些基本能力外,还有两个最具代表性的云上关系型数据库的高级特性:
支持读写分离。当并发数量上升时,关系型数据库容易出现性能瓶颈。这时比较有用的办法,就是实现基于多库同步的读写分离。云数据库在产品后台略加操作,就可以启用这个功能:从创建从库到建立同步,再到读写流量分发,云数据库都能自动完成。
支持自动调优。对于数据库来说,同样和性能有关的一个重要工作,就是性能的调优。以前我们经常需要手动地观测性能瓶颈,找出热点查询,再考虑是否有改进性能的办法。而在现代云数据库中……
阅读全文
2019-03-14 11:48:32
摘要:对象存储,顾名思义,就是在云端,可以存放任意对象的存储服务。要注意这里的“对象”指的是任意的二进制对象,保存到云上通常是以二进制文件的形式,不要和“面向对象编程”中的对象混淆起来。
初识对象存储
通俗地解释起来,你可以这样理解,对象存储是你在云上可以创建的一种“网盘”。这个网盘可以存储任意的二进制文件,包括结构化和非结构化数据。你可以随时上传下载,也可以修改和删除。当然,云上对象存储会保证你数据的可靠性、可用性和扩展性,你不需要操心这些细节。
那么,同样是存储服务,对象存储和云硬盘有什么区别呢?
第一个主要区别,在于访问的接口与形式。
云硬盘其实是挂载到虚拟机的虚拟硬盘,它是通过实现操作系统级别的底层接口,作为虚拟机的块存储设备而存在。我们也必须连接到相关的虚拟机,才能访问它里面的数据。
而对象存储,本质是一个网络化的服务,调用方主要通过高层的 API 和 SDK 来和它进行交互。不管是面向外部公开互联网服务,还是和内部应用程序对接,对象存储都是通过提供像 HTTP 这样的网络接口来实现的。所以它的独立性很强,不需要依赖其他组件就可以运作。
第二个主要区别,也是对象存储的一大特征,就是对象存储内本身不存在一个真正的文件系统,而是更接近一个键值(Key-Value)形式的存储服务。
这里的键就是对象的路径(路径中包含斜杠符号“/”),这里的值就是存储对象的二进制文件。
键值系统和云硬盘上经典文件系统的核心差异,就在于文件系统保存了更多的元数据,尤其是实现了目录结构和目录操作。而键值系统中,所谓的目录其实是多个对象共享的路径前缀,可以说是用前缀模拟出了目录。
第三个主要区别,在于对象存储的巨大容量。
作为云计算最具代表性的服务之一,它的可扩展性(Scalability)是毋庸置疑的,对象存储能够轻松地容纳上 PB 的超大容量数据,这是任何的云硬盘所不能企及的。所以对象存储是名副其实的大数据存储。
但从另一个角度说,对象存储和 HDFS 这样的大数据文件系统比起来,又有自己独到的优势:对象存储本身也是非常擅长和适合处理小文件的,即便是海量的小文件,对象存储也不会像 HDFS 那样处理起来捉襟见肘,可以说是“大小通吃”。
对象存储的高级特性
存储分层
在生产环境下的对象存储,我们往往会存放大量的文件和数据,这些文件的访问频率其实是会有很大差异的。比如说,对于一些比……
阅读全文