36氪客户端4.0版本开发架构总结: 第三方分享认证模块的实现

前言

不知不觉加上实习和正式入职36氪已经半年左右,从第一次去实习以及接触较为正式的软件开发,对很多事情的懵懵懂懂,到琦哥让我自己去全新设计我们基于Swift重写的下一个大版本的底部交互,虽然物理时间比较短,却感觉已经走过了很长的一段路。在这之间,总觉得有很多东西想总结一下,特别是这次设计底部交互的逻辑以及在切向Swift过程中对这个语言的进一步的体会。

这是第一次除了公司内部分享外写技术文章,除了因为觉得这些感悟有分享的价值之外,可能更希望和别人碰撞出一些思维的火花,让我们在开发的过程中继续改进这种架构。虽然毫无疑问我认为自己设计的这套架构是很优雅的,但是确实也没有看到别的程序采用这么多的基础数据类型.对很多问题的解决思路都是根据优雅做判断, 对性能的判断也是模模糊糊的基于在国外 Mooc 平台上的几门介绍计算机底层的公开课上收获的一些东西做出的.

实话说我本来想先写总体的架构(也是第一个完成的事情), 但是因为我只是设计了对我们客户端业务区的对外接口封装, 内部实现大部分都是选用公开的第三方库. 所以, 对里面的实现并不能做到百分之百的把握(实话说, 我觉得一个人不自己写一个那种库,只是看看代码,真的很难说自己了解那个东西,计算机太容易给一个人造成我懂了的假象, 但是实际上懂的人也许没有那么几个).综合以上, 打算自己在后面的时间利用晚上和周末, 自己实现那些东西的底层(这里所说的底层,是说自己利用苹果自己的框架提供的接口)之后, 再逐步的分模块的介绍每一个部分的架构,总体的架构要放到最后面去写了.

说明

这篇文章在讲一些设计决策的时候, 会涉及到一些底层的考虑, 我不能保证这些讲解都是百分百正确的, 因为它们都是建立在我以前上的课程和实验的基础上, 有很多都已经模糊了, 但是又不想查资料写一些无关痛痒的简介(请原谅我的懒惰)!虽然我现在在学一些反编译和黑客技术, 力求能够从底层的层面彻底搞清楚这些东西,但精力有限, 也只是刚刚开始.总之,大家带着批判的思维来阅读这篇文章,欢迎指出里面的错误.

程序示例和 Cupid 库的代码在下面, 程序示例包含我们这一部分底部构建的全部代码!

Cupid


正文

业务区的搭建

我做东西一般不会一开始就去选择第三方库, 因为觉得看别人的东西特别是做东西的时候看别人的东西容易给自己造成误导, 做出一些并不是很适合自己的客户端的设计决策.所以我一般都会根据自己的业务区先设计具体的上层接口, 然后再去选用第三方库, 看哪一个能够比较好的实现自己的接口.

下面是我们客户端的上层接口的示例图, 因为我们主要采用的是通过 OAuth 获取认证信息, 然后让服务器拉用户数据的方式; 所以可能和你们的客户端的方式不是很一样.

业务区具体代码可以从 Github 的代码实例中查看. 但是可以从这个图示中可以看到设计的大体思维方式, 就是更多的使用 Swift 中枚举和结构体这两种基础数据类型, 然后使用闭包做回调, 减少使用类这种引用类型; 结构体扮演的角色主要是信息的流通通道和较为复杂单一的数据封装, 枚举则主要作为轻量型的数据传递; 虽然类仍然是业务区的中流支柱,毕竟无论是 MVC, MMVC, VIPER等各种架构 程序的方式, 都无法绕开苹果提供的最上层的 Framework, 而那些仍然大部分是基于 NSObject 的.

为什么我更喜欢枚举和结构体,下面你会看到,越往下其实用到的类会越少.一个很重要的原因可能就是个人偏好, 有时候我也在想是不是用 Tuple 会是更好的解决方案, 但是因为对计算机底层技术的了解有限, 无法做出这种决策. 真的期待哪位大牛能写一本叫做 Swift, The Good Parts 的书, 高级语言的灵活性对编程的泛滥确实并不是那么好, 现在越来越少的能够看到让自己能够眼睛一亮的代码了.还有一个原因,就是使用基础数据类型不用担心内存泄露的问题, 而且一个 run loop 完成后, 整个过程中调用栈会自动的被清空, 实际上,在写 Cupid 的过程中, 碰到几次因为一行代码的原因, service Provider 被提早释放, 造成 completion handler 没有被调用. 记得前一段时间因为学 Hand off 和 state restoration 技术, 用 Swift 翻译了苹果的 PhotoOff demo, 然后将它的下面的数据交互更改为 Struct + NSCache 的实现, 最后稳定状态下内存占用量大概只有原来的一半, 内存泄露数量从60多处降到了10处不到(当然, 我觉得和 Swift 的实现更加安全也有一定的关系), CPU 的使用效率也更加的高效.最后, 越往下面的东西, 可能涉及到的数据操作会更少, 因为真正的数据在服务器或者数据库的底层才会操作, 而数据库的底层自己写可能真的没有成熟的第三方实现更加高效.苹果自己的 News 都是使用第三方的 FMDB. 这些地方更多的是担当一个信息流通的通道, 并没有必要使用类这种重量型的数据类型(虽然, 现在编译器的优化已经让类和结构体的性能影响可以忽略), Swift 的语言特性, 让结构体+枚举+闭包的实现更加优雅!

