geekuzzw

geekuzzw 查看完整档案

广州编辑华南农业大学  |  软件工程 编辑保密  |  PHP开发工程师 编辑 www.javion.top/ 编辑
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

geekuzzw 收藏了文章 · 5月27日

为什么 InnoDB 使用 B+ 树

每一种解决方案都是为了解决某一类问题而产生,所以在问为什么使用某种方案的时候,其本质就是在探索该方案是用来满足什么样的需求,解决什么样的问题。

所以探究 InnoDb 为什么使用 B+ 树这个问题,就是要弄清楚 B+ 树是用来满足什么的需求,解决什么样的问题。

要满足什么样的需求

我们先看一下一些常用的 SQL 语句

# 根据某个确定值来查询对应的信息
select id, name, email from user where id = 1;

# 通过区间值查询
select id, name, email from user where id > 12 and id < 20

# 通过范围查询并进行排序
select id, name, email from user where id < 123 order by id desc limit 10;

从以上的几个常用的 SQL 我们可以看到在对数据库进行查找数据的过程中主要有以下三类需求:

  1. 根据某个值精确快速查找
  2. 根据区间的上下限来快速查找此区间的数据
  3. 查询符合条件的记录并根据某些字段进行排序

所以,需要找到一种符合上面所有需求的方案。目前比较常用于查询的数据结构有以下两种:

  • 散列表

散列表

散列表(哈希表)是根据是一种根据(key, value)直接进行访问的数据结构,它通过哈希函数将 key 值映射到散列表对应的位置上,查找效率非常高。

索引里其中的一种索引类型哈希索引就是基于散列表实现的,假设我们对名字建立哈希索引,则查找过程如下图所示:

对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码(上图散列表的位置),散列表里的每个元素指向数据行的指针,由于索引自身只存储对应的哈希值,所以索引的结构十分紧凑,并且可以直接根据键值直接找到对应的数据记录,这让哈希索引查找速度非常快!但是哈希索引也有它的劣势,具体如下:

  1. 只有精确匹配索引所有列的查询才有效,比如我在列(name, address)建立哈希索引,如果只查询数据列 name, 则无法使用该索引。
  2. 哈希索引不是按照索引值顺序存储的,即 key 经过哈希函数计算后的哈希值不是按顺序的,所以也就无法用于排序,就不能根据区间进行查找。
  3. 哈希索引只支持等值比较查询,如 = 和 in(),不支持范围的查找,如 id > 17。

所以,哈希索引只适用于特定场合,在适当的场景使用,的确能带来很大的性能提升。比如在 InnoDB 里,就有一种特殊的功能叫 “自适应哈希索引”,如果 InnoDB 注意到某些索引列值被频繁使用时,它会在内存基于 B+ 树索引之上再创建一个哈希索引,这样就能让 B+ 树也具有哈希索引的优点。

所以散列表结构无法满足上文提到的需求。

​接着我们来看看树。

平衡二叉树

平衡二叉树可用于查找,且其查找的时间复杂度近似 O(log2n),但是可以用平衡二叉树作为索引的结构吗?

答案是不能。

因为数据库表的数据通常是很多的,正常都是存放在磁盘上的。而磁盘的速度相比内存的速度是慢很多倍的,所以要尽量减少读取磁盘的次数,通过从内存读取数据来提高速度。

那么,如何将尽量多且有效的索引数据放到内存中呢?

这里有两个问题要解决:

1、尽量多

读取磁盘数据的时候,都是按磁盘块来读取的(局部性原理与磁盘预读),并不是一条一条的读。在使用树这种结构作为索引的数据结构时,我们每查找一次数据就需要从磁盘中读取一个树节点,也就是对应的一个磁盘块,所以如果我们能把尽量多的数据放到磁盘块中,那么每次读取的数据就会较多。

而平衡二叉树是每个节点只存储一个键值和数据,也就是说,存储的时候,每个磁盘块只存储一个键值和数据。

那如果存储了海量的数据,可以想象平衡二叉树的节点将会非常多,树高也会极其高,在查找数据的时候就会进行很多次磁盘 IO,效率将会极低。

