高阳Sunny

高阳Sunny 查看完整档案

北京编辑中国科学院  |  联想之星 编辑SegmentFault  |  CEO 编辑 segmentfault.com/lives 编辑
编辑

SegmentFault 思否 CEO
C14Z.Group Founder
Forbes China 30U30

独立思考 敢于否定

曾经是个话痨... 要做一个有趣的人!

任何问题可以给我发私信或者发邮件 sunny@sifou.com

个人动态

高阳Sunny 赞了回答 · 1月16日

程序员遇到不专业的产品怎么办

能这么问的一定是互联网公司,外包公司基本没这回事儿,规格说明书可不是说变就变的。

这事儿的本质不是需求改不改的问题,其实是定责的问题嘛。

需求改了,原本的计划时间表要不要推翻?由此产生的延误、Bug 等风险谁来承担?工期变长了要加班怎么办?其实绝大部分人在意的是这些,而不是需求真的改没改。

如果需求即使改了,工期变长就变长你还不加班、到点儿正常走,延误的锅产品自己背,对你的绩效、OKR 等等没有任何影响,那他爱咋改咋改呗,为啥要不爽?

都不想背锅,那就立好规矩。进入开发前,需求想咋改咋改;进入开发后,需求要改,可以,开发要参与评审,不能产品自己说三天改完就是三天;每次迭代小步快跑,周期定短,本周期一旦开始开发,需求锁死,想改,对不起,等下周期再评审吧。

要是一开始就立不下来规矩,要么他走,要么你走,还废话干啥?这都已经不是产品的问题了,是公司在管理层面就有大问题,再待下去只会有更糟心的事儿。

关注 3 回答 3

高阳Sunny 赞了回答 · 1月16日

程序员遇到不专业的产品怎么办

这要看需求的类型,是加需求,还是改需求。

加需求:如果缺失该部分需求会影响产品的闭环,那双方都有问题,需求讨论会最起码要让产品流程、逻辑无大问题,缺失必要功能的产品无法达到上线的标准,如果不影响,那就需要跟产品协商是当前版本完成还是延期到下一个版本。

改需求:如果当前改动直接颠覆原先逻辑,那就要问清楚,到底是怎么回事,最好有领导确认,再重新排期。

关注 3 回答 3

高阳Sunny 赞了文章 · 1月16日

微软:开源现已成为跨公司协作的公认模型

微软:开源现已成为跨公司协作的公认模型

微软曾经是专有软件最纯粹的供应商之一,但在过去的十年里,它已经在某种程度上摆脱了这种形象。微软今日在一篇博文中表示,它从与开源世界的日益接触中学到了很多,并补充说,开源现在也是公司之间协作的“可接受的模式”。

2020 年,微软开源了更多自己的技术,该公司还与谷歌和 IBM 一起创建并加入了开源安全基金会(OSSF),并成为谷歌开源 Chromium 项目的最大外部贡献者。

微软表示,整个行业对开源技术的接受鼓励了跨公司的合作,尤其是在科技巨头之间,这些公司可以绕过大部分的律师业务,在几周内而不是几个月内联合起来。这凸显了开源在将世界上的大型科技巨头联合起来中所扮演的角色。

微软首席技术官 Azure Office 的开源主管 Sarah Novotny 说:“几年前,如果你想让几家大型科技公司在一个软件项目上联合起来,建立开放标准,或者就一项政策达成一致,通常需要几个月的时间与律师进行谈判、会议、辩论... ... 开源已经完全改变了这一点,当我们看到新的趋势或问题出现时,我们知道最好是共同解决这些问题,我们将在几周内走到一起,并使用既定模型来指导工作。”

微软强调了从开源投资中学到的几个方面,包括倾听社区反馈的重要性; 帮助员工在自主权和遵守公司政策之间找到平衡的必要性; 以及为什么“过度沟通”有助于消除不确定性和压力。

开源的兴起

快速浏览一下过去几年开源领域的情况,就会发现开源对于各种规模的企业来说是多么关键,IBM 以 340 亿美元收购了开源软件制造商 Red Hat,Salesforce 以 65 亿美元收购了 Mulesoft,微软自己也为 GitHub 提供了75亿美元。此外,如今所有的大型科技公司都依赖于开放源码项目,并为其做出贡献,同时在开放源码许可证下提供自己的许多工具。

在这充满挑战的一年中,大多数全球劳动力迅速转向远程工作,微软表示,世界可以从开放源码领域学到很多东西,由于其固有的全球分布,这个领域一直不得不拥抱远程优先和“数字优先”的思维模式。

Sarah Novotny 说:“对于我们这些深深地从事开放源代码的人来说,远程工作一直是我们的常态,因为开放源代码社区庞大,分布在全球各地,并且需要来自世界各地的开发人员的有效合作。”

segmentfault 公众号

查看原文

赞 1 收藏 0 评论 0

高阳Sunny 赞了文章 · 1月16日

CI/CD 平台迁移实践:从 Travis-CI 转移到 Github Action

LCTT 的 CI 已经在 Travis CI 上运转了多年,一致保持着良好的使用体验。自 2019 年 Github 推出了自家的 CI 工具 Github Action 后,我们就在考虑将 CI 从 Travis-CI 迁移到 Github,以降低维护和沟通的成本,并借助于 GitHub Action Marketplace 实现更强的功能。

项目首页

最近,因为 TravisCI 屡屡部署出错,而我们的账户因为使用的较多,已经超出了免费使用的限制,以此为契机,将 CI 从 Travis CI 迁移到 GitHub Action。

Travis CI 的提醒

项目介绍

Translate ProjectLCTT 翻译组的主要协作项目,几百位译者通过 GitHub 进行围绕开源、Linux、软件工程等领域的文章翻译,从 2013 年来,累计了大量的提交,致使项目下有非常多的文件。

Translate Project 借助于 CI 帮助译者对基本的文章格式和拉取请求进行检查;并定时执行命令,以进行所有的申请检查,对于超时未完成翻译的工作进行回收;对于文章的状态进行标记,生成相应的徽章。

生成徽章

迁移思路

Travis CI 和 Github Action 在使用方面,其实总体差异不会太大,都是基于 YAML 文件格式来编写配置文件。不过,和 Travis CI 不同的是,Github Action 支持多个不同的配置文件,因此,你可以根据不同的场景,设定不同的配置文件,降低单个配置的文件的复杂度。

此外,由于我们的脚本中依赖了一些 Travis CI 的环境变量,也需要将其替换为 Github Action 中的相应环境变量,从而确保脚本可以运转。

改造实践

1. 分析之前的 CI 流程

我们在 TravisCI 上的 CI 配置文件如图

配置文件

总体可以分为三块:

  1. 命令区:说明了安装阶段和执行阶段的操作有哪些
  2. 条件区:指定了这个配置文件在哪些条件下会生效
  3. 部署区:写明了构建产物如何进行部署

在命令区中,有预置的安装过程和后续的执行过程。在安装过程中,安装了一些依赖,并将当前的 pages 资源克隆到本地,以继承上一次构建生成的资料。

在条件区则指明了仅作用于 master 分支

在部署区便是将前面命令区的执行结果进行部署。

基本流程

在实际的执行过程中,还会根据环境变量不同,决定是否要执行特定的命令,这部分在后续的改造过程中,就可以调整部署,拆分到不同的文件中。

构建流程

2. 直接套用配置文件

在完成了基本的分析后,就可以建立新的 Action 配置文件了。由于基本的语法很类似,对于其中的不少内容可以进行直接套用。

比如,我们的配置文件在直接套用后,结果如下

直接套用后的结果

直接套用的文件已经可以直接运行,不过,这里有很多不满足需要的地方,所以需要做一些修改。

3. 恢复 Travis CI 的环境变量

由于我们使用的 Badge 等生成脚本并非我所编写,所以在这一次的迁移中,并不打算对齐进行调整,以避免出现故障。而脚本中依赖了一些变量,需要将其重新设置出来。

Github Action 提供了一些方法,可以让你手动设置环境变量。你可以在你的构建的步骤中,加入如下代码,从而在构建环境中设定 TRAVIS_BRANCHTRAVIS_EVENT_TYPE 环境变量,确保你可以使用这个环境变量。

 - name: Set ENV variables
        run: |
          echo "::set-env name=TRAVIS_BRANCH::${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')}" 
          echo "::set-env name=TRAVIS_EVENT_TYPE::$(if [ "schedule" == "${{ github.event_name }}" ]; then echo "cron"; else echo "${{ github.event_name }}"; fi)"

此外,由于 set-env 这个方法相对比较危险,你还需要在环境变量中,开启危险函数的执行。

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      ACTIONS_ALLOW_UNSECURE_COMMANDS: true

4. 拆分配置文件

Github Action 和 TravisCI 不同的一点是你可以将你的 CI 文件拆分成多个文件,从而降低每一个单独的配置文件的复杂度。

根据前面对于流程的分析,可以将我们的 CI 流程拆分成三个部分:

  1. 生成 badge 文件,应当跟随每一次提交进行
  2. 生成 status 文件,执行时间较长,可以定期执行
  3. 根据拉取请求内容进行整理,做核验

则将我们的配置文件拆分成三个不同的文件:

也得益于拆分开,则在 checker 中就可以免于安装一些必要的依赖,从而精简 CI 流程,提升 CI 的执行时间。

5. 测试 CI 的运行情况

在完成了配置文件的编写和拆分后,就可以进行本地的执行测试。Github Action 写完了,难免要执行一下,确保整个流程是正常的。

