浅聊下对app开发成长有益的一些技能

做个app开发, 表面工作好像就是画画UI. 但实际上涉及到各种点也不少, 而且很多还蛮复杂的. 以一个Android开发为例, 是否专精Android就够了呢? 我个人感觉不是的, 多学点其它方面的东西对自己的职业生涯是有益的, 而且也能反补回Android的开发上来. 那计算机行业各种各样的知识, 哪些才能对app dev们有益, 或者说有更大益处的呢? 本文就是想抛砖引玉, 也希望能帮助到一些初级中级的开发们.

p.s. 其实也是公司招了新人, 我正在手把手教人呢, 于是有感而发写了本文.

强烈推荐的技能

1. git

在版本管理上, 我使用过最初的CVS(好慢), SVN(单分支), Git.

可能现在应该是Git为主流了吧, 已经好多年没见过SVN了, 更不用提最早的CVS了. 而git自己也并不是简单的git commit, git push这么简单啦. 下面就挑几个有用的方面, 希望对还不知道的同学有益处.

1.1 git stash

当你正在做一个feature, 结果来了个紧急bug, 只好丢弃手上的工作(feat分支), 转开另一个fix分支来解决bug. 这时feat分支上已经有的工作怎么办?

我以前不会git stash时, 用的办法就是clone三个我们的代码库. 这样一个库做一个分支. 基本上就够用了. 碰到上面的情况, 我不用切分支, 用Android Studio打开另一个仓库就行了.

当然, 要是你的Mac硬盘不这么够, 如只有256GB, 可能对于一些大仓库(如几个, 甚至十几个G),这种方法就不太适合了

这时你可以用git stash来存储你的工作. 等解决完了bug, 再切回feat分支, 用git stash pop来取出刚刚存储的工作.

kotlin 复制代码
git stash  //把本地的修改保存起来, 再把分支变成最初的状态 
git stash save -m "save message" //进阶版的保存, 加上自己的注解来标识这次的保存是个什么东东

git stash list //查看有多少个保存的快照
/* 结果类似这样的: 
stash {0} branch_name1 "save message1"
stash {1} branch_name2 "save message2"
stash {2} branch_name3 "save message3"
*/

git stash pop // 取出第一个快照, 即 stash {0},  并恢复到IDE里
git stash apply 2 // 取出index = 2的快照,  即stash {2}, 并恢复到IDE里

1.2 git amend与force push

若是想多次提交, 但只有一次提交记录, 那就可以用ammend的commit

若是git amend过一次, 并push到远端了. 这时再push就会出问题. 这时就需要: git push -f, 表示是force push

1.3 解决冲突

刚开始从事开发工作时, 我更习惯于在IDE中操作Git. 但当有了冲突, 并且自己解决了冲突后, 我却总是苦于在IDE中找不到一个"conflict resolved"的按钮.

其实这时你只要git add这个文件, 即把这个冲突文件重新加入到git里, 就算向git表示, 这个文件的冲突已经得到解决了. 后续你就可以提交与push了.

1.4. git hook

git hook就相当于git提交器. 一些常用的使用场景有:

  • 每次push, 都要求先通过了所有单元测试, 才能提交. 这时写一个hook, 强制push前走单元测试就行了
  • 或者是每次push, 要求走lint来检查代码
  • ...

这个技术上不是问题. 不过我实践操作过, 发现这样让push变得慢多了, 开发人员Push个代码还要等好久, 有点难受.

所以我目前就没有加任何git hook到我们工程里. 要单元测试之类的就在远端CI/CD上做, 不在本地做, 就不影响开发的时间了.

1.5 git分支策略

我见过最多的两种策略就是:

1).

  • main代表上一次release的稳定代码.
  • 这时要是想新开一个release, 就从main上开一个release分支. 以后的feature, bug ifx全从release分支上来
  • 等release完了, 再把release分支合到main上

2).

  • main代表最新代码
  • 等到一个release快完成时, 再新开一个release分支, main则进入到下一个release版本了.

这两种策略都行, 我个人更倾向于第二种方式. 因为我对于"长期独立于main分支之外的工作分支(或release分支, 或是epic分支, ...), 都有种不放心. 因为以后要是合起main分支, 可能就要去解决很多很多问题. 所以我更倾向方案2, 即只有短期游离在main分支之外的release分支 (是在快发版了时才创建的分支, 发版了就合并到main上来了).

p.s. 对于Android开发, 可能没什么太大感觉. 但对于iOS开发, 每个开发的新加或删除文件都会触动project.pbxproj文件的修改, 这样大家再合起来时就很容易有冲突. 当年我在开发RN时, 就吃过这方面不少的苦头

总之, 就是要尽量让所有非main分支的分支, 生命短一些, 免得最后合并时一堆冲突.

