广告过滤工具AdBlock、Adblock Plus和uBlock的简单对比

Adblock Plus作者的那篇博客可能会影响很多人。我并不关心那些情怀的东西,只看疗效。

简单地对比了下AdBlock、Adblock Plus、uBlock在Safari for Mac上的效果,所有样本和环境均为当前最新版本。AdBlock开启Safari内容过滤后是最好的,成功地过滤掉了我常访问的一个BT下载网站上的所有广告,而不开启Safari内容过滤时,会出现部分广告先显示后隐藏的情况。uBlock漏掉了个别不容易屏蔽的。而Adblock Plus最差,缺省设置下一条都没过滤掉,在选择更多的过滤规则后才过滤掉一部分。由于样本很单一,本结论不具有普适性。

说句题外话,我觉得Adblock Plus这名字起得动机就挺不纯的,没有详细考证过,印象中这个东西是比AdBlock后出现的,而且这名字很容易让人理解成AdBlock的加强版。

变形金刚真人电影系列被重置

根据这条消息,变形金刚真人电影系列将会被新团队重置,原定在明年的第6部被取消。也就是说,看完今年大黄蜂的电影后,2021年前都不会有变形金刚主题的新片了。

这种壮士断腕的做法多少算是个好消息吧,经历了变5的失败,再让麦克尔贝这么折腾下去,变形金刚这个IP就完蛋了。

我对这件事是无可无不可的。作为一个八零后,我对变形金刚的情怀来自G1动画,所以我的关注点主要是还原G1动画风格的Master Piece系列。在MPM-3出来之前,我对电影系的玩具没多大兴趣。

当年变1上映的时候,我很难认同电影系的风格。但是后来从变1到变3,也逐渐地开始接受它,毕竟随著技术的进步,审美风格也会发生变化,没必要固守二、三十年前的东西。我对电影系最大的意见是剧情太烂,有句话很对,说一部戏好不好关键看反派角色,《蝙蝠侠之黑暗骑士崛起》之所以口碑不错,主要是大反派小丑这个角色很立体。回头说当年的G1动画最成功的一点也是霸天虎尤其威震天这个角色塑造得比较成功。反观电影系,相对于汽车人华丽的人形态和隐藏形态,霸天虎阵营就是一群猥琐的低级生物,而且人物性格的塑造极其脸谱化。

直到后来变4的时候,风格进一步变化,加入大量骑士元素,机械元素的减少导致科技感进一步下降。最要命的是变4的玩具做得实在是一塌糊涂。至于变5,那真是电影做得和玩具一样烂。

真是成也麦克尔贝,败也麦克尔贝。

iQunix F60使用感受

fullsizeoutput_392

我不喜欢冗余的东西。如果桌子足够大,我能接受的极限是87键。然而我的Filco 87圣手二代黑茶已经吃灰很久了,之前的主力是Poker II白青。所以目前主要的关注点还是在60键上。

我对Poker整体上还是比较满意的,尤其是按键编程的功能很方便。但是有两点让我很不满意。一是做工一般,键帽的活动幅度较大,远远没有Filco的扎实感。二是不支持蓝牙,无线化是一个用了就回不去的东西。

iQunix F60就是这么个东西,符合我对键盘所有的核心需求:支持蓝牙、做工好、60%布局、Cherry轴、PBT键帽。用了一段时间,整体是满意的。

买的银白色,收到的是侧刻,算是个小惊喜吧,虽然不如无刻骚气,至少不像正刻那么平庸。铝合金外框加白色PBT键帽的颜值很高,整体很有质感。

做工比Poker好很多,找回了Filco的扎实感。PBT的键帽不打油,这一点超过了Filco。

续航一般,轻度使用可以持续一周。信号强度也很一般,一米的距离,已能感受到明显的延迟。不过这些在实际的使用中不是什么大问题。

功能上,不支持键盘编程,这点不如Poker。但是可以用组合键交换左侧WIN键和ALT键,对Mac很友好。代替方向键的组合键位也比Poker合理。此外,可以用组合键切换有线和无线模式,支持在3台设备之间切换。

异地补卡下的北京中年

我妈的老SIM卡不能用在iPhone里。因为我的卡就是从大卡剪过来的,所以骑车转了一大圈,临近年关,大部分修手机的店、合作营业厅都关了,最后一个卖手机的店里的老板说这种老卡不能剪,只能换卡。

之前听附近移动营业厅里的大堂经理说,换卡需要机主本人、身份证和服务密码,而且异地补卡只能去部分较大的营业厅。这个可以在网上营业厅里查到。

事先在网上营业厅重置了服务密码。第二天一早,去了最近的可以异地补卡的营业厅。工作人员给了张纸条,让写下手机号、服务密码,他们查了一下,说是鉴权失败,让第二天再去。留了营业厅的电话,事先让他们查一下,确认可以办了再去。

第三天早上十点,打电话过去,说是办异地补卡的人还没来。十一点再打过去,查了一下,说是可以办了。去之前差点没带手机,因为感觉就是办张卡,回来装也一样。事实证明,不带会后悔。