这个时候你可以安装工具(https://github.com/nektos/act),来在本地执行 Action ,从而确认你的代码执行是正确的。

如果你是 macOS ,只需要执行 brew install act 就可以安装 act 工具,来完成 act 的安装。

安装完成 act ,就可以通过执行 act 命令来在本地执行 Action ,比如,执行 act pull_request 来触发 GitHub 的拉取请求事件

通过本地测试后,再将你的配置文件推送到 GitHub 上,进行生产环境的测试即可。

6. 移除 Travis-CI

通过上述的一些步骤,我们完成了从 Travis CI 到 GitHub Action 的迁移,此时,就可以移除项目根目录中的 .travis.yml 文件,彻底关闭 Travis CI。

7. 替换环境变量

在完成了基本的迁移后,需要对代码中的一些历史问题进行修复。在第三步中,我们对于 Travis-CI 的环境变量进行替换,但长期维护的项目应当尽量将这些未标注上下文的信息替换为有文档标注的,因此,我们需要将其替换。

替换环境变量主要依赖 Github 官方的环境变量说明,你可以参考官方文档

简化后,配置文件从之前的 27 行,减少至 17 行,变得更加的精简、易懂。

8. 修改 GitHub 的分支保护条件

为了确保修改符合标准,我们限制了新的拉取请求必须通过 CI 检查,才能合并进入 master 分支,因此,也需要修改相应的分支保护规则,确保设定相应的保护。

一些注意事项

1. 环境变量不同

如果你依赖了环境变量,则需要进行相应的修改。或者可以像我一样,先通过 set-env 来让本地拥有临时的环境变量,后续再逐步进行迁移。

2. Action 运行依赖要注意安全

Action 执行过程中会有两个部分。Action 本身流程依赖于 master 分支,但执行过程中调用的脚本是根据源决定的,因此,从安全角度来看,你应当尽可能将所有的流程放在 Action 中,而不是放在你的源码目录中。

3. 如何触发 CI 的 Pull Request 检查?

在进行 Pull Request 测试的时候,需要不断触发不同的 Commit ,你可以通过执行 git commit --allow-empty -m "Trigger notification" && git push 来触发一个空白的 commit, 推送到 Github 后,就可以再次触发 pull request 的构建,提升构建的效率。

总结

通过对 TravisCI 的流程整理、代码修改等流程,我们将之前的 Travis-CI 迁移至速度更快、性能更好的 GitHub Action ,一方面可以优化我们的工作流,另一方面,也让我们的代码更加简洁明了。

对于还在使用 Travis CI 的项目来说,也可以考虑迁移到 GitHub Action 中,来优化自己的工作流。

参考阅读

查看原文

赞 7 收藏 1 评论 0

高阳Sunny 关注了用户 · 1月16日

MicrosoftReactor @microsoftreactor

微软 Reactor 上海 是微软为构建开发者社区而提供的一个社区空间,以“予力多元化社区建设,帮助每一个开发者成就不凡”为使命,旨在通过不定期举办的技术讲座、开发者交流会面及技术沙龙和专题活动,帮助开发者和初创企业了解最新技术、学习最新知识、体验最新方案、结识业界同行、扩展职场人脉。

Reactor 为开发者社区提供免费的活动场地,欢迎点击申请:https://developer.microsoft.c...

关注 1

高阳Sunny 赞了文章 · 1月16日

自动化 CI 的安全问题

最近几天在处理 LCTT 的 CI 迁移问题,在处理过程中,我觉得有必要聊一下 CI 的安全问题。

对于现在的开源项目而言,CI 几乎是标配,有了 CI,才可以很好的处理贡献者的贡献,机器完成一些检查,降低人工核验的压力。

但如果你的 CI 没有处理好,就可能为你的项目带来安全隐患。

现行的 CI 大多是基于一个配置文件进行的,比如 TravisCI 的 .travis.yml 、GitHub Action 的 .github/workflows/xxx.yml 等。我们会在其中撰写一些代码,来完成我们的核验功能。

不过,在实际的研发过程中,处于代码格式化、代码工程化等方式,我们可能会考虑将其中的一部分放在项目的一些子目录中来存储。

不过,将脚本放在项目工程中的单独文件也引入了安全问题

一般来说, CI 在执行命令的时候,会依赖源分支的配置文件进行,因此,我们无需担心相应的配置文件被篡改。

但 CI 在执行本地的脚本的时候,是使用的是当前分支下的文件,这就会为项目的留下安全隐患,比如一些恶意的开发者可以将恶意代码插入相应的脚本中,从而窃取一些重要的信息,比如各种 Secret 之类的。

想要解决有两个思路:

  1. 不在项目文件中放置 CI 所需的资料:将脚本中的命令放置在配置文件中存储,就可以避免恶意开发者修改 CI 文件。因此修改的 CI 文件并不会被执行。
  2. 将 CI 所需文件放置在另外一个地方:现行的 CI 都提供了常用的命令,你可以将所需的配置文件放置在另外的 repo 下,并在 CI 流程中,加入相应的 clone 或下载,从而确保在 CI 执行的过程中有所需的文件。这样只需要确保另外保存的 repo 中没有相应的恶意文件即可。

总结

CI 是个好东西,但如果你的写法和用法有问题,依然会为你的系统带来安全风险。

查看原文

赞 2 收藏 0 评论 0

高阳Sunny 赞了文章 · 1月16日

思否有约 | @小傅哥:无论工作还是生活,都是生命每一个值得被珍惜的瞬间

image.png
小傅哥(喜欢的动漫形象)

本期访谈嘉宾:小傅哥
访谈编辑:袁钰涵

引子

电影《心灵奇旅》结尾处,杰瑞问准备回到地球的高纳:“So what do you think you'll do?How are you gonna spend your life?”
(那你认为你会做什么?你将如何度过这一生?)

高纳回道:“I'm not sure.But,I'm going to live every minute of it.”
(我也不知道,但是,我会珍惜当下的每一分钟。)


刚完成对小傅哥的采访时,对于他在采访过程中多次提到的“我喜欢比客户跑远一步,提出更高的需求去完成,即使加班也没有关系”,并不太理解。

但采访结束后看了一部名为《心灵奇旅》的影片后好像懂了,因为我们总喜欢把工作和生活分得明明白白,仿佛加班会让我们成为可怜的社畜,但某种程度上,工作也是生活,我们在其中追求自我,付出了我们的精力和时间只为收获属于自己更绚烂的人生。

小傅哥把工作和生活放在了一起,珍惜当下的每一分钟也包括了珍惜工作中的每一个任务,正是这些人生中的碎片组成了他。

在采访过程中,他说得最多的一句话就是:很顺利,我的生活没有太多的故事或困难。

仿佛在和我说:我没有什么不同,和许许多多的程序员都一样,顺着生活轨迹走到了今天。

是不是和许多程序员一样我并不知道,但是我知道的是——他的顺利和幸运都来源于他对生活的珍惜以及对人生的负责。

顺利在何处?

一本顺产的优秀书籍

小傅哥曾出过一本名为《重学 Java 设计模式》的书,当提到出书历程时,问小傅哥:“会不会觉得很难熬,有的作者形容出书就像难产”,小傅哥说:“并不是,它是顺产的,沉淀积累到了一定程度,它就出来了。”

这本书的诞生来自于小傅哥平时在思否这类社区平台分享的文章,他喜欢写这些文章,于他而言,写文没有什么 KPI,也没有什么压力,这不过是对于自身工作经验的沉淀,他用文章记录下那些他认为值得被记录的项目,其行为就像手账爱好者用手账本记录今日发生事件一般,究其本质都是对生活的记录与回顾。

后来这些文章在平台获得了不错的反响,也有许多朋友在平台中与小傅哥进行探讨,大家互相学习,在一次次讨论中成为前行路上的伙伴,而这些项目是链接彼此的介质。

项目文章越来越多后,链接的伙伴也越来越多,小傅哥像,如果把它整理成书籍,不仅是对这段日子总体的回顾,对自身有更深层次的沉淀,同时也能帮助到许多想学习 Java 的朋友,如此般,《重学 Java 设计模式》便水到渠成地诞生了。

后来这本书收获了不俗的成绩,还冲上了 Github 全球推荐榜,小傅哥用“羞答答的成绩”来形容这份喜悦。

没来得及经历的职场小白时光

初入职场,许多人单是适应工作节奏就已经筋疲力尽了,但小傅哥并没有经历过这种“职场小白”的时光。

读大学时学习的内容有许多都是进行考试、理论性操作,小傅哥感觉这样对于后期的职业发展不太好,于是那时混迹各种大佬建的 QQ 群。

这里发生了一件非常好玩的事情,当时作为一个有理想的青年,小傅哥混迹各种 Q 群后发现,许多群都是水聊天,有用的群并不好找。

没有条件就要创造条件,他把群内认识爱聊技术的,人单独创了群,名称叫东软帝国 ,当时说着要成为东北最大的软件帝国,后来某年发现真的有家公司叫东软,与朋友提起仍会相视一笑。

技术群内能学到很多东西,群内看到看到需要人的项目小傅哥就会去帮忙,于是到了真正毕业的时候,他已经做到:开发掌握得不错,需求能很顺利完成的程度了。

工作开始便能很好地完成需求,于是小傅哥不希望自己负责的内容只停留在完成这一步,他主动地提出更多需求,增加项目难度,这个习惯延续多年,成了他工作的常态,这种做法让他后期的职场生涯中少了许多焦头烂额的日子,倒是多了几分对于工作的热爱与优化项目的成就感。

这种做法一开始为我所不了解,后来我才明白于他而言生活与工作是一体的,那些项目是他生命中的一部分,对自己出品的东西填以热情,珍惜每一次接受委托的机会,这何尝不是对生命每一个瞬间的尊重。

对新生代程序员的一些建议

当初的项目讨论 QQ 群给了小傅哥很多帮助,这些年见证技术讨论群从 QQ 走到微信,其中不少还是小傅哥自己创建的,他仍非常建议新生程序员去加入大佬的微信群,虽然大家平时会水聊天,但在分享一些技术事件的时候,大家会认真地讨论与研究,这个过程中互相学习对方观点,某种程度上能拓宽自身视角,让程序员之路走得更宽更远,同样他自己也仍然在这些群里一边水聊天、一边探讨学习技术。

为何幸运?

热爱自身从事的行业

许多人在大学报志愿的时候,都是亮眼一黑,全家沟通进行了无数次大大小小的讨论才选定下来,最后可能因为家庭原因、学校问题、调剂问题,最后选择从事与专业毫无关系的工作或者跨专业考研,再给自己一次选择专业的机会。

但小傅哥的选择就简单而明晰,被问道为什么选择学计算机,他说好像无法选择一样,喜欢的东西和程序员的工作吻合度是如此的高,同时作为一名喜欢理工科的男同志,成为程序员成为了理所应当的事情。

他提到,如果一个人在迷茫的状态下选择了自身不喜欢的专业,日后的路会很困难,因为无法为自身带来愉悦感的工作,就很难提升到职业的高度,无法拥有归属感,在这种环境下工作,仿佛是被生活针对了一般,遇到困难也很难主动地想去克服,会有四处碰壁的挫折感。

所以感到自己能选择喜欢并且擅长的行业工作,是一件很幸运的事情,这让他拥有恒久的热情去投入到工作当中,这份热情如同熊熊燃烧的生命之火,点亮了他的人生。

幸运的职业生涯

小傅哥在一家偏传统的公司工作两年后,来到了互联网,工资提高的同时工作时长也变长了,面对这种改变,小傅哥很坦然地说:时间变长是为了更好的优化项目,对他而言,如果在固定时间内把需求完成并且做好,他是不会进行加班的,甚至还会提前离开。

工作中遇到的许多事情他都能从一个很积极的角度去面对。

从传统公司到互联网公司,当问小傅哥面试时感觉难吗,小傅哥没有直接说难度大还是小,而是回道“我从毕业到现在,一共面试了两次,一个是前公司,一个是现公司”。

面试的时候,小傅哥的兴趣爱好给了他很大的帮助,在日常生活中他喜欢写有关 Java 的东西、写开源项目、研究元码,即使自身可能没从事相关方面的工作,也会去看去写。

现在的小傅哥在一家不错的公司工作,小编问他要不要说一下东家的名字,小傅哥很快拒绝了这个提议,他说,现在还没有到能公布东家的程度,等到自己做出一些成绩后,再把自己和公司放在一起。

他的顺利和幸运都来源于他对生活的珍惜以及对人生的负责

小傅哥是一个优秀而不自知的人,许多他认简单且普通的事情,其实对于许多处于那个阶段的人而言,都是一个个需要去闯的难关,比如参加开源项目、跟着大佬们学做项目等等。

小傅哥说得风轻云淡,但谁也不知道他背后付出过多少努力,他很少提及这些付出,因为在他看来,那些努力都是向前走的助力,他从来不会认为给自己增加额外的工作量、加班是一件辛苦的事情,他接受这些存在,感谢这些存在为他带来的进步,甚至珍惜这些提升自我的时刻,然后感谢自己顺利又幸运的人生。

小傅哥对于工作的态度并非是“打工人”“搬砖”“恰饭工具”,他的经验与研究欲督促他不要机械化。

他很喜欢比需求方多走一步,通过自身的经验与思考,最后做出一个更优的项目能让他收获除了完成工作外的成就感,这些成就感来源与他与合作方对项目的认同,这些都是他工作的动力,在这个过程中他面临了加班,却又享受了成功。

不过对于这种态度,小傅哥坦诚地说:每个人会有自己的想法,不一样也正常,而他也并不是永远这么勤奋,只是他的兴趣刚好落在了研究上,对于一个项目进行深层次的研究与探讨能给他快乐,在生活中的其他事情上,他也有懒惰的时候。

无论工作上的勤奋还是生活中的懒惰,这些就是他对于人生的态度,该负责的时候负责,该偷懒就偷懒,在这种放松的状态下,享受自己短暂而又珍贵的人生。

坦荡、坦然还是他

虽然有时低调得都有点凡尔赛了,但小傅哥的确是个坦诚的人,说到为什么会在社区分享文章时,小傅哥特别实在地说:做这件事主要是对自身的一个沉淀,分享技术文章的时候,会有技术同好和自己一起讨论,交流的过程中会得到很多成长,这是属于他的学习方式,帮助他人的同时也收获了他人的帮助。后面还补上,当然阅读量也是支持作者走下去的重要因素。

对于写文、和工作小傅哥都把自己看的很清楚,而对于年龄,他更是坦然。

被问到年纪的时候,小傅哥利落地给出了一个数字:31,甚至他也很乐意和别人说自己已经是个工作 7 年的人,年轻有年轻的好,而成熟又有成熟的好。

网络上有许多关于这个年龄段的焦虑情绪,但小傅哥并没有为此所扰,循序渐进往下走就是他的态度,而职场中,只要仍旧拥有留下来和走出去的能力,其他事情倒不必去担忧那么多。

努力学习,充实自己,是他人生非常长一段时间的代言词,而这么做也不会让他感到生活如同紧绷的弦,难以支撑,因为这一切努力也好、奋斗也好,出发点不过是他对于工作与生活的珍惜,以及对那转而 30 年已过的人生衷心的感谢。


欢迎有兴趣参与访谈的小伙伴踊跃报名,《思否有约》将把你与编程有关的故事记录下来。报名邮箱:mango@sifou.com

segmentfault公众号

查看原文

赞 5 收藏 0 评论 2

高阳Sunny 赞了文章 · 1月15日

二零二零年终总结

前言

本文首发于我的博客,正在犹豫是否在思否上也发一遍,就看到了思否也在做年终总结,本文从较为感性的角度来总结过去的一年。

以下是正文部分。


回顾整个二零二零年于我而言最大的收获大概是:找到了方向,知道自己该做什么了。

在此前,我一直处于“不确定”状态,不确定是否要选择这条路,不确定是否足够热爱,不确定是否能坚持下去。

而此刻,我很清晰地知道自己该做些什么,想要些什么。

这篇博客主要从生活、工作、学习、思考、分享以及未来这几个方面简单总结下过去的一年。

关于生活

这部分放在这里其实有些多余,即便如此,我还是想表达出来,也许会有共鸣者呢

生活中的我,日常很简单。绝大部分时间都是宅在家里,不喜欢外出或者说不擅长社交。以前很少会觉得这样的日子是否会太孤独了。

不知为何,今年这种感觉尤其强烈。

生活在这个时代的我们似乎都太孤独了,无论是什么社会阶层、什么职业背景、什么性别状态,人就是孤独的。

渴望交流,却找不到合适的人; 渴望被爱,却害怕被伤害;

不久前看过一部电影《秒数五厘米》,里面有一句话给我的印象特别深刻——即使通了一千条短信,我们的心也只能拉近一厘米而已。

结合自己前些日子的一段经历,确实是这样,若只是排解寂寞,谁都可以取代。

关于工作

一谈到干我们这一行的,很多人可能第一反应可能就是加班,我并不反对加班,只是我们在加班时,应该思考一下为什么加班?

  • 是因为效率太低,本该工作时间内完成的事情,没有完成?
  • 是因为事情太多?
  • 还是只是因为老板没有走?

当我在谈论加班时,我谈些什么——不加没有意义的班。

关于学习

前段时间工作上出了一点事故——因为实体机没有设置防火墙导致被病毒入侵。

防火墙在我的印象中属于那种底层比较高深,晦涩难懂的东西,再加上基础知识的匮乏让我对防火墙频频感到恐惧。

如果对整体没有清晰的认识,只是盲目的网上搜查着别人写好的规则,运气好,可能能解决;
运气不好,可能还会导致服务器连接不上,别问我是怎么知道的...

而当需要面临比较复杂的定制化需求时,就更寸步难行了。

关于学习,这也是我一直想提醒自己的:务实基础,不要做“知识的搬运工”

附一张颇具讽刺意味的图:

附一张讽刺当代的开发者的图

不知何时,技术圈越来越喜欢贩卖焦虑了,每天醒来,面对大多都是这样的信息:

  • “关于 XXX 的那些你不知道的真相”
  • “吐血整理,万字长文搞定 XXX”
  • “全网最硬核解读 XXX 底层原理”
  • “搞定这道 XXX 面试题,大厂随便进”
  • “字节内部疯传的一份 XXX 失传资料”
  • ...

从侧面也反映出国内的软件开发者承担的职业发展压力。

和大部分人一样,我也时常会焦虑,但还是要对未来持乐观态度,毕竟高级人才无论何时都是紧缺的。

事实上,我们不得不承认一个残酷的事实——大部分从业者只是在做重复性、创新价值低的工作。这些工作在一定程度上会逐渐被取代,这不意味着这些工作会被取缔,而是更高效的完成。

通俗一点讲就是一个高手可以取代N 个低手。

关于思考

我一直觉得有三件事情在我们这个时代中极为重要,他们分别是:

  1. 编程
  2. 写作
  3. 英语

编程

毋庸置疑,技术改变世界。

写作

在这个信息爆炸的时代,为知识付费的行为已经逐渐被接受,付费渠道成为有效的过滤手段,也促使原创作者输出更高质量的内容。

当然写作能力并不是一蹴而就,需要不断积累、实践、总结。

从出来后,我就有一直刻意保持这个习惯,大多数时候我会选择用文字来记录(博客也是一种记录方式),可能是觉得用文字记录的方式更真实一些,回头看到那些写满地文字,会发现不知不觉中已经陪伴我走了这么远(内心戏较多,hhh..)。

英语

第三件事是我一直想要做,却还没有开始做(或者说没有坚持下去)。因为我一直认同一个观点:如果你英文不行,你基本与高手无缘了。

如何成功做好一件事

如何成功做好一件事情?给我最大的感触就是,一定要具备以下两个因素:

  1. 兴趣
  2. 成就感

前者是开始的动力,后者是坚持下去的动力。

关于分享

为什么要写博客?

一方面,阶段性地对一些知识进行总结,方便自己日后需要时查找。

另一方面,我一直觉得知识不是篮子里面的鸡蛋,不会因为你分享给他人而减少,相反,你会收获到更多其他的东西,这也是我开始写博客的初衷。

时至今日,小破站成立了六个月,刚好一百八十天。累计发文一百余篇,虽然不是每篇都是千字长文,但每篇都是经过思考一个字一个字码出来的。

可无奈整体访客却少得可怜,这不禁让我陷入沉思,是否有必要把部分精华内容发布到微信公众号上。

目前还没有公众号,创建一个公众号并不难,难的是如何取一个不错地名字及维护好这个公众号。

而对于取名字这件事情,我向来并不擅长,所以这件事情就一直被闲置了。

关于未来

马上就要迎来新的一年了,免不了制定计划为新的一年做好准备。我这个人似乎从来都不缺计划,缺的是完成计划的执行力。相比于计划本身,似乎更应该关注完成计划的效率。

  • [ ] 创建一个公众号?
  • [ ] 掌握 Go 语言
  • [ ] 务实计算机组成原理、操作系统原理、数据结构及计算机网络基础
  • [ ] 至少完成一百道 LeetCode 题目
  • [ ] 继续坚持跑步

新的一年,一起加油。

最后的最后用一段我比较喜欢的话,作为结束语:

你可以抱怨,你可以哭泣,可你要知道明天太阳还是一样会升起,你只需要知道这个世界对谁都是一样的,你过得很累,其他人也一样没有顺风顺水。累了,就去被窝里冥想发呆; 渴了,就穿上毛绒兔的拖鞋哒哒下楼,买一杯冰镇柠檬茶,或者去路边煮一碗热气腾腾的牛肉面;闻一闻路边的野菊,看几部幽默或感人的电影;哪怕这一切只是为了取悦那个心情不好的自己。最后,多多努力,努力做一个可爱的人,一个闪闪发光的人,不讨好,不将就,对过往的苦难情深意重,但绝不回头,你只需要一路向前,披荆斩棘就好,别忘了,带着笑:)

本文参与了 SegmentFault 思否征文「2020 总结」,欢迎正在阅读的你也加入。
查看原文

赞 1 收藏 0 评论 0

高阳Sunny 赞了文章 · 1月15日

A16Z 合伙人 Peter:开源,从社区到商业化

作者:Peter Levine、Jennifer Li
编译:芒果果

开源软件(0SS)运动创造了一些我们最重要和最广泛使用的技术,包括操作系统、 Web 浏览器和数据库。如果没有开源软件,我们的世界将无法运行,或者至少不会正常运行。

虽然开放源代码带来了惊人的技术创新,但商业创新尤其是软件即服务”(software-as-a-service)的兴起,对这场运动的成功同样至关重要。由于开源软件的定义是任何人都可以自由使用、修改和分发的软件,因此开源企业与其他类型的软件公司相比,需要不同的模型和不同的投放市场。

作为开源软件的开发者、企业家和投资者,Peter Levine 已经有了 30 多年的工作经验。他最近做了一个名为“开源: 从社区到商业化”的演讲,这场演讲借鉴了他自己的经验以及对数十位开源专家的采访。Peter Levine 跟踪了开源软件的兴起,并提供了一个实用的、端到端的框架,用于将一个开源项目转变为成功的业务。

Peter Levine 其人:

image.png

Peter Levine 是风险投资公司 Andreessen Horowitz 的普通合伙人,他专注于企业投资,曾任 Citrix 数据中心和云部门的高级副总裁和总经理,负责收入、产品管理、业务发展和战略方向。Peter Levine 于 2007 年加入 Citrix,当时他以 5 亿美元收购了企业级开源虚拟化软件的领先供应商 XenSource,并担任 CEO。

