Objective-C 使用引用计数作为 iPhone 应用的内存管理方案,引用计数相比 GC 更适用于内存不太充裕的场景,只需要收集与对象关联的局部信息来决定是否回收对象,而 GC 为了明确可达性,需要全局的对象信息。引用计数固然有其优越性,但也正是因为缺乏对全局对象信息的把控,导致 Objective-C 无法自动销毁陷入循环引用的对象。虽然 Objective-C 通过引入弱引用技术,让开发者可以尽可能地规避这个问题,但在引用层级过深,引用路径不那么直观的情况下,即使是经验丰富的工程师,也无法百分百保证产出的代码不存在循环引用。
计算 +load 方法的耗时
在 pre-main 时期,objc 会向 dyld 注册一个 init 回调,当 dyld 将要执行载入 image 的 initializers 流程时 (依赖的所有 image 已走完 initializers 流程时),init 回调被触发,在这个回调中,objc 会按照父类-子类-分类顺序调用 +load 方法。因为 +load 方法执行地足够早,并且只执行一次,所以我们通常会在这个方法中进行 method swizzling 或者自注册操作。也正是因为 +load 方法调用时间点的特殊性,导致此方法的耗时监测较为困难,而如何使监测代码先于 +load 方法执行成为解决此问题的关键点。
CocoaPods,GitLab CI 与组件自动化发布
在实施业务组件化后,大部分没有组件化工具链支撑的团队一般都会遇到组件发布效率问题,如果遇到多个特性一起上线时,发布的组件数量可能达到十几二十个,手动发布这些组件的话,费时费力,非常影响开发体验。同样的,这个问题也一直困扰着我们团队,虽然后期我们通过 CI 简化了单个组件的发布,组件负责人只需要根据 Podfile 中的版本提交相应 tag 即可触发发布动作,但是 CI 并没有解决多个关联组件发布的前后顺序问题————如果下层组件还未发布就发布上层组件,此组件的 CI 很可能会因为缺少下层组件的某些接口而执行失败。
基于 CocoaPods 的组件二进制化实践
火掌柜 iOS 客户端经过近两年的组件化推进,组件数量已经颇具规模,达到了近 100 个。随着组件数量和代码量越来越多,主工程的打包时间从最初的十几分钟,增加到了现在的四十分钟左右。依赖组件较多,改动相对频繁的上层业务组件,其发布时间也较为漫长。编译时长的困扰,已经明显影响了日常开发体验,同时也造成 CI pipeline 执行时间过长,在 runner 资源匮乏的情况下,不利于内部 CI 的推广。当前时间节点下,如何减少编译时长,已经成为开发团队较为迫切的需求。
掌柜客户端团队架构升级之路
前言
记得我是16年3月31号入职二维火的。在过去的两年多时间里,我一直在火掌柜客户端团队工作。一直以来都想写一篇blog记录一下掌柜团队的变化,这次正好借公众号系列文章的机会来完成这个小目标。
不知道看官大人发现没有,标题中的团队
2两字显得有点突兀。原因是在下不光想在这里聊聊掌柜客户端着两年多来的变化,也想说说团队工作方式的转变。
Feature Driven Development(特性驱动开发)
一、Feature Driven Development(特性驱动开发)
1.What do I mean by Feature Driven Development?
简而言之:在你的代码本身中包含app需要用到的一些特性和操作的信息,使用这些信息我们只需要通过添加一些少量的代码就可以添加app需要的各种功能。调试和诊断故障变得更加容易,因为您可以清楚地识别用户在做什么,而且它可以使应用程序的内部体系结构更加清晰。这可以帮助开发产品的每个人使用相同的术语。
火掌柜 iOS 团队 GitLab CI 集成实践
目前掌柜团队内部缺少组件发布平台,每次 App 发版都需要组件负责人去发布自己名下涉及的组件。这中间存在组件间依赖以及发布时间差问题,上层组件需要依赖下层组件的发布,负责人之间沟通起来极为耗时。所以团队暂时没有限制私有源仓库的推送权限,当发布时间比较紧时,方便负责人绕过 lint, 直接推送 podspec 到私有源仓库。
虽然这种发布方式能节省一部分时间,但是容易出现下层组件 lint 失败向上层传递的情况。久而久之,lint 不通过的组件将会越来越多。为了尽量避免这种情况的发生,引入 CI 对组件进行 lint 监测是个不错的选择。
以上就是掌柜团队当初引入 CI 的初衷。不过 CI 能带来的便利远不止如此,当然,这都是后话了。
二维火掌柜Android持续化集成探索
CI持续集成
前言:
此文章前部分将以最理想的持续集成理念来阐述。实际具体项目使用,本就应该针对自身项目的情况“因材施教”,具体场景具体配置使用。文章后部分将结合我组Android项目具体情况进行实践。
二维火掌柜Android模块化架构实践
模块化工作之前思考的问题
1. 模块化结构图
模块化之前项目结构:
模块化调整后项目结构:
模块化拆分原则:
-
依赖关系只能上层依赖下层,不能反向依赖。
上下层即上图中纵向关系,上层模块只能单向依赖下层的模块,如果两个模块间配置的是双向依赖,会出现循环依赖问题。例如:
A -> B
A模块依赖B模块,B ->A
B模块又依赖A模块,A -> B
A模块又依赖B模块…. 陷入死循环了。
组件化之组件生命周期管理
在没有实行组件化的项目中,经常会在 AppDelegate 看到各类初始化代码,这一部分代码一般用以配置某些 key 以及 secret ,或者开启某些服务,常见的有第三方推送、统计分析、IM服务等。当然,也有可能是开启一些自身的服务,比如 log 日志、 数据库初始化等。当一个 App 达到一定体量后, 未经整理的 AppDelegate 可能会变得臃肿。那么在实行组件化之后,该如何处理这部分代码呢?