所以平衡二叉树无法解决存储尽量多的索引到内存中这个问题。

2、有效的索引数据

我们所说的平衡二叉树,指的是逻辑结构上的平衡二叉树,其物理实现是数组。所以在逻辑相近的节点上,其物理位置可能相差会很远。因此,每次读取的磁盘页数据,很多可能是用不上的,即有效的索引数据并不多,所以在查找过程中还是要进行许多次的磁盘读取操作。

所以平衡二叉树也无法解决这个问题。

所以,能解决这两个问题的数据结构 —— B 树就被发明出来了。

B 树

B 树(Balance Tree),即平衡树的意思。B 树是从平衡二叉树演化而来,B树的每个节点可以存储多个关键字,它将节点大小设置为磁盘页的大小,充分利用了磁盘预读的功能。每次读取磁盘页时就会读取一整个节点。也正因每个节点存储着非常多个关键字,树的深度就会非常的小。进而要执行的磁盘读取操作次数就会非常少,更多的是在内存中对读取进来的数据进行查找。B 树的结构示例如下图所示:

由于 B 树的每一个节点,即每一个磁盘块存储的数据较多,所以一定程度上解决了上文提到的存储尽量多的索引的问题。也一定程度上的解决了存储尽量多的有效索引的问题。

但是,B 树只是一定程度上的解决了问题,我们需要更好的解决问题。即能不能的做到存储更多的有效的索引呢?

答案是可以。这时候就就需要 B+ 树闪亮登场了。

更好的解决了问题的 B+ 树

B 树一定程度上的解决了问题,而从 B 树演化而来的 B+ 树能更好的解决问题,所以现实使用中几乎已经没有使用 B 树的情况了。

B + 树的结构示意图如下:

那么 B+ 树和 B 树有哪些不同?

  • 在 B+ 树中,非叶子节点上是不存储数据的,仅存储键值。

因为在数据库中页的大小是固定的,InnoDB 中页的默认大小是 16 KB,如果不存储数据,那么节点就可以存储更多的键值,相应的树的阶树就会更大,对于同样的数据量来说,需要的树高就会变低,树会更矮胖,如此一来查找数据的时候进行磁盘的 IO 次数就会减少,提升查询效率。

由于 B+ 树的阶数等于键值数量,假设 B+ 树的一个节点可以存储 1000 个键值,那么 3 层的 B+ 树 可以存储 1000 x 1000 x 1000 = 10亿个数据。并且一般根节点是常驻内存的,所以查找 10 亿个数据,只需要 2 次磁盘 IO。

B+ 这个特点很好的解决了上文提到的存储尽量多的索引数据的问题,并且查询效率也高。

  • B+ 树的叶子节点中的索引数据是按顺序排列的,并且叶子节点间是通过双向链表进行连接的。

这个特点使 B+ 树在实现范围查找,排序查找,分组查找等操作时变得异常简单。而 B 树由于数据分散在各个节点,要实现这些操作很不容易。

由于索引数据是按顺序排序的,即每次读取了数据页的时候,里面的索引数据大部分都是需要用的,所以也很好的解决了上文提到的如何存储尽量多的有效的索引数据的问题。

总结

通过上面的分析,我们可以发现,在使用某种解决方案的时候,这种方案一定是用来满足某些需求的,在满足需求的过程中就会遇到一些问题,而最终的解决方案一定是能尽量好的解决问题并满足需求的。

所以,探究清楚某种方案是要满足什么样的需求,解决什么样的问题以及如何的解决了问题,也就明白了为什么使用这个方案。

更多好文,关注公众号获取

file

查看原文

geekuzzw 收藏了文章 · 3月10日

PHP 教父鸟哥 Yar 的原理分析

各位老铁在点赞、收藏的时候敢不敢报名小弟的直播分享,绝对有干货,绝对有惊喜!
一次早餐钱的投入,可能是薪资的翻倍,可能是视野的拓展!

模块越来越多,业务越来越复杂,RPC 就上场了,在 PHP 的世界里,鸟哥的作品一直备受广大网友的青睐。下面一起学习下鸟哥的 PRC 框架 Yar 。

揭开 Yar 神秘面纱