在加入 XenSource 之前,Peter Levine 是 Mayfield Fund 的普通合伙人。在 Mayfield 之前,他是 VERITAS Software 的早期雇员。在公司的11年任期内,他帮助公司发展成有超过 5000 名员工和超过 15 亿美元收入的公司。Peter Levine担任执行副总裁,负责全球市场,OEM 销售,业务发展和几个产品部门。他的职业生涯始于麻省理工学院的 Athena 项目的软件工程师。

Peter Levine 拥有波士顿大学工程学学士学位,曾就读于麻省理工学院的 Sloan School of Management。他现在是斯坦福大学商学院的管理学讲师,以前是麻省理工学院的企业家精神讲师。

Peter Levine 担任以下 Andreessen Horowitz 投资组合公司的董事会成员:Alluxio Inc.、Apollo、Cyngn、D2iQ、DigitalOcean、Labelbox、Mixpanel、Netlify、People.ai、PlanetScale、Shield AI 和 Udacity。此外,Peter Levine 还领导了该公司在 Figma 的投资。他也是麻省理工学院工程学院院长顾问委员会成员。

以下是这场演讲的全文:

开源最初只是一个边缘活动,但后来成为了软件开发的中心。我最喜欢的开放源代码早期轶事之一(当时它甚至还没有称为开放源代码,还只是“免费软件”)是 Linux/Unix 命令[ ~ } $BIFF,当一封新邮件到来时它会通知用户。这个口令是以伯克利一个嬉皮士的狗的名字命名的,它会跑出去对邮递员狂吠。我喜欢这个轶事,因为在早期,开放源码是如此的边缘化,以至于一个重要的命令是以一个开发人员的狗命名的。

我从事开源工作已经有几十年了,最初是作为麻省理工学院的 Athena 项目和开放软件基金会的开发人员,然后是开源公司 XenSource 的首席执行官。在过去的 10 年中,我一直是多家涉及开源的公司的董事会成员。从开发人员到董事会成员,我看到了开源的演变,看到了建立在开源项目基础上的大公司。

我真的相信,现在是建立开源业务的最佳时机。商业创新对于开源运动至关重要,在这里我提供了一个将开源产品推向市场的框架。

开源复兴正在进行中

image.png

过去的十年一直是开源的复兴。上图显示了过去 30 年的情况,在那段时间里,大约有 200 家公司以开源为核心技术成立。总的来说,这些公司在过去的 10 年里已经筹集了超过 100 亿美元的资金,并且趋向于越来越大的交易。事实上,四分之三的公司和 80% 的融资都是在 2005 年之后完成的。我认为我们才刚刚开始这次复兴。

这些投资带来了规模更大的 IPO 和更大的并购交易。

image.png

有趣的是,在 2008 年,Sun Microsystems(后来被 Oracle 收购)以10亿美元的价格收购了 mySQL。当时,我深信这个价格代表任何开源公司所能获得的最大收益。这笔交易使软件业将开源视为一种商品。

但是看看过去几年发生了什么。我们有 Cloudera、 MongoDB、 Mulesoft、 Elastic 和 GitHub,它们都是数十亿美元的 IPO 或并购交易的一部分。当然,还有 RedHat。1999 年,它以 36 亿美元的价格上市,今年,它以 340 亿美元的价格卖给了 IBM。将来,我很期待看到是否会有新的,更高的标准出现。

image.png

开源软件也在向更多的软件领域扩展。传统上,OSS 主要是围绕企业基础设施开发的,如数据库和操作系统(如 Linux & MySQL)。随着当前的复兴,开放源码软件的活跃发展几乎出现在每一个行业,金融技术、电子商务、教育、网络安全和其他等等。

那么,这种复兴背后的原因是什么呢?为了理解这一点,让我们回顾一下开放源码的历史。

开放源码从免费到 SaaS 的历史

image.png

开源 0.0-“自由软件”时代

开源始于 70 年代中期,我称这个时代为 0.0——“自由软件”时代。学者和业余爱好者开发软件,整个理念就是: 免费赠送软件。随着 ARPANET 取代互联网,网络使协作和交换代码变得更加容易。

我记得那时我去麻省理工学院或者开放软件基金会工作,我不知道我的薪水是从哪里来的。当时没有商业模式的概念,“自由软件”开发背后的资金(如果有的话)是来自大学或公司的研究补助金。

开源 1.0-支持和服务时代

随着 1991 年 Linux 的到来,开源变得对企业非常重要,并被证明是开发核心软件技术的一种更好、更快的方式。随着越来越多的基础开源技术,开源社区和企业开始尝试商业化。

1998年,开放软件行动组织创造了“开放源码”这个术语,大约在那个时候,第一个真正的商业模式出现了 RedHat、 MySQL 以及其他许多在免费软件之上提供付费支持和服务的公司。这是我们第一次看到一个可行的经济模式来支持这些组织的发展。

另一件值得注意的事情是,开源公司的价值与其专有同行相比相形见绌。当我看到 RedHat 和微软,mySQL 和 Oracle,XenSource 和 VMWare,封闭源代码公司的价值比开放源代码公司要大得多。业界认为 OSS 是一种不可能实现任何接近有限公司的潜在经济价值的商品。

开源 2.0-软件即服务和开放核心时代

到本世纪头十年中期,这些估值开始发生变化。云计算打开缺口,允许公司运行开源软件即服务(SaaS)。一旦我可以在云中托管一个开源服务,用户就不知道或者不在乎是否有开源或者专有软件,这就导致了对开源和专有公司的类似估值,并且表明开源确实具有真正的经济和战略价值。

一系列的收购,包括 Citrix 对我自己的初创公司 XenSource 的收购(更不用说 Sun 和 Oracle 对 MySQL 的收购)),也使得开源成为大型科技公司的关键组成部分。2001 年,微软 CEO 史蒂夫 · 鲍尔默称 Linux 为“癌症”现在,即使是微软也在其技术堆栈中使用开源,并在开源项目上投入大量资金。因此,下一个开源创业公司很可能会从一家大型科技公司分拆出来,就像从学术研究实验室或开发人员的车库分拆出来一样。

开源的良性循环

image.png

开源的历史强调,它的崛起是由于技术和商业创新的良性循环。在技术方面,开放源码是创建软件的最佳方式,因为它加速了产品反馈和创新,提高了软件可靠性,扩展了支持范围,推动了采用,并汇集了技术人才。开放源码是一种技术驱动的模式,这些特性从“自由软件”时代就已经存在了。

然而,只有当技术创新与商业创新相结合时,开放源码的全部潜力才能实现。没有商业模式,比如付费支持、 Open Core 和 SaaS 模式,就不会有开源复兴。

经济利益创造了一个良性循环,或称飞轮。我们的商业创新越多,开发者社区就越大,这就刺激了更多的技术创新,从而增加了开源的经济激励。在演讲的最后,我会谈到我认为 3.0 中开放源码的未来,并指出目前在技术和商业方面正在发生的一些有趣的创新。

但首先,让我们谈谈如何建立开源业务。

商业成功的三大支柱

image.png

开源企业的成功依赖于三大支柱。这些最初以阶段的形式展开,一个阶段通向下一个阶段。在一家成熟的公司,它们随后会成为可持续业务需要维护和平衡的支柱:

1.Project-community fit,您的开放源码项目创建了一个开发人员社区,他们积极地为开放源码基础做出贡献。这可以通过 GitHub stars、 commit、 pull request 或 contributor growth 来衡量。

2.Product-market fit,产品市场匹配,用户采用你的开源软件,这是通过下载和使用来衡量的。

3.Value-market fit,价值市场契合,你可以找到一个客户愿意为之付费的价值主张。这里的成功是以收入来衡量的。

这三大支柱必须贯穿于公司的整个生命周期,并且每一个都有一个可衡量的目标。

Project-community fit

image.png

项目社区适应是第一个支柱,是关于临界社区规模和项目与开发商的牵引力。尽管 OSS 社区的规模各不相同,但强大的追随者和日益增长的受欢迎程度是 OSS 项目激发一组开发人员强烈兴趣的关键指标。这些指标包括 GitHub 的星级、协作者的数量以及拉请求的数量。

开源项目可以在很多地方启动,包括大公司或学术界。但是,一个项目从哪里开始并不重要,重要的是有一个项目负责人来推动项目,而这个项目负责人通常会成为商业实体的首席执行官。

实现项目与社区的契合需要高度的接触参与和开发者社区的持续认可。最好的项目负责人将在包容和主张之间达到微妙的平衡,做出明确的决定以提供项目指导,同时确保每个人的声音都被听到并且贡献得到认可。达到平衡后,该项目将保持健康增长,并吸引更多人为该项目做出贡献和分配。并分发项目。

作为投资者,我们强烈倾向于为 OSS 项目负责人提供资金,因为他们了解内部和外部的代码库,并且是维持开发人员社区的精神和愿景的守护者。

产品市场契合度

image.png

一旦你有了项目领导者和活跃的合作者团队,下一阶段就是理解和衡量产品与市场的匹配度。在这个过程中,项目领导者需要具体化: 开源软件帮助解决的问题是什么?它是为谁解决这个问题的?市场上有什么替代品?如果不能清楚地理解您的用户和他们的用例,项目可能会被拉向许多方向并失去动力。

当上述问题得到解答后,可以观察到自然采用率(以下载次数为准)。产品与市场的契合是以后销售活动的先决条件。理想情况下,OSS 用户成为增值产品或服务的渠道领先者。我们将在“进入市场”部分中详细介绍这一点。

在进行产品与市场的契合度研究时,重要的是要考虑将如何描述商业产品,以及如何交付有人愿意支付的产品和服务。我要指出的一个常见陷阱是,有时 OSS 产品可能太好了。产品与市场的契合度可能非常好,因此不需要价值与市场契合度,这意味着没有自然的扩展来增加收入。因此,在您推动有机采用的同时,您和您的社区应该仔细考虑将来可能希望实现的商业化。

价值市场契合度

image.png

最后一个阶段,通常也是最困难的阶段,是寻找价值市场契合点和创造收入。虽然产品市场适应性通常由单个用户来完成,但价值市场适应性通常集中在部门和企业买家身上。价值市场匹配的秘密在于关注消费者关心并愿意为之付费的东西,而不是你能够赚钱的东西。

通常情况下,价值市场匹配与产品的功能关系不大,更多的是关于产品如何被采用,以及它所带来的价值类型。OSS 提供的价值不仅仅在于它的功能,还在于它的操作效益和规模特性。因此,在考虑商业产品时,需要考虑的一些问题是: 你的产品是否解决了核心业务问题或者提供了明确的运营利益?复制或者寻找替代品难吗?是否存在开放源码软件中没有实现的团队或组织所需的规模能力?

image.png

尽管不是详尽无遗的清单,但是开源公司发现价值市场适合以下功能:

  • RAS(可靠性,可用性,安全性)
  • 工具,附加组件
  • 性能
  • 审计
  • 服务

选择商业模式

image.png

选择什么样的商业模式取决于你能为客户提供什么价值,以及如何最好地提供这种价值。值得注意的是,这些商业模式并不是独一无二的,而且有可能建立一个包含多种模式元素的混合业务。

支持和服务是开源 1.0 时代的典范,而 RedHat 确实在这方面垄断了市场并达到了规模。如果你决定沿着这条路走下去,你很可能最终会与 RedHat 竞争(这就是为什么五年前,我写了一篇博客文章“为什么再也不会有另一个红帽子: 开源经济学”

Open Core 模型将增值的专有代码置于开源软件之上,是本地软件的良好模型。如果您拥有可以保护专有性的超有价值组件(例如安全性或集成性),而又不损害开放源代码的采用,那么 Open Core 将是一个很好的模型。需要注意的是:使用 Open Core 在决定哪些特性属于哪些代码时,社区异化可能会成为一个问题。我在自己的公司看到了这一点,找到适合社区的校准方法非常重要。这里的终极陷阱是,你的社区决定他们不喜欢你在专有方面的行为,于是他们分支项目,或者围绕同一个代码库启动一个新项目。

在 SaaS 模型中,您提供了一个完整的托管软件产品。如果你的价值和竞争优势在软件的 Operational excellence,那么 SaaS 是一个不错的选择。然而,由于 SaaS 通常是基于云托管的,公共云可能会选择使用你的开源代码来竞争。

云与竞争护城河

image.png

一旦开源业务达到一定的成熟度,公共云的威胁和许可的话题就可能出现。授权是一个备受争议的话题,虽然它很重要,但我看到公司在早期花费了太多的时间来讨论授权。

我还认为我们对公共云供应商的威胁反应过度了。尽管这些供应商可能拥有开源项目,但是到目前为止,我所知道的还没有一家开源公司被云供应商完全取代。

对于一个开源公司来说,更重要的问题是: 如果代码不是一条有竞争力的护城河,那么什么才是?

这个问题的答案可以追溯到使开源如此强大的原因:社区以及你如何看待开发。独立的开源公司有三大竞争优势:

1.企业客户不希望供应商锁定。

2.他们想从编写代码的人那里购买。

3.大公司没有您的专业知识。

当你把这三个因素结合起来,我认为这是一个真正具有竞争力的附加值,也是为什么我们还没有看到大云完全取代独立开源公司的原因。

现在我们已经涵盖了三个支柱,让我们看看如何围绕它们建立一个组织。
这时可以回答上刚才提出的问题,如果代码不是一条有竞争力的护城河,那么什么才是?答案就是:社区。

走向市场: 开源是漏斗的顶端

image.png

开源社区是由开发人员驱动的顶级活动。建立业务就是将开源漏斗顶端连接到一个强大的价值驱动的商业产品。漏斗这个概念并不新鲜,但对于开源公司来说,它确实有不同的表现。在这一部分,我想要介绍开放源码的努力是如何集成和编织到不同阶段的商业努力中的,以及如何让每个阶段与其他阶段和谐地工作。

开源进入市场的渠道分为四个阶段和关键的组织职能。

  • 开发者社区管理提高了对开源产品的认识和兴趣。
  • 有效的产品管理可以为您的免费开源产品吸引大量用户。
  • 潜在客户的产生和业务发展会评估这些用户确定企业中潜在价值和销售机会的意图。
  • 自助服务(自下而上)和销售服务(自上而下)的动作为企业提供并扩展了付费产品或服务的价值。

让我们更详细地研究每个阶段和功能。

阶段1:意识和兴趣–开发者社区管理

image.png

通过用户注册和下载量来衡量,与开发者的口口相传对于后续阶段的成功至关重要。在公司成立之初,创始人通常是公司成立之初的第一位福音传播者。随着公司的扩张,拥有一个专门的开发人员团队非常重要,他们既有技术专长,又有很强的沟通能力。虽然通常是一种罕见的组合,但是当某人同时具有技术和沟通技能时,通常很容易发现。完成后,请雇用这些开发人员,并在与开发人员社区互动的会议和社交媒体上吸引他们,并说明您项目的重要性和价值。

需要调整销售和开发人员宣传信息时,不应该让他们强调“销售”他们应该引起人们的兴趣,让人们了解产品,任何强调销售的做法都有可能损害他们在社区中的信誉。

开展业务时,还需要确定其名称和品牌是否与开源项目相同。公司在两方面都取得了成功,而且两者都有利有弊。独立的名称,如 Databricks 和 Spark,防止品牌稀释和提供许可的灵活性,同一个名称通常会为 OSS 项目提供更多动力,但是也可能会因为被认为被利用牟利而是开源社区不再被关注。

最后,用户注册和下载是开源和专有软件的一个共同的衡量标准,所以关键不在于你测量的是什么,而在于测量的精确程度。在 XenSource,我们在某一点的数字不准确,因为我们的下载指标包括大量已启动但尚未完成的下载。如何衡量用户注册和兴趣将防止下载成为一个虚荣的指标,而这种虚荣指标不会导致程序进入下一阶段。

第二阶段: 考虑-产品管理

image.png

一旦你加入了一个开发者社区,你的目标就是最大化开发者和用户的喜爱、采用和价值。开源漏斗的第二阶段通常是通过产品管理来完成的。

有效的产品管理将执行一些功能来支持这个阶段: 管理封闭和开放源代码的路线图,与你的开发者和用户沟通决策,并在产品中建立分析,以收集更多的使用模式的洞察力和预测销售机会。

与专有软件不同,开源企业通常有两个路线图需要管理。开放源码软件的 CEO 和创始人经常把大部分时间用于管理这些路线图以及彼此之间的关系。我喜欢在单个页面上看到这些布局,以显示这些互锁和相互联系的方式以及每种功能中可用的功能。

成功的公司和创始人都有一个框架或指导方针,帮助他们描述和沟通什么是付费的,什么是免费的。例如,PlanetScale 致力于保持开放源代码,任何可能产生供应商锁定的东西,这种价值维护了开放源代码社区和企业客户的良好意愿。拥有功能比较表会很有帮助,以便客户和您的社区了解免费软件和付费软件提供的不同价值。

关于研究和开发的透明度以及将社区反馈纳入产品路线图对于维护社区信任尤其重要。许多成功的开源公司仍然活跃在相应的开源项目中,并且经常成为贡献者的领导者。例如,Databricks 对 Spark 的贡献是其他公司的10倍。

当涉及到产品本身,你应该建立分析,帮助你了解你的用户和预测的开放源码软件用户的百分比将转换为买家。一旦用户拥有了产品,产品使用分析将有助于根据价值市场匹配度确定产品市场匹配度,以及从免费用户到付费用户预测销售机会的人数。例如,如果每 100 个用户中有 5 个持续转化为付费用户,那么你可以使用 5% 作为建立你的财务模型的估计值。

这将是一个复杂的过程,您应该尝试产品包装以识别免费和付费之间的最佳界限。对于许多开源创始人而言,这种产品试验是一段永无止境的旅程,而他们进入市场的成功取决于紧密的产品反馈周期。

第三阶段: 评估及意向-潜在客户产生与业务发展

image.png

下一阶段的评估和意图是是关于利用潜在客户生成和销售开发来验证和完善这些理论。目标是找到从用户到企业购买者的路径,通过销售合格线索(SQLs)来衡量成功与否。

第一部分是对外营销。出站营销应该优先关注特定的细分市场,基于你的开发者在渠道顶端的传道中的众所周知的模式。关注您的开源用户,您将了解哪些角色和部门正在使用该产品以及他们的兴趣是什么。然后你可以把你的对外营销目标对准工程经理、 devops 或 IT,他们会发现你的产品很有价值。

接下来是销售拓展工作。销售开发代表应该让客户成功,而不是过度推销,并且对用户的需求以及他们如何使用产品充满好奇。

产生潜在客户时,有两个主要的过滤器可以对其进行限定:1)开发人员或用户代表什么组织?2)他们是否下载或参与了您的项目以获取与更大的企业目标相关的内容?

