Android工程师的自我提升

to be senior

Posted by 宸笙 on July 1, 2018

起因

前些天和rengwuxian大佬聊起Android的进阶等话题,后续主席说要不写篇文章吧,于是便有了这篇小结。

正文

最近两三年的Android行情很多人也许渐有耳闻,行情好像不那么好了,门槛高了,人多了,岗位少了,不好找了,其中不乏很多转后端或炙手可热的大前端,人工智能等等,笔者的理解是,或许前些年的移动互联网或许太火热了,现在渐趋理性,2015年开始有了某厂缩招等信号,2016年很多创业公司相继倒下,不管是薪资还是岗位确实收缩了很多,不过笔者的观点一直是中高阶工程师还是不愁工作的,或者说在这样的大环境下,还不如调整心态提升自我成为中高级工程师。

高级工程师?

其实不同公司对高工的定义不尽相同,也有一些见仁见智的考量,先看下某厂的一个jd:

基础能力:

  1. 计算机、通讯、数学等相关专业本科以上学历;
  2. 熟练掌握java,精通android sdk,3年以上android开发经验,熟悉android系统版本差异;
  3. 良好的数据结构和算法基础;
  4. 熟悉uml,熟悉常用的设计模式,有设计或者重构实施经验;
  5. 熟悉http/https协议,有网络编程经验;
  6. 熟悉常用的三方库及其特点。

附加能力:

  1. 熟悉并发编程,有稳定性、流畅度、包size、内存等性能优化经验者优先;
  2. 熟悉classloader,有动态加载和插件化开发经验者优先;
  3. 熟悉渲染机制和动画原理,有阅读android源码经验者优先;
  4. 熟悉tcp/ip协议,有网络性能优化经验者优先。

不同的职位细分可能稍有差异,比如做SDK和做App的,个人看法如下:

  1. 对java和Android的熟悉程度决定了你的专业程度;
  2. 工作年限取自经验值,一些来自经验和实践的能力需要时间积累;
  3. 数据结构与算法是基础能力,技术往上进阶的必要条件;
  4. 高阶程序员必须学习的设计和重构能力,需要熟悉设计模式并在项目中较好的实践,重构能力不言而喻,怎么读懂历史代码并在保证不影响的前提下进行迭代重构,这方面的学习没有太多的对错,容易进入误区个人推荐的方式是 Refactoring to Patterns(后文会阐述)。
  5. 了解常用三方库的实现有助于你更好的理解这些库的设计思路,大厂也有机会让你造轮子,阅读优秀三方库的源码,直接的好处是能更好的驾驭它们,如果自己实现一个也能较好借鉴,这其中除了代码细节还有抽象的设计能力;
  6. Http,tcp,内存,包size?App做性能优化,网络流量优化,卡顿优化等需要;
  7. 插件化和热修复,大厂都有较好探索和落地实现;
  8. 一些性能问题需要对系统的坑和特性的深度了解,阅读Android系统源码就有必要了,所以你常看到jd里面有有通过阅读源码定位并解决问题的能力也是不无道理的,其实这里基本涉及到的是复杂性思考和解决问题的能力,阅读复杂代码的能力,当然,你可以从三方库的源码中开始也是可以的;

虽然不同公司对高工的界定有很多差异,这里需要合理看淡大厂的一些标准,不吹不黑,大厂需要解决很多技术瓶颈和性能问题,所以需要更深的基础和能力,谈及很多说到大厂面试造航母的情况,不过很多大厂也有人力探索自研的一些框架;小公司可能偏向于全能的候选人,承担的项目更多,能扛各个端的问题;

高级工程师用户画像

