如何快速熟悉项目

如何快速上手一个项目,是每个程序员都会遇到的问题,我来分享一下,我是如何做的

前言

现在好多文章,在教大家如何面试,跳槽。跳了之后呢,如何快速熟悉项目,通过试用期呢。

大家在入职都会面对一个问题,就是熟悉项目。那么熟悉

相信大家都在看到一座代码大(shi)山放到自己面前,都不知从何下手。如果有老同事讲解,健全的文档供查阅,那么入手起来就很方便。但就我入职以来多年经验,大部分公司的项目文档不全。你一入职,老同事就甩手(对,你是去接锅的);除了HR姐姐的入职培训,没有更多的信息;这种情况下,该如何快速入手项目呢。

这里代码部分拿PHP项目举例,其他语言的读者也可借鉴思想。

何谓熟悉了项目

一个项目,它的存在就是为了解决问题,那么熟悉项目就是,了解他能解决什么问题。

那么就需要向这个 项目提问–发起请求。再看我们能得到什么样的回答–响应。

那么我们能提什么问题呢?比如,Android APP问:现在手机手机壳是什么颜色?我要根据这个颜色变换壁纸。显然向项目提出这样的我问题,项目是不能回答的。

那么我们得到了什么回答(响应)呢,我得到了它返回给我的参数。哦不仅仅是这些,这背后它查阅了什么数据,或者更改了什么数据,还给其他项目发送了请求,或者消息,这都是这项目的响应。

所以熟悉项目我们要知道:

  • 可以解决什么问题
  • 解决问题过程中做了什么?

把项目当黑盒

这里我们抽象一下,参考 冯·诺伊曼结构

冯·诺伊曼结构-百度百科图

不论我们的http服务,Api服务,Rpc服务,都可以抽象成如上模型。

http服务的输入就是http请求,运算器是php-fpm程序,控制其表现的是php代码,储存是磁盘,内存,或是redis,输出是http响应

Rpc服务的输入就是TCP报文, 运算器是php常驻程序。

MySQL服务也能这样抽象,输入是MySQL格式编码的TCP报文,运算器,控制器是MySQL程序,存储是磁盘,内存。输出也是TCP报文, 然后在php程序解码出数据。

那么熟悉项目就是可抽象为:

  • 了解系统的I/O

什么是输入输出

一个项目运算器,控制器,就是这个项目的程序代码。存储器就是数据。这就好比一个线团,不知从哪开始理,如果你立马就能看懂咋回事,那么这篇文字你看到这里就可以关了。

在抽丝剥茧时,我们会先找到一个线头作为开始,而代码,就需要找到输入。

网页,APP是项目里所见即所得的输入,也是最容易理解的,从这个方向输入可以看到用户用例。

php我么这里把它作为运算器,php代码作为控制器。

php内部自己实现了一个Zend虚拟机,能编译php代码成opcode并运行。可以把它比做运算器

产生的日志,图片等文件写入,作为项目里面的存储器

数据,不论本地还是远程的,我们都作为输出。(输出数据保存,输出数据查询请求)。特别是关系型数据库,从关系结构可推测出系统建模。

一个具体的项目对用户提供服务,在多服务的架构里,同样它也会是一个请求发出者,此时它发出的请求作为输出。例如:Rpc请求,Redis操作。

自己熟悉项目时,第一时间就开始啃代码是很难的,这是把它当作一个黑盒,从什么样输入,会得到什么样的输出,开始理解系统,只有这中间代码做了什么不用第一时间关心。

就像TDD一样,接到的是需求,不那么关心中间实现过程。这样的参数输入能得到那样的数据返还,这个代码的happy-path就算过关了。

所以接下来,我开始从项目,输入,输出,存储开始给大家讲解快速熟悉项目。

输入

有哪些输入呢?

http请求,tcpwebsocket, 自定义rpc请求。还有消息,cron都是输入。

这里我联想到ServerLess,只关心输入输出

输出

SQL,Redis, Curl, RPC,文件写入,应用对外发出的请求都是输出。

配置日志记录

Http 日志

  • 在浏览器端开启请求记录

例:

这里只是抓了http请求,还有个websocket容易被忽略,可以通过WS标签过滤查看。

在浏览器端开启产看http请求是相较于抓包,避免了添加https证书问题。

  • 在服务端开启日志记录
