A/B 测试库 SkyLab

这是我参与更文挑战的第8天,活动详情查看: 更文挑战

一个功能或者 UI 设计往往有多种解决方案,为了决定采用哪种解决方案,往往需要数据说话。所有只能做出两个版本来测试用户的不同反应,这就是 A/B 测试,也叫桶测试分流测试,就好像统计学领域里面的双样本假设测试。

SkyLab 是一个 A/B 测试库,是由著名 AFNetworking 网络库和 Alamofire 网络库的作者 Mattt 所编写。SkyLab 由 Objective-C 编写,核心代码只有 200 行左右,现在已经被作者 archived。

SkyLab 采用 Block 的方式对外提供调用接口,来接收版本 A 和 B 的区别处理。这样设计的接口易用性非常高。

+ (void)abTestWithName:(NSString *)name
                     A:(void (^)())A
                     B:(void (^)())B;
复制代码

SkyLab 一共提供了三种解决方案:

  1. 在两种方案中随机选出一种
  2. 在不同权重的方案中,根据权重随机选出一种
  3. 在多个条件中,随机选出几个条件。

被选中的方案保存在了 NSUserDefault 中,使得每个用户在使用过程中,不管是被随机到哪种解决方案,都能够保持相同的策略。

其中,最难的是如何根据不同的权重随机出对应的方案?比如,一共有 A、B、C、D 四种方案,被随机到的概率需要设置为 10%,20%,30%,40%,该如何设计算法呢?

这个问题本人在面试的时候被问道过。

下面是 SkyLab 的解决方案的步骤:

  1. 将所有方案的权重按照顺序不断的累加,将累加结果放到数组 mutableWeightedSums 中;
  2. 随机出一个 0 到权重总和的数字 r;
  3. 在 mutableWeightedSums 中找到第一个大于 r 的坐标 idx,这个 idx 就是被随机到的坐标。

下面是核心代码:

static id SLRandomKeyFromDictionaryWithWeightedValues(NSDictionary *dictionary) {
    if ([dictionary count] == 0) {
        return nil;
    }
    
    NSArray *keys = [dictionary allKeys];
    NSMutableArray *mutableWeightedSums = [NSMutableArray arrayWithCapacity:[keys count]];
    
    double total = 0.0;
    for (id key in keys) {
        total += [dictionary[key] doubleValue];
        [mutableWeightedSums addObject:@(total)];
    }
    
    dispatch_once(&srand48OnceToken, ^{
        srand48(time(0));
    });
    
    double r = drand48() * total;
    
    __block id randomObject = nil;
    [mutableWeightedSums enumerateObjectsUsingBlock:^(NSNumber *cumulativeWeightedSum, NSUInteger idx, BOOL *stop) {
        if (r <= [cumulativeWeightedSum doubleValue]) {
            randomObject = keys[idx];
            *stop = YES;
        }
    }];
    
    return randomObject;
}
复制代码

SkyLab 也可以当做练手项目,写出一个 Swift 版本,可以查看本人写的版本

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享