内容简介:我是在世界杯期间才知道有个旅游网站叫“马蜂窝”,后来一直也没关注。没想到最近几天,马蜂窝重新回到了大众的视野。只不过,这次亮相好像是从广告的另一面出现的,因为这几篇文章对马蜂窝进行了数据分析,得出了若干结论。
本文转自微信公众号: 余晟以为(ID:yurii-says) ,作者余晟。
我是在世界杯期间才知道有个旅游网站叫“马蜂窝”,后来一直也没关注。没想到最近几天,马蜂窝重新回到了大众的视野。只不过,这次亮相好像是从广告的另一面出现的,因为这几篇文章对马蜂窝进行了数据分析,得出了若干结论。
目前来看,马蜂窝对这几篇文章提出了异议,但是似乎还没有给出合理可信的解释。事实的真相如何,或许还要等等才有答案。不过我还是推荐大家阅读这几篇文章,相信大多数人会从中获得不少启发。
说到数据分析,似乎许多人都会一点,无非是算算总数啦,算术平均啦,看看极值啦,好一点的还知道方差、标准差。但是光这样做数据分析,能得出的结论相当有限。怎么办呢?更复杂的数据分析要怎么做?许多人一看到“更复杂”,就想起复杂的数学公式、建模、曲线拟合等等,让人头痛。
其实数据分析也可以不用那么复杂,搞清楚数据之间的关联就可以有不少发现了。比如这几篇文章就提供了非常有趣的视角,比如:
-
所有创造内容的账号中,最活跃的1.5万个账号,他们的行为似乎有共同的节奏,同时活跃,同时沉寂;
-
所有餐饮点评的发布日期分布,周一到周五保持了相对平缓的变化,周六周日则猛跌,大众点评则以周末两天为高峰;
-
所有酒店点评的发布日期分布,周四到周六开始骤降,而携程艺龙则以周末为高峰;
-
所有餐饮点评的发布时间分布,中午12点~13点,下午18点~20点为低谷,这两个时间段对应大众点评为高峰;
看到这些分析的时候,我忽然想起许多年前看过的一部破案电视剧。
犯罪分子为了打劫资金,苦心孤诣提前半年做准备,有人提前“出国打工”,有人男扮女装,时间选择大年三十以鞭炮声为掩护……劫案完全按照预先的设计进行,可谓天衣无缝。警方翻来覆去侦查,始终找不到任何破绽和线索。
最终,案件的突破来自一个小细节:犯罪嫌疑人说自己某年某月某日乘火车回来,所有的行程都能对上,都有证明。然而警方检查当天车站记录的时候,发现当天那次火车晚点了。沿着这条线索,之前那些精心设计、严丝合缝的环节就像多米诺骨牌一样悉数倒下了……
这几天的马蜂窝事件和这部电视剧里剧情,它们说明的都是同样的道理: 制造几份漂亮的数据 (证据) 是很容易的,但是制造内在逻辑统一的数据 (证据) 是很难的。
那么,上面说的这些事情,和软件开发有什么关系呢?
要知道,我们开发的软件大多是要运行在现实世界里的,是要与现实世界打交道,与现实世界保持一致的。只不过真实世界的内在逻辑——火车晚点了就不能直接坐上当班汽车,饭点才有事件和兴致发餐馆点评——往往不能原样进入软件世界,所以软件系统里只剩下数据作为真实世界的载体,用数据来反映世界。
虽然大家常说“要用数据说话”,但许多时候数据也是会愚弄人甚至骗人的。那么怎样避免被数据愚弄,怎样识破数据的骗局呢?简单的经验是, 不能仅仅就数据来看数据,而要看到许多数据之外的东西。
数据之外有什么?最明显的是现实世界的约束。比如汽车上坡当然要比下坡慢,口袋里没有钞票了就买不了东西等等。在生活中,这些东西都很好理解,似乎是“不言自明”的,甚至你没觉察到也摆脱不了这些约束。但是进入到软件的世界里,程序员开发的时候往往就把这些约束忘在脑后了,或者完全依赖于产品经理给出的规则。所以有的游戏里汽车上坡和下坡的速度竟然是一样的,有的账户系统可以可以“逆向”充值给银行卡,储值余额却变成负数……
我刚刚工作的时候,在书上看到的一个例子让我印象深刻。天上的飞机需要知道航向,所以Plane对象有个成员变量是heading。通常我们会用一个整型数值表示它,但是那本书上提到这是不对的!因为航向只能在0度到360度之间,所以你用整型数值时一定需要给setter加上一段逻辑,确保这个值只能设置在0到360之间。否则,难保其它系统读到heading时不会出错。“只有加上了对应的约束,变量才不再是原始普通的数字,而变成了能承载业务价值的数据”。
许多年过去了,我仍然记得当时的惊讶:原来竟然可以这样!原来竟然应该这样!
后来我自己在开发中一直保持这样的习惯,虽然麻烦,也因此避免了许多故障。再往后看到《领域驱动设计》才明白:在设计软件系统时,领域知识往往是最重要的,而领域知识的一大部分就在于识别领域中的各种约束。这些约束很难由产品经理巨细靡遗地穷举出来,而必须由参与开发的所有人达成共识,在系统里实现它。但是无论如何,这些约束都是必不可少的,没有它们,系统就很可能出现各种稀奇古怪的现象。
我曾经见过奇特的仓储费账单,数额大到让所有人吃了一惊,大家伙查来查去才发现入仓时间竟然在公元229年。如果约束落在系统里,第一时间发现异常并且报出来,就可以省去后面的许多折腾。当时我说“公元229年还是三国时期呢”,所有人都笑了。
其实这个例子一点也不好笑,看看我们常见的系统,身高、年龄、体重、车速、生日等等数据,许多时候就是想当然直接用原生数据类型来表示的,所以取值为负数,甚至几千万上亿也“无可厚非”,当然后果也非常严重。
数据之外的天地不只有约束,数据的内在逻辑和关联也是相当重要的。
在分析马蜂窝的文章里提到,马蜂窝做了些修改,比如清空了某些账号,所以看起来数据正确了。但是稍作一点拓展就会发现,数据完全对不上,比如之前这些账号留下的那些牛头不对马嘴,“身份今天是男明天是女”的点评仍然存在着。如果数据真实,并不会发生性别剧烈变化的情况;如果数据关联可信,也不会出现“删了账号帖子还在”的情况。
不过,这种“按下葫芦浮起瓢”,“顾头不固腚”的现象并不是个例,我就见过许多系统有这种问题,稍微改动某个细节,就会全盘大乱。这还不是最要命的,最要命的是发现异常的时候根本不知道因果链条是怎样的,从哪里萌发,中间经历了哪些环节,下面还会影响什么……
之所以会出现这种问题,不少时候是系统开发过于想当然,过于图省事,假设其它一切都是“按部就班”正常发生的,所以只记录了“最核心”的数据,相关的数据和状态则完全没有保存。于是,系统的状态就只能靠一堆零散孤立的点来承载,点与点之间没有明确关联,不能彼此印证,也无法回溯历史上的各个片段。
这方面最明显的例子就是记账系统。许多人都见过“想当然”的记账系统,每一笔账目发生的时间、金额都要记录下来,但也仅此而已了,绝没有记录所涉及账户的即时余额,涉及的账户里也没有对应的记录。结果某天发现账户出错,只能手工一笔笔地追查,效率极低,而且容易额外引入错误。
出现这种情况当然很糟糕,但也有一定的道理。记账这回事已经有几千年的历史,但“在会计活动中对每一项经济业务,按相等金额在两个或两个以上有关账户相互对应地同时进行登记”的复式簿记法,直到12世纪才在意大利诞生,引入我国更是要等到晚清时期。如今许多做软件开发的人未必学过会计知识,做出的记账系统没有复式簿记的思想,也情有可原。
其实按我的经验, 往往越是复杂的系统,越是复杂的功能,越是应该学“复式簿记”,也就是不怕麻烦,清楚记录因果链条,提供详细回溯能力。 以前我们曾做过一套计费系统,其实就是把一大堆阶梯价目表做到系统里,上线后经常有客户来吵架,说计费出错了,每次都要劳心劳力来核对。即便系统没有出错,也没有办法第一时间否认系统出错,第一时间证明给用户看。
后来大家痛定思痛,花大力气把计算过程做成了“自解释”的:每一步都有详细的记录,按照哪一份标价表格的第几条规则,具体是怎么计算的……总之,每一笔费用都有详细的计算过程可查,而且各子系统之间需要维持状态关联,保证彼此的数据和状态实时一致,出现问题及时报警。 这样做繁琐是繁琐了点,但上线之后不久就解决了争议,程序员有了更多不被打扰的时间,用户也有了信心。
最后,我们在分析问题时也应当注意数据的关联。
我经常说,正确合理的分析,一定有多个独立数据来源可以彼此验证。之所以这么说,是因为看到了太多的分析,给出的原因、理由看似合理,却根本无法得到多重验证,所以其实根本没有找对原因。
比如某个程序异常的原因是“网络瞬断”,那么它用的是什么样的网络?哪一段在当时发生了抖动?共用此网络的其它应用有没有受影响?如果我们再模拟一次网络瞬断,程序的表现是否相同?…… 只有得到这一系列答案,掌握多种数据,我们才能最终下结论说是“网络瞬断”。否则一口咬定“网络瞬断”,往往要么是能力不及,要么是偷懒甩锅。
总而言之,马蜂窝的事情或许还要“让子弹飞一会儿”,但检查自己手头的代码有没有落实约束,有没有实践“复式簿记”的思想,定位问题时多找一些数据彼此验证,却是马上就可以做的事情。
*文章为作者独立观点,不代表虎嗅网立场
本文由余晟以为© 授权虎嗅网 发表,并经虎嗅网编辑。转载此文章须经作者同意,并请附上出处(虎嗅网)及本页链接。原文链接:https://www.huxiu.com/article/268069.html未来面前,你我还都是孩子,还不去下载虎嗅App猛嗅创新!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ANSI Common Lisp
Paul Graham / Prentice Hall / 1995-11-12 / USD 116.40
For use as a core text supplement in any course covering common LISP such as Artificial Intelligence or Concepts of Programming Languages. Teaching students new and more powerful ways of thinking abo......一起来看看 《ANSI Common Lisp》 这本书的介绍吧!
Base64 编码/解码
Base64 编码/解码
RGB HSV 转换
RGB HSV 互转工具