## file: /etc/nginx/nginx.conf

http {
...
    ## 这是默认的日志
    log_format main '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $bytes_sent '
                       '"$http_referer" "$http_user_agent" "$gzip_ratio"';
    ##  注意这里新增了一个 $request_body
    log_format log_requets '$remote_addr - $remote_user [$time_local] '
                       '"$request" "$request_body" $status $bytes_sent '
                       '"$http_referer" "$http_user_agent" "$gzip_ratio"';
...
}

nginxaccess_log会记录GET请求以及参数,POST请求就需要额外配置,这里我们新增了一种日志格式——log_requets

## file: /etc/nginx/conf.d/www.conf
server
{
...
    root  /usr/share/nginx/html/xiunobbs/;

    ## 这里使用新的格式日志
    access_log  /var/log/nginx/access_xiuno.log log_requests;
    error_log /var/log/nginx/error_xiuno.log;
...

例:

图中最后一行POST,日志请求记录了提交的内容。

消息队列和Cron输入

消息队列一般要通过查日志记录来查阅。cron这块除了一般的Linux crontab,还有一些专门的cron管理工具。这点需要询问IT运维部门得知。

SQL日志

MySQL举例,数据库软件会有日志记录,为了debug,我们把一般的操作日志打开。这样就能,记录所有提交到该数据库的sql记录。

## file /etc/mysql/my.cnf
general_log_file        = /var/log/mysql/mysql.log
general_log             = 1
log_output              = FILE

配置好,重启数据库,再运行项目就能记录代码的SQL操作了。

例:

至于bin-log,这个只记录编辑操作,不记录查询操作。

Redis日志

monitorredis的调试命令,输入后,当前窗口会返回redis处理的每一个命令,它能帮助我们了解在redis上发生了什么操作。redis是没有任何配置能够将操作命令记录到日志。

Redis 能够记录一些服务状态改变日志,以及慢日志。

登陆到redis-cli,然后键入monitor,\n

这里我们可以用这个命令将日志操作日志记录到文件里。

nohup redis-cli monitor > /var/log/redis/redis_op.log 2>&1 &

Memecached日志

在启动memcaced是带上参数-vv

memcached -vv

通过如下配置把Memcached的日志记录到文件里。

memcached -m 64 -l 0.0.0.0 -p 11211 -u memcache -vv > /var/log/memcached.log 2>&1

RPC 日志

如果该Web项目依赖了RPC,需要也需要进行记录。

日志汇总

捕获到以上日志后,就能知道这个Web项目,接收到到了什么请求,查了什么DB,操作了Redis什么,请求了什么RPC

但是在3个窗口来回切换,有些不便,接下来我们想办法让他们在展示在一个窗口内。

tail -f -q /var/log/nginx/access_xiuno.log   /var/log/mysql/mysql.log /var/log/redis/redis_op.log /var/log/memcached.log

效果如下:

好的这里就是通过日志,配置请求来熟悉代码。

AOP日志

好了到这里,这篇文章就快结束了,什么,以上日志方式你都没发实现,Http网关,数据库,消息队列都是运维在负责,他们做的日志级别不够,或者没有收集。以上都搞不定。

那就要祭出大招,PHP-AOP,这个利器了。在不影响原代码逻辑,注解方式侵入代码,无需DBA,运维配合就能通过PHP代码,完成Requst,MySQL请求,Redis请求的日志记录。

详情看我的文章:PHP7中使用AOP

这里就不做展开了。哦,如果你要熟悉的代码是 函数式编程风格,那么这个Go!AOP就无能为力。动手该代码加日志吧。

文档和代码的关系

Jira/RedMind/Tower/禅道/Teambition 等也存有很多信息,不过这太依赖于公司制度和员工态度,有的人全是口头交流,软件只是用来记录状态的;有的员工事无巨细都记录在案,经手过的任务,都自带Wiki。

代码,于任务管理工具之间的联系,一般是在提交记录或分支名命名带有任务ID号。这样可以通过代码找到任务ID,再查阅当时的备注信息。

最后

通过如上操作,你已能够通过日志,了解到这段代码做了什么,梳理出主要业务。快速上手。至于参数校验,逻辑判断,最总都会落实到I/O操作的不同上。

祝愿你早日熟悉公司业务,扛起大梁。