第四阶段: 采购和扩展-内部和现场销售

image.png

获得销售合格的销售线索后,您可能会有两个针对企业的销售动议。第一种可能是自下而上的自下而上的行动,其中企业内的用户有机地采用并购买产品。通常,此产品将用于个人。第二个是销售服务动议,该动议使用更传统的自上而下的动议在部门级别进行交易或扩大整个企业的使用范围。

成功和失败

image.png

正如我的同事 Martin Casado 在他的《增长、销售和 B2B 新时代》演讲中所指出的,协调有机增长和企业销售可能会导致开源业务出现一些常见的失败模式。首先,您的开源用户不会吸引购买者。在这种情况下,您具有很好的产品市场契合度,但没有价值市场契合度。

在第二种失败模式中,OSS 项目的增长落后于企业销售。在这里,你的产品与市场的契合度可能没有那么高。在第三种情况下,你的商业产品会毁掉你在开发者社区中的信誉。在专有源中可能有太多,而在开放源代码中可能不够,这样你的开放源代码项目就会枯萎。

顶部的漏斗提供了接下来所有的关键,所以首先投资在你的开发者社区,开源项目,和用户之前的正式营销和销售。永远不要忽视这三个核心问题: 谁是你的用户?谁是你的买家?你的开源和商业产品是如何为每个人提供价值的?

image.png

如果成功的话,你可能会看到一个类似上面的图表。在 y 轴上,我们有每个客户的收入,在 x 轴上,是时间。这张图表是我作为 GitHub 前董事会成员直接观察到的,它显示了自上而下和自下而上的销售,因为它把收入汇总在一起。这里的要点是: 如果你的收入看起来像一个千层蛋糕,这是一个好兆头。橙色线是个人自下而上的收入,通常是一条收入线。下一个收入线可能是销售部门的买家,但这是自上而下,通常使用内部销售。下一部分是现场销售,或直接销售,销售或扩大整个企业的帐户。为了优化每一条收入线,不要让销售活动自然发生; 要有一个拥有特定功能并有目的地推动这项工作的人。

最后,根据你的产品,你可能只有自助服务或只有内部销售。这没关系,这真的取决于产品的复杂性,以及在哪里以及如何最好地使用它。我确实发现,大多数开源公司都有一些自上而下和自下而上的组合,通常从自下而上开始,然后在此基础上建立一个收入扩展功能。

OSS 3.0-开源是每个软件公司的一部分

image.png

随着软件吞噬了世界,开源正在吞噬软件。

今天,几乎所有主要的科技公司,从 Facebook 到 Google,都是在开源软件的基础上发展起来的。这些公司越来越多地建立自己的开源项目,例如 Airbnb 有 30 多个开源项目,Google 有 2000 多个。

在未来,良性循环将继续下去。技术上,人工智能、开源数据和区块链都是新兴创新的例子。下一代商业模式可能包括广告支持的 OSS,如大型专有企业支持开源项目; 数据驱动的收入; 以及通过区块链货币化的加密代币。

我相信开源3.0将扩展我们对开源业务的看法和定义。开源将不再是 RedHat、Elastic、Databricks 和 Cloudera;它至少将是 Facebook、Airbnb、Google 和其他任何将开源作为其主要内容的业务。当我们以这种方式看待开源时,正在进行的复兴可能只是处于起步阶段。开源软件的市场和可能性远远超出我们的想象。

segmentfault 公众号

查看原文

赞 2 收藏 0 评论 0

高阳Sunny 赞了文章 · 1月15日

技术干货 | mPaaS 客户端问题排查:漫长的 3s 等待之谜

面对日益复杂的技术世界,App 在开发、上线和运维阶段所遭遇的问题也越来越多。这些形形色色的问题可能来自整个链路的任意环节,而不仅仅是代码层面。

对于开发者来说,排查手段已经不再局限于构建代码过程中的调试,往往需要扩充排查方法,从多种途径对问题进行分析和定位。这篇文章会和大家分享 mPaaS 开发者的一例小程序网络性能问题排查之旅。

问题背景

“笑联科技”反馈基于 mPaaS 开发的 App 中,其集成的小程序访问客户自建的 Web API 存在连接慢的性能问题。问题复现视频如下:

播放问题复现视频

从问题复现的情况看,打开小程序后,页面数据的加载有一个“漫长”的等待过程。

和开发者沟通后了解到,页面初始化所必须的部分数据是通过自有的 Web API 获取到的,数据返回慢会导致页面加载的等待。另外开发者也提到,这个问题存在地域性和偶发性,既部分地区的部分用户在一段时间内会被这个问题严重困扰。

问题分析与排查

如前文所述,数据是通过 Web API 获取的,自然我们希望通过外部手段去确认这个 Web API 本身是否存在性能问题。

然而,通过浏览器或 Postman 等工具去访问该 Web API ,均无法复现问题,后端的响应都是毫秒级。但是因为开发者提到该问题存在地域性和偶发性,因此无法直接排除部分原因。

由于我们并不是 App 的直接开发者,对于这类问题,一种常规的手段是抓取 HTTP 报文来观察和理解 App 背后的行为特征。比较幸运的是,我们的测试用 iOS 手机可以复现问题,通过 Charles 抓取 App 报文,我们有如下发现:

Web API 的地址为:https://api.xiaolianhb.com/

当 Charles 开启 SSL Decryption 时(中间人解密 HTTPS Body 模式),问题无法复现。

当 Charles 关闭 SSL Decryption 时,问题可以复现,数据加载明显存在一个 3s 的等待情况。

上述现象 2 和 3 强烈暗示问题可能和 HTTPS/SSL 协议层面相关(开启 SSL Decryption 时,HTTPS 连接由 Mac 笔记本和服务器进行;关闭 SSL Decryption 时,HTTPS 连接由 iPhone 和服务器进行)。

对于 SSL 层面的问题,则需要抓取 TCP 报文做进一步的确认和分析。使用 Wireshark 进行网络层抓包(基本抓包步骤:iPhone 正常接入网络;iPhone 通过数据线连接到 Mac 上,并对手机网卡搭建一个虚拟映射;Wireshark 在该映射上进行抓包;详细步骤参考这里)。

问题复现并抓取到相关报文后,首先确认问题,如下图所示:

1.png

通过上图日志可以看到,在 TLS 握手阶段,客户端在流程上延迟了 3s 才把 Client Key Exchange 消息发给服务端,而正常情况下,不应该存在如此漫长的等待情况。于此同时,开发者在 Debug 包上的前端嵌入调试也确认了相关情况,如下图所示:

2.png

接下来需要搞清楚,客户端为何在握手阶段等待了如此之久以及这 3s 期间客户端在做什么?放开网络包过滤条件后,通过阅读网络包的上下文,我们有了进一步的发现,如下图所示:

3.png

在上图中,可以看到客户端一直尝试与一个 IP 为 243.185.187.39 的站点建立 TCP 连接,但均遭遇失败。这里会有两个疑问:1. 这个站点是干什么的?2. 为何客户端要在 TLS 握手过程中先去连该站点?

通过同一个网络包中的 DNS 查询记录,尝试反查该 IP 对应的域名地址,发现该站域名为:a771.dscq.akamai.net:

4.png

通过公网搜索该域名,得知这个域名是 Let's Encrypt (全球最大的免费证书机构)证书的 OCSP (Online Certificate Status Protocol,用于校验证书状态) 地址,但需要进一步确认该证据。在网络包中,查看服务端返回证书帧的详细信息,确认证书的 OCSP 地址为 http://ocsp.int-x3.letsencrypt.org

5.png

由于该 OCSP 地址和网络包中看到的不一致,本地通过 nslookup 再进一步确认:a771.dscq.akamai.net 是 ocsp.int-x3.letsencrypt.org 的一个 CNAME 地址(这种配置一般为了站点加速):

6.png

结合上述情况和公开资料,可以确认在 3s 的等待期内,客户端尝试去连接证书提供的 OCSP 站点地址,意图确认证书的吊销状态。仔细观察会发现,本地解析出的 IP 地址和手机端抓包看到的 IP 地址是不一样的,这里大概率是 Let's Encryped 证书的 OCSP 地址被“污染”导致的。

7.png

到这里,我们可以看到问题的小结为:客户端需要和 https://api.xiaolianhb.com/ 建立 HTTPS 连接,在 TLS 握手阶段,客户端无法连上该站点证书提供的 OCSP 地址,因此无法确认证书的吊销状态,3s 后触发超时放行机制,客户端和站点正常建立 HTTPS 连接,请求发送和数据返回流程得以进行。

既然 Let's Encrypt 证书的 OCSP 域名被“污染”已经成为事实,因此,要解决该问题,最快的解决方案是更换站点证书,保证 TLS 握手流程的顺畅。

小结

在这个案例中,我们可以看到有些时候,问题和代码、SDK 亦或是系统 Bug 并无直接关联,异常情况可能来自一个意想不到的地方。

回到问题症状上,更进一步的疑问是:为何桌面浏览器或网络工具受影响较小?为何 Android 手机不受影响?这些症状细节上的差异,均和不同系统或工具对协议的实现形式相关。

开发者很难在一开始的规划阶段就能把这些细枝末节的问题都预估到,因此,出现问题之后,深入的问题剖析配合日志解读往往是理解程序行为背后逻辑的重要手段。

CodeDay#5:深入探索支付宝终端

在过去的一年中,我们通过与众多终端开发者在能力对接、需求沟通中发现,愈来愈多的研发团队面临业务需求爆发时难以找到有效的方式进行高并发支撑。

大家的问题呈现出了共性特征:如何实现动态发布?如何进一步提升研发效率?支付宝是否有最佳实践?

因此,此次 CodeDay 我们把焦点放在“支付宝终端”,尝试通过 4 个议题分享,带领大家了解支付宝作为一款超级 App,如何借助容器化技术实现动态发布、更新能力,并沉淀出一套可复用的技术体系。

点我立即报名

作者名片-东雷.jpg

延伸阅读

动态-logo.gif

底部banner.png

查看原文

赞 1 收藏 0 评论 0

高阳Sunny 赞了文章 · 1月14日

当音乐学博士搞起编程,用一本书改变了Java世界!

前言

说到Spring,也许现在的开发者们最先想到的是 Josh Long

file

超快的语速与现场代码能力,让很多Java开发者折服。

然后Spring的历史上,最传奇的还是要数其创始人:Rod Johnson!

先不说别的,看到他的学历,你就震惊的了,悉尼大学的音乐学博士!不要惊讶,不是计算机!

也许就是因为这样一颗理性思维与艺术细胞结合的秃顶大佬,才能造就Spring这样的产物吧。

file

Rod Johnson

Rod Johnson,就是上图这位头顶略微地中海的男子,但是秃脑袋瓜并没有让Rod Johnson变得难看,好几个同学一致认为这家伙长得很酷。

按照他身边的密友所描述的,Rod Johnson平日里看上去就像是一个典型的英国绅士,虽然他好像出生在澳大利亚,但是现在住在伦敦。说起话来也是一板一眼,有条有理。字正腔圆而略有点尖的口音让人听起来特别清楚。

大多数人都认为Rod Johnson似乎天生缺少一样东西:幽默感。但实际上看看下面这端开场白:

回到2001年,当我写下第一行代码时,那些代码并没有放到GitHub,没放在上面是因为GitHub当时不存在,所以我想Spring应该比Git老三四岁...

让人不禁宛然一笑,Rod Johnson也跟其他程序员一样是个挺可爱的人吧。

file

轮子理论

提到Rod Johnson,大家还总会想起轮子理论
所谓轮子理论,就是指:不要重复发明轮子,这是西方国家的一句谚语,原话是:Don't Reinvent the Wheel。意思是企业中任何一项工作实际上都有人做过,我们所需要做的就是找到做过这件事情的人。拿到软件领域中就是指有的项目或功能,别人已经做过,我们需要用的时候,直接拿来用即可,而不要重新制造。

Rod Johnson想告诉我们,Spring就是在不重复发明轮子的理念及指导原则上做起来。

于是一夜之间,随着Spring在全世界的风风火火,特别是吹到我们祖国的时候,也许是爱屋及乌的原因吧,轮子理论也被众多的Spring粉丝当成做人做事做程序的信条及原则。

Spring与Expert One on one J2EEDevelopment without EJB

Spring,可以说就像是Rod Johnson的代名词一样,大家对Rod Johnson印象最深的成就自然是SpringFramework和Expert One on one J2EEDevelopment without EJB。

Java从诞生之日到如今经历了风风雨雨数十年,从低谷到高峰,JAVA之所以是世界上最受欢迎的开发语言之一,Spring框架起到了非常重要的作用。

当时间还停在21世纪初,Java EE的整个系统框架处在臃肿、低效、脱离现实的种种现状之中,将其进行轻量化成为业内的一致的呼声,此时Rod Johnson就像一颗璀璨的明珠一样横空出世,积极寻求探索革新之道。

Rod Johnson最开始在2000年为伦敦金融界提供独立咨询业务时曾经写了一个简单的框架,以此为基础他编写了interface21框架,这是一个力图冲破Java EE传统开发的困境,从实际需求出发,着眼于轻便、灵巧,易于开发、测试和部署的轻量级开发框架。可以说这就是Spring的前身,Rod Johnson当时的观点就是 :如何让应用程序能以超出当时大众所惯于接受的易用性和稳定性与J2EE平台上的不同组件合作。

Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵。最终于2004年3月24日,发布了1.0正式版。

配合Spring的诞生,Rod Johnson在同年编著了Expert one on one J2EE design and development一书,堪称经典,直至今日,还有不少莘莘学子将其视为Spring必读宝典。

file

这本书甫一面世,就在Java世界掀起了轩然大波,不断改变着Java开发者程序设计和开发的思考方式,影响至今。Rod Johnson根据自己多年丰富的实践经验,对EJB的各种笨重臃肿的结构进行了逐一的分析和否定,并分别以简洁实用的方式替换之。

