项目接盘侠复盘总结

写作背景

19年3月入职日事清,之前大佬年前撤了去创业,经过几个月的空白期,Android终于落下的一堆需求和山一样的老旧Bug,笔者作为接盘侠,勇敢的打开了上古时代的13款MacbookPro,然后便开始和这台电脑一起开启了无尽的长征。

心态要及时调整

接盘,回首一年,最重要的是心态要稳住。你无时无刻都在经受精神上的考验,最常见的就是代码你看不懂,你没有任何交接,也没有人参与过你的项目,基本上感觉就是“举目无亲”的感觉。这仅仅是个开始,我尝试了好多办法,推荐两个觉得有效的两个方法

  • 先做一些和业务逻辑无关的需求
  • 找IOS开发,最了解项目的人询问你不懂的业务点

笔者接盘初期开始做一些UI改动,比如月视图中颜色,字体,排版,四象限选择界面改版。从UI入手减小了出大问题的概率,也不会太因为接触很大的日程模块难以理解,多次改不好而信心受挫,而且通过Layout Inspector工具也能最准确的定位功能Activity。笔者项目里就有很多没有使用的旧界面,因为“不舍得”删掉,所以从UI找到页面,比从跳转关系定位Activity要准确快速。

而针对业务,一定要找和你业务重合度最高的人去了解,但仅仅能做参考意见,比较Android和IOS实现差异还是有差异,还有另一个最直接的参考就是负责你的测试。

还有一些带崩心态的方法,建议不要尝试:
  • 从全局着手,妄想对项目有一个好的理解
  • 询问产品经具体需求
  • 期望后台(服务端)帮助梳理代码逻辑

Android端近几年技术迭代非常快,笔者日事清项目从15年开始第一次提交,所以笔者项目当中,MVC,MVP,MVVM, 组件化,模块化,kotlin都有尝试,同时因为缺少完整的项目重构,项目结构上会很混乱,而从这个全局角度来梳理项目会看到项目中“脏,乱,差”,容易想离职。

敏捷项目主导下的项目,产品经理其实给不出具体的需求,也没有具体需求文档。尤其产品经理也换过的项目,能够准确依赖的是你的代码正确逻辑和IOS的逻辑,因为你的代码可能有BUG和历史遗留问题,对所有的问题都保持怀疑态度。

服务端理解客户端开发工作有差异,服务端技术相对成熟,技术限制和债务较少。


稳住,我们能赢

初期面对项目,会有很多累积的Bug,一下子堆积到面前,而很多问题是影响线上用户的,SAAS软件,对应的是客户的压力。接盘的前两个月,事后觉得最正确的办法是做新功能,改UI问题,这些东西都是稳住当时的心态。

开放心态:

如果你无法做到开放心态,就非常容易陷入杠精和键盘侠的死循环,进而非常想逃避接盘的现实,类似鸵鸟。在面对项目中存在的问题,要接受存在的问题,也要接受别人看不到你面临的问题的窘境,独立开发也要学会向上管理,否则,争取不到时间和理解,你会时时刻刻想变成鸵鸟。这样做无益于解决问题。

在接盘过程中,经常会出现很多项目问题,笔者修复了一个BUG之后,上线之后,用户反馈所有的第三方登陆集体不能使用,这是很严重的线上事故,问题在下午被提出,然后才知晓有热更新,加班更新上去来解决问题。另一个让笔者印象深刻的是5月份上线新版编辑器,导致大量笔记数据丢失。这个案例稍后详细分析,在这个过程中,心态难免会受到冲击,因为独立开发意味着是你一个人应对所有的压力和责任,很容易产生项目接盘太难,离职找下一家是更好的选择这样的想法。
在这里插入图片描述

稳住原有逻辑和代码
  • 我们拿刚才的新旧版编辑器灰度问题来分析做法(4-11开始)。
    在这个做法之前,尝试过自己模仿原有逻辑重写新版所有相关页面,面临了一个很大的问题,“庞大”,涉及到的逻辑点很多,涉及到的文件(Class)很多,原有的逻辑高度依赖(所有页面工具直接依赖RichEditor,这也是新写的原因),工作量非常大,且非常不稳定,我不能保证重写出来的旧逻辑不会有问题,资源匮乏的情况下,我只能放弃这种冒险的方案。

(git checkout .)这个操作很容易带崩心态,不建议轻易尝试