RPC 采用客户端/服务器模式。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息的到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
这和我们外网 api 的原理不都一个样么?那么我们一起看看高大上的 Yar 是怎么在玩。

Yar 功能演示

客户端代码,假设该服务设在局域网10.211.55.4

<?php
 
class RpcClient {
    // RPC 服务地址映射表
    public static $rpcConfig = array(
        "RewardScoreService"    => "http://10.211.55.4/yar/server/RewardScoreService.class.php",
    );
 
    public static function init($server){
        if (array_key_exists($server, self::$rpcConfig)) {
            $uri = self::$rpcConfig[$server];
            return new Yar_Client($uri);
        }
    }
}
 
$RewardScoreService = RpcClient::init("RewardScoreService");
var_dump($RewardScoreService->support(1, 2));

服务器端代码

<?php
 
class RewardScoreService {
    /**
     * $uid 给 $feedId 点赞
     * @param $feedId  interge
     * @param $uid  interge
     * @return void
     */
    public function support($uid,$feedId){
        return "uid = ".$uid.", feedId = ".$feedId;
    }
}
 
$yar_server = new Yar_server(new RewardScoreService());
$yar_server->handle();

访问结果如下

uid = 1, feedId = 2

Yar 远程调用的实现原理

实际呢,yar client 是通过__call这个魔术方法来实现远程调用的,在Yar_client类里面并没有任何方法,当我们在调用一个不存在的方式的时候,就会执行__call方法,这个在框架中非常常见。

Yar 协议分析

1449906349384302

在 yar 中规定的传输协议如下图所示,请求体为82个字节的yar_header_t和8字节的打包名称和请求实体yar_request_t,在yar_header_t里面用body_len记录8字节的打包名称+请求实体的长度;返回体类似,只是实体内容的结构体稍微不同,在reval里面才是实际最后客户端需要的结果。

整个传输以二进制流的形式传送。

Yar 数据传输的整体流程分析

yar_transport.h中,定义了yar_transport_t结构体,先不考虑并行处理的接口,以socket传输协议为例子学习,代码简化一些如下:

typedef struct _yar_transport_interface {
    void *data;
    int  (*open)(struct _yar_transport_interface *self, char *address, uint len, long options, char **msg TSRMLS_DC);
    int  (*send)(struct _yar_transport_interface *self, struct _yar_request *request, char **msg TSRMLS_DC);
    struct _yar_response * (*exec)(struct _yar_transport_interface *self, struct _yar_request *request TSRMLS_DC);
    int  (*setopt)(struct _yar_transport_interface *self, long type, void *value, void *addition TSRMLS_DC);
    int  (*calldata)(struct _yar_transport_interface *self, yar_call_data_t *calldata TSRMLS_DC);
    void (*close)(struct _yar_transport_interface *self TSRMLS_DC);
} yar_transport_interface_t;
 
 
typedef struct _yar_transport {
    const char *name;
    struct _yar_transport_interface * (*init)(TSRMLS_D);
    void (*destroy)(yar_transport_interface_t *self TSRMLS_DC);
    yar_transport_multi_t *multi;
} yar_transport_t;

然后在transports/socket.c中定义了yar_transport_socket

yar_transport_t yar_transport_socket = {
    "sock",
    php_yar_socket_init,
    php_yar_socket_destroy,
};

整理了整体的执行流程如下图

1449981251375331

Yar 数据的打包和解包

鸟哥在yar_packager.c中首先定义了一个结构体,初始化的时候会把各个yar_packager_t注册到**packagers数组中。

struct _yar_packagers_list {
    unsigned int size;
    unsigned int num;
    yar_packager_t **packagers;
} yar_packagers_list;
typedef struct _yar_packager {
    const char *name;
    int  (*pack) (struct _yar_packager *self, zval *pzval, smart_str *buf, char **msg TSRMLS_DC);
    zval * (*unpack) (struct _yar_packager *self, char *content, size_t len, char **msg TSRMLS_DC);
} yar_packager_t;

然后通过传入的nameyar_packager_tname做比较,相同则返回该实例

