三体动画观后感

像标题一样随便韶韶

1-4可以,5-9烂,10之后超越经典。泰勒的补完,罗辑和庄颜的爱情故事比原版强。给岁月以文明(野蛮)不如给岁月以爱。

在我眼中是部好剧,我希望看到下一部的。所以在这多说两句尽一点自己的力量。

我反对因为是国产就给予特别宽容的评价,早些年的大圣,哪吒我认为过誉了。现阶段的国产动画我觉得也不需要再谈什么宽容评价鼓励发展了,不需要了。市场在这技术也有了。

对于这部剧一边倒的差评其实也是预料之中。但现在的关键是还有没有续集了。在这件事上我到希望 B站或是游族的管理层能从一个纯粹的商业的角度去考虑。目前三体播放量5.7亿,合单集3800w 。对比一下当下最火的鬼灭第一季3730w播放量甚至还略有胜出。相信只要两方的管理层脑子正常应该是还能有第二季的,期待一下。

流量为王的时代下被骂也是流量。希望不喜欢这部作品的朋友们也继续发力,为了我能看到第二季谢谢。

先说说不好的点

章北海同志出场戏太牵强了,一个海军大校凭什么有球闪实验的密钥。

色调,什么玩意。

表情,根本就是颜艺。灵笼就这么玩一点长进都没有。动不动就瞳孔地震,四边眼白,是不是有病。

宏原子那个只针对人的引力场是什么鬼。还有时间乱流。科幻算是被编剧理解透了,反正你不能证伪是吧。这点也不是不能原谅,毕竟流浪地球2相控矩阵核弹都能有人洗。但是下不为例啊。

优秀的点

场面,特效。各种追车爆炸啥的。实验室空间站宇航服等等细节还是挺带感的。

美女,各种美女。希望第二部庄颜不要再出现中分发型了,拜托了。

章北海,虽然出场生硬但是气势到位,点赞。

泰勒的补完更加合理。原著中被揭穿导致泰勒的下线个人觉得不太合理,危机纪元的人类根本没有这么圣母的道德标准。几个面壁者都是堪比韦德的人物,没有那么脆弱。自己的刚愎自用导致女儿死亡从而退场的设定合理多了。

罗辑和庄颜的爱情故事。4-9 的初识阶段是特么的灾难。原著中关于这部分基本是空白,大刘也从来没有写过谈恋爱的戏份(估计也写不出来,这家伙绝对是个FF党)。按照原著的核心思想,给岁月以文明。实际描写的故事只有给岁月以野蛮。所有智慧生物在这个宇宙的存在根本都没有意义。科幻小说这么写没什么问题,但是搬上荧幕要被大众接受是不可能的。科幻毕竟是小众。两人这段爱情不仅丰富了作品内核,也丰满了人物形象和动机。绝对是值得赞赏的改编。而且故事写的也不错。

最后分析下为什么这部作品的评价为什么会这么差

B站这个群里人均三体粉。一千个人有一千个三体,何况播放量都3000w了。不被喷才是不正常的。

被喷的这么惨也有三体这部作品的特殊性。B站甚至豆瓣你都再找不出一部用户阅读量这么高的作品了。这是其一。

其二,这部分读者因为读过原著自然有原著党的优越感。不批判两句那是不行的,这是豆瓣与生俱来的特殊性。在这部作品上这一行为也发展到B站了。

其三,这部分读者虽然读过三体但99%没怎么读过其他科幻。更遑论把三体动画的影视化与其他科幻小说的影视化相比较。

拿安德的游戏来比较,如此丢失原著精髓的改编,并且电影本身也不好看的豆瓣也拿下了7.1。要是按照三体动画的标准去评分那画面是真不敢想。

科幻要想影视化特效,场面,情节的修改增加都是必不可少的。相较之下流浪地球算是讨了巧,两部电影搁小说里面不知道有没有2000字的篇幅。如何改动都不容易召喷,而且读者数量相较三体少的多。但是这也不是郭导你搞相控矩阵核弹的理由!

以上。还是希望制作方的管理层一定要脑子清楚啊。别像隔壁腾讯一样,搞了一部全职高手就摆烂了不可取啊。

cosmic估算方法学习笔记