RichEditor是一个js离线版本的编辑器,我们想对其进行改造来适应灰度方案,就要基本不改来保持原有的稳定,而我们面临的是所有对这个Class的依赖。

// 富文本载体
public class RichEditor extends WebView {
    public RichEditor setEditingListener(OnEditingListener editingListener) {
        mEditingListener = editingListener;
        return this;
    }
}
// 字体设置
class FontStyleLayout : LinearLayout {
    private val richEditor: RichEditor? = null // 直接依赖
}
// 录音
class RecordView(val context: SuperActivity, private val callback: CallBack) {
    interface CallBack {
        fun richEditor(): RichEditor // 直接依赖
        fun recordingStatus(isRecording: Boolean)
    }}
// 工具栏
class FontStyleRootLayout(private val fontView: View, val richEditor: RichEditor)

为了不改动原有逻辑,我们必须将所有依赖点抽象出来,抽象出一个旧的富文本,于是笔者尝试抽象出接口

interface IReditor : IRichEditor, IReditorCompat {
	/* 省略 */
    fun showLoading()
    fun dismissShow()
    fun focusEditor()
    fun setEditable(editable: Boolean)
    fun setDisable()
    fun generateNote(corpusId: String, date: String)
    fun setBold(checked: Boolean = true)
    fun setItalic(checked: Boolean = true)
}

interface IReditorCompat {
	/* 省略 */
    fun redo()
    fun undo()
    // 笔记联通
    fun connectDoc(params: MutableMap<String, String>)
}

interface IRichEditor {
    /* 省略 */
}

这个基本操作,只是为了保证灰度前提下的旧版本稳定,保障生产环境的稳定。在这个前提下我们也保证了我们不会对旧功能的缺失,所以我们可以大胆的去做一个新的编辑器实现。

class Reditor : WebView, IReditor, IReditorCompat {
    override fun connectDoc(params: MutableMap<String, String>) {
        jsBridge.connectDoc(params)
    }
}
步步为营,构建出新逻辑

笔者经过职业的洗礼,深刻认识到到,资源这个词的重要性,如果把自己的时间和技能作为资源,企业或者项目的基础是稳定,攘外必先安内。接过任何一个项目,无论有没有技术债务,熟悉原有的东西都是一个渐进的过成,我也见过项目不大的被新入职的人完全推到重写,一开始也确实有过这样的想法,也被鼓励。有时候这是一种冲动的表现,掰着手机头算一算企业的需求排期,自己手里的人力,时间等资源,完全重写一个项目,哪怕很小的项目,也需要很多人的参与。而且,人力成本和时间成本,项目稳定的优先级,都比代码层面的东西要高。笔者能做的就是想办法逐步构建新的逻辑。

  • 新命名一个包名(空间)做新功能或者迭代
  • 将通用逻辑归类为工具,逐步替换
  • 需求不涉及,不做重构

上面三点是笔者觉得行之有效的办法,笔者11月份做周期功能时,将所有相关代码放在了新建的com.chancecreate包下,有意识的将新作的功能隔离在一个新的范围内,做好类的访问权限。然后笔者将一些重要的扩展方法也拷贝了一份到新的目录中。将资源文件也会单独命名,如不layout目录新建了v8,做好新旧边界。

对于新需求不涉及的地方,如果不是非常影响开发效率,或者非常影响整体架构,都不建议去触碰,笔者将这些东西称为雷区。比如笔者项目历经5年,其中网络框架有okhttp3,和HTTPClient,具体请求实现有OKHTTP原生的callback,自己封装的NoRequester,也有后来兴起的Retrofit+Rx,笔者项目当中rx1和rx2是同时存在的,这种笔者称之为雷区,一旦进入,就会耗费大量的资源排雷,否则就会生产环境炸一地鸡毛。

笔者每每看着Google推出jetpack,流着哈喇子,虽然不是银弹,至少会提高开发效率和开发难度。包括AndroidX,迁移的问题,总有一些会暴露在线上。笔者也认为不能因噎废食,但吃东西需要有足够的胃口。


别浪,猥琐发育

笔者入职刚刚满一年,历经了11个版本,前一段时间被问到类似于”重复中修改哪些字段需要提示仅修改当天还是以后,日程生成规则“仍旧是一脸懵逼。难道是笔者一年都没有吃透整个项目吗?现实是残酷的,我代码的原有逻辑就是旧的(落下的需求),但使用过程中很难发觉,所以参考旧的逻辑的新逻辑也是错的。这让笔者再一次清醒不少。