根据笔者所见到的一些高阶开发者和自我反思,觉得一个较好的Android工程师应该具有以下特点:

  1. 专业的Java和Android功底,具备相当的领域内经验;

    不赘述,必须;

  2. 优秀的思考,定位和解决问题的能力;

    很多人容易忽视思考的过程,某厂面试官问笔者的比较注重一些操作系统的细节和思路,最终自己也如愿通过了面试;而在一些更高级别(如P7)的jd中也不难发现一些如”是团队内的问题终结者”等描述;

  3. 较好的模块设计能力,编写通用组件库的能力,项目架构能力;

    封装公用组件库或基础性的SDK给不同App组使用,甚至是互联网上的诸多开发者,再往上能从模块设计到项目的整体架构的思考(有一定的架构意识);

  4. 用技术(不限于Android)去改善业务效率的敏感度;

    对业务中的变化能有一定的预判并在预留接口,封装变化,也能用技术去提高效率;

  5. 较好的代码品位,对编码有追求,重构能力;

    设计和重构能力应该是程序员的立身之本和持续需要精进的能力;

  6. 技术之外的能力:激情,沟通,负责和技术担当;
  7. 技术分享 or 指导新手;

    总结并分享技术对自己也是一种提升,参考德雷福斯模型,成为一个工作的胜任者之后便是培养胜任者的胜任者了,学习的最高层次是去教(会)别人;

  8. 对较新技术有一定的尝试并预判,自我驱动能力和自我纠错能力;

    一些层次较高的能结合经验加技术预判避免踩坑,对新技术心里有底,自我驱动能力在于在该阶段更多的需要自我驱动进步与成长,产出更多对团队有利的,自我纠错是避免初中级工程师容易出现的钻牛角尖,也是需要预判能力;

  9. 较好的技术视野;

    有了较好的技术功底之后,在解决一些技术痛点思路开阔会很有帮助,比如实现一个无埋点的低侵入性的统计或数据上报SDK,有用对View做代理实现的,有用AspectJ实现的,这些既需要对源码细节的反复走读也需要开阔的思路并落地实现。

  10. 靠谱。

    能力各方面都靠谱,老大才放心把任务交给你,这点在创业公司特别明显,比如当你成为一个SDK负责人的时候,出了问题全部找你,你有较大的修改和重构的自由度,不过也要全权负责,不仅对稳定性负责,还有可扩展等;

下面说说关于Android工程师自我成长的点:

程序员的自我修养

基础

计算机的基础知识,不赘述。

内功

长期目标,没有太多可定性的标准,只有更深。

  1. 宏观

    代码功底,对代码有洁癖,能写出可读性和扩展性俱佳的代码,对面向对象和代码模式有较好的理解和把握,从基础的写好代码到模块间的低耦合设计,慢慢提升的抽象和思考能力。

    对编码风格和编程范式的掌握,优秀的程序员应该应该多学习其他语言和不同的编程风格,比如从命令式到函数式,习惯函数式的思考方式的转变,比如司空见惯的RxJava,你能否从简单的观察者扩展到响应式的写法,在其他语言的实现如RxJs等,比如笔者之前在看一份国外源码时,俨然就是Java版本的Promise实现,再用RxJava的Api简单封装一个RxBus等;谈到事件总线,你可以思考为何在客户端出现的较多,本质上也是加了一个中间层实现解耦并统一处理,结合具体需求就有了事件调度模型等,其他平台也有类似EventEmitter的实现;这个过程中你会更好的驾驭和把握代码,语言的切换对你来说几乎没太多障碍和隔阂,慢慢的语言理解背后的意图和思路,同时也能写出更地道的代码,其实很多时候是对语言机制的不理解导致写的烂代码,比如在一些语言中的钩子函数(类似生命周期方法)中会在不同的时机调用,就不用大费周章另写;

    MV* 等你也可以发现这些在前端领域也是由来已久的;

    快速切换到其他语言或平台,你会发现具名函数,可变参数,解构,闭包,部分应用函数,curry化,尾递归优化,lambda等都能在其他环境中出现,就比如说闭包,在我们习以为常的用groovy写的gradle脚本就是用的淋漓尽致,如果懂了闭包的本意,你也能联想到Java中的内部类了,其实学习的这个过程也是为了后面的快速学习和迁移能力;

  2. 细节

    对代码的细节和内在机制有一定的了解,比如一些语法糖在编译之后的表现,类型擦除和反射等的细节,再下面就是一些JVM的细节,比如方法的调用过程是怎样的,形参到实参的赋值,函数调用栈是否真有(虽然得益于Java的封装,我们不用懂这些也能写代码,C++等基本都重视内存布局),而尝试在编译器的角度去思考也能推导出一些语法规则而不用靠记忆;