Cosmic 估算方法简介

COSMIC 软件度量方法简介

简单来说该方法是以数功能点的方式来预估项目工作量。把一个最小颗粒度的 story 拆分成 EXRW(输入、输出、读取、写入)4种功能点,最后再汇总统计来计算总工程量。

关于优缺点的思考

优点

快速,简便,通用

门槛低不需要专业人员参与,有助于和客户沟通确认实际需求,解释工作量。

缺点

改造、升级类项目的评估没有明显优势,可能难以适用。

内部逻辑复杂的项目恐怕难以适用,比如一个项目某个重点技术难点就要占据整个项目很大一部分时间的情况。

关于工程量估算的思考

敝人本专业是建筑环境与设备工程,我一直都在思考一个问题,为什么软件行业至今没有发展出像建筑工程行业一样成熟的项目估算,进度控制方法。

同时这个问题也可以转化成为什么建筑行业的成熟方法没有被套用在软件行业上。“人机料法环”六字真言多么顺耳。

大胆猜测之一,行业壁垒可能让两个行业缺乏顶层交流,软件行业可能从来不知道有这些方法可以借用。

但我认为这种可能性非常小,行业先贤在拓荒阶段肯定考虑过借鉴学习。大概率还是因为行业情况不同。建筑行业对质量的要求跟 IT 行业大部分情况下根本不是一个级别的。你不可能把一栋楼盖完住户入住之后再每个月升级打补丁。

还有就是 IT 行业的产品往往要求快速的研发发布抢占市场。

但我个人觉得以上的两种差别情况实际正在减少。IT 行业的渗透率越来越高,蓝海市场越来越少。红海市场的厮杀应该是质量、成本取胜而非速度。随着 IT 行业继续深入传统行业比如互联网+概念,汽车,飞机这些场景都需要堪比建筑行业的质量要求。理论上将来我们可能真有可能见到把建筑行业的工程管理方法引入到 IT 行业的一天。

回到 IT 行业的估算工作上来,就过往的经验来说估算不准确的情况 50% 因为需求不明确 40% 你估你的Boss就要下月交 9% 估算人员太过乐观 1% 估算人员过于悲观。就 90% 的情况来说你用什么方法根本不重要。就Cosmic 方法来说,能够增加和用户沟通便捷性,方便挖掘用户需求这方面来说,确实有其价值。也就是说对于交付甲方性质的项目有用,对于自研项目个人认为没有特别优势或劣势。

钱够用

经济学里面有一些常见的理论:适当的通胀可以刺激经济的发展。货币供应量需要符合市场流通的商品总量,如果货币量不足会影响市场的交易正常进行。这些理论导向一个结果——国家需要印钞,不断的加大货币供应量。

真的是如此吗?西太平洋上有个小岛,岛上的居民用一块大石头当作货币。今天张家卖给李家两只鸡售价是这块石头的千分之一,明天李家卖给赵家两只鸭售价是千分之二。看起来并无什么不妥。他们会遇到货币不足的情况吗?也就是说只要货币无限可分,哪怕全国只有一块钱也足够十亿人使用。

通胀可以刺激经济的发展?岛国日本过去几十年印了无数的钱,发了无数的债试图刺激经济。但几乎没有效果。这个观点的逻辑是这样的。因为通胀你手里的存款会持续减少,人不管是为了满足自己的基本生存需求还是更高级的追求都必须付出劳动努力去挣钱。大家更努力的工作了,经济也就发展了。所以这招在一个全民低欲望的社会里面失效了。可见促使社会发展的根本原因是人民的主观能动性,是科技、技术、劳动产生的生产力提高,而非什么通胀。

那么为什么会有这些理论,并且这些理论也确实主导着当今世界呢?

以下纯属个人臆想。

正如法律是统治阶级意志的体现。很多经济学家,新闻机构同样服务于统治阶级。自古以来没有比收铸币税更快的敛财方式了。为了使这一切合理化,还需要一套完整理论支撑其观点,美化其观点。所以一帮对人类社会毫无正面贡献的经济“学家”“编”出了一大堆的理论来忽悠世人。

下面开始民科暴论,经济学人请立刻撤离。