2. 一门外语, 如英语

这个基本上所有开发都是初高中就学过英语了. 但对于英语的掌握可能有多有少. 我个人感觉还是有必要学习门外语的.

一个是外国好多书籍, 等引入版权, 再等翻译, 排版, 印刷, ... 可能要花一两年才能看到中文. 若是你英语可以, 你可以直接看国外的英文技术书籍, 不能等翻译了, 相当于你又可以看中文书, 又可以看英语书, 学习知识的渠道就变多了.

二是github上, 和别人交流, 如提交pull request, 可能就得用英语.

三是很多文档, 可能就是英文的. 比如最新的iOS, android, kotlin, swift等文档都还是英文的. 你为了了解, 也不得不学英文.

上面是书面英语. 要是你想在口语或听力上有所进展, 方便你以后出国工作或是和国外同事交流, 你可以分两步来:

1). 工作英语 : 多从技术书籍, 技术博客上上学习如何描述一种技术上的行为

2). 生活英语 : 你可以多听听六人行的音频之类, 很生活化, 又不是很难. 我以前学习英语时, 把六人行的音频当成音乐一样, 来回播了几十次, 对于外国人的生活化用语, 语气腔调, 个别俚语慢慢熟练了.

= = = = = = = = = = = = = = = =

当然, 你要是主要做对日软件外包, 像大连等地方就不少对日的软件开发, 可能就要学点日语.

或者你对Ruby感兴趣, 很多Ruby书籍以日语为多, 你也可以学点日语.

总之, 就是学门外语, 多一些吸收知识的渠道.

3. 后台技术

现在少有app不联网了, 这就造成了: 我们app开发, 其实学一点点后台知识, 也有益于我们的日常app开发工作.

后台技术的选择

看你的喜好啦,

  • 若是你懂JS, 那可以用Node.js与Express
  • 若是你懂Python, 那Django可能适合你
  • 若你懂Kotlin, 那Ktor也行
  • 若你喜欢Ruby, Rails也行,
  • .... ....

我个人做过React Native, 因此学过JavaScript与TypeScript, 所以我更喜欢用Node.js与Express. 而且Node.js的相关资料较多, 有问题时很方便查阅

好处1: 提前给出假数据

若需求出来了, 但后台的开发工作要几天后才能完成. 在这时, 你就可以用自己的后台技术, 提前搞出一个自己小型服务器, 让自己和app开发团队的其它同学来访问它, 先得到假数据, 从而能不delay移动端的开发工作.

一个小技巧就是, 你不用自己去写response返回什么样的json数据, 你完全可以放一个json文件放到后台工程里, 这样返回时就直接访问这个静态文件就行了. 以Node.js为例, 那就是:

js 复制代码
const express = require("express");
const app = express();

app.use(express.static("../public"));
// 这会把public目录中的所有文件当成静态文件, 可以直接被mobile端访问到. 

好处2: 验证一些技术点

比如后台tech lead和你说, 他们的新接口可能会返回个304给你, 让你看着etag来决定访问的结果. 这时你可能就不知道HttpClient, HttpUrlConnection, 或是OkHttp这些mobile端的网络工具会如何处理etag, 要你自己去存储上一次后台接口的数据吗? 要自己存储每次的etag吗? offline时也能得到数据吗?

为了验证你的这些疑问, 你可以自己写一个后台, 来看下OkHttp如何处理这些工作:

js 复制代码
app.get("/data", (req, resp) => {
  app.set("etag", true);
  const requestVersion = req.headers["if-none-match"];
  const eTag = "W/20220307";
  resp.setHeader("ETag", eTag);
  
  if (eTag === requestVersion) {
    console.log(`/data 命中etag`);
    resp.statusCode = 304;
    resp.end();
  } else {
    console.log(`/data 无匹配, 返回新数据`);
    resp.json({ id: 34, name: "banana", price: 0.5 });
  }

});

好处3: 能够人为制造延时

若是你想测试一下skeleton的shimmer效果, 或是loading的动画是否正常, 但正常访问后台, 得到数据太快了, 看不到效果. 这时怎么办?

或是你想测试mobile端的请求timeout是否有效, 你就需要后台接口迟迟不给你响应.

正常的公司后台很难满足你的这种需求. 这时你就可以用自己的后台, 来模拟这种情况

js 复制代码
app.get("/data", async function(req, resp) {
    const result = generateRandomWord(count);
    // 做到了延时的效果, 这样来模拟网络较慢的情形, 或是想看loading动画时
    await waitMs(3000);
    console.log(`response returns`)
    resp.json(result);  
});


const waitMs = (n) => new Promise((resolve) => setTimeout(resolve, n));

好处4: 能人为出现错误

