暂存

移动端 iOS 年终工作总结-纯干货请自备酒水[转]

2018-03-04  本文已影响53人  吃蘑菇De大灰狼

原文: 移动端 iOS 年终工作总结-纯干货请自备酒水

主题:发展
内容大纲

观点:

进阶:

管理:

工具:

成果:


观点

Swift 发展观

Apple 在 WWDC 2017 大会上发布 Swift 4,Swift 4 带来了更快、更容易使用的 String 实现,可以保持 Unicode 的正确性,并增加对创建、使用广告管理子串的支持,它提高了开发者创建、使用和管理集合类型的能力,它支持结构化枚举类型的归档并允许对外部格式进行类型安全的序列化,包括 JSON 和 plist。

image

既然提到了 WWDC(https://developer.apple.com/wwdc/),相信 Swift 的发展观就没有太多争议了,近几年所有的官方演示视频都是基于 Swift 来演示的,作为 iOS 的开发人员可能会继续使用 Objective-C,但是如果对 Swift 是持抗拒心理的,那无疑对自身发展是不负责任的。

Apple 于 2017 年宣布 Swift 5 后会锁定 ABI,也就标志着这门语言会正式作为 iOS、macOS 的主流语言。同年 12 月,Apple 宣布会着手计划 iOS 和 macOS 的应用层面合并。配合 Apple 一直以来的对 Swift 幼儿教育以及在 AI、AR 等领域的推进,不难看出这门语言未来的发展潜力。

ReactNative 发展观

提到 ReactNative 就不得不说 FaceBook,其实现在主流的移动端开发规范就是这家公司设计的。当然除了 React 社区生态圈的加持和 Facebook 的大力推广以外,另外一个最主要的原因就是其在开发效率和应用性能方面取得了一个比较好的平衡:

image

跨平台这一特性对于小公司的吸引力则更体现在节约用人成本上,对简单的需求能做到一端多用,随时变更线上内容。

对于已经正在运营的项目,完全切 ReactNative 总是不太现实,其实大多数厂商的方法是对运营引流有影响的关键性页面(如:首页)进行 ReactNative 改版,这里可能就会引入一个 模块化 的概念,后面会有讲到。

image

对于想要入门的朋友,慕课网上一个入门级 ReactNative 教学还不错(http://coding.imooc.com/class/89.html)


进阶

模块化

模块化、组件化我后半年一直在调研的课题,对这些的研究也给我带来了从量变到质变的提升。

什么是模块化?

那么什么是模块化呢?《 Java 应用架构设计:模块化模式与 OSGi 》一书中对它的定义是:模块化是一种处理复杂系统分解为更好的可管理模块的方式。

我们可以把软件看做是一辆汽车,开发一款软件的过程就是生产一辆汽车的过程。一辆汽车由车架、发动机、变数箱、车轮等一系列模块组成;同样,一款大型商业软件也是由各个不同的模块组成的。

汽车的这些模块是由不同的工厂生产的,一辆 BMW 的发动机可能是由位于德国的工厂生产的,它的自动变数箱可能是 Jatco(世界三大变速箱厂商之一)位于日本的工厂生产的,车轮可能是中国的工厂生产的,最后交给华晨宝马的工厂统一组装成一辆完整的汽车。这就类似于我们在软件工程领域里说的多团队并行开发,最后将各个团队开发的模块统一打包成我们可使用的 App 。

image

一款发动机、一款变数箱都不可能只应用于一个车型,比如同一款 Jatco 的 6AT 自动变速箱既可能被安装在 BMW 的车型上,也可能被安装在 Mazda 的车型上。这就如同软件开发领域里的模块重用。

到了冬天,特别是在北方我们可能需要开着车走雪路,为了安全起见往往我们会将汽车的公路胎升级为雪地胎;轮胎可以很轻易的更换,这就是我们在软件开发领域谈到的低耦合。一个模块的升级替换不会影响到其它模块,也不会受其它模块的限制;同时这也类似于我们在软件开发领域提到的可插拔。

模块化分层设计

上面的类比很清晰的说明的模块化带来的好处:

在《安居客 Android 项目架构演进》这篇文章中,作者介绍了安居客 Android 端的模块化设计方案,这里作者还是拿它来举例。但首先要对本文中的组件和模块做个区别定义:

针对模块化作者的团队也定义了一些自己的游戏规则:

自从 Oasis Feng 在去年的 MDCC2016 上分享了模块化的经验后,模块化在 Android 社区越来越多的被提起。作者自然也不落俗的去做了一些研究和探索。安居客现在面临很多问题:例如全量编译时间太长(我这台13款的 MacBook Pro 上打一次包得花十多分钟);例如新房、二手房、租房等等模块间耦合严重,不利于多团队并行开发测试;另外在17年初安居客重新将租房 App 捡起推广,单独让人来开发维护一个三年前的项目并不划算,所以作者希望能直接从现在的安居客用户端中拆分出租房模块作为一个单独的 App 发布上线。这样看来模块化似乎是一个不错的选择。

所以作者做模块化的目的大致是这样的:

关于模块化组件化的生动解读来自安居客 Android 组组长张磊的博客 http://baronzhang.com

Pods 依赖库及组件化

组件化与模块化
安居客的 Android 团队内部成立了技术小组,基础组件的开发是技术小组很重要的一部分工作;模块化更多的是现有的方案受到来自业务上的挑战以及受到了 Oasis Feng 在 MDCC 上的分享和整个大环境的启发,现在正处于设计规划和 Demo 开发的阶段。

组件化
组件化不是个新概念,通俗的讲组件化就是基于可重用的目的,将一个大的软件系统拆分成一个个独立组件。

组件化的带来的好处不言而喻:

现在的安居客有是三个业务团队:安居客用户 App、经纪人 App、集客家 App。为了避免各个业务团队重复造轮子,团队中也需要有一定的技术沉淀,因此组件化是必须的。现在我们需要提供更多的、职能单一、性能更优的组件供业务团队使用。根据业务相关性,我们将这些组件分为:基础组件和业务组件。

阿里架构组同样是组件化的先驱者,以下是阿里架构组 Evans 对组件化的观点:

首先,我的理解分块化应该是有四种,组件化+模块化+插件化+解耦

第一,组件和组件其实是没有什么鬼明确的约束 ,因为组件一般都是单独开发、单独测试,不能直接放到主项目中开发,测试也是单独针对性的测试 (里面涉及到短链+组件的生命周期+….)

第二,模块化我的理解是,怎么做好project的模块化的拆分,我们内部一直在说越底层的模块,应该越稳定,越抽象,越具有高复用度,但是其实有一个壁垒就是怎么去提升模块的复用度,怎么去快速具备复用性高于代码复用性,这我们就要做好每个模块只做好一件事情,模块化结构要更加清晰,每个模块都只做一件事情,具有良好的延展性和拓展性,但愿不要出现下层模块依赖上层模块的现象,业务模块之间也尽量不要耦合。好处是同样的功能模块,可以在多个app中复用,业务隔离了跨团队开发代码控制和版本风险都变小了。

第三,解耦其实理解很简单就是在基于模块设计原则上, 让模块之间没有循环依赖, 让业务模块之间解除依赖,不相互调用。

概况的理解就是

而组件化现在主流的做法是通过 CocoaPods 对要包装的内容进行打包,提交到公司的私有库(开源项目是公有库),进行日常维护及开发。

环境自动切换 + 自动化打包测试 + 线上质量监控

环境自动切换

image

Debug 和 Release 仅仅是编译选项的不同,那么为什么要区分 Debug 和 Release 版本呢?

Debug 和 Release,主要是针对其面向的目标不同的而进行区分的。

Debug 通常称为调试版本,通过一系列编译选项的配合,编译的结果通常包含调试信息,而且不做任何优化,为开发人员提供强大的应用程序调试能力。

而 Release 通常称为发布版本,是为用户使用的,一般客户不允许在发布版本上进行调试。所以不保存调试信息,同时,它往往进行了各种优化,以期达到代码最小和速度最优。为用户的使用提供便利。

对于一些企业版应用或者有内部测试的需求其实还可以新增 Beta 版,收集核心用户的建议或者测试新开发的功能模块,对反馈做出迅速反应,灵活控制。

由于之前引入了组件化开发模式,所有我又加入了 UnitTest(单元测试)模式,只要用于对组件的分离化测试,快速定位问题。

切换环境的同时会对应切换应用的图标,能有效避免测试环节中的环境混淆和降低辨别成本。

image

自动化打包测试

关于自动化打包就不得不说在创业公司的经历,那时开发任务重,提测前常常加班到晚上 12 点,就算 bug 修完,也要等半个小时看着 Xcode 不慌不忙的打包完成上传测试平台发邮件才能安心回家。

鉴于这种惨痛经历,利用闲暇时间就搞了个自动打包脚本,后期又整理一遍并适配 Xcode 8.2 之后的版本。 做的了三步配置,杜绝污染,一行命令自动上传。

也是鉴于 Xcode 版本升级后的苦逼适配经历,最终选择了开源的 fastlane 包,从此搭上了组织的小火车,配合 Testflight 终于可以放心的玩耍了…

image

FastLane 是一种配置 iOS 和 Android 自动化 Beta 部署和发布的最简单的方法之一。它可以简化一些乏味、单调、重复的工作,像截图、代码签名以及发布 App。也能无缝衔接蒲公英、Fir等测试平台,这酸爽…

对于 Testflight,就像没故事的卓同学所说的。

Testflight 有个较大的使用门槛,需要收集用户的邮箱,之后在 Testflight 里输入苹果发出的邀请码才能开始测试。很多用户嫌麻烦就退出了,运营认为这样会给测试带来很大的不便。但是冷静了心态后其实事情并没有那么糟糕。真正对这个产品有兴趣的用户不会因为要填个邮箱就放弃了。那些流失的只是普通的用户。用户使用了 Testflight 后,后续的测试包的发布也会收到更新。不会像企业版那样,只能手动的告诉用户我们有新的测试包。当 beta 测试活跃用户超过 100 个会有一个质变。这些都是积极的重度用户,一群重度用户使用你的新版本几天,至少可以保证核心业务逻辑是没有纰漏的。

这里推荐配合测试的 SDK 质量监控服务——Bugtags,Bugtags 可以通过悬浮窗或者摇一摇的方式进行截图,并将捕获的 bug 图片上传到测试平台,其自身也包括 Crash 的自动上传。

image

线上质量监控
Crashlytics 成立于2011年,是专门为移动应用开者发提供的保存和分析应用崩溃信息的工具。

image

Crashlytics 有配套的 macOS 应用 Fabric 用户体验值得国内 SDK 服务商学习。

image

2013 年 Twitter 对 Crashlytics 进行人才和服务的多重收购,一年后 Google 收购 Firebase,从此 Fabric 和 Firebase 这对好基友就成为了应用崩溃报告的黄金搭档。

image

管理

团队核心组成架构

关于团队的观点,我基本和没故事的卓同学看法一致,除了技术的硬指标,在早期团队还有一个工程团队文化的问题。一个几十个人的项目,里面某个特定的人的积极性对于项目其实是不太重要的。他只要完成应该完成的工作。甚至和其他人不说话也影响不大。一个大的项目也不能因为任何一个人不在了就运行不下去。

我之前思考过团队文化是什么,怎么形容团队文化。后来看到一个说法感觉挺贴切。文化是空气,无处不在。公司没有规定下班后社交平台上看到用户反馈需要你去回应,也不会规定你发现其他部门的产品有问题是不当回事还是应该去和其他部门的人沟通,又或者看到一个更好的建议是不是要和公司提出来。这些行为背后的支撑就是团队文化。在团队里的人决定了价值观。

image

技术团队做事就像古代的八抬大轿,公司业务就像轿子里的小娘子,团队文化就像抬轿子时喊的号子,团队里的每个人就像是抬轿子的车夫。抬轿子的大多数人走的快,每个人的步子齐,那轿子里的小娘子就坐得很舒服,如果哪个环节出现问题都会对坐轿子的人有影响。

所以,车夫水平要挑好,号子要响亮提气,每个人的步伐要协调,轿子就能平稳上路,可是如果想快点赶路,那可能就要尝试不同的抬轿姿势,换更响亮的号子,排练更协调步子,甚至换个更轻的轿子、换个轮子…

硬件设备投入

接着上面的“花轿”说,硬件投入的重要性就不言而喻了,别人已经换上了带轮子的马车了,当然跑的飞快。

image

拿 Swift 的编译速度讲,MacBook Air 和 MacBook Pro 的处理器芯片和内存容量决定了两种电脑的编译耗时可能相差1倍左右,而一块外接显示屏能节省的频繁操作更是以少积多。

如果把一个工程师的薪资换算成时薪,配合硬件设备浪费掉的时间,将是一笔不那么明智的开销,当然如果你的工程师每天只是喝凉水看新闻,那请配给他一个保温杯和老花镜~

例会和文档化

有哪些会?

当我打算写这个主题时,反思了下过去都参加过哪些会议,发现有时会莫名其妙的就参加了一些完全无意义的会议。下面我们先看看一般程序员都会碰到哪些会议。

需求会

这类会议一般是产品或项目经理召集,组织参与项目的程序员一起讨论需求并确定排期。这类会议容易出的问题是,程序员到了会上才第一次知道需求,并陷入到需求细节的无休止讨论中。更好的方式是提前让程序员详细了解需求,会上只需敲定排期并让互相有协作依赖的程序员之间达成一致和形成承诺。

讨论会

这类会议的场景比较广泛,比如:项目进行过程中同组程序员之间就设计或实现的讨论,或与其他组项目合作人之间的讨论等等。这类会议容易出现的问题是临时把一堆人拉到会上,然后陷入混乱的自由讨论,失去焦点。

还有一类讨论会叫头脑风暴会,也是容易把一堆人拉到会上,开动头脑风暴。如今遗憾的领悟到这是最没效率也没效果的方式。头脑风暴会需要就待解决的问题让参与人员提前准备,搜集或阅读材料,不同人从不同角度各自提出自己的观点或方案,然后到了会上将所有观点和方案列出来,再开动头脑,碰撞连接一下,看看能不能风暴出一些新的观点或方案去有效解决问题。

周例会

一般来说一个部门或小组都会每周开个例会,例会容易被当作日常的例行工作而不被重视。例会应该有固定的时间和议程,而且例会是一群经常一起工作并熟悉的人开会。虽然开例会的人都在同一个部门,但并不意味着他们都会相互合作完成同一个项目或事情。所以,例会是通过了解各自工作来完成了解整个部门或小组工作进展的机会,而不是每周固定的休闲时光。当然我们也可以在每周的例会留出一段自由讨论时间,可以畅所欲言,增加工作之外交流。

除了周例会,有些实施敏捷方法的团队也会开每日站立会,每日站立会的一般内容是:

每日站立会议的主要目的是让团队成员互相交流互通工作情况,而不是为了让经理们了解情况而召开的会议。每日站立会不是一个团队的人站一圈各自说下工作情况,因为曾经发现彼此并不关心对方工作内容的人站一圈开这个站立会,其意义何在?

分享会

部门内、公司内或行业内都会有各类不同规模分享会,想清楚你为什么要去参加一个分享会?一般来说我只有两个原因,我对分享的内容感兴趣,这应该是大部分人参会的原因。另一个,即使分享内容我已经很熟悉,那么参会的原因一般就是对分享人感兴趣,想要去通过这个分享了解分享人。

还有一种情况可能是碍于面子参加一些完全没兴趣的分享会,恩,这种还是尽量规避吧。

临时会

总会碰到这种情况,突然有个人过来叫你临时去参加个会,然后你就一脸懵逼的去了。这种会似乎属于身不由己,不好规避,这类会议多是非计划性的任务驱动型会议。英特尔前 CEO 安迪·格鲁夫说过:

在现实中,有 20% 的情况还得靠任务导向会议来解决。但如果经理人将超过 25% 的时间用在应急的任务导向会议上,这个组织就一定有了毛病。
这种类型的会议随时召开,而且会针对具体情况产生决策,若这种临时紧急的任务驱动会议太多了,那问题肯定出在平时的工作中。

总结会

可能是项目上线或产品发布后的总结会,也可能是线上故障后的经验教训总结会。我以前开过的很多总结会都变成了领导的总结会,关于这类会大家有什么好想法吗?

对于以上这些千奇百怪的会议,于是有人制作了这幅漫画:

image

其实呢,凡事都有两面性,最难把控的永远是人,作为有效的讨论活动,会议本事没有问题,精耕细作也会在一定程度上保证质量。重要的是会议的气氛、主题以及控场力。

我之前遇到一个项目领导就很有特色,由于采取封闭式敏捷开发模式,需要每天确定工作内容,调节各部门间工作进展,所以需要每天做午会,但是当时并不枯燥而且团队协作融洽,因为在例会过后有组织抽签买饮料、零食和惩罚倒霉鬼的活动,如今想来,他确实是一个优秀的组织者。

以上这些会议内容来自博客园的 mindwind,让我们同情他一刻钟~

文档化
文档化和例会一样是充满争议的举措,本质上是为了让一切有据可查,方便后期查阅和减少交接工作负担。但也不乏反对者,认为是在浪费时间,形势主义。

还是一样的道理,稳定的方法不会错,难把握的是个人。把每一个账号密码整理保存也是文档化。保持会议记录、工作聊天日志也能在必要时不接受飞来的横“锅”~

组织 CodeReview

还是引用没故事的卓同学的话,Code review 是一件神奇的事情。所有有素养的工程师都觉得 code review 好,据我们所知国外很多优秀的 IT 企业都很注重 code review,但是在国内却很少看到有团队执行 code review。或者中小团队里很少看到 code review。

作为一个 leader,在 review 的时候帮助成员成长,和只是看下代码是不是能完成功能最后会引向不同的结果。看过一句很有触动的话,现在很多 leader 知道自己的工作里需要管理其他人,但是却忽略了还需要 lead 。
老实说推进 code review 确实遇到很多阻力。有团队里的也有团队外的。团队外的看法是 code review 拖慢了项目进度。我作为一个核心的开发成员,每天超过 20% 的时间是没有可见的工作产出的。有时别人写的有问题被我打回去改,一个已经完成的功能又多花了几个小时。团队内遇到的问题是,很多成员不理解这项工作背后的价值。

同样的感触来自上面提到的那家公司,负责我们的小组组长是一名有着 6 年移动端开发经验的优秀工程师,在一套严格的代码规范要求和 code review 的锻炼下,我的成长几乎是肉眼可见的(对比回看之前的代码),他对我们的指导也是无私且专业的,以至于我现在依然在感谢着他。

CodeReview 的方式

CodeReview 的内容

image

[1]架构/设计/常规
1.单一职责原则
这是经常被违背的原则。一个类只能干一个事情,一个方法最好也只干一件事情。比较常见的违背是一个类既干UI的事情,又干逻辑的事情,这个在低质量的客户端代码里很常见
2.行为是否统一,例如:
1)缓存是否统一
2)错误处理是否统一
3)错误提示是否统一
4)弹出框是否统一
5)……
3.代码污染
代码有没有对其他模块强耦合
4.重复代码–>应该抽取
5.开闭原则
6.面向接口编程
7.健壮性
1)是否考虑线程安全
2)数据访问是否一致性
3)边界处理是否完整
4)逻辑是否健壮
5)是否有内存泄漏
6)有没有循环依赖
7)有没有野指针
8)是否检查了数组的“越界“错误
9)……
8.错误处理
9.改动是不是对代码的提升
新的改动是打补丁,让代码质量继续恶化,还是对代码质量做了修复
10.效率/性能
1)关键算法的时间复杂度多少?有没有可能有潜在的性能瓶颈
2)客户端程序对频繁消息和较大数据等耗时操作是否处理得当