经济学不是科学,它没有任何公式可以带入现实进行任何有用的演算验证。气象学家可以预测明天的天气,经济学家炒股亏钱。

我认为人类不需要通胀,不需要经济学家,不需要金融杠杆,不需要任何金融衍生品。这些通通都是统治阶级以及附庸在统治阶级下的精英阶级的敛财工具。他们非但不能促进社会发展,还只会加大社会贫富差距阻碍社会发展进步。一个能够快速发展的社会应该是人民对生活充满希望的社会,而不是面对阶级鸿沟只感到绝望的社会。

总结,钱够用。

人性的等级

道德评判标准

你可能听过这样的观点,穷人的素质比富人差。事实是否真的如此?我对这个问题没有答案。

但是我相信经济基础决定上层建筑。这个上层建筑可以包含道德善良等概念。

因为物质的贫乏,人类可能会变得更加好斗,这应是生物的本能,生存是第一需求。

故,我认为对人的道德的评价理应基于其生存状况和经济情况。情况越好,标准越高。情况越差,标准越低。

列举一些极端的例子。犹太人当年在集中营当中为了生存发生了很多残害同胞的行为,这种行为是否应当被原谅。亿万富豪,捐出了自己 1% 的财产给穷人,这种行为是否值得表扬。只顾自己对社会毫无贡献甚至有害的是否应该被唾弃。

佛洛依德主张人有本我、自我超我。将其运用在这个问题上,当生存环境越恶劣时,人的行为越趋向于原始的兽性。当人的生理需求、安全需求得到满足时,我们才能把一个人当作人来对其进行要求。同时如果一个人的生理需求和安全需求都得不到满足时还能表现出极高的道德准测的,可以称之为圣人。

生理需求

我个人认为性需求是需要单独说明的一个。显然性需求属于生理需求,但是现在社会常常将其从正常的生理需求中刨去。出于求生欲,事先声明我没有任何为猥亵,强奸犯辩护的意思。只是当今社会有些法律限制私以为不太合理。

理想社会当中人人都能找到自己的另一半,从而解决性需求。我认为非理想状态下的现今社会应当建设尽量满足性资源匮乏群体的社会制度。尽量的意思是我不同意妓女或男妓的合法化。无论如何为这种古老职业辩解,这项职业始终对从业者的尊重需求有伤害,妨碍了从事这项职业人的真正自我实现。这份职业必然是往理想社会前进道路上的障碍。

尽量满足人的性需求其实还有很多其他的办法。例如,色情制品。包括但不限于影像,音频,文字,动画等等。私以为禁止这些产品就像禁酒一样糟糕。可能有人会说影像制品一样会对从业人员有伤害。我想说确实,但是我们还可以通过各种手段来保护从业人员将这种伤害降到最小甚至没有。一是个人隐私保护,二是现在的 CG AI 换脸等技术。日本已经有过关于 AV 产业对于降低性犯罪率的研究,这里不再详述。

理想社会

理想社会的第一步应当是每个人的生理需求、安全需求都得到了满足。在此基础上每个人去追求各自的自我实现。我想这就是马克思主义的每个人都可以充分自由发展的社会。

强调

重点强调,对人的道德评判应该基于其生存状况。不能用同一把尺去衡量当今社会的所有人这是不公平的。至少也应做到从生理需求加安全需求是否得到满足这条分界线来制定不同的评判标准。

前端笔试选择题

单选题

1、控制台输出的结果是?
var arraynew = new Array(5)
arraynew[1]=1
arraynew[5]=2
console.log(arraynew.length)

A、0
B、1
C、5
D、6

2、在 css 选择器当中,优先级排序正确的是()

A、id选择器>标签选择器>类选择器
B、标签选择器>类选择器>id选择器
C、类选择器>标签选择器>id选择器
D、id选择器>类选择器>标签选择器

3、CSS 样式,下面哪一个元素能够达到最大宽度,且前后各有一个换行?( )

A、Block Element
B、Square Element
C、Side Element
D、Box Elemen

4、JavaScript中window对象的子对象不包含以下哪个对象?( )

A. document B. self C. history D. message

5、下边代码输出的结果是( )
var val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing');

A: Value is Something
B: Value is Nothing
C: NaN
D: other