Spring1.0版本发布之后,Spring框架在Java社区里变得异常流行,当然这也要部分的归功于它不错的文档功能和详尽的参考文献,特别是对于一个开源项目而言尤其如此。

Spring框架的一个重要设计目标就是更容易地与已有的J2EE(现在称之为JavaEE或JEE)标准和商用工具整合。

也正因此,Rod Johnson奠定了自己的江湖地位,成为一个改变Java世界的大师级人物。

本文首发:https://blog.didispace.com/he...

版本变迁

Spring 几乎已经成为现在每一位 Java 开发人员都耳熟能详的开发框架,不论你是一名初出茅庐的程序员还是经验丰富的老司机,都会对其有一定的了解或使用经验。在现代企业级应用架构中,Spring 技术栈几乎成为了 Java 语言的代名词。我们不妨从最初的 Spring 开始,看看它为什么能够横扫千军,一统江湖!

Spring版本变迁:

  • 自2004年Spring1.0发布之后,Spring 框架迅速发展,不断进化。1.0的出现彻底改变了开发企业级Java应用程序的方式。 Spring的依赖注入与声明式事务意味着组件之间再也不存在紧耦合,再也不用重量级的EJB了。
  • 2006 年 10 月,发布Spring 2.0 ,具有可扩展的 XML 配置功能,用于简化 XML 配置,支持 Java 5,额外的 IoC 容器扩展点,支持动态语言。更小、更简单易懂的配置文件让Spring本身更便于使用
  • 2007 年 11 月 ,Interface21 项目更名SpringSource,同时发布了 Spring 2.5,支持 Java 6 / Java EE 5,支持注释配置,classpath 中的组件自动检测和兼容 OSGi 的 bundle。让我们有了更优雅的面向注解的依赖注入模型(即@Component和@Autowired注解),以及面向注解的Spring MVC编程模型。不用再去显式地声明应用程序组件了,也不再需要去继承某个基础的控制器类了。
  • 2009 年 12 月,Spring 3.0 发布,具有许多重要特性,如重组模块系统,支持 Spring 表达式语言,基于 Java 的 bean 配置(JavaConfig),支持嵌入式数据库(如 HSQL,H2 和 Derby),模型验证/ REST 支持和对 Java EE 的支持。XML被取代,终于可以写出一个没有任何XML配置的Spring应用程序。
  • 2013 年 12 月,Pivotal(2013 年 4月,VMware 和 EMC 通过 GE 投资创建了一家名为 Pivotal 的合资企业。所有的 Spring 应用项目都转移到了 Pivotal) 宣布发布 Spring 框架 4.0。包含了对Java 8 的全面支持,更高的第三方库依赖性(groovy 1.8+,ehcache 2.1+,hibernate 3.6+等),Java EE 7 支持,groovy DSL for bean 定义,对 websockets 的支持以及对泛型类型的支持作为注入 bean 的限定符。
  • 2017年9月,Spring 5.0 GA版本发布,开始支持JDK 8和Java EE 7,同时兼容JDK9。全面支持Servlet 3.1,还引入了一个全新的模块Spring WebFlux用于替代老话的 spring-webmvc;对Kotlin也有了更好的支持。
  • 而目前,最新的是5.3.2 GA版本。

具体版本可见:https://spring.io/projects/sp...

Spring在不同的领域不断发展:移动开发,社交API集成、安全管理、NoSQL数据库、云计算和大数据等等都是它正在涉足和创新的领域,使其前景更加广阔,甚至已经形成与传统的JavaEE平台分庭抗礼之势。

file

离开

江湖,有聚必有散。

2007 年,SpringSource 从基准资本获得了 A 轮融资(1000万美元)。在此期间SpringSource也收购了多家公司,如Hyperic,G2One 等。

但是等到了2009年8月,SpringSource反倒是以 4.2 亿美元被 VMWare 收购。

而在3年后的2012年7月,Rod Johnson就离开了他一手创建的Spring团队。

或许我们可以这样想,如果当初SpringSource 没有被VMWare 收购,是不是Rod Johnson 就不会离开团队,是不是现在的Spring会更好?答案我们自然不得而知。

Rod Johnson当年在SpringSource官方博客上公布这一消息时声称SpringSource将成为VMware下属的一个部门,而他将仍是SpringSource的领导者。他当时对未来的展望是:

此次决定是很自然而符合逻辑的:这将带来更多的新技术,并且对Spring框架以及Spring社区都有好处。

我很兴奋。希望你也是。这将极其有趣。

Spring框架将继续提供优质的企业级Java支持。我们从关注开发者如何创建和使用应用,到关注他们如何部署和运行企业级应用;为此我们创建了dm Server和tc Server。我们收购Hyperic也是为了改善开发者管理企业级应用的方法。

与VMware的合作中,我们计划创建一个简单,集成,创建-运行-管理合一的数据中心、私有云和公共云的解决方案。这个方案将融合应用架构的知识,连带中间件以及管理控件,确保一个虚拟环境在部署过程中以及运行时的最大效率及弹性。这是一个PaaS,建立在你已知的技术之上,从而最大的减少花费与复杂度。这是一个围绕开源、可移植的中间件技术的解决方案,既可以在传统数据中心的Java EE应用服务器上运行,又可以在如Amazon EC2之类的弹性云上运行,也可以在VMware平台上运行。

与VMware的vSphere以及其他云技术一起,我们将在框架和基础设施上带来一个全新的体验。SpringSource的应用框架、服务器及管理软件将成为VMware平台的眼睛和耳朵。

SpringSource的下一步工作将是这些新的挑战:基于我们的Build/Run/Manage(创建运行管理)系统,提供从桌面端到云端的最佳解决方案。让百万Java开发者都能享受到云计算带来的好处。

可能他当时心里想的是作为Java领域的重要厂商,在加入VMware后,其Java开发经验将与VMware的虚拟化平台相结合,增强其在企业服务市场中的竞争力。另外,SpringSource在全球大型企业中的广泛客户资源也能够让VMware受益。不管怎么说,似乎从现在的结果来看,Spring也做得不错,没有辜负Rod Johnson当初的一番期望。

传奇现今

现在的Rod Johnson成为了一个天使投资人,同时也是多个公司的董事(例如Neo Technology,elastic,Meteor和Hazelcast等著名的开源公司),早已走上人生巅峰。同时他依然还是经常会在技术大会上做演讲,游走在世界各地,为后来者传授各种技术经验及想法。

在去年10月份的SpringOne Platform大会上,Rod Johnson还特地做了一个关于Spring18岁的演讲,也许他的样子变了,但是讲起Spring,他还是像讲起自己的孩子一般滔滔不绝,Rod Johnson分享了Spring的起源、历史,总结了一些Spring框架发展过程的经验教训:

  • Spring的历史起源
  • Lesson 1: Fairy tales can offer useful lessons 寓言故事能提供有用的教训
  • Lesson 2: Need Clear, Shared Values 需要清晰,共有的价值
  • Lesson 3: Know where you're going 明确方向
  • Lesson 4: Quality beats quantity in a team 打造团队宁缺毋滥
  • Lesson 5: Market and sell your technical solution 营销你的技术方案
  • Lesson 6: Other people have great ideas. Borrow them but acknowledge their work 认可借鉴别人的好点子
  • Lesson 7: The developers you want need autonomy 开发者需要自治
  • Lesson 8: Question the "enterprise" mindset 质疑“企业级”观念
  • Lesson 9: Some Spring Advice 一些Spring的建议
  • Next For Me: Atomist - A Framework for Development and Delivery 我的下一站:Atomist——一个关于开发与交付的框架
  • Lesson 10: Raising software is like raising a child 开发软件像养育一个孩子

有兴趣的读者可以自行查看,视频地址如下:https://www.bilibili.com/vide...

你知不知道Rod Johnson?

你有没有看过Expert One on one J2EEDevelopment without EJB?

欢迎留言分享你的感受!

查看原文

赞 3 收藏 1 评论 0

高阳Sunny 赞了文章 · 1月14日

硬件测试的思考和改进:有道词典笔的高效测试探索

作者/ 刘哲
编辑/ Ryan
来源/ 有道技术团队(ID: youdaotech)

引言

当我们提到智能硬件的高效测试时,通常会考虑使用自动化测试的方案,提升产品的测试效率和质量。

由于智能硬件的使用过程中,包括了大量和用户的行为交互,这就导致在测试方案上,传统的软件自动化测试很难完全模拟用户的完整使用行为。

因此,我们除了要考虑借鉴和使用软件测试的思路之外,还要考虑如何实现硬件测试自动化。

一、背 景

有道词典笔 2.0 是网易有道自研的学习型智能硬件。

有道词典笔搭载了有道自研的 OCR、NMT、TTS 技术,为用户提供了一扫查词、中英文互译、语音助手、触屏、离线等功能。

当我们拿到词典笔 2.0 第一个版本的时候,首先看到的是它的硬件外观:

从硬件层面来看——

它包括了一块可触摸的屏幕,接口方面使用了 Type-C 方案,在下方有一个摄像头,背面有喇叭可以发音,按键方面有开关机、功能键和笔的触头。

同时在设备的内部还内置蓝牙和无线模块。

这个产品如何使用呢?用户的典型使用场景是:

手持有道词典笔,向下按压笔头开启补光灯和摄像头,在文字上方滑动,实现对文字的拍照。之后图片合成,进入 OCR 模型,识别出文字后,进入 NMT 模型,最后翻译结果展示出来,进入 TTS 服务。

所以,简单来说,它是以扫描识别行为为基础操作,实现若干功能的一款硬件产品。

现在我们知道软件方面的能力了,这时候就可以结合硬件一起来考虑,有道词典笔的高效测试要怎么做。

二、让硬件动起来

我们对一款产品做自动化测试,首先要找到用户的主要使用路径。

用户花了最多的时间使用的行为,就是我们需要花精力去考虑如何模拟的行为。

很明显,在这里用户的扫描行为引发的查词和翻译学习结果。

那我们就来看看,用户的实际操作是如何的。

我们对用户扫描的场景模拟,可以分成两个部分。

一个部分是对词典笔的控制,稳定的握持,另外一部分是对笔的移动。
image
在考虑实现这样的方案时,我们考虑过市面上现有的自动化方案,来实现对笔的固定和移动。

但是碍于成本和可复制性并不合适,所以没有采用。

让词典笔从左向右移动起来这件事情,是整个行为的难点。

那是否可以让词典笔不动,也实现一样的扫描效果呢?

我们决定换个思路。

我们让笔不动,文字从右向左移动,从而模拟笔从左向右移动的效果。
image
为了可以持续的测试,还需要文字再从左向右回来,然后再次从右向左。

当它成为一个循环的时候,就实现了持续的文字移动。

大家看这样运动的文字像是什么?

我们的第一反应就是传送带,就是工厂里见到的流水线上的移动,所以我们做了第一套方案。
image
我们把文字固定在传送带上,然后用电机驱动传送带,实现了文字的持续移动。

当文字可以稳定移动之后,我们通过 shell 去控制词典笔的扫描行为,包括了开关笔头灯、开关扫描行为等等。

然后我们可以把设定时间内的扫描内容传送到笔内的翻译引擎中,进入后续的翻译和发音流程。

文字动起来了,那让词典笔固定就相对容易一些。

我们做的第一个尝试是使用市面上已经有的支架,把词典笔固定在支架上方,大家可以看下视频。

可以把笔夹住,直接固定在传送带上。
image

但是我们也发现了一个问题,支架每次只能固定一只笔,而且稳定性并不佳。

我们看这个视频也能看出来,一直在晃,这个效果只能说是能用。

而且我们刚才也提到了,在测试的过程当中,通常是需要让多支笔固定的。

所以我们尝试自己做了一个支架,把N支笔固定在传送带上方,这样,我们就可以实现用户扫描行为的完整模拟了。

这是我们对词典笔高效测试的第一次尝试,就是让硬件动了起来。

三、让方案更稳定

接下来我们要解决的问题是,让方案更稳定。

为什么有这样的需求呢?

在很长一段时间,我们都在使用上面提到的方案。

我们通过这套方案实现了功能稳定性的测试,对功耗以及电池曲线等都做了上百次的验证。

但是随着我们测试版本的增加,我们迭代的加快,自动化测试的需求更加频繁了。

在使用过程中,我们看到影响文字移动的稳定性,也就是传送带的稳定性因素是挺多的。

比如说电机老化,传动轴稳定性了,组装的精密程度,都可能会造成它文字转动时快时慢,甚至有的时候会停下来。

另外我们的前期一次可以去测试6支笔,但是到了后期,我们的测试版本的增加同时要测试的笔可能接近20支。

这个方案的改进就提上了日程。

我们还是分成文字的移动,以及笔的支撑两个部分来改进。

文字在垂直往复运动,这个方案我们使用的是传送带。

如果文字在水平方向往复运动呢?

我们观察了生活中很多的物品,最后发现小朋友喜欢的钓鱼玩具是一个不错的选择。

就是这个。

image.png

首先它的转速是恒定的,它在设计决定了影响它速度的因素,只是电机本身。

另外它的性价比比较高,这就使得我们可以快速的复制和扩充测试能力。

如果我们把文字在转盘边缘排列,然后允许运动,是不是就可以形成类似移动的效果呢?

为此,我们在文案上进行了一定的设计和改进。

我们把文字做了弧形的排版,固定在转盘上,在转盘的边缘固定测试笔,继续使用之前的自动化脚本。

这样就实现了用转盘的方案来实现扫描的行为模拟。
image.png

虽然它整体是个弧形的样子,但是得益于词典笔的算法优化,我们实际的拼图效果还是比较优秀的,对于测试测试没有什么影响。

最后我们去改装了它的供电方式为电源供电,这样它就可以长时间的做一个测试了。

接下来我们要解决的就是词典笔的支撑改进。

最开始是用硬纸来制作的简易的支架,这依旧是个扩展性不佳的方案。

随着我们的后期的调整和改进,我们在设计的同时帮助下,做了一个支架的改良版,通过建模和 3D 打印的方式就把它生产出来了。

这样的话它足够精密,同时它支撑10支笔的测试,而且他可以快速的复制,扩充给其他需要测试的场所。

这是我们实际 3D 打印出来之后的产品:

这就是我们在目前测试使用的方案,到这里我们看到整体硬件自动化已经比较稳定了。

四、让控制可远程

现在我们要考虑的事情,就是让控制可以远程。

我们在硬件测试上做的方案,原本都是在公司进行的,测试的设备也都是 QA 内部团队在用。

但是今年年初的疫情改变了我们的工作方式,在很长一段时间里我们都是在远程办公。

为了方便让开发人员更方便去调试,也为了让方便异地工作的同事们可以随时的进行测试,还有就是希望我们的测试方案的可控性更强,我们开始在做一些可控性方面的探索。

整体来说让控制可以远程这件事,我们分成了5个目标。

首先,是我们的测试脚本可以远程开启和关闭。

第二,是我们需要能够控制硬件的开关,主要是转盘的开关和供电系统的控制。

比如在静止的时候就可以开启转盘,测完之后就可以关闭转盘。测试功耗之前给词典笔充电,测试开始要断开供电。

第三,是需要满足开发人员在家进行远程调试的这样一个需求。

在家办公的时候,我们和开发不是同一个网络,甚至不是同一个城市,那开发如何快速进入词典笔内部进行调试呢?

第四,我们希望整个测试过程是可以被看到的,我们可以通过视频的监控来确定它的测试状态。

最后,由于测试自动化完成了大多数的项目后,我们需要对测试过程中的数据进行跟踪,测试过程中的数据保存与展示也不可获取。

所以基于这5个目标,我们设计了下面这套测试框架。

大家可以看到整个系统架构如下。

首先我们引入了一个主机或者叫控制系统,这里是用树莓派 4b 来做的。

在树莓派上我们连接了一个摄像机,采用了 mjpg-streamer 的方案,开了一个 web 的监控服务,这样测试人员可以随时去观察我们的词典测试的运行情况。

然后在树莓派的 GPIO 上,连了一个 L298n 的一个芯片,通过 python 我们可以使用芯片对电机开关和速度进进行控制。

之后我们又连接了一套继电器,用来对词典笔的通断电进行控制。

为了实现内网转发穿透的能力,我们搭建了一个 ngrok 服务,然后在测验词典笔启动它里面去,这样就可以从任何位置 ssh 到词典笔内部。