同理, 除了自己的后台能很方便地给出延时, 你自己的后台也能很方便地给出error. 这样你就可以测试你代码中的关于出错时的edge case了.

总结

从上面几种场景来看, 学习一门后台技术, 真真很有必要. 特别是你越进阶, 跟后台的协作就越多, 这时你的一些提前研究, 自主的, 不依赖于后台的自己的服务器就能帮到你很多次.

3. 写脚本

脚本就是一些简单的自动化工具, 比如说每天几点上传build包到仓库里, 每次提交要求检查Lint, 自动把kotlin-android-extension的写法转成ViewBinding的写法(kotlin 1.8已经没有了KAE了), .....

这种工具能大大解放人力, 也就提高了开发的效率, 是很有必要的存在. 那使用什么来写脚本呢?

java写起来还蛮累的, 一个简单的hello world都要包到一个类里. 所以不在考虑范围之内. 其它的, 如Python, Ruby, Groovy都可以用来写脚本. 甚至我在github上还看过Jake Wharton以前就用kotlin写过脚本, 比如说这个diffuse.

这些语言的特点就是能直接用, 不用包到一个类里去. 所以使用起来很方便.

我个人极其喜欢ruby, 以及跟ruby很像的Groovy. 特别是Groovy, 天生兼容java, 同时处理起xml与json时又很方便. 所以我的大多数脚本都是用的Groovy.

总结: 这一小节就是讲要学一门易上手的新的编程语言, 主要就是用来写各种脚本.

推荐的技能

4 数据库与SQL

若是你时间有限, 暂时也不接触数据库, 那这里可以放一放.

若你的app里大量使用了数据库, 那SQL这块最好深入了解一下. 不然你连出现了一些数据库错误, 都不知道什么意思.

这里的知识包括但不限于:

  • SQL的查询, SQL的修改现有表结构, SQL架构多个表(外键, 主键, ...)
  • SQLite独有的知识 (手机端多是使用内置的小巧Sqlite. 这时你就要知道一些Sqlite的知识, 如Sqlite的表只支持rename table与 add column的alter table操作; 要是你想删除一列, SQlite就做不到)
  • ROOM这个三方库的知识. 即如何使用面向对象的方式来操作数据库.

好在SQLite比较小, 你完全可以下载一下SQlite下来, 然后在命令行里创建一个DB, 然后就用SQL语言来练手.

备注: 查看SQLite数据库的一个工具是

5 CI, CD

CI, CD全称就是continuous integration , 以及continuous deployment, 也就是持续集成, 持续部署.

好吧, 说人话就是"这个服务器会自己打包, 会自己发包到某一平台(如Firebase App distribution)"

这样一个智能化的工具, 其实就是一个后台服务器, 它一般会监听你的提交, 然后有提交了时, 就会触发整个app的build, 最后把打出来的apk, ipa, dmg, exe...文件发到一个平台上, 供QA拿来测试.

上面说的只是基本功能. 你完全可以定制自己的额外功能, 如:

  • 一有提交, 就build, 并且远端运行Lint与unit test
  • 一有错误, 就发邮件通知我们
  • 特定git分支上(如ready-release分支), 一有提交就会自动提交到AppStore或是PlayStore上, 创建一次发布
  • 普通分支上, build成功就发布到Firebase App Distribution上, 供QA与PO来测试.

CI/CD的最主要作用就是做到总在build, 即敏捷开发中提倡的, 有问题就早早发现, 不要等release时了才发现.

相关的CI/CD工具不少的. 像我们公司在用的CircleCI, 以及Github上的Github Action. 它们的配置文件一般都是yaml文件.

这些服务一般是一开始不收费的, 只有运行时间超过一定量了, 才会开始向你收费. 所以作为个人开发, 你完全可以自己去挑一个CI/CD服务器, 写一点CI/CD的配置文件出来, 练练手, 只要不太过量, 就不会向你收费的.

6 跨平台的开发

6.1 为什么学一门跨平台开发有用呢?

: 这其实是从长期的职业规划上来讲的. 因为我发现好多高层boss, 特别是非技术的boss, 一听到"跨平台"三个字就颅内高潮, 以为"跨平台 = 低成本", "跨平台 = 一次编写多处运行", 以及""跨平台 = 更少开发人员/成本". 于是在很多公司都开始推荐跨平台了.

也就是说, 我们app开发多学一门跨平台技术, 也算是有一条后路.

6.2 是否native开发就会灭亡?

这个问题我很早就考虑过, 我个人的感觉是"native开会仍是刚需, 是不会消亡的".

原因有多个 1). 跨平台并不意味着你不需要native知识. 像我做React Native时, 我就经常要去Android与iOS端做一些原生的工作, 做完后把结果发给React Native端. 所以严格来说, 做跨平台工作, 其实是对native开发的要求更高了, 要求你对Android, iOS, 甚至是web端都要熟练.