6、下边代码输出的结果是( )
var name = 'World!';
(function () {
    if (typeof name === 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})(); 

A: Goodbye Jack
B: Hello Jack
C: Hello undefined
D: Hello World

7、下列事件哪个不是由鼠标触发的事件()

A、click
B、contextmenu
C、mouseout
D、keydown

8、下列不属于javascript内置对象的是( )

A、Math
B、Date
C、RegExp
D、Window
E、Error

9、以下运行结果( )
for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}

A、0–9
B、10个10
C、10个9
D、无限循环

多选题

10、input元素的type属性的取值可以是( )

A、image
B、checkbox
C、button
D、select

11、下列关于web页面级优化描述最正确的是( )

A、减少HTTP请求的次数
B、进行资源合拼和压缩
C、Inline images
D、将外部脚本置于低端
E、减少不必要的HTTP跳转
F、以上描述都对

12、函数的调用方式有哪些:( )

A、直接调用
B、作为对象方法调用
C、作为构造函数调用
D、通过call和apply方法调用

参考文档

80道前端面试选择题

前端面试提纲

样式CSS

  1. 实现垂直居中
  2. 自适应布局 flex Grid
  3. 动画
  4. canvas

语言

  1. 原型链,作用域,闭包
  2. ES6,Pormise,async
  3. 设计模式,工厂、适配器、桥接
  4. 动态数据绑定的实现原理
  5. 全局状态管理 redux vuex
  6. TypeScript
  7. js 事件机制

框架

  1. 组件化理解
  2. Virtual Dom
  3. shadow dom

工程化

  1. 工程化的理解
  2. webpack loader
  3. 异步加载的实现原理
  4. CSS-module less sass
  5. 代码质量保障

性能优化

  1. 服务端渲染

调试

自动化测试

兼容性问题

编程思想

算法

其他

  1. 加班接受情况
  2. 职业规划
  3. 前端现状及未来走向
  4. 学习能力

JS 装饰器,一篇就够

原文地址

相关历史

三年多以前,Yehuda Katz 首先提出了装饰器的概念。TypeScript 在 1.5 版本(2015)中发布了对装饰器的支持以及许多 ES6 的相关特性。 一些主流框架,如 Angular 和 MobX 等开始使用它们来增加开发者体验:这使得装饰器非常受欢迎,并给社区带来了一种已经稳定的错觉。

Babel 第一次实现装饰器是在 v5 版本中,但由于该提案仍在不断变化,则在 Babel v6 中移除了它们。Logan Smyth 创建了一个非官方的插件(babel-plugin-transform-decorators-legacy),它延用了 Babel 5 中装饰器的行为;在 Babel 7 的 alpha 版本发布期间该库被移至 Babel 官方的仓库中。当时该插件仍使用旧的装饰器语法,因为新提案尚未明确。

自那时起,Daniel Ehrenberg、Brian Terlson 以及 Yehuda Katz 就一起成为了该提案的共同作者,该提案几乎已被完全重写。当然并非一切事情都已确定,因为至今尚未出现符合规范的实现方式。

Babel 7.0.0 为 @babel/plugin-proposal-decorators 插件引入了新的标识:legacy 选项,其唯一有效值为 true。这种突破性变更是必要的,它为提案从第一阶段到当前阶段平稳过渡作铺垫。

在 Babel 7.1.0 中,我们引入了对这个新提案的支持,并且当 @babel/plugin-proposal-decorators 插件被使用时,默认启用。而在 Babel 7.0.0 中如果我们不设置 legacy: true 选项,默认情况下就不能使用该语义(相当于 legacy: false)。

新提案同时支持使用装饰器实现私有字段(private fields)和私有方法(private methods)。我们尚未在 Babel 中实现此功能(在每个 class 中使用装饰器或私有元素),但我们会很快去出现它。

装饰器函数相关参数

新提案提出的第三个重要变化与传递给装饰器函数参数相关。

在提案的第一个版本中,类元素装饰器接收的参数分别为目标类(或对象),key 以及属性描述符 - 与传递给 Object.defineProperty 的形式类似。类装饰器将目标构造函数(constructor)作为唯一参数。

