Problem record: Stripping of iOS user behavior statistics code

Problem record: Stripping of iOS user behavior statistics code

[[140437]]

I have been working on a statistics module these days, recording the problems I encountered and some discussions, so this article does not have any answers or solutions, it is just a discussion.

What should I do?

What I am doing now is user behavior statistics in an app. Simply put, it records which page the user jumps from, which buttons they click on the page, how many times they clicked, and so on.

The statistical tools used are the existing Google Analytics, Flurry, and MixPanel. All I have to do is integrate them into my statistical module code and conduct statistics on various business events.

Take Flurry as an example. When the login button clickShootButtonAction is called to collect a user behavior statistics, the statistics code is as follows

  1. -?(IBAction)clickShootButtonAction
  2. {
  3. // ?Execute the following sentence, and you can see the record of this event in the background of Flurry  
  4. ????[Flurry?logEvent:@ "Click the camera button" ];
  5. }

or

  1. -?(IBAction)clickShootButtonAction
  2. {
  3. // ?Execute the following sentence, and you can see the record of this event in the background of Flurry  
  4. ???? //?Different from the above, this records a user's behavior path  
  5. ???? //? means: After taking a photo, the user shared the photo on Facebook on the photo sharing page  
  6. ????[Flurry?logEvent:@ "Save shared photos" ?withParameters:{@ "Share to" :@ "Facebook" }];
  7. }

It is normal to record hundreds of user actions in an application. This means that code like the above may appear hundreds of times in the Controller and scattered everywhere.

Is this normal?

If these codes are spread throughout our projects, the statistical module and the business code will be highly coupled, causing difficulties in separation, inability to reuse and other problems, which will make writing them tiring both physically and mentally.

Ideally, the controller should have as little code as possible, or even no code at all. It would be great if the statistics can be automatically calculated by including a header file. This is very convenient if you want to strip the statistics code or change the statistics method.

But the actual situation is not optimistic!!!

Is there a solution?

Based on the events being counted, we roughly categorize the methods that need to be counted into the following three types, and the difficulty of statistical stripping increases step by step:

  • ViewController lifecycle methods like viewDidLoad and viewWillAppear;
  • The method for performing event statistics once called;
  • Within the method, the method of statistics is performed only when the conditions are met;

So the question is, if we don’t want to add statistical code directly in the Controller, how should we count the above three methods?

Strip statistics code from the ViewController lifecycle

The statistics of this type of method is relatively simple. Write a category for UIViewController, hook the method that needs to be counted in UIViewController, and then plug the header file into the ViewController to be counted.

Strip out the statistics code that is called once

The stripping of this statistical code is rather troublesome. The trouble is that these methods are generated based on business logic, and the methods in each ViewController are inconsistent, so they cannot be handled in a unified way.

Regarding the stripping of this type of code, I checked some information, consulted some classmates, and discussed it in some technical groups. It is indeed possible to strip it, but the methods are not very reliable, so they are not recommended. They are listed one by one below.

  • Method 1: AOP + SPOC configuration file?

This method comes from the recently uploaded "Zen and the Art of Objective-C Programming" in the first section of Aspect-Oriented Programming. By adding the class name and method in the SPOC configuration file, hooking the method in the class, and then performing statistics.

At first glance, this idea is very good and it is very easy to write. When you want to add statistical code, you just need to add it to the configuration file. It is so exciting. But later I thought that this method would have problems in actual implementation.

First of all, the statistics module code and business code are scattered in two places. Statistics are hooked according to the specific class name and method name string to perform statistical operations. Because the statistics module is relatively independent, it is written by a single person, and others write business code. It is normal for business developers to modify method names at will. When business developers change a method name, they generally don’t think that the statistics side also needs to be changed; the statistics side students don’t know what the business students have changed. Therefore, this is only checked when debugging and encountering statistical anomalies, and the maintainability is too poor.

So this method makes the author happy, but the maintainer is very, very unhappy! ?

So this is not recommended!

  • Method 2: Agreed method name?

It was agreed upon from the beginning of development, for example, the function that needs to be counted (such as IBAction, named according to the agreement), and then hook the objc-sendmessage function to count the required methods. This method is actually similar to method 1, so it has the same problem. Moreover, artificial agreements are not particularly binding. If you are not careful, you will forget the agreement on the method name. There are no compiler warnings or error prompts, and you will not think of naming according to the agreed rules at this time. Moreover, the requirements are often changed. Some content that did not need to be counted originally suddenly needs to be counted later. According to this rule, the method name must be changed. The overall feeling is that the scene is too chaotic.

So this is not recommended!

Strip the statistical code that only counts when conditions are met

No solution!

Thinking about it, there is really no solution! Because the methods and ideas we used before are basically inseparable from AOP, and AOP itself hooks an entire method and adds some custom operations before and after the method. AOP has no way to understand what is inside the method, let alone count the events that meet certain conditions in the method.

what to do?

Just write the statistical code into the relevant methods honestly, there is really no other way!

***'s sadness

After all this back and forth, I still can't separate the statistics code from the business code. I thought the statistics module should be an independent module, but it ended up being stuck in each Controller code, which is really sad.

So what exactly caused such an outcome?

Looking back, we assumed at the beginning that the statistics module is an independent module and should be separated from the business logic. But in fact, statistics is a module that is closely integrated with the business, so can we think that the code of the statistics module also belongs to the business logic?

Anyway, if you think this way, you can write the statistics code into the Controller with peace of mind~

<<:  Why did Alipay copy WeChat’s red envelope function?

>>:  OS X 10.10.5 and iOS 8.4.1 routine updates

Recommend

Exploring quantum supremacy: Towards a supercomputing revolution

Quantum supremacy refers to the fact that quantum...

A review of marketing cases in 2021

The meaning of advertising is publicity, but it i...

Bluetooth 5.0 and Wi-Fi, which one is better for the Internet of Things?

The Bluetooth SIG’s announcement of Bluetooth 5 i...

How to solve the problem of low conversion? 6 key points for high conversion!

In an era of traffic panic, even if you have mill...

4 classic routines for brand marketing in 2020

As the pages of the December calendar turn, it in...

Octopus has parasites?! Octopus: That's my partner's penis...

In 1829, Georges Cuvier, a leading figure in the ...