[2]代码风格
1.可读性
衡量可读性的可以有很好实践的标准,就是 Reviewer 能否非常容易的理解这个代码。如果不是,那意味着代码的可读性要进行改进
2.命名
1)命名对可读性非常重要
2)是否跟系统属性命名造成冲突
3)英语用词尽量准确一点,必要时可以查字典
3.函数长度/类长度
1)函数太长的不好阅读
2)类太长了,检查是否违反的 单一职责 原则
4.注释
恰到好处的注释,不是注释越多越好
5.参数个数
不要太多,一般不要超过 3 个


工具

Gitlab 及 Git 相关规范

Gitlab
对于代码仓库开源首选 GitHub,不开源现在也有许多服务商,如:Gitee 等,如果有钱任性 GitHub 普通的团队套餐每个月每人 9 刀,但我相信大多数中小企业会选择 Gitlab。

image

还有就是服务端如果要自己配置 CI 服务不太方便。如果部署在自己的服务器上,其他一些服务脚本也部署在一起,会有很大的自主权。
综合之后选择了主流的 Gitlab。

第三方仓库都可能遇到父爱如山般的维护时期。

Git 相关规范
Git 相比 SVN 能避免大多数非人为问题,这点相信已经不需要论证了。但是那些人为的问题怎么办,那当然需要规范了。

合并的时候必须遵循以下条件:

这样的流程有什么好处呢?

每次都是在本地 merge 完清除了 conflict 之后再 push 会远端,那么别人更新本地 develop 分支,再合并的时候,就算出现 conflict 也只会是自己最新代码产生的 conflict。

Sketch 设计工具 + Zeplin 标注工具

移动端也属于前端,是做直接和用户打交道的事情,当然也包括设计狮,设计狮是一种很厉害的猫科动物,他们有着令人恐惧的像素眼和血统中的强迫症。(以上我喝多了说的,不要当真哈~)

Sketch 作为一款移动时代设计师新宠,自然有其存在的道理。


image

Zeplin 面向的用户是设计师和前端(Web、Mobile)工程师,相当于做的是中间桥梁这一块,核心功能为标注、Style Guide、备注文档与简单的团队协作。


image

成果

年终总结

Swifter 是一款基于 Swift 开发的,采用 MVVM 模式、RxSwift 函数式响应编程、组件化和 ReactNative 等技术的技术示例应用。

上一篇下一篇

猜你喜欢

热点阅读