招式

Android或相关的客户端技能,短期内可提高也较好反馈;

设计模式

  1. 必要性;

    不想争论一些关于”模式荼毒”的言论,至少在Java语言上是很有学习的必要的,不管是看开源代码还是日常沟通都能省力很多;

  2. 避免拿着锤子找钉子;
  3. 学习它,也忘了它;
  4. 怎么学(Refactoring to Patterns)?

    设计原则比具体的模式重要;

    注重模式的推导过程,其实很多常用的模式也很好理解并实现,这里可以看下Decorator模式的简单推导(借鉴Java的IO),也可以和Bridge模式比较是怎样从编译时依赖推迟到运行时依赖从而解决子类数量膨胀的,其实很多模式到后面基本都是继承转组合(想想组合优于继承的原则),而号称最难的Visitor模式也可以简单体会下是在结构稳定的前提下怎样动态扩展的,不过这些除非在较大的软件系统中才会用的比较多;

    理解和推导不难,在日常中识别变化并用模式去恰当封装就比较难了,需要时间积累和自我的嗅觉;

    混合使用;

  5. 目的是为写出更优秀的代码和从容应对需求变化,而非炫技(其他技术也是);

    不多说,本来目的是为了写出结构更优的代码,如果一些现代语言本身就内置了一些很优秀的功能或者需求本来就很稳定,此时用模式岂不是多余了;

其他通用技能

  1. Debug能力

    很多时候我们都是接受现有的项目开发,如果没有文档,代码可读性一般那如何调试,包括读代码的能力,很多时候是入了行硬着头皮学才慢慢提升的;

  2. 抽象和思考能力

    learn how to learn,think how to think

读源码的能力

  1. 读系统源码

    有必要读;

    抓主干忽略细枝末节避免”只见树木不见森林”;

    反复看会有收获,能理解系统的一些机制并解决实际问题,比如从Handler到HandlerThread,IntentService再到AsyncTask的过程,理解主线程的消息循环,没必要刚开始力求看懂;对于主线程的消息循环机制,基于事件驱动的客户端系统基本是用类似的机制,js和ios对应有EventLoop和RunLoop有异曲同工之妙;带着一个问题比如Activity声明周期方法是如何被回调的,View的事件分发等阅读源码;

  2. 读开源三方库源码

    很有必要读;

    其实很多时候程序员说的自我提升多半是想提升但是项目不够复杂,换句话说,在复杂的项目中才有复杂的问题,或者说可以借鉴别人是怎么解决的,身边没牛人就从开源世界中找,看下那些优秀三方库的作者是怎么构思代码的,拆解这些轮子,从提供的Api跟进源码并走完流程,其中肯定一些复杂的细节和包装;

    读源码时注意几点:

    (1) 解决了什么问题(很多时候带着问题去读源码比较高效);
    (2) 明确输入输出;
    (3) 对内是怎么封装复杂并做转化的;
    (4) 对外是怎样提供好用的Api的;
    (5) 整体思考如何实现解耦和可扩展的,并借鉴到项目中;

    感兴趣,可以自己写一个简单版本,比如简单实现一个IOC库,注入布局,View等,简单实现一个EventBus,体验下造轮子的过程和三方库代码背后的意图和设计思路;

    读后你会发现其实很多都是玩转反射,注解,泛型,编译时生成代码等操作,很多库都会有自由度(Api使用)和性能的取舍,所以很多都从运行时的反射转为了编译时的生成代码(javapoet); 其中还有很多设计上的巧妙,比如Retrofit是如何用Interface再用动态代理转化的,OKHttp是如何把网络请求过程抽象为链并支持开发者扩展的,经典的Volley是怎么封装网络细节只需开发者知道请求队列和错误回调即可使用并自己完成线程切换的,怎么巧用Handler实现卡顿检查的,这些都需要经验积累和扎实的功底;

