问题记录:iOS 用户行为统计代码的剥离

分享的文章 专栏收录该内容
23 篇文章 0 订阅

问题记录:iOS 用户行为统计代码的剥离

2015-07-15 09:06  编辑: suiling  分类:iOS开发  来源:MicroCai


calculator-791833_640.jpg

本文由 作者:@MicroCai 授权转载

这两天在搞一个统计模块,把碰到的问题和一些讨论记录下来,所以本文没有答案,没有解决方案,仅是讨论而已。

我要做什么?

我现在做的是一个 app 里面的用户行为统计,简单来说就是记录下用户从哪个页面跳转到哪个页面,在页面上都点击了哪些按钮,点击了几次等等之类的东西。

统计工具用的是现成的 Google Analytics,Flurry,MixPanel,我要做的就是将他们集成进我的统计模块代码,并进行各种业务事件的统计。

以 Flurry 为例,当点击登录按钮 clickShootButtonAction 被调用要做一条用户行为统计,统计代码是这样的

1
2
3
4
5
-?(IBAction)clickShootButtonAction
{
???? //?执行下面这句话,在?Flurry?的后台就能看到这个事件的记录
????[Flurry?logEvent:@ "点击拍照按钮" ];
}

或者

1
2
3
4
5
6
7
-?(IBAction)clickShootButtonAction
{
???? //?执行下面这句话,在?Flurry?的后台就能看到这个事件的记录
???? //?与上面不同的是,这边记录的是用户的一条行为路径
???? //?表示:用户拍照后,在照片分享页,将照片分享到了?Facebook
????[Flurry?logEvent:@ "保存分享照片" ?withParameters:{@ "分享到" :@ "Facebook" }];
}

而在应用里面记录上百个用户行为是很正常的事情。也就说类似上面的这种代码在 Controller 里面可能要出现几百次,还散落在各处。

这是正常的吗?

如果这些代码遍布我们的工程,使得统计模块和业务代码耦合度极高,造成剥离困难,无法重用等等各种的问题,写起来手累心也累。

对我们来说,最理想的情况下,Controller 里面这种代码越少越好,最好是一行都没有,包含个头文件就能自动统计那该多好。因为如果要剥离统计代码,或者更换统计方式,都是非常方便。

但实际情况不容乐观!!!

有解吗?

根据统计的事件,我们把需要统计的方法大致归类为以下三种,统计剥离的难度也逐级递增

  • 类似 viewDidLoad、viewWillAppear 这种 ViewController 的生命周期的方法;

  • 调用就进行一次事件统计的方法;

  • 在方法内,满足条件才统计的方法;

那么问题来了,如果我们不希望在 Controller 里面直接添加统计代码,应该怎么统计上面的三种方法?

剥离统计 ViewController 生命周期的统计代码

这类方法的统计比较简单,写个 UIViewController 的 category,hook UIViewController 的中需要统计的方法,然后将头文件塞到要统计的 ViewController 即可。

剥离调用一次就统计的统计代码

这个统计代码的剥离比较麻烦,麻烦的点在于这些方法是根据业务逻辑产生的,每个 ViewController 中的方法都不一致,没法用统一的方式来处理。

关于这类代码的剥离,我查了一些资料,请教一些同学,又在一些技术群讨论了下,确实可以剥离,但方法都不太可靠,所以不建议使用,以下一一列举。

  • 方法一:AOP + SPOC 配置文件?

这个方法来自最近微博上传的《禅与 Objective-C 编程艺术》最后一小节 面向切面编程 中。通过在 SPOC 配置文件中添加类名和方法,hook 类里面的方法,然后进行统计。

乍看之下,这个思路非常不错,写起来爽歪歪,要添加统计代码时,只要在配置文件中加一下就 OK,嗨到不行。但后来一想这种方式实际执行起来是会有问题的。

首先统计模块代码和业务代码是分散在两个地方,统计是根据具体的类名和方法名的字符串来 hook 后进行统计操作。因为统计模块比较独立,由一个单独的人来写,其他人去写业务代码。业务开发的同学随意修改个方法名还是比较正常的。当业务开发的同学改了个方法名,一般不会想到统计这边也要改;统计这边的同学也不知道业务的同学改了什么。所以这种只有调试时,碰到统计异常才会去检查这里,可维护性太差。

所以这种方法是写的人爽,维护的人非常非常的不爽!?

所以这种不推荐使用!

  • 方法二:约定方法名?

从开发的开始就约定好,比如需要统计的函数(例如 IBAction 之类的,按照约定命名),然后 hook objc-sendmessage 函数,统计所需的方法。这个方法其实和方法一类似,所以也有同样的问题。而且人为约定没有特别强的约束力,稍不留神就忘了方法名的约定,而且也没有编译器警告、错误的提示,根本就不会想到这时候要按照约定的规则命名。再且需求是经常变动的,有些原先不需要统计的内容,后来突然又要统计了,按照这种规则就要改方法名,整体的感觉就是场面太混乱了。

所以这种也不推荐使用!

剥离满足条件才统计的统计代码

无解!

想过去真真是无解啊!因为我们前面所用的方法和思路基本离不开 AOP,而 AOP 本身是 hook 一整个方法,在方法前后添加一些自定义的操作。AOP 是没有办法了解方法内部是什么样的,更何谈去统计方法内满足了一定条件再统计事件。

怎么办?

老老实实的将统计代码写到相关的方法里面吧,真没辙了!

最后的忧伤

折腾了这么些来回,结果还是没法将统计代码和业务代码分开。原以为统计模块应该是一个独立的模块,结果却捅到各个 Controller 代码里面去,实在令人忧伤。

那么到底是什么原因造成了这样一个结局?

回头看看,我们一开始就默认了统计模块是一个独立的模块,应该与业务逻辑分开来。但实际上统计是和业务紧密结合的一个模块,所以是不是可以这么想。统计模块的代码也属于业务逻辑呢?

不管怎样,这么想就可以心安理得的把统计代码写进 Controller 了~

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值