PHP_YAR_API yar_packager_t * php_yar_packager_get(char *name, int nlen TSRMLS_DC) /* {{{ */ {
    int i = 0;
    for (;i<yar_packagers_list.num;i++) {
        if (strncasecmp(yar_packagers_list.packagers[i]->name, name, nlen) == 0) {
            return yar_packagers_list.packagers[i];
        }
    }
 
    return NULL;
} /* }}} */

亲密接触完毕。纸上得来终觉浅,绝知此事要躬行。这篇博客只能是辅助大家在看源码时一起分析,觉不能抛开源码仅仅看这篇博客。

怎么样才能对这个内容真正的掌握呢,所以我有折腾了一个Java 版本的客户端,这样总算有所收获,这份代码也和我们平常写的业务逻辑还是有些区别,二进制的东西居多,整个过程下来对网络数据的传输有了更深刻的理解和学习哈。

Github 项目地址: https://github.com/zhoumengka...

查看原文

geekuzzw 关注了专栏 · 3月10日

周梦康

金三银四 还不上车补课?学了就是赚了 https://segmentfault.com/ls/1650000011318558

关注 4463

geekuzzw 收藏了文章 · 2月27日

一线技术管理者究竟在管什么事?

概述

上篇文章《一个人被提拔,不仅仅是能力,而是信任》 中分享了两个点:

  1. 什么样的工程师,容易被提拔?
  2. 当被提拔到一线管理者后,你的初衷是什么?

这篇文章分享 一线技术管理者 究竟在管什么事?

m_2_1.png

咱们从一次完整项目的发布说起,一次完整项目的发布,大概需要经过这几个大的节点:

项目立项 -> 需求评审 -> 视觉稿评审 -> 技术评审 -> 项目启动 -> 开发 -> 联调 -> 测试 -> 发布

有句话是这么说的,通过控制过程质量,来保证结果质量。

那么,一线管理者要做的就是保证每个节点的质量,来保证整个项目的质量。

怎么保证?往下看。

制定规范

技术评审规范

在技术评审前要熟悉产品同学提供的产品文档业务流程图交互原型图,反复与产品同学确认,在双方达成一致的情况下,再设计技术方案。

设计技术方案要从 总体 到 局部 ,做到面面俱到。

总体:

  • 总体结构图
  • 业务流程图
  • 时序图
  • 核心类图

局部:

  • 功能的变更
  • 数据库字段的变更
  • 业务流程上的变更
  • 上下游接口约定的变更

当技术方案确定了,我们就确定了:

  • 技术选型(前端/后端框架、日志中间件、消息中间件、数据库...)
  • 技术架构(组件与组件之间如何协同工作,如何部署)
  • 技术难点预知(明确存在的技术难点,并确定解决方案)
  • 性能瓶颈预知(明确可能存在性能瓶颈的地方,并确定应对措施)
  • 上下游系统交互(明确在流程中的哪个位置,约定接口文档提供时间、接口联调时间)
  • 功能模块划分(任务拆分和分配)

当技术方案确定了,需要输出文档:

  • 预估开发工期.xlsx,包括 系统模块功能功能简述研发人员工时(h)预计完成时间 等。

    功能除了包括正常的开发工作,还要包括 提供接口文档接口联调研发自测文档更新 等。

    正常的功能开发,拆分成工时的颗粒度最大为 2h,这样的颗粒度能够降低工作的复杂度,使不熟悉相关业务的研发也能够快速上手,比如 2h 就写一个方法。

  • 更新项目文档,包括 项目介绍产品文档业务流程系统结构接口文档数据字段外部依赖其他 等。

    这个分类可自定义,主要是为了解决 当人员发生流动 导致 系统交接时产生遗漏的问题。

代码风格规范

虽然代码风格并不影响程序的运行,也不会给程序带来潜在的危险,但是一段好的代码风格,阅读起来能让人赏心悦目,特别是阅读别人的代码,就像自己写的一样。

根据自己使用的语言,制定代码风格规范,可参考语言的相关标准,比如 PHPPSR

代码风格规范达成一致后,一定要落实到文档上!!!方便其他同事进行 CodeReview 时使用。

