2014年12月12日

小结(一)


渡过了工作以来最繁忙的一段时间,忙过之后留下一些感想,记录于此。

shared_ptr


记得在看陈硕的书时,大神提到

内存方面的问题在C++里很容易解决,我第一次也是最后一次见到别人的代码里的内存泄漏时在2004年实习那会儿,我自己写的C++程序从来没有出现过内存方面的问题。 –源自《Linux多线程服务端变成–使用muduo C++网络库 》P14

之所以C++在内存管理方面如此优秀,我理解的是,正是RAII思想,基于智能指针的使用。以前刚接触C++时,与人讨论到C++的优劣,往往大家都会说道C++程序容易内存泄漏,内存的管理很麻烦,不像Java没有负担。其实,深入的看Effective C++ 和陈硕的书之后,就会明白,所谓的内存申请和释放在C++里是很轻松的事。RAII(Resource Acquisition Is Initialization),即获取到资源就初始化,将我们申请的资源由其他的对象代为管理。资源的有效性就与对象的生命周期结合在一块了,而对象的生命周期由C++语言层面保证。即栈上的对象过了作用域必须会调用析构函数,因此会释放申请的资源。而基于智能指针的方式来管理资源的申请,除了可以解放对资源操着的心之外,还有一个重要的作用即资源的引用计数。资源的引用计数大于等于1时,并可保证资源不会被释放,这对于跨线程或者需要资源共享的情况下来说,极其方便。

有了智能指针,不难理解陈硕大神的意思。最近遇到的一个大坑,更强调了需要使用智能指针来管理对象了。坑是这样的,在一块较短的代码里,new了一块内存,然后对这块内存操作,操作完了delete,然而操作会在某种情况下抛出异常,然后会往复的执行这块代码直到成功。以往都没任何问题,但最近由于各种原因,就突然触发了异常的抛出,结果每次泄漏一点点内存,没多久内存泄漏就好几G了。如果采用智能指针管理,抛出异常之后,栈上的对象还是会正常的析构,释放内存,不会受异常的影响而导致泄漏。

关于智能指针的使用,强烈推荐参考陈硕大神的线程安全的对象生命期管理,看完之后绝对爽个爆。

想起在Python里,使用With语法,contextmanager module,我们可以方便管理资源。譬如从连接池获取连接之后,不用在意连接的返回,在open file之后,不用在意文件描述符的close。这些资源的释放操作都封装到with 语法里了。整个代码更加简洁,清晰有力。

解耦合


深刻感觉到如果系统复杂点,维护的状态很多,那么将系统内的各个模块进行解耦合就十分必要了。模块可能细小到某个函数,这个函数的作用一定要是十分清晰,最好如函数名所示。不要做意料之外的事情,因为做了其他事情(譬如顺便改变某个状态值),很可能会被遗忘,然后就是测试场景下的各种修修补补。在Effective C++的18条中,强调了要让接口易于正确使用,而不易被误用。分布式系统的设计强调design for failure,其实线上的系统也往往强调考虑各种failure的情况,如果很好的解耦合了,对于各种failure的情况处理起来也会简化,不至于一个failure导致系统维护的状态紊乱。

我们的系统需要经常去操作底层的分布式文件系统,而某一个操作,open, delete,rename等等都是会抛出异常的,健壮的代码肯定是需要捕捉这些异常,然而每个操作都基于一定的上下文,因此任何一步的异常抛出都需要考虑都上下文的影响,如果好的封装,解耦,处理这种异常就会得心应手。

PE


前端产品 不仅强调功能,还十分非常特别的强调用户体验,任何损害用户体验的设计往往会被骂成翔,每个人都深有感触。而对于后台系统来说,打交道的用户群体极其有限且固定, 除了自己,接触最多的就是测试和PE,同样需要兼顾他们的体验,与人方便才是与己方便。对于测试来说,希望的是能够方便的测试,包括自动化测试和手工的测试,自动化的测试用例往往基于系统的接口,手工的测试用例会基于系统的日志信息等,前者希望能够好的client探测系统状态,后者希望有详尽的日志能跟踪到系统内部状态的变化流程。对于PE来说,线上系统的大部分操作都由他们执行,因此希望的是每次变更都能对他们产生最小影响,即不需要做过多的要求,要求多了,容易错误。还要考虑到系统出错之后,如何方便的查看系统的状态以及迅速的恢复。

其实不管是前端还是后台,都是强调面向用户群体的体验,不仅仅是功能的实现。

结中结


团队里往往会存在一个牛逼的人物,这个人物的存在会让你感受到不管出现什么问题,最后他都能搞定,同时还凝聚着大家。当然,这不是说遇到事情,我们不需要尽力了,而是在你走这条路时,至少需要向他看齐。任重道远,上下求索。

最近的繁忙打断了之前的学习,后面希望补回来。

前一篇: 异步dns解析 后一篇: Python C++绑定