2). 移动端的版本更新很快, 几乎Android与iOS是一年一个大版本, 每个版本都有些新功能或新的限制. 而跨平台明显跟不上这样的节奏的. 以Android 6来说, Android 6当年引入了运行时请求权限, 这个东东, React Native就不能支持. 这时, 要么你自己去Android平台写请求的代码, 要么就让targetSDK不更新, 这样拖个一年半载, 让RN去解决这个问题 (当然, RN可能不会解决, 最终还是要靠你自己)

3). 目前主流的诸多跨平台技术, 全是跨平台UI框架. 跟UI无关的工作, 如Location request, permision grant, ... 这些全得下沉到native平台去做.

综上所述, 跨平台是不会取代native的, 而且native仍是很重要的.

6.3 跨平台的选择

现在的跨平台开发越来越成熟了. 我以前写React Native时写得欲仙欲死, 恨不得马上离职, RN的编写体验真的好差. 更麻烦的是, 一到了项目后期, 一调试性能, 各种RN的坑导致性能极差, 我们做为开发要做各种补救.

但现在很多框架都有了越来越友好的跨平台体验了. 比如说Flutter, Compose, Kotlin Multiplatform, ....

这些里面我个人更喜欢Flutter, 一个是出来得早, 资料更多; 二是比较有活力, 官方的支持越来越多, 现在连桌面端都想cover; 再就是渲染性能比RN也好一些.

推荐程度不这么强的技能

7 另一移动平台的开发

7.1 好处1: 有利于跨平台开发

这个其实是第6点"跨平台技术"的延伸. 比如说我在Flutter或React Native里写一个文件的解密功能, 这个不是UI, 所以不被Flutter与RN所支持.

好吧, 其实也有crypto-js这样的库支持ArrayBuffer级别(即java里的byte级别)的解密 , 但我试了下, 发现数据大时很慢, 这时我就只好正常到native端去做解密工作. 结果就是果然解密快多了.

回归正题, 正因为是跨平台, 所以我的原生插件就得既支持Android, 又得支持iOS. 于是我被逼无奈, 去学了Objective-C的解密算法. 于是相同的解密算法在Android端实现一次, 在iOS端实现一次, 两个native平台成功解密后再把结果给RN端.

所以说, 多移动平台的开发都懂一点, 会帮助到我们的跨平台开发.

7.2 有利平团队协作

我主业是Android开发, 但自从我学会了objc与swift后, 每当我碰到一些疑难问题, 想看下iOS怎么弄的时, 我只要打开xcode看下他们iOS的代码, 就知道怎么弄了. 所以会iOS的代码能帮到我们理解甚至是学习到iOS的一些做法. 这对于mobile端的协作, 或是Mobile端的统筹规划还是有用的.

8 html, css, javascript

这一点类似上面的第7点. 一般同学可能用不上. 但

  • 要是你的app里有大量webview, u并且你需要来debug这些html/css/js代码时,
  • 或是需要你用anoHttp或是GcdWebServer来构建自己的服务器时, 你可能就需要这三块的知识.

总结

所谓'逆水行舟, 不进则退', 我们app开发也要不断地学习, 不断地成长.

而且你在做开发时要学的东西, 和你在做tech lead时要学的东西还不一样, 所以我觉得上面各个点还是很适合想进阶为tech lead的同学来学习的.

文尽于此, 欢迎批评与指教. 也希望本文对你的职业规则有这么一丁点作用, 谢谢.

相关推荐
ii_best4 小时前
ios按键精灵自动化的脚本教程:自动点赞功能的实现
运维·ios·自动化
yuanlaile7 小时前
纯Dart Flutter库适配HarmonyOS
flutter·华为·harmonyos·flutter开发鸿蒙·harmonyos教程
yuanlaile7 小时前
Flutter开发HarmonyOS 鸿蒙App的好处、能力以及把Flutter项目打包成鸿蒙应用
flutter·华为·harmonyos·flutter开发鸿蒙
zacksleo9 小时前
鸿蒙原生开发手记:04-一个完整元服务案例
flutter
app开发工程师V帅14 小时前
iOS 苹果开发者账号: 查看和添加设备UUID 及设备数量
ios
CodeCreator181814 小时前
iOS AccentColor 和 Color Set
ios
iOS民工16 小时前
iOS keychain
ios
m0_7482389219 小时前
webgis入门实战案例——智慧校园
开发语言·ios·swift
Legendary_0081 天前
LDR6020在iPad一体式键盘的创新应用
ios·计算机外设·ipad
我是前端小学生1 天前
React Native 中的 View 组件:全面解析
react native