代码开发规范

  • 接入 统一可视化日志 平台。
  • 接入 统一配置中心 平台。
  • 接入 统一异常监控 平台。
  • 接入 统一消息中间件 平台。
  • 异常处理规范:直接返回、抛出异常、重试处理、熔断处理、降级处理。
  • 统一 API 规范:HTTP 接口、RPC 接口,Code、Msg、Data 等。
  • 分支开发规范:分支名称规范、热修复规范、上线规范 等。
  • 其他规范,大家可以自行补充 ...

代码管理规范

常用的代码管理工具:GitSVN

工具的使用,大家都知道,就不多说了,约定一些基础的规范。

  • 不要提交自己的用户配置,比如 IDE 配置。
  • 不要提交不能通过编译的代码。
  • 要早提交、常提交,提交之前要先更新。
  • 提交信息一定要认真填写,参考如下规范。

<type>(scope):<subject>,比如:fix(首页模块):修复弹窗 JS Bug。

type 表示 动作类型,可分为:

  1. fix:修复 xxx Bug
  2. feat:新增 xxx 功能
  3. test:调试 xxx 功能
  4. style:变更 xxx 代码格式或注释
  5. docs:变更 xxx 文档
  6. refactor:重构 xxx 功能或方法

scope 表示 影响范围,可分为:模块、类库、方法等。

subject 表示 简短描述,最好不要超过 60 个字,如果有相关 Bug 的 Jira 号,建议在描述中加上。

CodeReview 规范

说实话,由于种种原因,自己实施的并不好。

CodeReview 检查哪些问题?

  • 规范性检查

    • 是否遵循代码开发风格规范、代码开发规范。
    • 是否所有的变量都被正确定义和使用,注释是否准确。
  • 健壮性检查

    • 是否无意中陷入了死循环。
    • 是否存在异常未处理、资源未释放的情况。
    • 是否存在运行时错误(数组边界溢出、除以零的情况)。
  • 重用性检查

    • 是否存在相同的方法写了两次,是否可以写成通用类、方法、组件等。
  • 安全性检查

    • 是否存在 SQL注入、XSS、SSRF、CSRF、越权、文件上传 等漏洞。
  • 性能检查

    • 是否存在同步执行太慢,需要转成异步执行的情况。
    • 是否存在未加缓存,频繁链接 DB 的情况。
    • 是否需要使用连接池。

CodeReview 如何执行?

  • 前期准备

    • 制定 CodeReview 规范和标准,这样在审查过程中可以有据可依,有理可循。
    • 确定 CodeReview 审查者、参与者。
  • 实施期

    • 在 CodeReview 前,审查者需将 审查内容 及 审查的规范和标准 告知所有参与者和代码作者。
    • 在 CodeReview 时,审查者要进行逐项审查,不能因为时间不足等因素一扫而过。
    • 在 CodeReview 后,审查者要对发现的问题,给予解决方案,同时进行问题记录,便于事后跟踪。
    • 审查者不能只在发现问题时提问,遇到不清楚的代码设计和业务,也可以让代码作者进行讲解,便于自己熟悉整个业务和代码设计。
    • 期间营造一个讨论问题、解决问题的氛围,不能搞成批判会,这样会影响大家的积极性。
  • 事后跟踪

    • 对发现的问题,确定修复的难易程度以及影响的范围。
    • 对发现的问题,确定修复完成的时间点。
    • 对发现的问题,修复后要进行验证。

小结

如上就是一线技术管理者要做的事,这些只是 管事 当中的一小部分。

我猜想,有些读者可能会有这个问题:哪来的时间呀?业务代码天天加班都搞不完,哪些时间搞这些?

这个问题... 首先要承认在大部分的公司中,业务代码是刚需,因为是靠这些业务挣钱的,需要快速上线占领市场的。

当随着公司的发展,技术人员的扩充,规范肯定要慢慢建立起来的,否则就会出现这样那样的问题。

如果公司就几名技术人员,可以先不用搞这些,优先快速发展业务吧。

当各位发现有哪些地方不对 或 不完善的地方,欢迎批评指正。

推荐阅读

一起学习

查看原文

geekuzzw 赞了文章 · 2月27日

一线技术管理者究竟在管什么事?

概述