技术之外的其他素质

  1. 沟通,性格,心态等软素质;
  2. 写文档的能力;

    规范化的文档在排bug和沟通协作事半功倍

    如果你是一个SDK开发者,那更加需要写好文档,比如SDK快速入门文档,SDK最佳实践,在技术支持的工单对接中,清晰阐述问题和解决方案也是一项必须的能力,尽管很多工程师不以为然。

  3. 读英文文档的能力;

    在读系统源码或国外官网文档时很有帮助,很多时候,翻译者一个是水平有限一个是个加了主观的理解(好在技术类的翻译不会去接太多),不过直接读一手文档还是最有利的,当然前提是要看懂。

读书

看书能系统并快速的学习一些技术,这里分几类 (下列的书都很不错):

  1. 基础类

    《Java核心技术》

  2. 技术实战类

    《Spring实战》,《Android疯狂讲义》

  3. 领域内进阶提升类

    《Android开发艺术探索》,《Android设计模式源码解析》

  4. 最佳实践类

    Effective系列

  5. 重构和代码设计类

    《重构–改善既有代码的设计》,《设计模式》,《敏捷软件开发》

  6. 经典书系

    《代码大全》,《Unix编程艺术》,《程序员修炼之道–从小工到专家》

从1到6,级别逐步提高,对个人的帮助由外到内,越到后面越是一些费脑的和持续反复学习的,从入门到入行再到进阶再到最佳实践,辅之重构和设计技能,估计也数载过去了;

毕业到现在看了很多书,虽然看到很多失望的( 衡量标准:看一两回即觉味同嚼蜡的,如从入门到精通系列或者有些是部分章节有明显拖沓冗余之嫌),不过还是觉得能吸收到就算有收获,也开阔了很多思路,不局限于Java或Android。

心态

这个确实是逃不开的话题,也是必须正视的,很多问题也确实是心理问题。

  1. title

    正确对待title,很多时候title只是暂时设定的标的,衡量自己努力之后的结果而已,其实特别是在小公司,有的title比较虚,还不如自我提升来的实在。

  2. salary

    这个目前笔者也没有太多经验,很多时候能力和salary不一定成正相关,只能说如果偏离正常值和自身能力值太远会影响自我评价。

  3. 快与慢

    相信很多从业者都想快速成为高级工程师或以上,但是很多时候基础没打牢固会很尴尬,加上冒进的心态,其实浪费的时间越多, 个人比较倾向于稳步提升,很多时候也许只是时间问题;

  4. 浮躁

    当你的朋友圈有一些P6/7/8的大佬,或者一些来自同侪的压力,会不会影响你学习的心态,变得功利化;当年龄渐长很多结婚买房的话题随之而来,当初的沉下心提升技术变成了空谈;

  5. 技术焦虑

    Android是否快Over了,是不是太饱和了,要不要去下一个风口平台?

  6. 常想一二

    能改变的自有自己,调整心态

    自知的重要性,随着工作年限增加,我们会越来越了解自己,不会像刚毕业的时候虽激情满满但也常不知深浅,知道自己性格和能力,知道自己能做到的和力有不逮的,也能更加踏实合理地给自己设定一个大约够得着的阶段目标;

蓦然廿四,愿我辈都能提升,功不唐捐,就此搁笔,加油。