打醒重构4连击

  • 别因为看不懂代码而想要重构
  • 别因为看代码不爽就想重构
  • 别因为UI改版就想重构
  • 别因为后台换接口就想重构
  • 想重构:多些BUG -> 不改BUG -> 客户顶不住 -> 客服顶不住 -> 产品顶不住 -> CTO顶不住 -> 提出重构解决。这好像是唯一一条能走通的路(笔者并没有实践,但只剩下这一条了)

心情变好仨建议

  • 多写一些梳理文档
  • 补补注释
  • 给领导多发泄一些不满(和同事其他人发泄你的难处和窘境只会迎来附和,大部分结果不是你意识到了大家都不容易,而是1+1>2,加剧心情糟糕,很亏),领导会接受你的不满(心不凉了),给你可能解决方案(咋还有点热乎呢)。
    在这里插入图片描述
    接盘的项目并不会因为一年的参与就了如指掌,这是一个有着四年年项目历史的稳定项目,中间经历了两个人的迭代,使用了两种语言,做了简单的组件化,有大量的改写的第三方库。这对我来说都很难在日常迭代中触碰他们。
    打开IDE之后的头皮发麻
    笔者曾不止一次的想要去重构项目,甚至因为重构难度过大想要重写。从刚入职干劲很足,觉得一定要做好一款稳定的好应用,到现在加入企业的视角去思考项目的价值,进而会去考虑当前时间点重构或者重写带来的收益和损失,我并不会太着急去重写。虽然这意味着开发要面临长期的痛苦。

一些收获

  • 笔者之前从未在上线项目中使用kotlin,接触到项目中的大量kotlin,也算是加快了自己的学习实践脚步,从项目当中学东西很快,上一个大佬也算是在项目当中把kotlin的新特性尝试了一个遍,当时还非常不稳定的kotlin的协程,也有使用。这对我来说,也是一笔很大的财富。
  • 之前大佬尝试将项目改造为组件化,以目前来看,无论是资源不足还是项目耦合度过高的原因,这个改造是失败的,仅仅将登陆逻辑独立出来。这也提醒了我想要组件化的心,笔者曾经将一个项目用组件化改造过,现在看来,是因为项目适合,这里不仅仅指代码层面的适合,而是产品结构,开发人员,需求耦合上面的综合适合。在创业公司中,单一产品,独立开发和耦合的需求都应该成为选用这种技术的不适合方面的考虑。不要迷信一个方案带来的利好,而忽略提出这个方案团队所面临的问题。
  • 一切技术的采用是要恰当解决当下的矛盾。比如kotlin协程要解决线程切换的开销,这是一个很好的想发,这个想法也已经存在了很久。但,思考一下,我们没有面临线程切换开销带来的卡顿,用户体验不好或资源浪费的直接体现。换而言之,我们没有矛盾。这个时候采用某种技术可能仅仅是因为流行,技术要追赶流行,否则就要被淘汰,这是技术的私利考量。
  • 你不可避免的遇到职业生涯中的黑天鹅,小程序,快应用,RN,Flutter,每一个都想要成为移动客户端开发的黑天鹅,而且已经蚕食了客户端的市场。

客户端的红海

距离12年移动端兴起,16年移动端高峰,到18年小程序冲击,如今到了2020年,已经没有太多新的项目给我们去开启,走完一套新的流程,采用当下最流行最适合的方式。从Google官网的jetpack的推广难度和Flutter的采用,我们不难看到,客户端的红海,可能不至于夕阳红,但笔者确实感觉到了没有人在造新船了。我们不可避免的接手别人的项目,或者别人接手我们的项目。认清现实会带给自己一颗平常心。

总结

如果你真的做的不开心,尝试了很多办法仍旧感受到了巨大的压抑,和理想差别很大,建议跳槽。
如果你经历了几次跳槽发现仍旧接盘且不开心,建议转行(小程序,人工智能,区块链)新产业,能感受到程序员改变世界
如果以上两点都不行,建议自己创业。

已标记关键词 清除标记
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质? 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹?   那么C++就是你个人能力提升,职业之路进阶的不二之选。 【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署; 2.吊打一切关于C++的笔试面试题; 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块 基础篇 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 进阶篇 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 提升篇: 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页