为了方便我们去观察数据和判断结果,我们使用了 influxdb 来保存测试中产生的数据,使用 grafana 来展示结果。

所以有了这样一套服务之后,开发产品和测试都可以实时的去用它。

这里我们有一个简单的演示视频。

我们外网通过 ngrok 服务远程,开启测试服务,然后开启转盘运转,这时测试开始。

测试中的视频就是通过树莓派的摄像头传输回来的。

当测试结束后,通过同样的方式,我们可以关闭或者继续进行其他的测试。

我们做了第三部分,让控制可以远程之后,我们基本上实现了一套框架。这套框架把我们用户最核心的操作,也就是扫描,变得可以自动化,可以远程控制,它可以稳定的远程控制。

五、让功能自动化

最后我们我们再来说说功能自动化的事情。

为了提升部分测试用例的自动化程度,我们还尝试做了一件事情,就是让功能自动化。

因为我们的产品是基于 Linux加QT 的架构实现的,为了提升它的测试效率,我们希望可以把核心软件功能自动化。

但是经过调研,市面上目前并没有足够成熟稳定的自动化测试方案适合我们。

我们通常说的自动化,大概的流程是先做控件的识别、再对控件做操作,然后对控件做校验。

在没有比较好的方案的前提下,我们用了一个“曲线救国”的自动化方案。

有道智云提供的 OCR 服务,可以针对图片上的文字进行识别。

它可以提取图片上的文字,并给出对应的坐标。

所以我们做的是:

01

用截屏加有道智云的 OCR 识别功能,实现了对文字的定位,代替了对控件的识别,例如“查词”,给出是否存在以及坐标位置。

02

用系统的操作,针对上面定位的坐标去点击、滑动等,实现了类似对控件的操作,例如点击“查词”的坐标。

03

最后我们还是用截屏,加上智云 OCR 识别,对页面的内容进行判断,例如对查词结果的验证。

这样就实现了基本的元素操作和控制。

我们就这样,把用户行为的自动化,设计并实现出来了。

下面的视频演示了我们采用该方案,全自动进行OTA升级测试的过程。

正常情况下,OTA测试需要一名全职测试工作8小时,来完成30轮次升级的验证。

有了自动化的方案,这个过程实现了无人值守测试,每晚可以实现50-100轮次的验证,第二天测试人员只需要检查测试过程的记录即可。

六、总结

经过上面的这些步骤,我们基本上对有道词典笔 2.0 的用户最核心操作——扫描后划词翻译,实现了软件和硬件方面的自动化。

通过硬件和软件结合的自动化方案,我们得到的收益巨大:

>>大幅提升了测试效率:

单个版本需要120+小时的测试数据,包括但不限于功能测试、主功能稳定性测试、随机稳定性测试、功耗测试、充放电电池曲线测试、耳机稳定性测试、耳机兼容性测试、OTA 测试等等;这些测试85%可以通过以上的测试框架来自动测试,我们单个版本的测试只需要2-3天,1-2人即可完成。

>>明确了产品质量:

我们针对每一项测试设计了不同的质量指标(例如功耗分成12种场景,测试时在不同场景下进行验证),得出的结果和之前版本或者竞品进行对比,从而判断我们产品的质量好坏。一个版本会有上百个指标,而这些指标就告诉了我们产品是否可以上线,产品的质量到底如何。

>>帮助发现硬件生产过程中的质量问题:

某个版本在两个批次的硬件测试中,同样的测试脚本和测试方案,测试出来的数据差异明显。通过多轮次的验证,对硬件的拆解等判断,最终定位某电阻混件造成了差异,由于我们提早发现了这个问题,尚未完成生产的产线停工,避免了更大的损失。

—— END ——

查看原文

赞 1 收藏 0 评论 0

高阳Sunny 关注了用户 · 1月14日

nzbin @nzbin

琴棋书画均可,文史经哲具通。文艺青年,痴迷漫画。
GitHub:https://github.com/nzbin
CodePen:https://codepen.io/nzbin
Zcool:https://xudili.zcool.com.cn

关注 8

高阳Sunny 赞了文章 · 1月13日

中国创企笨鸟 400GB 数据泄露,包含超 2 亿个人信息,知名网红也中招!

中国创企笨鸟 400GB 数据泄露,包含超 2 亿个人信息,知名网红也中招!

国外安全网站 Safetydetectives 研究团队发现,中国社交媒体管理公司笨鸟(Socialarks)泄漏了不安全的ElasticSearch数据库,导致超过400GB的个人资料数据对外泄漏,当中包括几位知名人士和网红。

笨鸟公司成立于 2014 年,是一家为跨境 B2B 企业提供销售线索推荐与转化及 ABM 营销服务的公司,其总部位于深圳,在北京、上海、广州等地均有分支机构。

报道称,此次泄露受影响的数据包含来自世界各地至少 2.14 亿人的个人敏感信息,包含 3.18 亿条记录,总计 408GB。这些数据基本来自 Facebook、Instagram 以及 LinkedIn 等专业网络的社交图文、影片等。

image.png

Safetydetectives 团队在对可能不安全的数据库进行常规 IP 地址检查期间,发现笨鸟的 ElasticSearch 服务器是对外公开的,没有密码保护或加密功能。

笨鸟公司服务器上缺乏安全装置,这意味着拥有服务器 IP 地址的任何人都可以访问包含数百万个人隐私信息的数据库。

此外,值得注意的是,2020 年 8 月,笨鸟公司也遭受了一次类似的数据泄露,导致 1.5 亿的 LinkedIn、Facebook 和 Instagram 用户的数据被暴露。

Safetydetectives 发现,笨鸟泄露的个人数据包括:

  • 11651162 条 Instagram 用户个人资料;
  • 66117839 条领英用户个人资料;
  • 81551567 条 Facebook 用户个人资料;
  • 55300000 条 Facebook 用户个人资料。

令人惊讶的是,安全研究团队发现的受数据泄漏影响的配置文件数量与该公司 8 月数据泄漏中提到的数量相同。但数据库的大小、托管这些服务的公司以及索引的数量存在很大差异。

从安全研究团队发现的泄漏数据中,可以确定人们的全名、居住国家、工作地点和联系方式等信息,还能直接链接到他们的个人资料。

下图显示了来自 4200 万条记录的按国家/地区分类的用户资料样本。

image.png

根据 Safetydetectives 网络安全团队负责人 Anurag Sen 的说法,笨鸟此次泄露的全部数据都是从社交媒体平台“刮走”的,这既不道德,又违反了 Facebook、Instagram 和 LinkedIn 的服务条款。

在这些用户的个人资料里,安全研究人员发现了几位美食博主和其他社交媒体网红的数据。

image.png

每条记录都包含从有影响力的 Instagram 帐户中抓取的公共数据,包括其履历、个人资料图片、关注者总数、位置设置以及个人信息,例如电子邮件地址和电话号码的联系方式。

image.png

Instagram记录公开了以下详细信息:

  • 用户全名;
  • 六百多万用户的电话号码;
  • 一千多万用户的电子邮件地址;
  • 个人资料链接;
  • 个人资料图片;
  • 资料描述;
  • 平均评论数;
  • 关注人数;
  • 所在国家;
  • 具体位置;
  • 常用标签。

泄露的 Facebook 用户资料包括 4000 万个电话号码、3200 万个电子邮件地址等。

Facebook 记录公开了以下详细信息:

  • 用户全名;
  • 电子邮件地址;
  • 电话号码;
  • 所在国家;
  • 喜欢、关注和评论数;
  • Facebook 链接与个人资料图片;
  • 资料描述。

LinkedIn 用户个人资料中泄漏的电子邮件地址多达 3100 万以上。

LinkedIn 记录显示了以下详细信息:

  • 用户全名;
  • 电子邮件地址;
  • 职务简介,包括职务和资历等级;
  • 个人资料链接;
  • 用户标签;
  • 域名;
  • 连接的社交媒体帐户登录名,例如 Twitter;
  • 公司名称和营业利润率。

目前尚不清楚该公司如何设法从多个安全来源获取私人数据。

image.png

数据抓取现象普遍,如何防止个人信息泄露?

在笨鸟公司的案例中,私人信息是从多个来源获得的,该公司的服务器安全性不足。当提取或泄露包括电话号码、电子邮件地址等私人信息被获取,很可能被利用。大量的数据被出售或提供给其他恶意方,会使数据抓取的潜在后果更加广泛和严重。

为防止数据泄露,个人用户需要加强防范意识,定期检查所在网站是否安全,设置复杂的安全密码,不随意点击电子邮件中的连接,避免在不安全的 Wi-Fi 网络上使用信用卡并输入密码。

数据抓取是从网站提取私人信息的一种手段。由于无缝连接的在线服务和平台的迅速蔓延,数据抓取在网上已变得司空见惯。

大多数数据抓取完全是无害的,并且由 Web 开发人员、商业智能分析师和部分企业出于在线市场研究目的而进行。但是,即使此类数据是合法获得的,如果存储这些数据时没有足够的网络安全性,也可能会发生影响数百万人的大泄漏。

segmentfault 公众号

查看原文

赞 5 收藏 1 评论 1

高阳Sunny 赞了文章 · 1月13日

InfoWorld 公布 2020 最佳开源软件名单,25 款软件上榜

近日,InfoWorld 公布了 2020 年最佳开源软件将的名单,入选获奖者都拥有领先的开放源码技术的实践经验。

每年,InfoWorld 都会为企业和 IT 专业人士颁发最佳开源软件奖。今年是 InfoWorld 的第 14 个年头,软件开发专家评选出了包括 25 个在数据分析、云计算、机器学习和软件开发领域得到认可的创新产品。

2020 年 InfoWorld 最佳开源软件奖得主包括:

1.Apache Airflow

image.png

Apache Airflow 是一个开源工作流管理平台,于2014年10月在 Airbnb 上启动,为公司管理提供工作流程的解决方案。通过创建Airflow,Airbnb 可以以编程方式创作和安排其工作流程,并通过内置的用户界面对其进行监视。该项目于 2016 年 3 月成为 Apache Incubator 项目,并于 2019 年 1 月成为顶级 Apache Software Foundation 项目。

GitHub 地址:https://github.com/apache/airflow

2.Apache Arrow

image.png

Apache Arrow 是与语言无关的软件框架,用于开发处理列数据的数据分析应用程序。Apache Arrow 由 Apache 软件基金会于 2016 年 2 月 17 日宣布,其开发由其他开源数据分析项目的开发人员联合领导。最初的代码库和 Java 库是由 Apache Drill 的代码植入的。

GitHub 地址:https://github.com/apache/arrow

3.Apache Druid

image.png

Apache Druid 于 2011 年成立,2012 年 10 月根据 GPL 许可开放源代码,并于 201 5年 2 月迁移至 Apache。Apache Druid 可以快速提取大量事件数据,并在数据之上提供低延迟查询。

GitHub 地址:https://github.com/apache/druid/

4.Apache Superset

image.png

Apache Superset 是用于数据探索和数据可视化的开源软件应用程序,能够处理大量数据。该应用程序由 Airbnb 开发,并于 2017 年进入 Apache 孵化器。

GitHub 地址:https://github.com/apache/superset

5.Apromore

image.png

Apromore 是一个协同业务流程分析平台,支持流程挖掘的全部功能。

Apromore 提供了基于最先进的研究的丰富的过程挖掘能力,以推动数字转换和 Operational excellence。

GitHub 地址:https://github.com/apromore

6.Argo

BBF94398-ABF9-4BC1-93FD-E481E19F025C.jpg

Argo 是容器本地工作流引擎,与 Kubernetes 一起使用。Argo 最初由 Intuit 开发,可以直接与 Kubernetes 资源以及 Docker 主导的自定义步骤进行交互。

GitHub 地址:https://github.com/argoproj

7.Bottlerocket

image.png

Bottlerocket 是一款基于 Linux 的容器主机开源操作系统,包括出色容器主机必备的软件包,并与现有的容器协调程序集成。Bottlerocket 使用基于映像的简单模型,可在必要时进行快速而完整的回滚。它支持 Docker 映像和符合 Open Container Initiative (OCI) 映像格式的映像。

GitHub 地址:https://github.com/bottlerocket-os/bottlerocket

8.Chapel

image

Chapel 是一种现代编程语言,是专门为超级计算机和集群设计的。Chapel 语言的语法有很多源头,除了常见的如 C,C++,Java外,它还借鉴了一些科学研究性语言比如 Fortran 和 Matalb 里的概念。

GitHub 地址:https://github.com/chapel-lang/chapel

9.Drupal

image

Drupal 是使用 PHP 语言编写的开源内容管理框架(CMF),它由内容管理系统(CMS)和 PHP 开发框架(Framework)共同构成。连续多年荣获全球最佳 CMS 大奖,是基于 PHP 语言最著名的 WEB 应用程序。

GitHub 地址:https://github.com/drupal/drupal

10.Gatsby

image

Gatsby 是基于 React 构建的、速度非常快的、现代化网站生成器。Gatsby 可以构建博客、电子商务网站、成熟的应用程序等。

GitHub 地址:https://github.com/kevinmichaelchen/gatsby-hubspot-poc

11.Hasura

image.png

Hasura GraphQL engine 提供了一个 Console 用于查询和更新数据库,可以提供可扩展的 Web API 层以访问数据。Hasura 跨不同数据源解锁数据,连接到现有的数据库和服务,并获取即时 API,以使数据可立即访问。

GitHub 地址:https://github.com/hasura/graphql-engine/

12.JanusGraph

image.png

JanusGraph 是可扩展的图形数据库,用于存储和查询分布在多机集群中的包含数千亿顶点和边的图形。

GitHub 地址:https://github.com/JanusGraph/janusgraph

13.Jekyll

image.png

Jekyll 是一个简单的免费的 Blog 生成工具,类似 WordPress。但是和 WordPress 又有很大的不同,它只是一个生成静态网页的工具,不需要数据库支持。但是可以配合第三方服务,例如 Disqus。最关键的是 Jekyll 可以免费部署在 Github 上,而且可以绑定自己的域名。

GitHub 地址:https://github.com/jekyll/jekyll

14.K9s

image.png

K9s 是一个管理 Kubernetes 集群的工具,以不断更新的方式封装了所有 kubectl 功能,可以让开发者快速查看并解决 Kubernetes 中的日常问题。

GitHub 地址:https://github.com/derailed/k9s

15.KubeDirector

image

使用标准的 Kubernetes 自定义资源功能和API扩展来部署和管理复杂的有状态扩展应用程序集群。KubeDirector 利用了本地 Kubernetes API 扩展和设计哲学,支持与 Kubernetes 用户/资源 管理以及现有客户端和工具的透明集成。

GitHub 地址:https://github.com/bluek8s/kubedirector

16.Lem

image

Lem 是使用 Common Lisp 重写 Emacs 的全新方法,Common Lisp 使 Lem 可以访问 GUI 库以获得 Electron GUI 的 alpha 版本,对 C/C++ 的无缝调用以及对大量第三方库的访问。

GitHub 地址:https://github.com/lem-project/lem

17.Open Policy Agent

image

Open Policy Agent 提供了一个通用的授权引擎,该引擎将策略决策与应用程序级执行分离开来。它接受一系列 JSON 属性,根据其权限内的策略和数据对它们进行评估,比ing对应用程序作出响应。

GitHub 地址:https://github.com/open-policy-agent/opa

18.Optuna

image

Optuna 是主要面向深度学习超参数调优开发的框架,专为机器学习而设计,具有脚本语言特性的用户API。在实现之初就考虑到了大型模型参数调优的各种实际情况,并逐一针对它们设计了解决方案。

GitHub 地址:https://github.com/optuna/optuna

19.Prisma

image

Prisma 是新一代的数据库工具集,ORM 框架,能够管理复杂的数据库构建和读写,拥有优异的开发体验,快速开发 GraphQL、REST、gRRC 等服务,适用于任意语言和数据库。

GitHub 地址:https://github.com/prisma/prisma/discussions

20.QuestDB

image

QuestDB 是一个开放源代码的 NewSQL 关系数据库,旨在更快地处理时间序列数据。 为了提供出色的查询性能,QuestDB 提供了用于交互式查询的代码编辑器以及一些基本的表和可视化工具。

QuestDB 可在 Linux、MacOS 和 Windows 上运行,并使软件包可用于 Docker 和 Homebrew。

GitHub 地址:https://github.com/questdb

21.Redis

image

