摸鱼精选第 4 期

Swift 在 58 安居客房产实践

大厂的代码基本上都是在已有的 OC 工程里面加入 Swift 混合编程,本文总结了在 OC 和 Swift 混编遇到的一些问题。

  • Swift 调用 OC 的 framework,必需开启 Module 模式,否则无法 import
  • OC 反射时需要注意,Swift 的生成的 Class String 是"ModuleName.ClassName"的格式,NSClassFromString 无法对应到 OC 的类。可以在 Swift 的类增加注解@objc(ClassName),指定 OC 的类名即可。

常见内网穿透工具使用总结

本文介绍了几个内网穿透工具:

  • nps-npc (开源,推荐)
  • frp (开源)
  • ngrok (碧源,免费)

RabbitMQ,RocketMQ,Kafka 事务性,消息丢失和消息重复发送的处理策略

本文重点关注分布式的一致性,介绍了三者是如何处理分布式事务的,以及在消息防丢失、消息持久化的不同。

错误处理原则及其在 Swift 中的应用

常见的错误处理方案:

  • 运行时错误
  • 错误码
  • 异常
  • 代数数据类型

其中运行时错误常见的就是fatalError之类的。

错误码就是 NSError 之类的,根据 code 判断不同的错误。

关于异常和错误码的讨论就没停止过,但作者认为“对于调用方来说异常要么被传递,要么被显示处理,可靠性得到了保证。中间的调用方如果不需要处理异常,仅仅使用 try 就可以,避免了对主流程的影响,易用性非常好。总的来说,异常比错误码在可靠性和易用性都可以做的更好”。

Swift 5.5 的 async/await 最低支持 iOS 13 版本,结合异常是非常丝滑的。

在使用 Future/Promise 时,统一结果和错误是比较常见的做法,如 Result

探索 Flutter 中线程模型/消息循环的底层逻辑

作者通过阅读 Flutter 引擎 C++源码来窥探 4 种 Task Runner 的具体实现:

  1. Platform Task Runner :对应平台如 Android/iOS 的 UI/Main Thread。
  2. UI Task Runner:所有 Dart Framework 层的代码均在此现场执行。
  3. Raster Task Runner:真正执行渲染任务,光栅化所有从 UI Task Runner 中提交过来的任务,最终渲染到屏幕上。
  4. IO Task Runner:通常执行耗时计算任务,例如下载/解码远程图片,再交给 Raster Task Runner 渲染。

Swift 代码优化指南 | 如何最大化实现性能提升?

作者是快手团队的,从以下 3 个方面考虑优化 Swift 代码

编译速度优化

作者认为某些情况下的类型推断比较费时,但是都加上类型的话,又失去了 Swift 的语法糖优势以及良好的代码风格。

内存分配与占用

  • 再讨论 Struct 的使用
  • 用轻便的 Enum 替代 String
  • 优化集合类型
  • 减少不必要的桥接
  • 善用写时复制

运行时速度优化

  • 了解三种函数派发
  • 使用 final,private 优化派发方式

Android 组件化多 module 依赖优雅方案

如题。

Android 响应式架构最佳实践——MVI

作者提出一种新的架构"Model-View-Intent",简写 MVI。结合 MVVM 和 MVI 模式的优点,得出最终的方案:MVI + LiveData + ViewModel。

总的来说是有点借鉴 Flux 的单向数据流的思路,因为传统的 MVVM 是双向绑定,引入一个 ViewState 概念,在 state 更新时刷新 UI。感觉就是细化了一些 ViewModel

Android 项目架构设计深入浅出

  • 总结一个普通 Android 项目从 0 到 1 再到 N 的架构演进历程。
  • 对一个架构完整的大型 Android 项目中各层级及其核心模块进行展开讲解。
  • 对各框架 SDK 中一些共性的底层原理进行抽象总结。
  • 梳理一些架构设计和项目开发中遇到的通用问题及其解决方案。

解读 Go 语言的 2021:稳定为王

在 2021 年,官方团队按时发布了 Go 语言的 1.16 版本和 1.17 版本。

Go 官方网站也换了,目前是 go.dev,将散落各处的 Docs、Packages 都放在二级域名下。这对开发者来说绝对是利好啊。

Go Module 正式上岗之后,我们就有了一个从模块到代码包(以及子代码包)再到源码文件的多级代码组织方案。其中,源码文件是代码编译的最小单元,代码包是代码组织的最小单元,而模块则是代码发布的最小单元。

还有一些其他更新,比如标准库的改进,废弃了 io/ioutil,性能的提升,对 arm64 支持的增强。

语法方面没有太多变化,泛型会在 2022 年即将发布支持。

C++ template 学习笔记

作者是腾讯公司的,引入原文导读:

template 是 c++ 相当重要的组成部分,堪称 c++语言的一大利器。在大大小小的 c++ 程序中,模板无处不在。c++ templates 作为模板学习的经典书籍,历来被无数 c++学习者所推崇。第二版书籍覆盖了 c++ 11 14 和 17 标准,值得程序猿们精读学习,特此整理学习笔记,将每一部分自认为较为重要的部分逐条陈列,并对少数错误代码进行修改

大部分人说道 C++,想到的第一个词就是复杂!其实大可不必,C++的内容很多,但是大部分是给库作者用的,比如 template 等其他高级特性。如果是做应用开发,工作中用到的东西其实不多,我估计只有 20%是常用的。

Flutter 重构 QTalk

QTalk 是去哪儿网内部的一个 IM 沟通工具,同时集成了很多内部的系统,比如 OA 审批,门禁打卡,请假审批,预定会议室,驼圈(驼厂朋友圈)等功能;方便内部办公沟通、交流的同时,也为无纸化办公,流程审批等提供了支持。

QTalk 计划采用 Flutter 来做到 iOS、Android 、PC 三端统一复用组件的目的。

  • 混合架构:选用 Flutter 2.0 的 Engine Group 方案 + PlatformView 的方式。这也是比较常规的做法吧,根据不同的 TargetPlatform 加载不同的原生 View
  • 状态管理:目前主流方案就是 provider、BLoC、mobx、redux、fish-redux 等几种,一番比较权衡之后,作者选用了 fish-redux + Eventbus 的方案。fish-redux 负责 Logic 层和 UI 层,EventBus 负责 Logic 层和 Data 层。EventBus 采用单例分发的模式,无需引入 context。
  • Dart 和 原生代码一起断点调试:由 Native 端启动 App,然后打开编译 Dart 代码的 ide 或者终端,使用 flutter attach 命令连接你的 Dart 代码到运行中的应用,这时候就可以同时调试 Native 与 Dart 与代码了。
  • PC 端有很多原生平台相关能力 Flutter-desktop 尚未拥有,比如多窗口,录屏,web 使用,拖拽文件共享,menubar 配置等。解决方案就是引入 NativeShell 框架,采用多引擎方式解决 PC 端遇到的多窗口问题,改变工程结构,在 dart 启动 main 函数之前增加一个 rust 类来管理窗口,调用 rust 中的各平台系统库来把各种语言(c++ c# oc 等)写成系统 api 统一成 rust 类型的文件,减少平台差异性

浅谈缓存最终一致性的解决方案

在解决缓存一致性的过程中,有多种途径可以保证缓存的最终一致性,应该根据场景来设计合适的方案,读多写少的场景下,可以选择采用“ Cache-Aside 结合消费数据库日志做补偿”的方案,写多的场景下,可以选择采用“ Write-Through 结合分布式锁”的方案 ,写多的极端场景下,可以选择采用“ Write-Behind ” 的方案。