新的装饰器提案更加强大:元素装饰器会接收一个对象,该对象除更改属性描述符外,还允许更改 key 值,可以赋值(static,prototype 或者 own),以及元素的类型(field 或 method)。它们还可以创建其他属性并在装饰类上定义运行函数(完成器)。

类装饰器接收一个包含类描述符的对象,使得类在创建之前修改它们成为可能。

超越“双十一” | ebay支付核心账务系统架构演进之路

原文地址

ebay支付新一代核心账务系统FAS(Financial Accounting System)自今年3月上线以来,帮助全球百万卖家处理交易合计超百亿条,日均实时处理线上千万支付流量,每日payout金额超千万美元。系统上线至今稳定运行,并成功做到“三无”:无一次数据丢失,无一次转账错误,无一次整体宕机。系统后台仅由5台普通计算机组成,对硬件资源要求极低,且几乎无需运维。本文旨在介绍该系统背后的架构演进,希望为大家解决同类问题提供一种不一样的思路。

参考文献:

[1]https://raft.github.io/
[2]https://martinfowler.com/bliki/DomainDrivenDesign.html
[3]https://martinfowler.com/eaaDev/EventSourcing.html
[4]https://rocksdb.org/
[5]https://github.com/Netflix/chaosmonkey
[6]https://github.com/eBay/Gringofts

Raft算法

原文地址

拜占庭将军问题是分布式领域最复杂、最严格的容错模型。但在日常工作中使用的分布式系统面对的问题不会那么复杂,更多的是计算机故障挂掉了,或者网络通信问题而没法传递信息,这种情况不考虑计算机之间互相发送恶意信息,极大简化了系统对容错的要求,最主要的是达到一致性。

针对简化版拜占庭将军问题,Raft 解决方案类比

假设将军中没有叛军,信使的信息可靠但有可能被暗杀的情况下,将军们如何达成一致性决定?

Raft 的解决方案大概可以理解成 先在所有将军中选出一个大将军,所有的决定由大将军来做。选举环节:比如说现在一共有3个将军 A, B, C,每个将军都有一个随机时间的倒计时器,倒计时一结束,这个将军就会把自己当成大将军候选人,然后派信使去问其他几个将军,能不能选我为总将军?假设现在将军A倒计时结束了,他派信使传递选举投票的信息给将军B和C,如果将军B和C还没把自己当成候选人(倒计时还没有结束),并且没有把选举票投给其他,他们把票投给将军A,信使在回到将军A时,将军A知道自己收到了足够的票数,成为了大将军。在这之后,是否要进攻就由大将军决定,然后派信使去通知另外两个将军,如果在一段时间后还没有收到回复(可能信使被暗杀),那就再重派一个信使,直到收到回复。

………………

小总结

Raft 是能够实现分布式系统强一致性的算法,每个系统节点有三种状态 Follower,Candidate,Leader。实现 Raft 算法两个最重要的事是:选主和复制日志

参考链接:

Raft 官网:https://raft.github.io/

Raft 原理动画 (推荐看看):http://thesecretlivesofdata.com/raft/

Raft 算法解析图片来源:http://www.infoq.com/cn/articles/coreos-analyse-etcd

如果 Safari 做不到对,快有何用?

一个困扰了一周的 bug

2016 年的一天,当我们发现 iPhone 上的浏览器不能正确通过我们的 CDN 鉴权后,我们花了数天的时间来 debug。简单来说当时的情况是,我们需要同时上传 3 个文件,我们会用用户 token 来换 3 个独立的随机数 id,这三个 id 会被 CDN 服务器认为合法,用户可以直接上传到 CDN 上而无需在我们自己服务器上中转。
但 iOS 用户很快就出现了一个奇怪的问题,用户 3 个文件只能成功上传 1 个,剩下 2 个无法正常上传。再进一步调试后我们发现,在上传任意一个文件后,剩下两个 id 变成了非法。再进一步地,我们发现 Safari 获得的 3 个 id 竟然是完全相同的?!
复现
我很快设计出了能够构建出这个问题的重现:

原文链接

面试题分享

今天做了几道面试题,分享一下

题目一

解释:

var a = { name: "hello" }, b = { name: "hi" }
function exchange(a, b) {
  var c = b; b = a; a = c;
  a.name = a.name + "1";
  b.name = b.name + "2";
  console.info(a.name, b.name);
}
exchange(a, b);
console.info(a.name, b.name);