上篇文章《一个人被提拔,不仅仅是能力,而是信任》 中分享了两个点:

  1. 什么样的工程师,容易被提拔?
  2. 当被提拔到一线管理者后,你的初衷是什么?

这篇文章分享 一线技术管理者 究竟在管什么事?

m_2_1.png

咱们从一次完整项目的发布说起,一次完整项目的发布,大概需要经过这几个大的节点:

项目立项 -> 需求评审 -> 视觉稿评审 -> 技术评审 -> 项目启动 -> 开发 -> 联调 -> 测试 -> 发布

有句话是这么说的,通过控制过程质量,来保证结果质量。

那么,一线管理者要做的就是保证每个节点的质量,来保证整个项目的质量。

怎么保证?往下看。

制定规范

技术评审规范

在技术评审前要熟悉产品同学提供的产品文档业务流程图交互原型图,反复与产品同学确认,在双方达成一致的情况下,再设计技术方案。

设计技术方案要从 总体 到 局部 ,做到面面俱到。

总体:

  • 总体结构图
  • 业务流程图
  • 时序图
  • 核心类图

局部:

  • 功能的变更
  • 数据库字段的变更
  • 业务流程上的变更
  • 上下游接口约定的变更

当技术方案确定了,我们就确定了:

  • 技术选型(前端/后端框架、日志中间件、消息中间件、数据库...)
  • 技术架构(组件与组件之间如何协同工作,如何部署)
  • 技术难点预知(明确存在的技术难点,并确定解决方案)
  • 性能瓶颈预知(明确可能存在性能瓶颈的地方,并确定应对措施)
  • 上下游系统交互(明确在流程中的哪个位置,约定接口文档提供时间、接口联调时间)
  • 功能模块划分(任务拆分和分配)

当技术方案确定了,需要输出文档:

  • 预估开发工期.xlsx,包括 系统模块功能功能简述研发人员工时(h)预计完成时间 等。

    功能除了包括正常的开发工作,还要包括 提供接口文档接口联调研发自测文档更新 等。

    正常的功能开发,拆分成工时的颗粒度最大为 2h,这样的颗粒度能够降低工作的复杂度,使不熟悉相关业务的研发也能够快速上手,比如 2h 就写一个方法。

  • 更新项目文档,包括 项目介绍产品文档业务流程系统结构接口文档数据字段外部依赖其他 等。

    这个分类可自定义,主要是为了解决 当人员发生流动 导致 系统交接时产生遗漏的问题。

代码风格规范

虽然代码风格并不影响程序的运行,也不会给程序带来潜在的危险,但是一段好的代码风格,阅读起来能让人赏心悦目,特别是阅读别人的代码,就像自己写的一样。

根据自己使用的语言,制定代码风格规范,可参考语言的相关标准,比如 PHPPSR

代码风格规范达成一致后,一定要落实到文档上!!!方便其他同事进行 CodeReview 时使用。

代码开发规范

  • 接入 统一可视化日志 平台。
  • 接入 统一配置中心 平台。
  • 接入 统一异常监控 平台。
  • 接入 统一消息中间件 平台。
  • 异常处理规范:直接返回、抛出异常、重试处理、熔断处理、降级处理。
  • 统一 API 规范:HTTP 接口、RPC 接口,Code、Msg、Data 等。
  • 分支开发规范:分支名称规范、热修复规范、上线规范 等。
  • 其他规范,大家可以自行补充 ...

代码管理规范

常用的代码管理工具:GitSVN

工具的使用,大家都知道,就不多说了,约定一些基础的规范。

  • 不要提交自己的用户配置,比如 IDE 配置。
  • 不要提交不能通过编译的代码。
  • 要早提交、常提交,提交之前要先更新。
  • 提交信息一定要认真填写,参考如下规范。

<type>(scope):<subject>,比如:fix(首页模块):修复弹窗 JS Bug。

type 表示 动作类型,可分为:

  1. fix:修复 xxx Bug
  2. feat:新增 xxx 功能
  3. test:调试 xxx 功能
  4. style:变更 xxx 代码格式或注释
  5. docs:变更 xxx 文档
  6. refactor:重构 xxx 功能或方法