Redis 是一个高性能的 key-value 数据库,它的出现,很大程度补偿了 memcached 这类 key/value 存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了 Java、C/C++、C#、PHP、JavaScript、Perl、Object-C、Python、Ruby、Erlang 等客户端,使用很方便。

GitHub 地址:https://github.com/redis/redis

22.Seldon Core

image

Seldon Core 是一个用于在 Kubernetes 上部署机器学习模型的开源平台。它使得在 Kubernetes 上部署机器学习模型和实验变得更加容易和快速,可以在任何云上运行任何工具包。

GitHub 地址:https://github.com/SeldonIO/seldon-core

23.Sourcegraph

image

Sourcegraph 是一个方便的代码查看插件,可以集成到工作流中统一搜索过程,使用户可以快速、完整的了解整个代码库。

开发者可以在 Web 浏览器上从代码仓库、安装包,甚至是函数里搜索代码,也可以直接点击被完全创建链接的代码来阅读文档、跳转到变量定义或者马上找到可用的 Demo。

GitHub 地址:https://github.com/sourcegraph/sourcegraph

24.SPIFFE

image.png

SPIFFE 用于安全地标识动态和异构环境中的软件系统,采用 SPIFFE 的系统可以在任何运行位置轻松,可靠地相互进行身份验证。

GitHub 地址:https://github.com/spiffe

25.Vulkan

image

Vulkan 是一个跨平台的 2D 和 3D 绘图 API,它是 AMD Mantle 的后续版本,继承了前者强大的低开销架构,使软件开发人员能够全面获取 Radeon GPU 与多核 CPU 的性能、效率和功能。

Vulkan 能够支持深入硬件底层的控制,为 Windows 7、Windows 8.1、Windows 10 和 Linux 带来更快的性能和更高的影像质量。Vulkan API 还提供超高的 OS 兼容性、渲染特性和硬件效率。

GitHub 地址:https://github.com/SaschaWillems/Vulkan

segmentfault.com 公众号

查看原文

赞 7 收藏 5 评论 0

高阳Sunny 赞了文章 · 1月13日

写在2020年结尾——2020总结

回顾

又是新的一年了,回顾20年,想写点什么,删了又写,写了又删;翻看自己的文章记录,发现最后写的文章已经是19年的年终总结,已经很久没有写文章了。

去年的总结来说,比以往更忙了一些,今年相对来说更忙,但是忙的时候却也比较有充实感。今年做了很多新东西,包括项目改版,以及维护项目过程中做的很多程序上的优化,也算是在不断的进步。相比去年来说,今年能明显的感觉bug写得比较少,有用得代码写得比较多,明显更加细心,也算是个不小的进步。

一整年来没写啥技术文章,一方面来说,所做的东西相对比较杂乱,不太好成体系,另外就是有些想写的东西,已经有很多相关的文章,感觉也没必要写出来凑数。对于一个开发者来说,写东西和写代码一样,总想研究一些新东西,然后把经验分享出来,让大家分享、点赞,提高成就感 ;要么就是想做一些成体系的教程出来,做成体系课,赚点钱花花。但是这些对于今年的我来说,精力都不是很够。

关于工作

对于工作上来说,对于目前的公司情况来说,倒是积累了一些技巧。首先就是把工作分成几种类型,从大类型上来说,分为 bug产品开发需求运营需求。然后再给不同的类型再排个紧急次序,一开始还需要做个笔记分配一下不同需求开发时间,后期基本上把所有的需求类型在脑子里过一下就能排出开发现后顺序以及开发时间。

一般来说,需求开发通常是一个跨度比较大的周期,一般都是一周两周。且需求通常来说也是成一套体系来进行管理的,一般对需求体系拆分做两种形式拆分。一种是以一个项目为体系,另外一种是按照开发需求的优先顺序进行拆分。以项目体系进行拆分通常是某个项目的需求包含内容比较多,通常时间都是横跨一个周或者两个周;以开发需求优先顺序拆分通常是以周为工作量单位进行划分,把当前这个周的需求划分出来再排个优先级进行处理。

对于bug来说,那么通常就是处理玩一段时间的需求之后,再抽出一到两天的时间来进行专门的处理,这样子处理bug的时候不会受到需求干扰,不会分心,也就不会写完bug引入新的bug。

而对于运营需求来说,通常就是数据上的导出处理,一般这种情况都是紧急插入需求,需要对原任务进行一些拆分处理后才能做。

虽然今年工作相对比较忙,但是一直都比较顺利,没太大的插曲,倒是积累了很多除了程序开发本身技能之外的项目处理经验。

关于生活

说到生活,基本上都是焦虑中度过的吧,随着小孩慢慢长大,花钱的地方也多,目前又没有房子,对于以后小孩上学的问题一直很焦虑,疫情影响,老婆的工作也不太顺利,钱也很难攒下来。很明显的,今年发际线明显变高了,为了阻止头发继续往下掉,不得不剪了个光头。

生活另外一方面的焦虑就是小孩越来越大了之后需要挺多时间陪,自己的时间也更少了,抽不出太多时间学习,等到小孩睡得时候已经很晚了,然后再想学习,发现已经没有前几年时候那种精力了。

没啥存款,对于未来,暂时不知道咋办,只能走一步看一步吧,对生活还是抱着一些希望。

本文参与了 SegmentFault 思否征文「2020 总结」,欢迎正在阅读的你也加入。
查看原文

赞 3 收藏 0 评论 1

高阳Sunny 赞了文章 · 1月13日

代码家:简明数据库史

本文作者:代码家,资深开发者,热衷于开源社区,GitHub 20K 的 Star,15K 的 Follower;数字货币信奉者,热爱二级市场交易(股票+数字货币);目前在真格基金做投资。

如果你想与代码家交流,可以加他的微信:daimajia(著名来源和身份),如果你在创业,或者有想法创业,也欢迎投递 BP 或者和代码家邮件交流: huiwen@zhenfund.com

在工业时代,煤炭和钢铁的使用量是一个国家发达程度的指标。而到了信息时代,数据量将是新的发达程度指标,几乎所有行业竞争本质上都是数据的竞争。支撑数据增长的背后,是一代又一代不断演化的数据库引擎,在真格基金的投资工作中,不断的开始有中国团队尝试挑战数据库领域海外的垄断地位,打造新一代的数据库引擎。业余时间,对整个数据库发展史做了个简单的总结。

整个数据库大致经历了四个发展阶段。

第一阶段:非关系型数据库

在现代意义的数据库出来之前(20 世纪 60 年代),文件系统(File system)可以说是最早的数据库,程序员们读取文本文件,并通过代码提取文件中的关键数据,在脑海中尝试构造数据与数据之间的关系。当年能流行起来的编程语言,往往都有很强的文件和数据处理能力(比如 Perl 语言)。随着数据量的增长,数据维度的多元化,以及对于数据可信和数据安全的要求不断提升,简单的将数据存储在 txt 文本中,成为极其具有挑战的事情。

随后,人们开始提出数据库管理系统(Database Management System, DBMS)的概念。数据库的演进抽象来看是人们对 数据结构 和 数据关系 这两个维度展开的思考和优化。

层次模型和网络模型(1960)

第一阶段的数据库模型(Database model) 是层次模型(Hierarchical Databases)。

图 1:一个表达学校结构的层次模型数据库

层次模型是最早的数据库模型。随着早期 IBM 大型机逐渐推广开来。这个模型相对于文本文件管理数据,是个巨大的提升,但也有很多问题。

问题:

  • 尽管能比较好的表达 一对一 ( one to one) 结构,但在 多对多(many to many) 结构上难以表达

    • 如:图中能较好的表达一个系有多个老师,但很难表达一个老师可能属于多个系。
  • 层次结构不够灵活

    • 如:添加一个新的数据库关系有可能对整个数据库结构带来巨大变化,以至于在真正的开发中带来巨大的工作量
  • 查询数据需要脑海中随时有最新的结构图,且需要遍历树状结构做推导

而后在层次模型的基础之上,人们提出了优化方案,即:网络模型(Network Model)。

图 2:网状模型的数据库

网络模型是关系型数据库出来之前最为流行的数据库模型。很好的解决了数据的多对多的问题。但依然存在以下问题:

问题:

  • 难以从代码层面实现和维护
  • 查询数据需要脑海中随时有最新的结构图

第二阶段:关系型数据库

模型初期(1970)

关系模型( Relational Model) 是相对网络模型的巨大飞跃。在网络模型中,不同类型的数据总是会依赖另一类数据,如图 1 中,Teachers 从属于 Departments,这是层次模型和网络模型在真实设计和开发中痛苦的根源(因为你总是要在脑海中记录当前的网络结构,想象一下一个拥有几千张表的复杂系统)

关系模型一大创新就是拆掉了表和表之间的链接,将关系只存储在当前表中的某一个字段中(fields),从而实现不同的表之间的相对独立。如下表:当你只看 Table2 的时候,你就知道 Product_code 会指向一个 产品的具体细节,Table2 和 Table1 在保持相对独立的同时,又自然而然的连接了起来。

图 3:关系型数据库
Table2 中的 Product_code 列指向了 Table1 中对应的数据,从而建立 Table2 和 Table1 的关系

1970年,当 E.F.Codd 开发出这个模型时,人们认为是难以实现的,正如上面的例子一般,当你检索 Table2 时,遇到 Product_code 列,就需要再去 Table1 遍历一遍。受限于当时的硬件条件,这种检索方法总是会让机器难以负载。但很快,大家质疑的问题,在摩尔定律加持下,已经不再是问题。大家如今所听说的 IBM DB2, Ingres, Sybase, Oracle, Informix, MySQL 就是诞生在这个时代。

至此数据库领域诞生了一个大的分类:联机事务处理 OLTP(on-line transaction processing),代指一类专门用于日常事务的数据库,如银行交易用的增删改查数据库。后面还会提到另一类数据库,专门用于从大量数据中发现决策的辅助数据库 On-Line Analytical Processing – OLAP(联机分析处理)数据库。

数据仓库(1980s)

随着关系型数据库的发展,不同业务场景数据化,人们开始有了汇集不同业务场景数据,并尝试进行数据分析并辅助业务决策的想法(Decision Support System)。在此需求之上,诞生了数据仓库( Data warehouse)的概念。

如下图:一个企业往往把不同的业务场景数据存在不同的数据库中,在没有成熟的数据仓库产品之前,数据分析师往往需要自己做大量的前期准备工作来汇集自己所需的数据。而数据仓库本质上就是解决数据分析和挖掘的业务场景。

图 4:数据仓库

解释:ETL 是 Extract(提取),Transform(转换),Load(加载)的缩写。因为数据在不同的数据库或者系统中,可能存在格式不统一,单位不统一等等情况。需要做一次数据的预处理。

数据仓库是一个面向主题的、集成的、非易失的、随时间变化的用来支持管理人员决策数据集合。

OLAP(联机分析处理)

1980 年代有了数据仓库的概念和实现后,人们尝试在此基础上做数据分析。但分析的过程出现一些新的问题。最明显的是效率问题。因为之前的关系型数据库并不是为数据分析而打造。数据分析师想要的是一个支持多维的数据视图和多维数据操作的引擎。

如下面👇的数据魔方一般,相比于上面提到的关系型数据库中的二维数据展示和二维数据操作而言。OLAP 数据库对多个维度的数据可以快速的组建和操作。

数据魔方
将多个维度的数据组织和展示

数据魔方的多种操作

1993 年,关系型数据库创始人Edgar F. Codd提出联机分析处理(OLAP)的概念。本质上是多维数据库和多维分析能力的概念。目标是满足决策支持或多维环境特定的查询和报表需求。

第三阶段:NoSQL

时间继续推进,互联网时代到来以后,数据量的暴增给关系型数据库也带来的新的挑战。最为明显的挑战有以下两点:

挑战一:数据列的扩展成本巨高

关系型数据库因为提前定义了 Table 的字段(Fields),当数据库已经拥有数以亿计条的数据之后,业务场景需要一列新的数据,你惊讶的发现,在关系型数据库的规则限制下,你必须要同时操作这数以亿计的数据爱完成新的一列的添加(不然数据库会有报错出现),对生产环境的服务器性能挑战极大。

可以想象一下 Facebook,Twitter, Weibo 这样的社交网站,每天字段都在不断的变化,来添加各种新的功能。

比如需要添加 status 列,你必须要在某一时刻同时为数以亿计的行,添加 Active 或者 In-Active 内容,否则数据库会无法满足合规约束

挑战二:数据库性能的挑战

业务规模不断上升之后,关系型数据库的性能问题开始浮出水面,虽然数据库供应商都提出了各种解决方案,但底层关系绑定式的设计依然是性能天花板的根本原因。开发人员开始尝试分库、分表、加缓存等极限操作来挤出性能。

在此挑战之上,人们提出了新的数据库模型 – NoSQL。

针对扩展数据列的问题,NoSQL 提出了新的数据存储格式,去掉了关系模型的关系性。数据之间无关联,这样就换回了架构上的扩展性。

新的数据结构,将相关性数据都放在一起

NoSQL 更底层的创新源自于天生为集群可扩展场景所打造。

而在 NoSQL 理论基础之上,根据企业应用场景又拓展出了四大类型的数据库:

  • 文档型数据库(Document-Oriented):如大名鼎鼎的 MongoDB、CouchDB。文档泛指一种数据的存储结构,如 XML、JSON、JSONB 等。
  • 键值数据库(Key-Value Database) :大家所听说的 Redis、Memcached、Riak 都是键值对数据库
  • 列式存储数据库(Column-Family):如 Cassandra、HBase
  • 图数据库(Graph-oriented):如 Neo4j、OrientDB 等。聚焦在数据间关系链的数据组织方式。

随着企业数据的不断变大,对数据处理能力也提出了新的要求。日常所听到的大数据(Big Data)一词,代表一个庞大的技术体系结构。包括了数据的采集,整理,计算,存储,分析等环节。数据库只是其中一环。如下图,饿了么2017 年大数据架构,文中所提到的数据库,基本上只代表了图中存储环节。大家日常所听到的 Hadoop、Kafka、Hive、Spark、Materialize等都是大数据引擎,千万不要搞混了。

数据库只是大数据概念中的一部分

第四阶段:

随着云时代的到来,基于云环境所打造的云原生数据库不断地开始占了数据库市场份额。

云原生数据库和托管/自建数据库最大的区别就是:云原生数据库是面向独立资源的云化,其CPU、内存、存储等均可实现独立的弹性,利用大型云厂商的海量资源池,最大化其资源利用率,降低成本,同时支持独立扩展特定资源,满足多种用户不断变化的业务需求,实现完全的Serverless; 而托管数据库还是局限于传统的服务器架构,各项资源等比率的限制在一个范围内,其弹性范围,资源利用率都受到较大的限制,无法充分利用云的红利。

http://mysql.taobao.org/monthly/2020/05/01/

基于云原生数据库技术,未来创业团队无需花费巨大精力来应对海量数据来袭,只需聚焦在业务即可。

云原生数据库的代表如:阿里云的 PolarDB、腾讯云的 CynosDB、华为云的 TaurusDB、亚马逊云的 Aurora。

最后,以阿里 CIO 学院的一个数据库分布图结束这篇文章,图示中的数据库产品和分布图很好的代表了当前数据库产业的格局。

附录:

数据库领域里有一个不得不提的 CAP 理论,感兴趣的可以阅读阮一峰的 Blog

CAP 理论

在近代数据库领域,有一个 CAP 理论,CAP 分别代表:

  • Consistency(数据一致性)
  • Availability(数据可用性)
  • Partition tolerance(分区容错)

CAP 理论简单理解就是分布式数据库不可能同时做到一致性、可用性和分区容错这三个指标。更具体的解释可以参考阮一峰的 Blog,写的非常棒,这里就不展开。

关系型数据库库选择了一致性和分区容错,而 NoSQL 为了适应业务需要,选择了分区容错和可用性。

查看原文

赞 16 收藏 6 评论 1

高阳Sunny 赞了文章 · 1月13日

TypeScript 渐进迁移指南

Nathaniel 原作,翻译转载自 New Frontend

我在大概一年前写了一篇如何把 Node.js 项目从 JavaScript 迁移到 TypeScript 的指南。指南的阅读量超过了七千,不过其实当时我对 JavaScript 和 TypeScript 的了解并不深入,把重心更多地放到特定工具上,而没怎么从全局着手。最大的问题是我没有提供迁移大型项目的解决方案。显然,大型项目不可能在短时间内重写一切。因此,我很想分享下我最近学到的迁移项目到 TypeScript 的主要经验。

