中美程序员不完全对比
我是在美国工作过两年,回国经历了逆文化冲击,现在勉强算是适应了国内互联网公司的节奏。随便聊聊,没有崇洋媚外的意图,只是刚好最近被剥削得很不爽,趁机吐槽一下。
1.年龄
美国公司:
同事里 20 多到 70 多岁的都有,众数是三四十的中年人,大部分工作目标都是为了早日退休,攒够钱就随时办退休 party。也有些纯粹因为热爱工作、热爱写代码选择不退休的。 我们组的核心成员之一,是位 72 岁的老头,他每天 4 点多起床到公司写一会儿代码,等天全亮就戴上头盔去骑山地车锻炼,9 点多回公司继续工作。对这老头印象深刻,是因为他逻辑清晰、思路锐利,他是 code review 小组的成员,经常在邮件里破口大骂其他人写的代码写得有多烂,被投诉,只好在邮件里道歉,过几天继续骂,在我工作的两年里一直循环。 我的另一位资深同事,是位 68 岁的架构师,热爱工作,每天都乐呵呵的,对我这种新毕业生也很友好,有人问他什么时候退休,他回答说他死的那天。
我国公司:
回国之后我现在工作的公司,员工平均年龄在 30 岁以下。年纪大的都去哪里了呢?极少数在管理层。
2. 加班
美国公司:
从没加过班,晚上发版除外(会默认第二天调休)。 经常正开着会,时间到了 5 点半,产品打断领导说到点了他要回去喂狗(他是一个 50 岁的不婚族,养了一院子狗),然后就散会下班了。 加班需要申请,有次我申请工作日晚上加班,没批准只好回家了。因为加班费会比较高,需要从项目预算走,领导控制预算不给批。 偶尔周末去办公室取东西,几层停车场只有两三辆车。
我国公司:
996 是常事了。 印象比较深的是我司之前有个清华本科+美国硕士的小伙子,每天 7 点半准时下班,结果试用期被辞退了,原因是工作态度不积极,据说后来还和公司打了官司,不知输赢。
3. 代码质量
美国公司:
项目在前期花的时间是最多的,比如说需求分析、架构讨论、技术讨论。 写代码会考虑得比较长远,比较有时间去考虑开发原则、维护成本,领导也会乐意去安排版本来解决技术债务。
我国公司:
国内互联网节奏会要快得多,讲究小步快跑,就几天的开发时间,不管三七二十一先上线再说,刚开始我都惊呆了。
4.工作氛围
美国公司:
老美的公司确实比较尊重员工,在员工关怀上做得比较好。我可以感受到,和领导职位不同,但是我们人格是平等的,彼此尊重。 记得有一次发版前几天,组里程序员说他压力太大,领导给他假期让他放松调整,版本被延迟上线。 美国有 family first 的文化。有个老印同事,家里老人身体不好,公司同意他回印度工作照顾家人,远程跨国工作。经常有同事因为要看孩子比赛请假。领导自己也会偶尔周五请假,因为要去和女儿一起参加学校的公益活动。 对差异性接受度也比较高。同事有变性人、残疾人,大家相处得都很好。
我国公司:
绝大部分领导高高在上(我遇到的),官威很大。请个假,和求他借钱似的,组长还提醒我让我请假原因不要写“旅游”不然可能会不给批假。 记得有个需求,大家都认为不合理没必要,我去找领导沟通,刚提了一句还没展开,领导直接甩脸色“你是领导还是我是领导”。 有个同事因为耿直,和领导不和,被各种排挤冷暴力,逼他自己辞职拒给赔偿金。 开个线上事故复盘会,做 root cause 分析,就像要把人钉在耻辱柱一样,我不理解这对解决问题有什么帮助。
5.工作之外
美国公司:
很注重对健康的投资。至少 1/3 同事有每天早上去健身房的习惯。公司很多球场,晚上下班能看到很多同事在楼下踢足球、打排球。健身不只是为了锻炼,还是很多同事的爱好。看起来平平无奇的程序员,可能都是隐藏的运动高手,多年马拉松选手、山地车骑手遍地都是,还有不少极限运动爱好者。 喜欢看牙医。喜欢看各种体育比赛。喜欢旅游,基本上每年至少一次家庭旅游,游轮是热门项目。 一部分同事热衷慈善回馈社会,小到捐血捐钱做公益,大到组织慈善拍卖会。 据我观察都没啥夜生活,下了班就开车直接回家两点一线,偶尔聚餐也是和同事朋友。可能是我自己的感觉,人和人之间的链接比较淡薄,所以华人码农也会经常吐槽空虚无聊。 已婚同事的其他时间和我国的一样,花在养孩子和投资上。
我国公司:
办公室的好多同事,不敢看体检报告。都是 20 多岁的年轻人,检查出来啥的都有,胆囊炎、结石、痛风。。。前几天还有一个要好的同事请假去做痔疮手术的(捂脸),据他说是因为久坐,加班经常吃小龙虾。 相比之下离职率高太多了,每个月都有几个认识的同事离职,跳槽的、转行的、回老家躺平的。 除了领导们,几乎每个人看起来都很焦虑,都想着退路,想着搞点什么副业。
35岁奥地利最帅总理辞职,超360万年薪加入硅谷当「码农」
除了北妈,说实话你们🍋不?
来源:https://mp.weixin.qq.com/s/kHyPm1ww8msBGn-TMtn58w
字节面:什么是伪共享?
CPU 如何读写数据的?
先来认识 CPU 的架构,只有理解了 CPU 的 架构,才能更好地理解 CPU 是如何读写数据的,对于现代 CPU 的架构图如下:
可以看到,一个 CPU 里通常会有多个 CPU 核心,比如上图中的 1 号和 2 号 CPU 核心,并且每个 CPU 核心都有自己的 L1 Cache 和 L2 Cache,而 L1 Cache 通常分为 dCache(数据缓存) 和 iCache(指令缓存),L3 Cache 则是多个核心共享的,这就是 CPU 典型的缓存层次。
上面提到的都是 CPU 内部的 Cache,放眼外部的话,还会有内存和硬盘,这些存储设备共同构成了金字塔存储层次。如下图所示:
从上图也可以看到,从上往下,存储设备的容量会越大,而访问速度会越慢。至于每个存储设备的访问延时,你可以看下图的表格:
你可以看到, CPU 访问 L1 Cache 速度比访问内存快 100 倍,这就是为什么 CPU 里会有 L1~L3 Cache 的原因,目的就是把 Cache 作为 CPU 与内存之间的缓存层,以减少对内存的访问频率。
CPU 从内存中读取数据到 Cache 的时候,并不是一个字节一个字节读取,而是一块一块的方式来读取数据的,这一块一块的数据被称为 CPU Line(缓存行),所以 CPU Line 是 CPU 从内存读取数据到 Cache 的单位。
至于 CPU Line 大小,在 Linux 系统可以用下面的方式查看到,你可以看我服务器的 L1 Cache Line 大小是 64 字节,也就意味着 L1 Cache 一次载入数据的大小是 64 字节。
那么对数组的加载, CPU 就会加载数组里面连续的多个数据到 Cache 里,因此我们应该按照物理内存地址分布的顺序去访问元素,这样访问数组元素的时候,Cache 命中率就会很高,于是就能减少从内存读取数据的频率, 从而可提高程序的性能。
但是,在我们不使用数组,而是使用单独的变量的时候,则会有 Cache 伪共享的问题,Cache 伪共享问题上是一个性能杀手,我们应该要规避它。
接下来,就来看看 Cache 伪共享是什么?又如何避免这个问题?
现在假设有一个双核心的 CPU,这两个 CPU 核心并行运行着两个不同的线程,它们同时从内存中读取两个不同的数据,分别是类型为 long
的变量 A 和 B,这个两个数据的地址在物理内存上是连续的,如果 Cahce Line 的大小是 64 字节,并且变量 A 在 Cahce Line 的开头位置,那么这两个数据是位于同一个 Cache Line 中,又因为 CPU Line 是 CPU 从内存读取数据到 Cache 的单位,所以这两个数据会被同时读入到了两个 CPU 核心中各自 Cache 中。
我们来思考一个问题,如果这两个不同核心的线程分别修改不同的数据,比如 1 号 CPU 核心的线程只修改了 变量 A,或 2 号 CPU 核心的线程的线程只修改了变量 B,会发生什么呢?
分析伪共享的问题
现在我们结合保证多核缓存一致的 MESI 协议,来说明这一整个的过程,如果你还不知道 MESI 协议,你可以看我这篇文章「[10 张图打开 CPU 缓存一致性的大门][10 _ CPU]」。
①. 最开始变量 A 和 B 都还不在 Cache 里面,假设 1 号核心绑定了线程 A,2 号核心绑定了线程 B,线程 A 只会读写变量 A,线程 B 只会读写变量 B。
②. 1 号核心读取变量 A,由于 CPU 从内存读取数据到 Cache 的单位是 Cache Line,也正好变量 A 和 变量 B 的数据归属于同一个 Cache Line,所以 A 和 B 的数据都会被加载到 Cache,并将此 Cache Line 标记为「独占」状态。
③. 接着,2 号核心开始从内存里读取变量 B,同样的也是读取 Cache Line 大小的数据到 Cache 中,此 Cache Line 中的数据也包含了变量 A 和 变量 B,此时 1 号和 2 号核心的 Cache Line 状态变为「共享」状态。
④. 1 号核心需要修改变量 A,发现此 Cache Line 的状态是「共享」状态,所以先需要通过总线发送消息给 2 号核心,通知 2 号核心把 Cache 中对应的 Cache Line 标记为「已失效」状态,然后 1 号核心对应的 Cache Line 状态变成「已修改」状态,并且修改变量 A。
⑤. 之后,2 号核心需要修改变量 B,此时 2 号核心的 Cache 中对应的 Cache Line 是已失效状态,另外由于 1 号核心的 Cache 也有此相同的数据,且状态为「已修改」状态,所以要先把 1 号核心的 Cache 对应的 Cache Line 写回到内存,然后 2 号核心再从内存读取 Cache Line 大小的数据到 Cache 中,最后把变量 B 修改到 2 号核心的 Cache 中,并将状态标记为「已修改」状态。
所以,可以发现如果 1 号和 2 号 CPU 核心这样持续交替的分别修改变量 A 和 B,就会重复 ④ 和 ⑤ 这两个步骤,Cache 并没有起到缓存的效果,虽然变量 A 和 B 之间其实并没有任何的关系,但是因为同时归属于一个 Cache Line ,这个 Cache Line 中的任意数据被修改后,都会相互影响,从而出现 ④ 和 ⑤ 这两个步骤。
因此,这种因为多个线程同时读写同一个 Cache Line 的不同变量时,而导致 CPU Cache 失效的现象称为伪共享(False Sharing)。
避免伪共享的方法
因此,对于多个线程共享的热点数据,即经常会修改的数据,应该避免这些数据刚好在同一个 Cache Line 中,否则就会出现为伪共享的问题。
接下来,看看在实际项目中是用什么方式来避免伪共享的问题的。
在 Linux 内核中存在 cacheline_aligned_in_smp 宏定义,是用于解决伪共享的问题。
从上面的宏定义,我们可以看到:
- 如果在多核(MP)系统里,该宏定义是
cacheline_aligned,也就是 Cache Line 的大小;
- 而如果在单核系统里,该宏定义是空的;
因此,针对在同一个 Cache Line 中的共享的数据,如果在多核之间竞争比较严重,为了防止伪共享现象的发生,可以采用上面的宏定义使得变量在 Cache Line 里是对齐的。
举个例子,有下面这个结构体:
结构体里的两个成员变量 a 和 b 在物理内存地址上是连续的,于是它们可能会位于同一个 Cache Line 中,如下图:
所以,为了防止前面提到的 Cache 伪共享问题,我们可以使用上面介绍的宏定义,将 b 的地址设置为 Cache Line 对齐地址,如下:
这样 a 和 b 变量就不会在同一个 Cache Line 中了,如下图:
所以,避免 Cache 伪共享实际上是用空间换时间的思想,浪费一部分 Cache 空间,从而换来性能的提升。
我们再来看一个应用层面的规避方案,有一个 Java 并发框架 Disruptor 使用「字节填充 + 继承」的方式,来避免伪共享的问题。
Disruptor 中有一个 RingBuffer 类会经常被多个线程使用,代码如下:
你可能会觉得 RingBufferPad 类里 7 个 long 类型的名字很奇怪,但事实上,它们虽然看起来毫无作用,但却对性能的提升起到了至关重要的作用。
我们都知道,CPU Cache 从内存读取数据的单位是 CPU Line,一般 64 位 CPU 的 CPU Line 的大小是 64 个字节,一个 long 类型的数据是 8 个字节,所以 CPU 一下会加载 8 个 long 类型的数据。
根据 JVM 对象继承关系中父类成员和子类成员,内存地址是连续排列布局的,因此 RingBufferPad 中的 7 个 long 类型数据作为 Cache Line 前置填充,而 RingBuffer 中的 7 个 long 类型数据则作为 Cache Line 后置填充,这 14 个 long 变量没有任何实际用途,更不会对它们进行读写操作。
另外,RingBufferFelds 里面定义的这些变量都是 final
修饰的,意味着第一次加载之后不会再修改, 又由于「前后」各填充了 7 个不会被读写的 long 类型变量,所以无论怎么加载 Cache Line,这整个 Cache Line 里都没有会发生更新操作的数据,于是只要数据被频繁地读取访问,就自然没有数据被换出 Cache 的可能,也因此不会产生伪共享的问题。
作者:小林
来源:https://mp.weixin.qq.com/s/zeGxBx77TFGtVeMRBVR-Lg
2021年互联网公司“死亡”名单,看看有没有你的老东家
几年前我就知道IT桔子一直在统计互联网公司的死亡清单,没想到他们一直坚持在做,目前统计了2014年至2022年,随时更新,上榜公司表示:简直是社死现场!
这里面包括也很多的知名公司,如:
找ofo小黄车 、学霸君、环球易购、叮咚快买、菜鸟团、巨人教育、买卖宝、DaDa英语等
因为是公墓嘛,所有还有一个让人哭笑不得的功能,就是“上香“,你要不要为你已经倒闭的前公司上个香呢?
在这份名单中,清晰的记录了公司名称,存活时长、倒闭时长、所属行业、公司地点、成立时间、获投状态,我们根据行业来看看,2021年总计倒闭公司821家,都是什么情况。
2021年《教育类》公司死亡清单
2021年《金融类》公司死亡清单
2021年《游戏类》公司死亡清单
2021年《区块链类》公司死亡清单
总计分为23个大类,详细的可以去IT桔子的网站查看。
如:手机游戏类公司 公司死亡795家,死亡原因70%都是因为资金问题。
如:交友社区类公司 公司死亡464家,死亡原因40%都是市场定位有问题,30%的原因是产品问题,也有10%的原因是资金问题。
针对除了行业的大类分析,每个公司的死亡原因也进行了详细说明。
如买卖宝,存活时间有14年2个月,曾经获得过红杉资本、腾讯、京东等的融资。估值97.5亿元。
死亡原因:竞争不足。
如杰睿教育,存活时间有10年9个月,曾经获得过赛领资本、千帆资本、真格基金等的融资。估值26.6亿元。
死亡原因:政策监管。
数据说明
死亡公司数据库网页声明:
一、本网页基于IT桔子投资数据库而打造的“死亡公司数据库”,致力于展现中国新经济领域近些年倒闭的创新创业公司;
二、“死亡公司数据库”的公司关闭时间是依据公开媒体报道及部分估算,可能会存在些许误差,但我们着力确保更高的可靠性;
三、IT桔子对所收录公司运营状况的判定来源如下:
1、公开媒体报道公司关闭、破产清算的;
2、公司自身在微信、微博等渠道宣布关闭、破产清算的;
3、公司明显经营异常:公司被注销;公司产品比如APP或微信持续6个月及以上没更新;公司因为监管被抓、无法经营……交叉比对后确认没有持续经营。
这几天也看了不少博主对2022年的进行了预测,但是,我们始终要相信:世界上唯一不变的是一直在变。特别是作为一名在互联网觅食的程序员,一定要提升自己的技术和管理能力,投资自己是最正确的选择。
对于那些想创业的朋友,一定要三思而后行,别一时想不开就出来创业!
守住自己的钱袋子,别乱投资!猥琐发育,只要还有本金,没下赌桌,就还有翻身的机会,不要梭哈!
2022年,我们一起加油!
作者:机器人的秘密探索
来源:https://www.sohu.com/a/515405099_121124372
收起阅读 »
腾讯三面:40亿个QQ号码如何去重?
大家好,我是道哥。
今天,我们来聊一道常见的考题,也出现在腾讯面试的三面环节,非常有意思。具体的题目如下:
文件中有40亿个QQ号码,请设计算法对QQ号码去重,相同的QQ号码仅保留一个,内存限制1G.
这个题目的意思应该很清楚了,比较直白。为了便于大家理解,我来画个动图玩玩,希望大家喜欢。
能否做对这道题目,很大程度上就决定了能否拿下腾讯的offer,有一定的技巧性,一起来看下吧。
在原题中,实际有40亿个QQ号码,为了方便起见,在图解和叙述时,仅以4个QQ为例来说明。
方法一:排序
很自然地,最简单的方式是对所有的QQ号码进行排序,重复的QQ号码必然相邻,保留第一个,去掉后面重复的就行。
原始的QQ号为:
排序后的QQ号为:
去重就简单了:
可是,面试官要问你,去重一定要排序吗?显然,排序的时间复杂度太高了,无法通过腾讯面试。
方法二:hashmap
既然直接排序的时间复杂度太高,那就用hashmap吧,具体思路是把QQ号码记录到hashmap中:
mapFlag[123] = true
mapFlag[567] = true
mapFlag[123] = true
mapFlag[890] = true
由于hashmap的去重性质,可知实际自动变成了:
mapFlag[123] = true
mapFlag[567] = true
mapFlag[890] = true
很显然,只有123,567,890存在,所以这也就是去重后的结果。
可是,面试官又要问你了:实际要存40亿QQ号码,1G的内存够分配这么多空间吗?显然不行,无法通过腾讯面试。
方法三:文件切割
显然,这是海量数据问题。看过很多面经的求职者,自然想到文件切割的方式,避免内存过大。
可是,绞尽脑汁思考,要么使用文件间的归并排序,要么使用桶排序,反正最终是能排序的。
既然排序好了,那就能实现去重了,貌似就万事大吉了。我只能坦白地说,高兴得有点早哦。
接着,面试官又要问你:这么多的文件操作,效率自然不高啊。显然,无法通过腾讯面试。
方法四:bitmap
来看绝招!我们可以对hashmap进行优化,采用bitmap这种数据结构,可以顺利地同时解决时间问题和空间问题。
在很多实际项目中,bitmap经常用到。我看了不少组件的源码,发现很多地方都有bitmap实现,bitmap图解如下:
这是一个unsigned char类型,可以看到,共有8位,取值范围是[0, 255],如上这个unsigned char的值是255,它能标识0~7这些数字都存在。
同理,如下这个unsigned char类型的值是254,它对应的含义是:1~7这些数字存在,而数字0不存在:
由此可见,一个unsigned char类型的数据,可以标识0~7这8个整数的存在与否。以此类推:
一个unsigned int类型数据可以标识0~31这32个整数的存在与否。
两个unsigned int类型数据可以标识0~63这64个整数的存在与否。
显然,可以推导出来:512MB大小足够标识所有QQ号码的存在与否,请注意:QQ号码的理论最大值为2^32 - 1,大概是43亿左右。
接下来的问题就很简单了:用512MB的unsigned int数组来记录文件中QQ号码的存在与否,形成一个bitmap,比如:
bitmapFlag[123] = 1
bitmapFlag[567] = 1
bitmapFlag[123] = 1
bitmapFlag[890] = 1
实际上就是:
bitmapFlag[123] = 1
bitmapFlag[567] = 1
bitmapFlag[890] = 1
然后从小到大遍历所有正整数(4字节),当bitmapFlag值为1时,就表明该数是存在的。 而且,从上面的过程可以看到,自动实现了去重。显然,这种方式 可以通过腾讯的面试 。
扩展练习一
文件中有40亿个互不相同的QQ号码,请设计算法对QQ号码进行排序,内存限制1G.
很显然,直接用bitmap, 标记这40亿个QQ号码的存在性,然后从小到大遍历正整数,当bitmapFlag的值为1时,就输出该值,输出后的正整数序列就是排序后的结果。
请注意,这里必须限制40亿个QQ号码互不相同。通过bitmap记录,客观上就自动完成了排序功能。
扩展练习二
文件中有40亿个互不相同的QQ号码,求这些QQ号码的中位数,内存限制1G.
我知道,一些刷题经验丰富的人,最开始想到的肯定是用堆或者文件切割,这明显是犯了本本主义错误。直接用bitmap排序,当场搞定中位数。
扩展练习三
文件中有40亿个互不相同的QQ号码,求这些QQ号码的top-K,内存限制1G.
我知道,很多人背诵过top-K问题,信心满满,想到用小顶堆或者文件切割,这明显又是犯了本本主义错误。直接用bitmap排序,当场搞定top-K问题。
扩展练习四
文件中有80亿个QQ号码,试判断其中是否存在相同的QQ号码,内存限制1G.
我知道,一些吸取了经验教训的人肯定说,直接bitmap啊。然而,又一次错了。根据容斥原理可知:
因为QQ号码的个数是43亿左右(理论值2^32 - 1),所以80亿个QQ号码必然存在相同的QQ号码。
海量数据的问题,要具体问题具体分析,不要眉毛胡子一把抓。有些人完全不刷题,肯定不行。有些人刷题后不加思考,不会变通,也是不行的。好了,先说这么多。我们也会一步一个脚印,争取每篇文章讲清讲透一件事,也希望大家阅读后有所收获,心情愉快。
作者:爱码有道
来源:https://mp.weixin.qq.com/s/YlLYDzncB6tqbffrg__13w
别被你的框架框住了
我短暂的职业生涯被 React 充斥着。
还没毕业前我从 Vue 2.x 入手开始学习框架,在一个我当时觉得还行现在回看完全不行的状态进了公司。然后开启了跟 React 死磕的状态,从 class 组件到函数式组件,从 Redux 到 Recoil,从 Antd 到 MUI...
不久前一个呆了2年多的项目成功结束,接下来要去一个新项目,新项目要用 Angular,于是我开始告别从毕业就开始用的 React,开始学习这个大家少有提及的框架。
得
回顾这几年,要说 React 带给我最多的是什么,我觉得可能是思想,是一种编程范式。为了理解 React 新的函数式组件,我去学习 FP,但我并不是一个原教旨主义者,所以我当然也不认同你想学 FP 就得去学 Lisp 的说法。
在这期间我发现小黄书的作者 Kyle Simpson 也写了一本专门为 JSer 介绍 FP 的书,书中前言部分我深以为然:
The way I see it, functional programming is at its heart about using patterns in your code that are well-known, understandable, and proven to keep away the mistakes that make code harder to understand.
是的,编程范式的作用是为了让人们更好地组织和理解代码,编程范式应该去服务写代码的人,而不是人去事无巨细地遵循编程范式的每一个规则,理解每一个晦涩难懂的概念。
I believe that programming is fundamentally about humans, not about code. I believe that code is first and foremost a means of human communication, and only as a side effect (hear my self-referential chuckle) does it instruct the computer.
敏捷需要以人为本,写代码其实也一样。我们要做的应该是理解编程范式本身以及它背后的作用,或许在未来的某天你会突然发现,原来我用了这么久的这个玩意儿有一个这么有意思的名字,亦或者你可能永远也解释不清楚那个概念到底是什么:
A monad is just a monoid in the category of endofunctors.
一个单子不过是自函子范畴上的幺半群。
那是不是搞不懂我就不能玩 FP 了?然后我就得站在鄙视链底端,被 Haskell、Lisp 玩家们指着鼻子嘲笑:你们看那家伙,其实啥也不懂,他那也叫 FP?
这个问题我没有答案,或许可以留给大家来讨论。但是到这里我至少明白了 React Hooks 为什么要叫 "hook";为什么有一个 hook 叫 "useEffect";我也理解了为什么大家都说不要用 hook 去实现 class 组件的生命周期。
除了写好 React 本身,我也尝试了纯函数、偏函数、柯里化、组合和 Point-free 风格的代码,确实得到了一些好处,也确实带来了一些不便。
可能这些思想就是学习 React 带给我最大的 side effect 吧(笑。
失
与 React 准备 all in FP 相反的是,与 Angular 短暂接触的我发现它全面拥抱 OOP。与当时 React 从 class 组件切换到函数式组件一样,首先你得把编程范式思想完全转变过来才能很好地理解 Angular。这又促使我不得不去复习许多被我丢弃很久的 OOP 思想。
到这我不禁想起一次公司内 TDD 训练营,作业完成后去找 coach 讲解,讲解过程中 coach 讲到了抽象能力、隔离层、防腐层。那时我才发现自己 OO 的抽象能力和一起的后端小伙伴一比实在是差到不行,只有大学时候的能力。反思过后像是被 React 给“惯”坏了,几乎已经丢掉了这部分能力。
老实说我接触 React class 组件时间并不长,第一个项目只有短短几个月。后面两个项目虽然去写 Java 了,但是第一个都是一些修修补补的工作,更像是在做 DevOps,后来的项目去写 Java BFF,毫无抽象可言,全是数据 mapping。然后又进到了一个将“追求技术卓越”贯彻执行的项目,成了那批最早吃函数式组件螃蟹的人。
于是我接触 class 组件的时间就只有作为毕业生的那短短几个月而已。
然后当我看到 Angular 文档中的依赖注入时,我脑子只能零星蹦出一些概念:SOLID、解耦。别说细节,我甚至不知道我蹦出来的这些东西是不是对的。于是我又只能凭着自己的记忆去邮件里搜相关的博客大赛的文章。
我好像已经丢掉了 OOP 了。
种下一棵树最好的时间是十年前,其次是现在。
悟
跳出all in FP 的 React 我发现世界不是非黑即白的。说是全面拥抱 OOP,但其实你可以很轻易的在 Angular 中发现 FP 的影子 -- 用 pipe 来处理数据,用 Rx 来处理请求。
既然是以人为本,编程范式本就不应该对立,它们明明可以互补,在自己擅长的领域处理自己擅长的事情,哪怕是同一个项目。看惯了两个阵营吵架的场景,好像这样的场景才是我想要的。
于是我又回忆起某天在项目上和大家讨论的项目分包问题,最后的结论是 OOP 的以对象和 domain 分包的策略在大多数时候要优于单纯的 FP 的方式。它能让功能更集中,让大家更容易找到自己想要找的东西。
但是回过头来静静思考,我虽然会好好学习 OOP,但是我目前大概率不会去深入学习相关的建模方法。因为在目前我的工作环境下,我没看到有前端同学需要深刻理解建模方法的场景,大多数情况浅尝辄止即可。
以我自身的经历来看,DDD 我看过也参加过培训,也跟着项目后端小伙伴在搭建项目时从零到一实践过。但是在实践不多的情况下,整个过程逃脱不了学了忘忘了学的魔咒。大概唯一的用处就是当我被抓到后端去干活能看懂他们为什么要这么组织代码,至于建模的那个过程,被抓去干活的我是大概率不会参与的。(当然如果你有相关的经历还请喷醒我,比如你作为偏前端的小伙伴就是要熟练掌握建模方法,不然工作就做不下去了)
不要被技术栈限制住了自己,其实以前一直对这句话一知半解,虽然可能现在的理解也没有很强。可是当你从一个框里跳出来以后,去思考画框这个人的想法,你可能能够得到一些不一样的思考。对于 Thoughtworker 来说学习一个新框架,一门新语言可能不是什么问题,那我们是不是可以更进一步,想想那些看起来“虚无缥缈”的东西呢。
别被你的框架框住你了。
作者:Teobler
来源:https://juejin.cn/post/7032467133611294733
环信广纳人才,base北京,欢迎大家踊跃跳槽/推荐~~ps:双休不加班
1、高级Android开发工程师:
1. 3年及以上Android开发经验,具有成熟Android APP产品开发经验者优先;
2. 熟练掌握Android SDK,Java,设计模式,http,多线程编程者优先;
3. 有NDK开发经验优先;
4. 熟悉Android Framwork,插件开发,有APP架构设计优先;
5. 有SDK开发经验优先;6.有IM开发经验优先
2、iOS开发工程师:
1. 3年及以上iOS开发经验,具有成熟iOS APP产品开发经验者优先;
2. 熟悉iOS框架以及各种特性,深刻理解常用设计模式, 熟练使用网络、多线程、数据库等客户端开发技术;
3. 扎实的Objective-C或Swift语言基础;
4. 分析问题和解决问题的能力强,有大规模代码的阅读和修改经验者优先;
5. 有较好的学习能力和沟通能力,有创新能力和责任感,对移动端产品有浓厚的兴趣;
3、前端工程师:
1. 计算机及相关专业本科及以上学历,至少3年以上前端开发工作经验;
2. 有丰富的Web前端开发经验,熟悉HTML5开发,浏览器渲染原理,熟悉React框架;
3. 工作认真负责,乐观开朗,有较强的逻辑分析、问题排查能力,善于团队合作;
4. 良好软件工程思想,良好的编程能力和编程习惯;
5. 熟悉HTTP、WebSocket等协议;
6. 有针对海外开发者产品经验的优先考虑;
7. 有SDK开发经验者优先考虑;
4、高级SDK跨平台开发工程师(Flutter/Electron/RN/Unity/Unreal):
1. 熟练使用 Java script/C#/Dart 其中至少一种以上开发语言。
2. 熟悉使用 C++,有多语言混合开发经验。
3. 有过 Android/iOS/Windows/macOS 其中至少一种原生平台应用的开发经验。
4. 使用过跨平台框架,有框架和原生混合开发经验。例如:Electron/ Unity/Flutter 其中的一种或者多种。
5. 有即时通讯相关的开发经验属于加分项。
6. 有跨平台框架的插件,中间件或者 SDK 开发经验属于加分项。
7. 本科及以上学历, 有两年以上的工作经验。
5、中高级后台工程师(Erlang/Go/C++):
1. 3年以上软件工程师工作经验,有Erlang,Go,C++经验或感兴趣优先;
2. 大型通讯软件,通讯协议开发经验优先;
3. 计算机科学、自动化、通讯等相关专业本科以上学历;
4. 熟悉TCP/IP,HTTP、WebSocket协议;
5. 熟悉SQL、Kafka、Redis;6.熟悉Linux操作系统;
6、中高级Java工程师:
1. 3年以上大型互联网分布式产品或网络软件设计经验;
2. 强大的需求分析能力与编码能力;
3. 精通Java语言,精通异步编程、多线程编程;
4. 精通Spring、Spring Boot、Sp;
7、产品经理:
1. 5年以上to B产品规划与设计经验,3年及以上互联网产品工作经验,计算机或相关专业本科以上学历,有IaaS、Paas、中台方向相关经验者优先;
2. 具备良好的需求分析和产品设计能力,熟练使用Axure/Sketch等产品原型工具;
3. 具备丰富的PaaS平台相关经验,理解PaaS、SaaS等架构逻辑,对业界领先的云平台有一定研究;
4. 对产品的发展趋势有敏锐的洞察力和创新意识,重视细节与用户体验,对用户使用流程、交互流程敏感;
5. 2年以上B端产品经验;6.有研发经验可以作为加分项;
8、初级测试和高级自动化测试工程师:
1. 计算机本科及以上学历;
2. 2年以上自动化测试经验;
3. 熟悉mysql或者相关数据库,能熟练编写sql脚本优先;
4. 熟悉Java\\Python和Linux操作系统;
5. 熟悉自动化测试,熟悉robot framework\\Appium\\Selenium等测试框架,有多个大型实际项目自动化测试经验者优先;
6. 良好的表达沟通能力、细致、责任心、团队精神;7.具备追求卓越的质量观念,并有志成为测试领域的高端人才。
9.运维工程师:
1. 有3年以上互联网系统运维工作经验。
2. 熟悉Linux操作系统的管理维护(部署、配置和调优),熟练使用Linux Shell或Python或者golang编程语言。
3. 熟悉Docker以及相关容器技术,使用过docker-compose、mesos 等容器编排工具,进行过开发维护经验者优先。
4. 熟悉Prometheus等常用监控软件。
5. 熟练使用nginx, redis, kafka 等常用软件,并进行调优。
6. 熟悉TiDB或者CockroachDB优先。
7. 热爱运维工作,能承受压力,具备较强的问题分析和解决能力。
8. 积极主动、责任心强,良好的沟通能力和团队协作精神。
10、高级产品市场经理
岗位职责:
1.负责环信即时通讯云的价值挖掘、内容组织并推动将产品及价值传递给用户,主要产出物为:产品技术及解决方案干货内容;客户案例;产品彩页;产品PPT;市场软文;市场活动演讲PPT;官网内容;市场活动产品资料等
2.行业研究,分析行业及竞争对手动向,为产品团队提出产品定位建议
3.做为公司产品对外接口, 不定期参加公司对外直播公开课演讲以及行业会议演讲
任职资格:
1.有技术背景,懂得如何与研发团队、销售及用户沟通和协作;
2.熟悉通讯云领域SaaS、PaaS产品,理解并挖掘相关产品核心价值;
3.沟通能力强,写作能力强;
4.有IM通讯云领域市场分析,行业分析,顾问咨询经验者优先;
5.有产品经理或项目经理经验者优先;
6.本科以上学历;
7.5年以上工作经验;
--------------------------------
以上岗位如有意向,可私信我,咱们内推搞起来!
成功推荐朋友入职可获奖励5000~20000元,欢迎大家踊跃推荐!
最新·前端的工资分布情况 - 你拖后腿了吗?
前言
要说我们工作最关心的东西肯定少不了这两个方向:
- 我们前端开发的工资分布情况
- 技术更新的风向
今天我就和大家分享小生最近收集的一些数据。
关于行业的平均薪资水平我们一定不要拿一些特例当成范例。最能反应行业的平均薪资的指标应该是正态分布的中间值。
再说明一点:
知乎和脉脉上的薪资水平比整体偏高,不建议作为依据。
总体分布情况
我们先看一下每个工作年限对应的平均工资是多少(这里只收集了北上广深杭五个城市)
工作年限 | 应届生 | 1-3年 | 3-5年 | 5年+ | 可信度 |
---|---|---|---|---|---|
北京 | 9.5K | 13.7K | 19.5K | 25.9K | 较高 |
上海 | 8.8K | 12.9K | 17.6K | 22.5K | 较高 |
深圳 | 9K | 12K | 15.9K | 21.8K | 较高 |
杭州 | 8.9K | 11.7K | 15.8K | 20K | 存疑 |
广州 | 7.9K | 10.1K | 13.6K | 17.8K | 不高 |
数据来源: http://www.jobui.com/salary/?cit…
说明:
- 应届生的样本数相对来说少了很多,可信度不会很高。
- 这里没有按学历区分,所以 985 高校的同学可能觉得偏低。
绝大多数人,3-5 年经验,薪资范围基本都在 15k - 20k。所以千万不要妄自菲薄。
北上广深杭平均工资
- 这部分的数据来源于 - 职友集
全国
- 全国 平均工资为: ¥12330(这个数据基本被一线城市平均了)
- 分布最多的区间为:10K 到 15K
北京
- 北京 平均工资为: ¥18770
- 分布最多的区间为:20K 到 30K
上海
- 上海 平均工资为: ¥16220
- 分布最多的区间为:10K 到 15K
深圳
- 深圳 平均工资为: ¥15090
- 分布最多的区间为:10K 到 15K
广州
- 广州 平均工资为: ¥11390(广州表示不服,竟然没有全国平均高?)
- 分布最多的区间为:10K 到 15K
杭州
- 杭州 平均工资为: ¥14350
- 分布最多的区间为:10K 到 15K
后话
我也看了下看准网发布的数据(不分地区的平均工资达到了 ¥19800)和一些其他来源的数据。结合个人的经验,认为这份数据还是比较客观的。
作者:小生方勤这次你是否又拖后腿了呢?
来源:https://juejin.cn/post/6844904082193268749 收起阅读 »
iOS - UIApplication
一、UIApplication
1.简单介绍
(1)UIApplication对象是应用程序的象征,一个UIApplication对象就代表一个应用程序。
(2)每一个应用都有自己的UIApplication对象,而且是单例的,如果试图在程序中新建一个UIApplication对象,那么将报错提示。
(3)通过[UIApplication sharedApplication]可以获得这个单例对象
(4) 一个iOS程序启动后创建的第一个对象就是UIApplication对象,且只有一个(通过代码获取两个UIApplication对象,打印地址可以看出地址是相同的)。
(5)利用UIApplication对象,能进行一些应用级别的操作
2.应用级别的操作示例:
(1)设置应用程序图标右上角的红色提醒数字(如QQ,微博等消息的时候,图标上面会显示1,2,3条新信息等。)
@property(nonatomic) NSInteger applicationIconBadgeNumber;
代码实现和效果:
(2)设置联网指示器的可见性
【开奖咯!】回帖晒晒端午节你们公司都发了什么?顺便抽个奖!~
开奖咯!本次使用excel开奖,真实随机(参考链接https://www.excelhome.net/316.html)。
部分用户回帖不符合活动要求,不参与本次开奖。
参与回帖的10个随机幸运伙伴是:
获得点赞最多的
柳天明 5
AuCf 4
Lambert 3
获得3个最惨伙伴:
yangjian、春春、孤狼☞小九
请以上同学在6月17日 23:59前,将你的收件人,地址,电话,衣服图案(星空/字母)+尺码(L-3XL)信息发站内私信给@admin,超过领取截止时间未提交信息,视为放弃领取~
感谢大家参与!下次见~
=================================
首先祝各位端午安康
然而端午来临之际,各种群兴起了一些攀比之风
有这样的
还有这样的
还有这样的
然而我是这样的:
不过节日没福利的同学们也没关系.环信精心为大家准备了端午福利 有福利的也可双喜临门!!!
活动规则
- 活动时间:即日起至 6 月 15 日 中午 12:00 截止
- 参与方式 :在本篇帖子下留言关于端午福利或端午计划的回复(图文皆可,发图请单独开帖然后链接回到本帖下方)
- 活动结束后,将从所有参与回帖的用户里随机抽取10人,赠送imgeek定制T恤。😉
- 并且选出3个端午福利寒酸的盆友赠送夏日清凉挂脖风扇😆
- 点赞最多的前3名直接获得一件T恤!
- 获奖名单将会在 6 月 15 日公布于本篇帖子下。