Nitro Hsu

Translate

软件工程笔记-翻译

Photo by NESA by Makers [https://unsplash.com/@nesabymakers?utm_source=medium&utm_medium=referral] on Unsplash [https://unsplash.com/?utm_source=medium&utm_medium=referral]前言: 整体浏览收藏夹的发现了这篇来自Google的François Chollet关于软件工程的一些心得,读完感觉甚是戳中当下开发和管理过程中的很多痛处,翻译一下,仅供参考。 原文链接[需破窗]: https://medium.com/s/story/notes-to-myself-on-software-engineering-c890f16f4e4d 开发阶段 1. 代码并不仅仅是可以执行。代码也是一种跨团队沟通的方式,一种给别人描述如何解决问题的方式。方便阅读的代码不算是好,因为它本身就是编写代码最基础的部分,它涉及到清晰的代码结构、见名知义的变量名、对于复杂代码逻辑的插入注释。
9 min read
Twitter

我如何使用Twitter

Photo By https://media.threatpost.com前言:在浏览GUI相关文章的时候读到了《重构:改善既有代码的设计》的作者Martin Fowler写的一篇如何使用Twitter的帖子,结合自己使用微博的方式感觉挺有用的, 徜徉在互联网世界一不注意就会陷入时间黑洞,所以翻译一下分享出来。 原文链接: How I use TwitterThe things I do to make Twitter useful and avoid the time-traps martinfowler.comMartin Fowler [https://martinfowler.com/articles/2022-use-twitter.html] 在马一龙对Twitter功能各种建言之前,关于Twitter的一些讨论早就让我想写一篇关于如何使用Twitter的文章。Twitter已经变成我互联网生活重要的一部分,互联网生活又占据了我的大部分时间。就像其他工具一样,Twitter有许多种使用方式,所以你如何使用它决定了它可以发挥多大作用。 作为一个平台,Twitter最大的
5 min read
Git

实用Git快捷命令

Photo by Roman Synkevych 🇺🇦 [https://unsplash.com/@synkevych?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText] on Unsplash [https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText] 在我们使用Git作为版本管理的时候,可以将一些经常使用的操作命令或者命令组合通过别名的方式添加git alias或者shell alias以此来缩短输入,减少git command help的时间,提高开发效率。 添加别名的方式主要分为两种: 1、git alias 以Mac OS为例,在当前用户目录下的.gitconfig文件中添加alias模块, [http] cookiefile = /Users/
4 min read
Translate

技术文档系统-引用

前段时间在微博看到某位大V分享的Divio公司关于如何写好技术文档的博文,五一假期读完感觉非常条理,原文按照示例、指南、技术手册、释义等四个维度讲解了不同文档的写作要点、针对的目标群体给出了许多有用的建议。本想按照遵照原文意思翻译一下,结果Google搜索发现中文社区已经有同学翻译好发布为博文,那就不做重复工作了,直接分享出来,亦作参考。 Divio原文:https://documentation.divio.com/ 翻译版本: https://tinggengyan.github.io/2021/10/03/the-documentation-system_how_to_write_good_document/
1 min read
Java

唯一ID生成算法

前言 唯一ID在互联网大厂的业务线中广泛使用,比如订单号、数据库主键、IM消息序号、交易流水号等等,这些ID的共同特点是唯一标记某一个业务记录或者消息、部分ID自增、全局有序或者局部有序。 UUID作为是一种全局唯一的方案是可供使用的选择之一,但在实际操作中大家一般使用的很少,几个原因: 1. 16个字节128位占用太多的存储空间不适合用来作为主键; 2. UUID的版本1基于MAC地址和时间戳,可保证全局唯一,但容易被硬件追踪; 3. 后续版本使用伪随机数、SHA1又没有前向兼容,用在特定业务的一定范围内使用没有问题,但作为分布式系统的唯一ID不适合。 所以就有了各个互联网大厂分享的各自业务中实现唯一ID的不同算法和系统部署方案,唯一ID算法主要核心聚焦在以下几点: * ID位数 * ID算法原理 * 全局唯一 * 全局(局部)趋势有序 * 时钟回拨问题 * 外部系统依赖 技术实现汇总 从大厂分享的技术实现汇总如下: 厂牌技术方案ID位数全局唯一有序时钟回拨外部系统依赖TwitterSnowFlake64全局唯一局部有序block waitMongoDB
3 min read
Life

逝去的哥

新冠疫情依然在国外肆虐,国内的防控形势还在紧绷着没有一丝的放松,这次疫情就像一把无情之刀突然的刺向人群,悄无声息地蔓延,等待着大流行。年前有敢于自己身边的人竟然还能感染甲流,不免心有余悸,奥司他韦的药品名称依然常记于脑海。之前在老家,人们常说老人难熬冬,意思就是对于老人来说冬天是最难熬过去的,尤其是上了年纪又有一些基础病,一场感冒可能就把自己送走了。这次新冠对老人的考验就更大了,本身免疫力低,又是肺部感染,稍不注意就要器官插管带ICU监护,能活过来大难不死,撑不过去也就是新的十年就说声再见,化作一捧尘土回归了自然。 昨天在微博刷到一篇关于纽约哈特岛埋葬无人认领的尸体棺材的新闻,联想前几天看他们科普尸体焚烧进化史的视频,一声感慨又想到了因病去世的东哥,最后应该也是在病痛的折磨中离去的吧。 夜晚嫂子的一声电话,东哥还是没能挺过这一关,走了,从确诊癌症到死亡也就是半年的时间,从一个胖实的中年汉子到最后的骨瘦如柴,看着都能想象到的痛苦与挣扎,无奈这样也没能驱走病魔,最终还是离我们而去。 如果说老人的离去是自然的凋零,但一个中年人的逝去就好像自然的背叛,我似不惑,何罪之有?但生命的一次过活
3 min read
Tech

Golang依赖包管理知多少(4)-v2与后续版本

前言 成功的项目随着逐步成熟以及新功能的加入,过去的特性和设计方案可能不能满足需求。开发者可能想整合一下他们所学的知识比如移除废弃函数、重命名参数或者分割复杂的包为多个可维护模块。这些变更都需要下游用户付出努力来迁移他们的代码来适配新的API,所以他们不会没有认真权衡过收益和成本而做出变更的。 对于一些还在实验中的项目,比如主版本为v0的项目,用户会预期到偶尔的重大变更。对于已经发布为稳定版本的项目,比如主版本为v1或者更高版本的项目,重大的变更需要在一个大版本上进行。这篇文章主要介绍了大版本策略、如果创建并发布一个新的大版本以及如何维护一个module的多个主版本。 * 主版本与module path * 主版本策略 * 发布v2及后续版本 主版本与module path modules模式规范了一个重要的原则,导入兼容性原则: 如果一个老版本的包和一个新版本的包使用相同的导入path,那么新版本的包必须向后兼容老版本的包。 一个新的大版本的包不会向后兼容之前的版本。这就意味着一个新的大版本module必须有一个不同于历史版本的module path。从v2版本开始,
7 min read
Golang

Golang依赖包管理知多少(3)-发布一个module

前言 这篇文章将讨论如何编写并发布可被其他module依赖引用的一个module。 注意:这篇主要涉及开发配置直至v1版本,如果你对v2版本迭代感兴趣,可以参考v2版本与版本迭代 [https://www.nitrohsu.com/v2-go-modules]。 本文默认使用Git作为例子, 但是Mercurial、Bazaar等其他版本管理工具也是支持的。 * 项目配置 * 版本与module * v0-初始版本、非稳定版本 * v1-第一个稳定版本 项目配置 本文需要你有一个已经存在的项目作为例子,所以我们以认识Go modules [https://www.nitrohsu.com/golang-modules.html] 文章结尾的文件为例子: > $ cat go.mod module example.com/hello ​ go 1.12​ require rsc.io/quote/v3 v3.1.0 ​ $ cat go.
8 min read
Golang

Golang依赖包管理知多少

前言 本文内容结合自己的理解,对Golang官方博客针对Golang新版本modules包管理系统的文章翻译。 使用Go modules Go从1.11和1.12已经初步支持modules,新版Go包依赖管理系统通过显性的版本依赖使得更加易于维护。这篇文章主要介绍了在开始使用Golang modules时的一些基本操作。 一个module是许多Go Pakcage的集合,在它的根目录有一个go.mod文件。go.mod文件中定义这个module的module路径,也定义了需要导入的module路径、外部依赖,这些都是modules成功构建所必须的。每一个外部依赖都有一个module路径和版本号组成。 从Go 1.11开始,如果当前目录或者它的父级目录中有go.mod文件并且此目录不在$GOPATH/src 下面,go命令就会开启对modules的支持(如果在$GOPATH/src目录下,为了保持兼容即便存在go.mod文件go命令还会使用原有的GOPATH模式)。从Go 1.13开始module模式就会默认启用了。 下面就开始介绍在使用module模式开发Go代码过程中的几个步
12 min read
Golang

Golang依赖包管理知多少(2)-迁移工程到modules模式

前言 在golang工程中可以使用多种依赖管理策略,像dep、glide这种Vendoring工具非常的流行,但是它们又各自为政并不能很好的兼容。很多项目把工程文件放在GOPATH目录下存储为一个Git仓库,其他人通过 go get命令依赖存放在GOPATH中最新版本的代码。 Go modules系统在Go1.11时发布,它通过go命令提供了一个官方的依赖管理解决方案。这篇文章主要讲述了迁移原有工程到modules的一些工具和技术。 注意:如果你的工程已经标记为v2.0.0或者更高版本,在增加go.mod文件时需要更新工程中的module path。我们将会在后面的文章中解释如何做才能在v2或者更高版本时不让你的用户糟心。 * 原工程中使用了依赖管理工具 * 使用一个依赖管理器 * 不使用依赖管理器 * 在modules模式下的测试用例 * 发布一个版本 * 导入和规范module path [import_module] 原工程中使用了依赖管理工具 为了转换一个使用依赖管理工具的工程,需要执行以下命令: > $ git clone https://github.
10 min read
Android

Retrofit、Volley、HttpClient比较

Retrofit作为现在大家用的最多HTTP请求框架,非常流行,Github上star 3w+。它为什么能超越Volley、HTTPClient能够一枝独秀呢?那先看看其他两个HTTP栈的实现。 HTTPClient Java界老牌HTTP栈实现,由Apache维护,它支持HTTP1.0/1.1、极其丰富的API来支持各种子协议,代码庞大臃肿也变成了它的缺点,虽然它的创建一开始是为了弥补Java SDK中java.net包HTTP请求的简单实现,Android在6.0以后彻底弃用了它,转而推荐使用HTTPURLConnection。 Volley 作为Google官方开源的一款HTTP栈,它支持切换HTTPURLConnection、HTTPClient底层协议栈的切换,同时提供了请求线程池、缓存的支持,刚一推出也是收获许多赞赏,但是它就像G家好多产品一样,几年一次的维护和有些bug都需要使用方去维护解决,都是开发者逐渐抛弃的原因。虽然从Volley开始,这些HTTP栈的实现都在逐渐向上层实现,因为不管是Android、iOS大部分App的网络交互都是Restful-API的实现,
3 min read
Tech

Java动态代理类的生成和调用

Java的动态代理在开发中都有大量的使用,如Spring框架,Android的HTTP开发框架Retrofit,本文主要关注动态代理编写使用背后的代理类是如何的生成以及与代理对象的调用是如何实现的,以Retrofit这个框架中动态代理的使用为例子进行分析。 在Retrofit中,某类的API接口大多定义在一个Service接口类中,某一个API接口则被声明为Service接口类的一个方法,通过方法的注解、参数来描述具体API参数等信息。在调用某个API接口时,Retrofit实例调用create()创建Service接口类的实例对象来完成调用,具体源代码如下: public T create(final Class service) { // 必须是接口,并且不允许是继承来的接口 Utils.validateServiceInterface(service); //是否预加载 if (validateEagerly) { eagerlyValidateMethods(service); } //动态代理的核心代码 return (T) Proxy.newProxyIn
10 min read
Android

SVG Path命令属性

Android从5.0开始支持SVG矢量图,通过Vector Asset工具将SVG文件转换VectorDrawable定义的XML文件中,在运行时inflate这个xml文件来绘制图层,这对于减小APK资源文件体积和避免混乱的分辨率支持上都有很好的效果,同时Android通过Support支持库的形式给予了低版本的支持。 Android上对SVG的支持是受限制的,仅支持SVG tiny1.2版本的属性和标签,而且不支持text标签。 path标签是SVG中最常用的标签,这其中最重要的属性就是d(command)属性,它标明这个路径的绘制起点、终点、中间路径关键点、两点之间是否为直线、弧线、贝塞尔曲线等等。 d(command)属性主要分几类: 起点 用M、m来表示,如M150,0 表示从path的起点, 从x-150,y=0的坐标起点开始绘制 终点 用Z、z来表示,无参数 表示path的终点,链接到path的起点,闭合path,然后结束绘制 直线 假设当前点坐标为(10,10) L、l表示直线线段,如L100,100,
4 min read
Chrome

Blink内核相关术语、映射关系

在读Adblock Plus for Chrome插件的源代码时,拦截入口处有几个判断非常重要,这涉及到当前打开Tab的URL、来源、打开方式等概念,对应到Blink中术语有page、main frame、iframe、document等,翻阅一下Blink的README文档,找到官方的介绍在此做一下记录。 Page 一个Page对应于一个Tab,当然前提时OOPIF(Out-of-Process iframes)没有开启。每一个渲染进程可能包含多个Tab。 Frame Frame对应于HTML中的frame,可能是主frame或者iframe,每个Page在树形结构中可能包含一个或者多个frame。 DOMWindow 一个DOMWindow对应Javascript中的一个window对象,每个Frame有一个DOMWindow。 Document 一个Document对应Javascript中的一个window.document,每个Frame有一个Document。 ExecutionContext 一个ExecutionContext是一个抽象概念,在渲染进程的主线程
1 min read
Life

门前一棵花树

元旦假期即将收尾,年末总结也写完了,源代码看了一个流程细节还未整理,然后就是照例进行的online大扫除:整理照片、清理存储空间、维护一下服务器、看看欠费是不是该交了[尴尬状]。 传送门 每次整理照片都能发现好多的意外,就比如把OneDrive的照片从Google Photo迁移的过程中发现一张中文命名的照片,好奇怪,怎么可能会有这样的原始照片,而且还是“我和张XX”的名字,这一定是假的“我”,放大看来果然是乱入,两个大学同学的合照被这样命名真是怀疑人生的节奏...然后把结婚的时候用iMovies制作的一段我俩的视频照例上传,先去搜索了一下Google Drive上是否存在,只记得是“Love”开头,输入关键词“Love”结果Google的情感联想搜索就开始了,文件名字在此刻不是关键了,除了含有“Love”文件名的照片以外,它把所有合照一并检索出来了,囧字D,竟然还有宠物狗的合照,嗯,感情不分你我,合到一块拍照就是爱,哈哈哈。 花树 在OneDrive上整理之前合辑的照片,又翻到了G318之旅几个GB的照片,翻看到那一片片的油菜花,联想到草稿箱里面还没动笔的6.27、6.28几天的
3 min read
Summary

敦刻尔克-2018

2018年即将结束,就好像2008年才刚刚走,一晃的十年,一飘而过的年轮总是写在脸上,那个稚嫩未脱的娃儿现在已然成长为一个肚皮微凸、熬夜犯困、卡丁车要看油价的青年汉子。 前天上班的时候还在和同事讨论说,现在的工作周报写起来有人喜有人烦,喜在每周回过头去看看自己有什么收获、做了什么工作、有什么需要亟待加强学习的地方,烦在每周临下班了如果没有提前做个准备总要去高速运行一下大脑或者翻看一下Git log才能记起来到底做了什么。嗯,我还是比较喜欢前者,而且更激进一些,每天都要做一下记录,而且时间划分为上下午,虽不至于每一刻钟都要精确,但大概的事情有几件还是要理清楚的,最后的结果如何,为什么要这么做都要记录。大体翻看了一下,再去找了一下自己的绩效表,大概一致,没有太多的出入,默默地给自己的一年工作打个分数,领导对自己有他的评价,自己对自己的工作也有一份心底评价,几差几落心底亮堂着。 凡事有记录有规划,失败了也是一种经验的总结,告诉自己舵轮应该转几度,不至于回头告诉自己我们就是失败了,No Reason就很扯了。 今年全年贡献给12306的流量和消费金额应该是勇创新高了,往返帝都和泰安的次数
4 min read
University

重读大学

夏天的热惹不起冬天的冷,一双凉拖却可以穿越夏秋一脚跨入严冬,这就是老舍先生不想说实话的济南。济水之南,望山望水望雨荷的济,千佛百泉看泰山的南。一条经十路就像长安街,你堵着我,我堵着你,争相回望妈妈喊着回家吃饭的路途,如若不是高架一跃而起你可能真的是站在帝都国贸桥上思考你的人生路为什么走的这么慢,这么缓,慢慢,缓缓,慢慢… 就像陈小熊唱的那个济南,丢了历史的厚重,但又没有展现立体的现代感,相比成都、杭州、西安,济南就像一条打着补丁的裤子,想改成裙子却又没有好裁缝。拆拆建建之间一座座历史的厚重慢慢都被埋在了穿梭之间,变成一张张黑白照片放在博物馆里供后来人一览而过,一声叹,如同当年的北平一样被拆的面目全非到最后还是落下一个迁址的结果,现在呢,唯一能追忆的可能也就是那处洪家楼基督教堂。虽远望其壮观但从未踏足,每次心底默念下次路过一定要进去感受一下,或许心不诚则不灵,极近十年也从未成行,便留遗憾。遗憾之外,却是旁边那所静之所动的山东大学。 济南没有山大,济南可能不完整,山大没有济南山大还可以是山大,山大不仅是济南的,还是威海的、还是青岛的。千年之后的山大在遍地开花的大拆大建就没有停止,合并山
2 min read
Chrome

Chromium Android工程迁移编译过程

本文从Chromium编译的中间产物入手深入分析、学习Chromium Android版本的工程化定制流程。初始工作依赖于Chromium的ninja、GYP构建系统,在构建完成后基于编译中间产物,迁入Android Studio作为新的构建工程,测试编译发布的过程。 注:这种编译过程除了资源文件外其他编译中间产物,都不可修改,不具备大规模定制化的可能性,仅作为熟悉编译过程和代码结构的学习、测试使用。 前提 Chromium代码结构、Android开发、Android Studio使用 编译Chromium 编译步骤可以参考Chromium团队的文章 [https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md] ,可以选择编译目标为chrome_public_apk、content_shell_apk,本文以chrome_public_apk为例。 编译结果APK 在以chrome_public_apk为编译目标后,在经历一段时间后编译完成,在out/**
5 min read
Bitcoin

EOS的账户授权和多重签名

EOS在它的技术白皮书中介绍了账户、授权、以及多重签名的技术概念,我们也可以从EOS的代码中一窥其中的奥秘,它与BTC、ETH的区块链实现有什么区别或者有更为先进的地方,那就需要先从概念入手细细体会。 钱包 钱包是一个存储账户Key、权限Key的客户端。它支持一个或者多个账户,通过高复杂度的密码来加锁、解锁钱包。EOS的代码中自带了一个轻量级的钱包-keosd。keosd通过调用cleos接口来与区块链建立连接。 在这一点上与BTC、ETH基本一致,由于BTC、ETH并没有多权限、授权的概念,这是EOS钱包中的一大特点,这对于后期的账户找回也会有略许的差别。 账户 一个账户以人类可读的名字存储在区块链中,它按照权限配置从属于一个个人或者组织。在转账或者推送一笔交易到区块链的时候账户是必须要有的。 BTC简单说账户就是Address,它没有人类可读标记,就是一串Base58编码之后的字符,区分大小写;ETH的账户也是Address的概念,是一串公钥加工后的十六进制串,不区分大小写,但ENS的出现弥补了人类识读的短板,现有的很多钱包也支持ENS对Address的解析;EOS的原生支
5 min read
Bitcoin

以太坊矿工奖励之多少

以太坊通过PoW(工作量证明)的共识算法来生产一个新的区块,通过不断的调整区块nonce值来让以太坊网络上的矿工来计算不同的随机数,当计算出的随机数小于maxUint256除以header.Difficulty时就意味着挖矿成功,一个新的区块产生了。 在广播给全网新区块产生的同时,系统会发放一定量的以太币作为挖矿成功的奖励。与比特币挖矿不同的是以太坊协议不仅承认最长链上的区块(1),对于同时产生的非最长链的区块(1·)鼓励子区块(2)来将它索引起来,并将它(1·)称为子区块的叔块,索引了叔块的子区块也会获得一定的奖励,系统最多允许索引两个叔块,叔块与当前区块的高度差最大为6。 所以矿工奖励主要是三个部分:区块奖励、Gas奖励、索引叔块奖励;当然挖出叔块的矿工也会给予奖励。 1. 区块奖励,在4370000块硬分叉之前奖励5个以太币,之后奖励3个以太币; 2. Gas奖励,区块内所有交易的Gas费用归矿工所有; 3. 索引叔块奖励,每索引一个叔块会奖励区块奖励的1/32; 挖出叔块的奖励 =(叔块高度+8-索引叔块的区块高度)*区块奖励/8 挖矿奖励: 区块高度1-437
2 min read
Summary

话别指尖四年

2018年即将走过六分之一,农历新年的钟声也即将敲响,这是作别家乡北漂后在老家度过的第一个春节。从腊月二十六一路高速长途跋涉到家就是一阵的忙碌,从房子装修清理到走亲访友各种大事小事,从没有如此的忙碌地过年,也终于在这年末之余的夜晚,听着自选歌曲,让自己空档运转的大脑动动笔。 ·车·房· 从繁忙一路红色的帝都五环路到一晃眼以为帝都经济衰退的大马路,从每辆电动车一个车位的小区到停满马路汽车的乡村小镇,这就是中国式迁徙的一个缩影,回家过年就像候鸟每年一次的长途跋涉,不管你是自驾、高铁、汽车还是腿儿着,这是农历新年大写的注脚,它代表了亲情友情的联络,代表了无数割舍的相聚,一年间隔的结点。一杯敬去年的过往,一杯迎来年的喜庆。从谁家的车换成了什么牌子,邻居们也能猜到他家是不是今年发了大财,是不是瞬间土豪金。一眼望去的攀比和面子,全都写在脸上,尴尬之余的尴尬,且算还是尴尬吧,哈哈哈。相聚之间,从车子再到房子,或许这就是中国城镇化建设十多年缩影的延续,2010年后你再也看不到农村在自家宅基地上翻盖新房子的场景,倘若有一个村子在用尽全力的盖新房子,那或许只有一种可能,那就是这个村子要拆迁了。慢慢地进城
7 min read
Kernel

Zircon进程对象

概要 一个Zircon进程就是一个程序的实例:一个或者多个线程的指令执行以及一系列的资源。 描述 进程对象是以下资源的一个集合: * 句柄 [https://fuchsia.googlesource.com/zircon/+/HEAD/docs/handles.md] * 虚拟内存地址区 [https://fuchsia.googlesource.com/zircon/+/HEAD/docs/objects/vm_address_region.md] * 线程 [https://fuchsia.googlesource.com/zircon/+/HEAD/docs/objects/thread.md] 一般来说,进程是一系列关联代码的执行直到进程被强制终止或者进程主动退出。 进程属于作业,它可以在资源、权限和生命周期控制的角度将多个进程组合为一个应用程序。 生命周期 一个进程通过 sys_process_create() 系统调用来创建,
1 min read
Kernel

Zircon内核对象

Zircon是基于对象的内核。用户模式下的代码基本上都是通过对象句柄与OS资源交互。句柄可以被认为是某个OS子系统与某个资源之间的活动会话。 Zircon动态地管理着如下资源: * 处理器时间 * 内存和地址空间 * 设备IO内存 * 中断 * 信号和等待 应用层内核对象 IPC * 通道 [https://fuchsia.googlesource.com/zircon/+/HEAD/docs/objects/channel.md] * 套接字 [https://fuchsia.googlesource.com/zircon/+/HEAD/docs/objects/socket.md] * 先进先出队列 [https://fuchsia.googlesource.com/zircon/+/HEAD/docs/objects/fifo.md] 任务 * 进程 [https://fuchsia.googlesource.com/
2 min read