迁移一个包含成千上百个文件的大型项目可能比你想象得要容易。整个过程主要分 3 步。

注意:本文假定你已经有一定的 TypeScript 基础,同时使用 Visual Studio Code,否则,一些地方可能不一定直接适用。

相关代码:https://github.com/llldar/mig...

开始引入类型

花了 10 个小时使用 console.log 排查问题后,你终于修复了 Cannot read property 'x' of undefined 问题,出现这个问题的原因是调用了可能为 undefined 的某个方法,给了你一个「惊喜」!你暗暗发誓,一定要把整个项目迁移到 TypeScript。但是看了看 libutilcomponents 文件夹里上万个 JavaScript 文件,你对自己说:「等以后吧,等我有空的时候。」当然那一天永远也不会到来,因为总有各种酷炫的新特性等着加到应用,客户也不会因为项目是用 TypeScript 写的就出大价钱。

如果我告诉你,你可以增量迁移到 TypeScript 并立刻从中受益呢?

添加神奇的 d.ts

d.ts 是 TypeScript 的类型声明文件,其中声明了代码中用到的对象和函数的各种类型,不包含任何具体的实现。

假定你在写一个即时通讯应用,在 user.js 文件里有一个 user 变量和一些数组:

const user = {
  id: 1234,
  firstname: 'Bruce',
  lastname: 'Wayne',
  status: 'online',
};

const users = [user];

const onlineUsers = users.filter((u) => u.status === 'online');

console.log(
  onlineUsers.map((ou) => `${ou.firstname} ${ou.lastname} is ${ou.status}`)
);

那么对应的 user.d.ts 会是:

export interface User {
  id: number;
  firstname: string;
  lastname: string;
  status: 'online' | 'offline';
}

然后 message.js 里定义了一个函数 sendMessage

function sendMessage(from, to, message)

那么 message.d.ts 中相应的类型会是:

type sendMessage = (from: string, to: string, message: string) => boolean

不过,sendMessage 也许没那么简单,参数的类型可能更复杂,也可能是一个异步函数。

你可以使用 import 引入其他文件中定义的复杂类型,保持类型文件简单明了,避免重复。

import { User } from './models/user';
type Message = {
  content: string;
  createAt: Date;
  likes: number;
}
interface MessageResult {
  ok: boolean;
  statusCode: number;
  json: () => Promise<any>;
  text: () => Promise<string>;
}
type sendMessage = (from: User, to: User, message: Message) => Promise<MessageResult>

注意:我这里同时使用了 typeinterface,这是为了展示如何使用它们。你在项目中应该主要使用其中一种。

连接类型

现在已经有类型了,如何搭配 js 文件使用呢?

大体上有两种方式:

Jsdoc typedef import

假设同一文件夹下有 user.d.ts,可以在 user.js 文件中加入以下注释:

/**
 * @typedef {import('./user').User} User
 */

/**
 * @type {User}
 */
const user = {
  id: 1234,
  firstname: 'Bruce',
  lastname: 'Wayne',
  status: 'online',
};

/**
 * @type {User[]}
 */
const users = [];

// onlineUser 的类型会被自动推断为 User[]
const onlineUsers = users.filter((u) => u.status === 'online');

console.log(
  onlineUsers.map((ou) => `${ou.firstname} ${ou.lastname} is ${ou.status}`)
);

确保 d.ts 文件中有相应的 importexport 语句,这一方式才能正确工作。否则,最终会得到 any 类型,显然 any 类型不会是你想要的。

三斜杠指令

在无法使用 import 的场景下,三斜杠指令是导入类型的经典方式。

注意,你可能需要在 eslint 配置文件中加入以下内容以免 eslint 把三斜杠指令视为错误:

{
  "rules": {
    "spaced-comment": [
      "error",
      "always",
      {
        "line": {
          "markers": ["/"]
        }
      }
    ]
  }
}

假设 message.jsmessage.d.ts 在同一文件夹下,可以在 message.js 文件中加入以下三斜杠指令:

/// <reference path="./models/user.d.ts" /> (仅当使用 user 类型时才加这一行)
/// <reference path="./message.d.ts" />

然后给 sendMessage 函数加上以下注释:

/**
* @type {sendMessage}
*/
function sendMessage(from, to, message)

接着你会发现 sendMessage 有了正确的类型,IDE 能自动补全 fromtomessage 和函数的返回类型。

或者你也可以这么写:

/**
* @param {User} from
* @param {User} to
* @param {Message} message
* @returns {MessageResult}
*/
function sendMessage(from, to, message)

这是 jsDoc 书写函数签名的风格,肯定没有上一种写法那么简短。

使用三斜杠指令时,应该在 d.ts 文件中移除 importexport 语句,否则无法工作。如果你需要从其他文件中引入类型,可以这么写:

type sendMessage = (
  from: import("./models/user").User,
  to: import("./models/user").User,
  message: Message
) => Promise<MessageResult>;

这一差别背后的原因是 TypeScript 把不含 importexport 语句的 d.ts 文件视作环境(ambient)模块声明,包含 importexport 语句的则视为普通模块文件,而不是全局声明,所以无法用于三斜杠指令。

注意,在实际项目中,选择以上两种方式中的一种,不要混用。

自动生成 d.ts

如果项目的 JavaScript 代码中已经有大量 jsDoc 注释,那么你有福了,只需以下一行命令就能自动生成类型声明文件:

npx typescript src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types

以上命令中,所有 js 文件在 src 文件夹下,输出的 d.ts 文件位于 types 文件夹下。

babel 配置(可选)

如果项目使用 babel,那么需要在 babelrc 里加上:

{
  "exclude": ["**/*.d.ts"]
}

否则 *.d.ts 文件会被编译为 *.d.js 文件,这毫无意义。

现在你应该就能享受到 TypeScript 的益处了(自动补全),无需额外配置 IDE,也不用修改 js 代码的逻辑。

类型检查

如果项目中 70% 以上的代码都经过以上步骤迁移后,你可以考虑开启类型检查,进一步帮助检测代码中的小错误和问题。别担心,你仍将继续使用 JavaScript,也就是说不用改动构建过程,也不用换库。

开启类型检查的主要步骤是在项目中加上 jsconfig.json。例如:

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "checkJs": true,
    "lib": ["es2015", "dom"]
  },
  "baseUrl": ".",
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

关键在于 checkJs 需要为真,这就为所有项目开启了类型检查。

开启后可能会碰到一大堆报错,可以逐一修正。

渐进类型检查

// @ts-nocheck

如果你希望以后再修复一些文件的类型问题,可以在文件头部加上 // @ts-nocheck,TypeScript 编译器会忽略这些文件。

// @ts-ignore

如果只想忽略某行而不是整个文件的话,可以使用 // @ts-ignore。加上这个注释后,类型检查会忽略下一行。

使用这两个标记可以让你慢慢修正类型检查错误。

第三方库

维护良好的库

如果用的是流行的库,那 DefinitelyTyped 上多半已经有类型定义了,只需运行以下命令:

yarn add @types/your_lib_name --dev

npm i @types/your_lib_name --save-dev

注意:如果库属于某组织,库名中包含 @/,那么在安装相应的类型定义文件时需要移除 @/,并在组织名后加上 __,例如 @babel/core 改为 babel__core

纯 JS 库

如果用了一个作者 10 年前就已经停止更新的 js 库怎么办?大多数 npm 模块仍然使用 JavaScript,没有类型信息。添加 @ts-ignore 看起来不是一个好主意,因为你希望尽可能地确保类型安全。

那你就需要通过创建 d.ts 文件增补模块定义,建议创建一个 types 文件夹,加入自己的类型定义。然后就可以享受类型安全检查了。

declare module 'some-js-lib' {
  export const sendMessage: (
    from: number,
    to: number,
    message: string
  ) => Promise<MessageResult>;
}

完成这些步骤后,类型检查应该能很好地工作,可以避免代码出现很多小错误。

类型检查升级

修复 95% 以上类型检查错误并确保每个库都有相应的类型定义后,你可以进行最后一步:正式把整个项目的代码迁移到 TypeScript。

注意:我上一篇指南中提到的一些细节这里就不讲了。

把所有文件改为 .ts 文件

现在是时候把 d.ts 文件和 js 文件合并了。由于几乎所有的类型检查错误都已修正,类型检查已经覆盖所有模块,基本上只需要把 require 改成 import 然后把代码和类型定义都放到 ts 文件中。完成之前的工作后,这一步相当简单。

把 jsconfig 改为 tsconfig

现在我们需要的是 tsconfig.json 而不是 jsconfig.json

tsconfig.json 的例子:

前端项目

{
  "compilerOptions": {
    "target": "es2015",
    "allowJs": false,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "noImplicitThis": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "lib": ["es2020", "dom"],
    "skipLibCheck": true,
    "typeRoots": ["node_modules/@types", "src/types"],
    "baseUrl": ".",
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

后端项目

{
  "compilerOptions": {
      "sourceMap": false,
      "esModuleInterop": true,
      "allowJs": false,
      "noImplicitAny": true,
      "skipLibCheck": true,
      "allowSyntheticDefaultImports": true,
      "preserveConstEnums": true,
      "strictNullChecks": true,
      "resolveJsonModule": true,
      "moduleResolution": "node",
      "lib": ["es2018"],
      "module": "commonjs",
      "target": "es2018",
      "baseUrl": ".",
      "paths": {
          "*": ["node_modules/*", "src/types/*"]
      },
      "typeRoots": ["node_modules/@types", "src/types"],
      "outDir": "./built",
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

因为这样修改后类型检查会变得更严格,所以可能需要修复一些额外的类型错误。

修改 CI/CD 和构建流程

改到 TypeScript 后需要在构建流程中生成可运行的代码,通常在 package.json 中加上这一行就行:

{
  "scripts":{
    "build": "tsc"
  }
}

不过,前端项目通常用了 babel,你需要这样设置项目:

{
  "scripts": {
    "build": "rimraf dist && tsc --emitDeclarationOnly && babel src --out-dir dist --extensions .ts,.tsx && copyfiles package.json LICENSE.md README.md ./dist"
  }
}

别忘了改入口文件,比如:

{
  "main": "dist/index.js",
  "module": "dist/index.js",
  "types": "dist/index.d.ts",
}

好了,万事俱备。

注意,dist 需要改成你实际使用的目录。

结语

恭喜,代码现在迁移到了 TypeScript,有严格的类型检查保证。现在可以享受 TypeScript 带来的所有好处,比如自动补全、静态类型、esnext 语法、对大型项目友好。开发体验大大提升,维护成本大大降低。编写项目代码不再是痛苦的过程,再也不会碰到 Cannot read property 'x' of undefined 报错。

替代方案:

如果你希望一下子迁移整个项目到 TypeScript,可以参考 airbnb 团队的指南

查看原文

赞 7 收藏 4 评论 0

高阳Sunny 关注了用户 · 1月13日

掌门教育前端 @zhangmenjiaoyuqianduan

关注 1

高阳Sunny 赞了文章 · 1月12日

Mac 下有哪些好用的终端工具

这篇笔记主要是用来整理自己一直在使用的一些较为好用的终端工具/扩展。

因为我个人的终端配置是ZSH + iTerm2,所以本文的部分ZSH 扩展可能不适用于其他Shell用户。

brew

经常与终端打交道的用户,对这个一定不陌生,它就是类似Ubuntu下的apt-get这样的包管理工具。

通常我需要搭建一个全新的开发环境时,它一定是第一个需要安装的工具。

安装 brew(brew 官网

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

常用命令如下:

命令描述
brew search package搜索软件包
brew install package安装软件包
brew uninstall package卸载软件包
brew list列出已安装清单
brew help获取帮助

OSX 扩展

osx 扩展是zsh 提供的一个控制终端和访达(功能之一)的扩展工具。

其中最为常用是ofd命令,将当前shell窗口在访达中打开。

另一个较为常用的命令是cdf,可在shell中直接跳转至当前访达窗口所在的路径(如果存在多个访达窗口,那么跳转至最前面的那个)。

其他常用命令如下:

命令描述
tab在当前目录打开一个新窗口
split_tab在当前窗口打开一个水平窗口
vsplit_tab在当前窗口打开一个垂直窗口
ofd在访达窗口中打开当前目录
pfd返回最前面的访达窗口的路径
pfs返回当前查找程序选择
cdfcd 到当前访达窗口所在的路径
pushdfpushed 到当前访达目录
quick-look快速查看指定文件
man-preview在预览应用程序中打开特定的手册页
showfiles显示隐藏文件
hidefiles隐藏隐藏的文件
rmdsstore以递归方式删除目录中的.DS_Store文件

tmux

tmux 是一个终端下窗口分割的工具,有关它的具体介绍,请查阅这篇笔记

autojump

autojump - 目录快速跳转命令行工具,从此告别cd... cd...

autojump 是一个WindowsLinuxmacOS 都能使用的命令行工具,这是仅介绍macOS 的安装方式。

brew install autojump

使用brew安装完成之后,还需要进行配置,以下方法二选一:

  • ~/.bash_profile 文件中加入语句 [[ -s $(brew --prefix)/etc/profile.d/autojump.sh ]] && . $(brew --prefix)/etc/profile.d/autojump.sh
  • ~/.zshrc 文件中,修改 plugins=(git) 插件配置行,以开启 zshautojump 插件的支持 plugins=(git autojump)

常用命令

命令描述
j foo跳转到包含 foo 的目录
jc bar跳转到包含 bar 的子目录
jo file在访达中打开包含 file 的目录
autojump --help打开帮助列表

Spaceship ZSH

Spaceship ZSH——是一个极简、强大和可定制的ZSH提示符。

我是在无意间发现的这个终端工具的,先来看一下实际效果。

image

特点

Spaceship ZSH 有很多很棒的特点,这里仅仅列举一些我所看见的。

  • 颜值即正义
  • 展示当前Git 仓库的状态
  • 展示各种语言的当前版本
  • 展示最后一条命令的总执行时间

安装

Spaceship ZSH 的安装方式有多种,这里仅介绍通过oh-my-zsh的安装方式,其他方式可参考官网

  1. 克隆仓库
git clone https://github.com/denysdovhan/spaceship-prompt.git "$ZSH_CUSTOM/themes/spaceship-prompt"
  1. spaceship.zsh-theme 链接到oh-my-zsh 的主题目录
ln -s "$ZSH_CUSTOM/themes/spaceship-prompt/spaceship.zsh-theme" "$ZSH_CUSTOM/themes/spaceship.zsh-theme"
  1. 编辑~/.zshrc
ZSH_THEME="spaceship"

tldr

tldr 是一个比man 更好用的命令行手册。

它衍生出了各种语言的客户端,这里直接使用官网推荐的方式进行安装:

npm install -g tldr

安装完成之后,第一次使用tldr命令需要下载相关依赖:

tldr tar
Page not found. Updating cache...
Error: connect ECONNREFUSED 127.0.0.1:443

如果出现上面这个输出,表示命令行需要使用代理,如果不知道如何设置,可以参考这篇笔记

正常输出如下:

tldr tar
✔ Page not found. Updating cache...
✔ Creating index...

  tar

  Archiving utility.
  Often combined with a compression method, such as gzip or bzip.
  More information: https://www.gnu.org/software/tar.

  - [c]reate an archive from [f]iles:
    tar cf target.tar file1 file2 file3

  - [c]reate a g[z]ipped archive from [f]iles:
    tar czf target.tar.gz file1 file2 file3

  - [c]reate a g[z]ipped archive from a directory using relative paths:
    tar czf target.tar.gz --directory=path/to/directory .

  - E[x]tract a (compressed) archive [f]ile into the current directory:
    tar xf source.tar[.gz|.bz2|.xz]

  - E[x]tract a (compressed) archive [f]ile into the target directory:
    tar xf source.tar[.gz|.bz2|.xz] --directory=directory

  - [c]reate a compressed archive from [f]iles, using [a]rchive suffix to determine the compression program:
    tar caf target.tar.xz file1 file2 file3

  - Lis[t] the contents of a tar [f]ile [v]erbosely:
    tar tvf source.tar

  - E[x]tract [f]iles matching a pattern:
    tar xf source.tar --wildcards "*.html"

上面那个node 的客户端不是交互式的,如果需要自动的,可以使用 tldr++,这是一个Go 语言编写的交互式客户端。

参考链接

查看原文

赞 1 收藏 0 评论 0