业务区和 Cupid 库的交互

业务区和 Cupid 的交互可能就比较简单了, 因为 Cupid 存在的目的就是为业务区服务的, 至少之所以选在这个库最主要的原因是它可以更好地为业务服务, 当然, 开发一个库的目的是为了更适应普遍大众(开发者)的需要.实际上, 我一开始的实现是使用 MonkeyKing, 但是因为公司业务需要我们没有办法去掉支付宝的分享功能, 在仔细审查 MonkeyKing 的代码后,觉得并不适合这种业务需求才决定重写一个自己的库, 十分感谢 MonkeyKing 的开发者 @nixzhu 和@Limon-catch, 实际上, 很多 ServiceProvider 的实现方法都是 Copy 的 MonkeyKing 的代码, 当然, 为了适应自己的逻辑做了很多的修改. 在下面的一节会详细的介绍 Cupid 库和其它分享库的核心区别.

下面是业务区和 Cupid 的交互图:


这一块全部实现可以在 Github 的代码实例中查看, 就不多做介绍.

Cupid 内部库的构造

其实 MonkeyKing 写的很好, 但是可能有人问, 为什么有一个很好的东西, 还要自己再花时间去写一个一样的东西, 答案当然是, 他们不一样! Cupid 从内到外都采用了完全不同的实现方式, 它的一些优点可以在主页上查看, 我觉得 Demo 也很优美, 从界面到代码.

内存结构

下面一张图是 Cupid 的交互和其它第三方分享库和核心的区别:


需要注意的是这个上面关于调用栈的思维是推测的, Swift 中如何处理结构体和枚举对我来说还是一个黑箱子; 我觉得假如我是编译器的作者就会采用这种思维方式.通过这种设计思维, 可以很有效的降低程序中单例类数量, 更好的利用内存空间, 特别是对于我这种一年分享不了几次的用户.

数据类型

之所以选择重写 MonkeyKing 还有一个很重要的原因就是我们的应用要支持剪切板和支付宝的分享, 我觉得基于 enum 封装大批量数据的思维虽然调用的简洁度可以更高, 但是在可扩展性上面并没有做到更强. 所以 Cupid 选择了基于 Protocol 的方式来实现特定的 Service Provider, 如果你们看源代码的话, 可能会发现实现一个特定的 Service provider是十分的 easy 的, 而且你不需要更改任何其它的地方, 可以做到绝对的兼容.

本来我在 Service Provider 基于基类实现和基于接口实现做了一些取舍, 最后之所以选择基于接口实现除了因为我不喜欢各种 override, 还有一个原因是因为每一个 Service Provider都有各种特定的需求, 是很独特的, 基本上没有任何共同的特点.

下面是 Cupid 处理一个分享或者认证的调用路径, 这样就不用像很多的第三方分享一下, 要 register 账户, 而且维持许多的单例:



结束语

就像一开始的说明,这里面的很多底层交互都是自己的猜测或者说自己觉得会那么实现底层,和实验的结果, 请用批判的角度理解这里面的内容, 在自己的工程中灵活的使用这些东西.如果各位读者有了解里面细节的, 欢迎补充!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,455评论 25 707
  • 九儿蘭心 2017-09-27 13:25 · 字数 71 · 阅读 0 · 日记本 老爸 明天就三年了 不敢说这...
    九儿蘭心阅读 308评论 0 0
  • 撬开头颅 用勺子挖出脑浆 填满眼睛 眼珠扔进水泥 砌进墙里 四肢发霉 肌肤生螨 我是死掉的尸体 我死了 我告诉你 ...
    狐夕阅读 228评论 0 0
  • 昨天的晨读材料讲的是信任,信任这个词适用范围很广泛,也是我们最常用最熟悉的一个词汇。那么,接下来我就说说自己身边的...
    捡到蜜罐的熊阅读 157评论 0 3