scope 表示 影响范围,可分为:模块、类库、方法等。

subject 表示 简短描述,最好不要超过 60 个字,如果有相关 Bug 的 Jira 号,建议在描述中加上。

CodeReview 规范

说实话,由于种种原因,自己实施的并不好。

CodeReview 检查哪些问题?

  • 规范性检查

    • 是否遵循代码开发风格规范、代码开发规范。
    • 是否所有的变量都被正确定义和使用,注释是否准确。
  • 健壮性检查

    • 是否无意中陷入了死循环。
    • 是否存在异常未处理、资源未释放的情况。
    • 是否存在运行时错误(数组边界溢出、除以零的情况)。
  • 重用性检查

    • 是否存在相同的方法写了两次,是否可以写成通用类、方法、组件等。
  • 安全性检查

    • 是否存在 SQL注入、XSS、SSRF、CSRF、越权、文件上传 等漏洞。
  • 性能检查

    • 是否存在同步执行太慢,需要转成异步执行的情况。
    • 是否存在未加缓存,频繁链接 DB 的情况。
    • 是否需要使用连接池。

CodeReview 如何执行?

  • 前期准备

    • 制定 CodeReview 规范和标准,这样在审查过程中可以有据可依,有理可循。
    • 确定 CodeReview 审查者、参与者。
  • 实施期

    • 在 CodeReview 前,审查者需将 审查内容 及 审查的规范和标准 告知所有参与者和代码作者。
    • 在 CodeReview 时,审查者要进行逐项审查,不能因为时间不足等因素一扫而过。
    • 在 CodeReview 后,审查者要对发现的问题,给予解决方案,同时进行问题记录,便于事后跟踪。
    • 审查者不能只在发现问题时提问,遇到不清楚的代码设计和业务,也可以让代码作者进行讲解,便于自己熟悉整个业务和代码设计。
    • 期间营造一个讨论问题、解决问题的氛围,不能搞成批判会,这样会影响大家的积极性。
  • 事后跟踪

    • 对发现的问题,确定修复的难易程度以及影响的范围。
    • 对发现的问题,确定修复完成的时间点。
    • 对发现的问题,修复后要进行验证。

小结

如上就是一线技术管理者要做的事,这些只是 管事 当中的一小部分。

我猜想,有些读者可能会有这个问题:哪来的时间呀?业务代码天天加班都搞不完,哪些时间搞这些?

这个问题... 首先要承认在大部分的公司中,业务代码是刚需,因为是靠这些业务挣钱的,需要快速上线占领市场的。

当随着公司的发展,技术人员的扩充,规范肯定要慢慢建立起来的,否则就会出现这样那样的问题。

如果公司就几名技术人员,可以先不用搞这些,优先快速发展业务吧。

当各位发现有哪些地方不对 或 不完善的地方,欢迎批评指正。

推荐阅读

一起学习

查看原文

赞 5 收藏 3 评论 0

geekuzzw 关注了专栏 · 2月18日

Swoole

PHP的协程框架

关注 5387

geekuzzw 关注了用户 · 2019-12-27

CrazyCodes @crazycodes

https://github.com/CrazyCodes... 我的博客
_
| |__ __ _
| '_ | | | |/ _` |
| |_) | |_| | (_| |
|_.__/ __,_|__, |

         |___/   感谢生命可以让我成为一名程序员

                         CrazyCodes To Author

关注 4664

geekuzzw 报名了系列讲座 · 2019-12-13

geekuzzw 关注了专栏 · 2019-11-20

民工哥技术之路

公众号:民工哥技术之路、《Linux系统运维指南 从入门到企业实战》作者。专注系统架构、高可用、高性能、高并发,数据库、大数据、数据分析、Python技术、集群中间件、后端等开源技术分享。

关注 16078

geekuzzw 关注了专栏 · 2019-10-31

PHP / Laravel / 全栈

PHP 和 Laravel 的精华文章分享。

关注 4338

认证与成就

  • 获得 23 次点赞
  • 获得 8 枚徽章 获得 0 枚金徽章, 获得 1 枚银徽章, 获得 7 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2016-06-08
个人主页被 543 人浏览