小白如何学习大神的小项目

0. 背景

最近Workflow项目作者
也就是一位低调的架构师(懂的都懂
起因只是为了供Workflow项目使用,
而低调地写了一个json-parser

但我看完之后觉得🤩🤩🤩wow~
这代码如此简单,却应有尽有
如果十年前的我能看到这样的项目就好了!
因此22同学冒着被打的风险,
结合这个项目写了这篇,
aka,《小白如何学习大神的小项目》
给当年的啥都不会的自己,也给需要的小童鞋~
So,有经验的朋友可以不用往下看了👋

其实,大家都希望多看优秀前辈的作品
学习里边经典的设计雅的编码风格
但前辈们的项目往往又太大、太难、太复杂
如果Jeff Dean能开个几百行代码的小项目
我会让十年前的自己每天大声朗读一遍👌

1. 了解项目要解决什么问题

理解项目最大的障碍在于:
看不到它的需求。
所以上来看复杂的项目会觉得很奇怪,
为什么要这样做?

回到项目本身:json-parser,顾名思义,
就是我们网络传输常用json格式,
而收到这么一串内容之后,
解析到具体数据结构,
方便我们后续用接口访问。

比如json里给我们这串内容是个数组:
[1, "abc", 12.3, -4]
我们希望得到的数据结构是类似
struct json_value[4];
或者std::vector<JSON_VALUE>;
在工程上这件事很常见,叫做:反序列化

2. 项目结构和前置知识

项目往往需要依赖其他项目进行构建的,
因此我们需要先来看看目录结构
它包括哪些内容,需要依赖什么其他项目
我们先看看这个json-parser:

070d27ce181f4c473af3487c5a3f256f.png

基于C写的,所以人均都能看得明白:
里边有用于构建项目的Makefile
开源所需要的LICENSE
项目主页文档README.md

然后就是简单的代码本码,
可以看到四舍五入只有800行
适合懒癌晚期的你👍
项目依赖有多种做法,这里是源码依赖
也可以交给githubsubmodule
或者交给不同系统的包管理工具。
最后附上示例程序和性能测试用例,
方便使用者直接上手使用。

3. 了解构建方式, 快速run起来

以前我的大学时期,是没有教怎么构建项目的
入职百度之后学的第一件事就是写Makefile
(想念当年一起学的小伙伴果冻同学
现在学校里对工程构建的教学要重视多了
先前有遇到过大学生问怎么构建Workflow
说是老师给的作业???🤔
Makefile是C++项目构建的必备知识
新的构建方式还有cmakebazel等,
都值得后续了解。

这份Makefile麻雀虽小五脏俱全,
基本要素都有了:

CFLAGS = -g -Wall -O2
CC = gcc
LD = gcc

all: test_speed parse_json

test_speed: json_parser.o rbtree.o test_speed.o
    $(LD) -o test_speed $

parse_json: json_parser.o rbtree.o test.o
    $(LD) -o parse_json $^

clean:
    rm -f parse_json test_speed *.o

Linux/Mac下直接执行命令make
就可以run起来~
避免新手IDE、构建搞半天然后从入门到放弃

4. 广搜看项目:初窥内核中的数据结构list.h和rbtree.h

看项目到底是bfs还是dfs
我们可以对第一层先bfs看个大概,
梳理出有哪几块内容,
再针对每块内容dfs直到搞明白为止。

json-parser中内容很少,
值得一提的是仅有的两个依赖:
listrbtree
学习委员划重点:
链表和树,是工业项目最基本的数据结构
因为用的C99写的,
因此从Linux kernel里搬了这两结构过来用
感兴趣的小伙伴
可以借此机会围观下kernel的代码风格,
一个双向链表是长这样的:

struct list_head {
    struct list_head *next, *prev;
};

然后我们就可以愉快地嵌入到其他结构中
基于任何结构类型制作一个双向链表
但>~< 这不是这次要介绍的重点~~~

5. 深搜看项目:接口设计、架构层次、编码风格

接口设计的三个重点:简单!简单!还是简单!
我们先通过test.cc感受一下接口设计:

int main()
{
    ...
    json_value_t *val = json_value_create(buf);
    if (val)
    {    
        print_json_value(val, 0);    
        json_value_destroy(val);   
    }
   ...

输入一段内容,输出一个反序列化好的对象
不需要初始化任何东西,不需要其他参数。
什么额外的optionsparamsconfig
能不要尽量不要,
不要让使用者有其他心智负担。

create对应destroy,都很严谨的
明确的内存生命周期更有利于开发者理解。
接口设计是最体现细节和品控的~
如果哪个项目会create对应delete
或者new对应destroy之类的
甚至更过分调用new不需要delete
我直接一口屏幕喷到鲜血上

那么架构层次呢?
项目整体的编程范式和架构是否统一很重要。

这个项目足够简单,
因此我们可以很快抓到它的架构重点:
它是C语言中面向对象的写法
整体围绕json_value_t
打开头文件可以看到这个对象的几个方法:

int json_value_type(const json_value_t *val);    
const char *json_value_string(const json_value_t *val); 
double json_value_number(const json_value_t *val);

json的结构里,
数组里的元素可以是对象
对象里有可以是数组
因此数据的表达可以是递归的。
而json-parser解析的架构层次一样,也是递归

刚才介绍到的用户接口函数👇

json_value_t *json_value_create(const char *doc)

它会调用到我们递归的入口:

ret = __parse_json_value(doc, &doc, 0, val);

我们需要抽象出一些结构去进行递归
把刚才的数组、对象的关系装到list/rbtree
涉及到递归调用的接口有以下这些,
感兴趣的小伙伴欢迎源码进一步阅读

static int __parse_json_value(const char *cursor, const char **end, int depth, json_value_t *val);   
static int __parse_json_object(const char *cursor, const char **end, int depth, json_object_t *obj);   
static int __parse_json_elements(const char *cursor, const char **end, int depth, json_array_t *arr);
static int __parse_json_array(const char *cursor, const char **end, int depth, json_array_t *arr);
static int __parse_json_member(const char *cursor, const char **end, int depth, json_member_t *memb); 
static int __parse_json_members(const char *cursor, const char **end, int depth, json_object_t *obj);

这里就不细说状态转换图了
毕竟本文不是教大家怎么解json0a83427ddb607fe840f7537482578ec4.png
另外,编码风格很重要。
多看风格好的项目,
才能不被有毒的代码带跑偏。

秉承作者一贯的编码风格,
这个项目简洁优雅赏心悦目。
感兴趣的小伙伴可以跑一下测速,
虽然项目还未刻意往高性能去优化,
但状态机写出来性能还是比较优秀的。

而清晰的架构层次和优秀的编码风格,
都是性能的保证。

6. 最后一些废话

这个小项目,之所以那么让我眼前一亮
是因为它如此简单,简单到让我看到
再小的东西都可以写得很棒啊!!!
我们往往看到前辈们站得很高
但其实有许多机会,可以从前人身上
学习怎么把一点一滴的小事做好

十年前没有珍惜的机会的话,
那么现在有就很幸福了👩🏻‍💻
如果还能在学习过程中,有空去模仿下华生🥜
去记录一些优秀作品、po出好文,
那已经是目前的我,最大的建设性了。


想深入学习,一起学习小而美项目,提高基本功,基础概念深入理解,疑难解答,欢迎大家加入极客星球,我们一起进步,掌握核心技术,既能挣钱又能抗压,挣钱和事业两不误,对星球感兴趣的,点击查看-> 极客星球

cb0a41d5f50d0112ef8ca96bdd5e3dfa.png

进腾讯了|学习技术哪家强


53fceb3623a51fff1a51ed460d62178a.png

- END -


看完一键三连在看转发点赞

是对文章最大的赞赏,极客重生感谢你8263bb9be4b88ba913f36746bc1b62ee.png

推荐阅读

7a8816f41b20e5cb5bf2fd3aa50ff7d3.png

定个目标|建立自己的技术知识体系


b2e88b09f8f97b5431c37f86ff437882.png

大厂后台开发基本功修炼路线和经典资料

6440de75ebd12a5fe158b59b4d37d150.png

难走的路,从不拥挤

你好,这里是极客重生,我是阿荣,大家都叫我荣哥,从华为->外企->到互联网大厂,目前是大厂资深工程师,多次获得五星员工,多年职场经验,技术扎实,专业后端开发和后台架构设计,热爱底层技术,丰富的实战经验,分享技术的本质原理,希望帮助更多人蜕变重生,拿BAT大厂offer,培养高级工程师能力,成为技术专家,实现高薪梦想,期待你的关注!点击蓝字查看我的成长之路

校招/社招/简历/面试技巧/大厂技术栈分析/后端开发进阶/优秀开源项目/直播分享/技术视野/实战高手等, 极客星球希望成为最有技术价值星球,尽最大努力为星球的同学提供面试,跳槽,技术成长帮助!详情查看->极客星球

                                                                求点赞,在看,分享三连04a93def5d0bd183a0aa85af86804523.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值