答:

var a = {
  name: "hello"
}, b = { name: "hi" }

function exchange(a1, b1) {
  /**
   * 传参进函数内部,JS 会创建参数的副本,这里用 a1, b1 指代副本,
   * 但若参数是对象,拷贝的只是指针。
   */

  var c = b1; 
  b1 = a1; // b1 等于 a
  a1 = c; // a1 等于 b
  a1.name = a1.name + "1"; // b.name 等于 hi1
  b1.name = b1.name + "2"; // a.name 等于 hello2

  /**
   * a1.name 被赋值的同时, b.name 也被赋值,因为此时 a1 和 b 指向的是同一个对象。
   * 下面执行 console.log(a1 === b) 可以确定
   */
  console.log(a1 === b)

  // a1.name 等于 b.name 等于 hi1
  // b1.name 等于 a.name 等于 hello2 
  console.info(a1.name, b1.name);
}

exchange(a, b); // hi1 hello2
console.info(a.name, b.name); // hello2 hi1

题目二

时间比较题:输入一组时间字符串,求出这组时间中的间隔最小的时间差(分),如输入 “23:59”,”00:00”,返回1 ; 假设输入数组的长度大于2且小于2000; (本题可以写伪代码)

/**
 * @param {string[]} timePoints
 * @return {number}
 */
var findMinDifference = function (timePoints) {

  const timeTicks = new Array(1440).fill(0);

  for (let point of timePoints) {
    const [hour, min] = point.split(':');
    const minutes = parseInt(hour) * 60 + parseInt(min);
    if (timeTicks[minutes] === 1) {
      return 0; 
    }
    timeTicks[minutes] += 1
  }

  let first;
  let prev;
  let min = Infinity;

  for (let i = 0; i < timeTicks.length; i++) {
    if (timeTicks[i] === 1) {
      if (first === undefined) {
        first = i;
      }
      if (prev !== undefined) {
        // 比较两组存在的时间之间的差值
        min = Math.min(i - prev, min);
      }
      prev = i;
    }
  }
  // 比较头尾的差值
  return Math.min(min, 1440 - prev + first);

};

var result = findMinDifference(['00:00', '00:01', '12:59', '23:58',])
console.log(result) // 1

题目三

假如有一个接口getUersById(userId),返回用户信息的json; 要求getUersById能缓存用户信息,即同样的userId请求仅向服务器发送一次,其余从内存中获取,以提高效率。 高阶要求: 假设有getUersById,getShoolInfoById, getDeviceInfoById … 都需要缓存结果,提供一个通用的 辅助 函数。

function memoize(func) {
  var memoized = function() {
    var args = arguments,
        key = args[0] || 'cache',
        cache = memoized.cache;

    if (Object.keys(cache).indexOf(key.toString()) > -1) {
      return cache[key];
    }

    var result = func.apply(this, args);
    memoized.cache[key] = result || cache;
    return result;
  };
  memoized.cache = new Object();
  return memoized;
}

// test code

var userId = 1
function getUserId() {
  userId ++
  return userId
};

var meGetuserId = memoize(getUserId)

console.log(meGetuserId()) // 2
console.log(meGetuserId()) // 2
console.log(meGetuserId()) // 2

题目四

  1. 输入一个数字, 交换两位数字, 最多交换一次, 输出可以得到的最大的数字; 如输入: 1234 交换 1,4后, 得到4231;
var maximumSwap = function (num) {
  var numStr = num.toString();

  for (var i = 0; i < numStr.length; i++) {
    var nbr = numStr[i];
    var index = i;

    for (var x = numStr.length - 1; x > i; x--) {
      if (numStr[x] > nbr) {
        nbr = numStr[x];
        index = x;
        console.log('待交换 nbr', nbr)
      }
    }

    if (nbr != numStr[i]) {
      var arr = numStr.split('');

      var tmp = arr[i];

      arr[i] = arr[index];
      arr[index] = tmp;
      console.log('交换后数', parseInt(arr.join('')))
      return parseInt(arr.join(''));
    }
  }
  return num;
};

// test code
console.log(maximumSwap(5987)) // 9587