补卡也需要用手写板签字和人脸识别,因为是2d图像识别,所以很傻,需要摇头、点头、眨眼、张嘴,在张嘴这一步重试了很多次都失败……

补的第一张卡插到手机里不能识别,第二张才成功。

总结以上,异地补卡需要注意这些点:

  • 本人、身份证、服务密码(服务密码可以去网上营业厅重置,前提是卡还在,还能接到短信)
  • 去能办理异地补卡的营业厅(可以在网上营业厅查询,或者打客服电话)
  • 不要去太早,最好事先打电话让他们查一下,确认可以办了再去
  • 一定要带手机和开卡槽的工具,现场装卡测试
飞利浦电动牙刷HX9903/42使用感受

效果虽说没别人说的夸张,也的确刷得很干净,再就是缓解了胳膊的疲劳感。

有个问题。刚开始的几天,虽然电池已经充满,但是震动强度很一般,而且手柄底部的压力警示灯一直闪,试过拔掉刷头,问题还在,说明是手柄的问题。直到提示电量紧张后第二次充电,之后才恢复正常。

App、多种刷头、多种模式、压力警示和三级震动强度都是噱头,刷个牙而已,HX6730足够了,多交的几百块钱除了智商税,也就颜值和无线充电有点价值了。

电动牙刷不是个用了就回不去的东西,不过体验确实很好,刷牙不再是例行公事和负担,而是件挺有意思的事。

用OTP Auth替换了Authy

Authy的界面很花哨,但并不实用,管理多个两步验证账号时查询效率很低。OTP Auth采用更直观的列表布局,并且支持搜索,在用户体验和效率上有更大的优势。两者之间没有批量迁移数据的方式,只能逐个手动添加,很麻烦。

对XSS的防御更适合放在前端

很多项目会把转义操作放在后端接口获取参数的地方,从而忽略了这样一个问题——为什么主流框架都不在获取参数的方法里实现这一点?

以Laravel为例,如果可以这样获取转义后的参数:$request->escape('content'),代码会显得更优雅,而实际上只能用自己封装的函数手工转义:my_escape($request->get('content')),很丑陋的代码。

事实上,主流框架并非没有提供防御XSS的封装,只是都放在模板引擎里。这样做的依据是,XSS的原理是在原本用于展示的数据里包含了可执行的文本,但不是所有展示的位置都不应该包含可执行的文本。从另一角度上说,后端应该校验前端传递的数据,但不应该篡改它。

十公里租房补贴是个天才的福利制度

十公里以内是个很适合通勤的距离,以任何一种公共交通方式都可以把时间控制在半小时左右。

通勤时间每增加半小时,生活质量都会下降一个量级,而生活质量是会直接影响一个人的工作质量和稳定性的。所以有些公司有十公里内租房补贴的福利,这项制度天才的地方在于,如果把这些补贴以工资的形式发放,员工可能仍然会因为住得远导致幸福感很差,所以增加了很多不稳定的因素。这项制度间接地强制员工把自己收入的一部分用在提高自己生活质量上面,记得那个朝三暮四、朝四暮三的故事吗?公司花同样的钱,却得到了更大的价值。

癸丑望,月有食之

大概这是我第一次看月全食,暗红色,挺大个儿,但是拍出来就显得很小。论效果,iPhone X还不如几年前的LX5。

P1030593
P1030594

解决Laravel的Facade在被Mock时不自动注入依赖的一种方法

由于集成了Mockery,Laravel的Facade对单元测试非常友好,只需要一行代码就能实现mocking。

例如,测试目标方法中调用了订单工具类的一个方法,在使用依赖注入的方式时,需要用三行代码实现对这个方法的mocking:

1
2
3
$fakeOrderTool = m::mock(\App\Tool\Order::class);
$fakeOrderTool->shouldReceive('getById')->once()->with($id)->andReturn($fakeOrder);
$this->app->instance(\App\Tool\Order::class, $fakeOrderTool);

而用Facade是这样的:

1
OrderFacade::shouldReceive('getById')->once()->with($id)->andReturn($fakeOrder);

当测试目标方法也属于订单工具类时,需要部分mock这个类,所以还要加上一行:

1
OrderFacade::makePartial();

但如果订单工具类的构造方法里有需要注入的依赖关系,这里并不会被执行。所以我在工具类基类里封装了一个方法,用反射机制实现手工注入依赖关系:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 注入依赖,用于单元测试
*
* @return void
* @author donieli
* @since 5
* @version 5
*/
public function injectDependencies()
{
$reflector = new \ReflectionClass(get_class($this));
$params = $reflector->getConstructor()->getParameters();
$args = [];
foreach ($params as $param) {
$paramClass = $param->getClass();
if (empty($paramClass)) {
throw new \Exception('Dependency named '.$param->getName().' cannot be injected.');
}
$instance = app()->make($paramClass->getName());
$args[] = $instance;
}
call_user_func_array([$this, '__construct'], $args);
}

然后就可以这样处理:

1
2
3
OrderFacade::shouldReceive('getById')->with($id)->once()->andReturn($fakeOrder);
OrderFacade::makePartial();
OrderFacade::injectDependencies();