【译】13简单的优秀编码规则(从我15年的经验)

原文地址:https://hackernoon.com/few-simple-rules-for-good-coding-my-15-years-experience-96cb29d4acd9#.ddzpjb80c 嗨,我的工作作为一个程序员超过15年,并使用许多不同的语言,范例,框架和其他狗屎。我想和大家分享我写好代码的规则。 1. 优化VS可读性 去他妈的优化 始终编​​写易于阅读且对开发人员可理解的代码。因为在硬可读代码上花费的时间和资源将远远高于从优化中获得的。 如果你需要进行优化,那么使它像DI的独立模块,具有100%的测试覆盖率,并且不会被触及至少一年。 2. 架构第一 我看到很多人说“我们需要快速做事,我们没有时间做架构”。其中约99%的人因为这样的想法而遇到了大问题。 编写代码而不考虑其架构是没有用的,就像没有实现它们的计划一样,梦想你的愿望。 在编写代码的第一行之前,你应该明白它将要做什么,它将如何使用,模块,服务如何相互工作,它将有什么结构,如何进行测试和调试,以及如何更新。 3. 测试覆盖率 测试是好事,但他们并不总是负担得起,对项目有意义。 当你需要测试: 当你编写模块时,微服务将不会被触及至少一个月。 当你编写开源代码。 当你编写涉及金融渠道的核心代码或代码。 当您有代码更新的同时更新测试的资源。 当你不需要测试时: 当你是一个创业。 当你有小团队和代码更改是快速。 当你编写的脚本,可以简单地通过他们的输出手动测试。 记住,带有严格测试的代码可能比没有测试的代码更有害。 4. 保持简单,极度简单 不要编写复杂的代码。更多更简单,那么更少的错误它可能有和更少的时间来调试它们。代码应该做的只是它需要没有非常多的抽象和其他OOP shit(尤其是涉及java开发人员)+ 20%的东西可能需要在将来以简单的方式更新它。 5. 注释 出现注释说明你的代码不够好。好的代码应该是可以理解的,没有一行注释。但是如何为新开发人员节省时间? - 编写简单的内联文档描述什么和如何方法工作。这将节省很多时间来理解,甚至更多 - 它将给人们更多的机会来提出更好的实施这种方法。并且它将是全球代码文档的良好开端。 6. 硬耦合VS较小耦合 始终尝试使用微服务架构。单片软件可以比微服务软件运行得更快,但只能在一个服务器的上下文中运行。 微服务使您可以不仅在许多服务器上,而且有时甚至在一台机器上(我的意思是过程分发)高效地分发您的软件。 7. 代码审查 代码审查可以是好的,也以是坏的。 您可以组织代码审查,只有当您有开发人员了解95%的代码,谁可以监控所有更新,而不浪费很多时间。在其他情况下,这将是只是耗时,每个人都会讨厌这个。 在这部分有很多问题,所以更深入地描述这一点。 许多人认为代码审查是一个很好的方式教新手,或者工作在不同部分的代码的队友。但是代码审查的主要目标是保持代码质量,而不是教学。让我们想象你的团队制作代码用于控制核反应堆或太空火箭发动机的冷却系统。你在非常硬的逻辑中犯了巨大的错误,然后你给这个代码审查新的家伙。你怎么认为会发生意外的风险? - 我的练习率超过70%。 良好的团队是每个人都有自己的角色,负责确切的工作。如果有人想要理解另一段代码,那么他去一个负责任去问他。你不可能知道一切,更好的优秀的理解小块代码而不是理解所有。 8. 重构没啥用 在我的职业生涯中,我听到很多次“不要担心,我们以后会重构它”。在未来,这会导致大的技术债务或从头开始删除所有的代码和写作。 所以,不要得到一个债务,除非你有钱从头开发你的软件几次。 9. 当你累了或在一个坏的心情不要写代码。 当开发人员厌倦时,他们正在制造2到5倍或者更多的bug。所以工作更多是非常糟糕的做法。这就是为什么越来越多的国家思考6小时工作日,其中一些已经有了。精神工作不同于使用你的二头肌。 10. 不要一次写全部 - 使开发迭代 在编写代码分析和预测之前,您的客户/客户真正需要什么,然后选择您可以在短期内以高质量开发的MVF(最有价值的功能)。使用这样的迭代来部署质量更新,而不是腰部时间和资源对不合理的愿望和牺牲与质量。 11. 自动化VS手动 自动化是长期的100%成功。所以如果你有资源自动化的东西,现在应该做。你可能认为“只需要5分钟,为什么我应该自动化?但让我计算这个。例如,它是5个开发人员的日常任务。 5分钟* 5天* 21天* 12个月= 6 300分钟= 105小时= 13....

2018-02-07 14:03:12 · 1 min · Eddie Wang

JavaScript 高级技巧

0.1. 安全类型检测 javascript内置类型检测并不可靠 safari某些版本(<4)typeof正则表达式返回为function 建议使用Object.prototype.toString.call()方法检测数据类型 function isArray(value){ return Object.prototype.toString.call(value) === "[object Array]"; } function isFunction(value){ return Object.prototype.toString.call(value) === "[object Function]"; } function isRegExp(value){ return Object.prototype.toString.call(value) === "[object RegExp]"; } function isNativeJSON(){ return window.JSON && Object.prototype.toString.call(JSON) === "[object JSON]"; } 对于ie中一COM对象形式实现的任何函数,isFunction都返回false,因为他们并非原生的javascript函数。 在web开发中,能够区分原生与非原生的对象非常重要。只有这样才能确切知道某个对象是否有哪些功能 以上所有的正确性的前提是:Object.prototype.toString没有被修改过 0.2. 作用域安全的构造函数 function Person(name){ this.name = name; } //使用new来创建一个对象 var one = new Person('wdd'); //直接调用构造函数 Person(); 由于this是运行时分配的,如果你使用new来操作,this指向的就是one。如果直接调用构造函数,那么this会指向全局对象window,然后你的代码就会覆盖window的原生name。如果有其他地方使用过window.name, 那么你的函数将会埋下一个深藏的bug。 ==那么,如何才能创建一个作用域安全的构造函数?== 方法1 function Person(name){ if(this instanceof Person){ this.name = name; } else{ return new Person(name); } } 1....

2018-02-07 10:14:56 · 2 min · Eddie Wang

突然觉得自己好像没学过JS

0.1. 先看题:mean的值是什么? var scores = [10,11,12]; var total = 0; for(var score in scores){ total += score; } var mean = total/scores.length; console.log(mean); 0.2. 是11? 恭喜你:答错了! 0.3. 是1? 恭喜你:答错了! 0.4. 正确答案: 4 解释: for in 循环循环的值永远是key, key是一个字符串。所以total的值是:‘0012’。它是一个字符串,字符串'0012’/3,0012会被转换成12,然后除以3,结果是4。 0.5. 后记 这个示例是来自《编写高质量JavaScript的68个方法》的第49条:数组迭代要优先使用for循环而不是for in循环。 既然已经发布,就可能有好事者拿出去当面试题。这个题目很有可能坑一堆人。其中包括我。 这里涉及到许多js的基础知识. for in 循环是循环对象的索引属性,key是一个字符串。 数值类型和字符串相加,会自动转换为字符串 字符串除以数值类型,会先把字符串转为数值,最终结果为数值 正确方法 var scores = [10,11,12]; var total = 0; for(var i=0, n=scores.length; i < n; i++){ total += scores[i]; } var mean = total/scores....

2018-02-07 10:09:42 · 1 min · Eddie Wang

发起Ajax请求当页面onunload

0.1. 同步Ajax 这种需求主要用于当浏览器关闭,或者刷新时,向后端发起Ajax请求。 window.onunload = function(){ $.ajax({url:"http://localhost:8888/test.php?", async:false}); }; 使用async:false参数使请求同步(默认是异步的)。 同步请求锁定浏览器,直到完成。 如果请求是异步的,页面只是继续卸载。 它足够快,以至于该请求甚至没有时间触发。服务端很可能收不到请求。 0.2. navigator.sendBeacon 优点:简洁、异步、非阻塞 缺点:这是实验性的技术,并非所有浏览器都支持。其中IE和safari不支持该技术。 示例: window.addEventListener('unload', logData, false); function logData() { navigator.sendBeacon("/log", analyticsData); } 参考:http://stackoverflow.com/questions/1821625/ajax-request-with-jquery-on-page-unload 参考:https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon

2018-02-07 09:18:54 · 1 min · Eddie Wang

git合并上游仓库即同步fork后的仓库

1. 前提说明 仓库A: http://gitlab.tt.cc:30000/fe/omp.git 仓库B: 仓库Bfork自仓库A, 仓库A的地址是:http://gitlab.tt.cc:30000/wangdd/omp.git 某一时刻,仓库A更新了。仓库B需要同步上游分支的更新。 2. 本地操作 // 1 查看远程分支 ➜ omp git:(master) git remote -v origin http://gitlab.tt.cc:30000/wangdd/omp.git (fetch) origin http://gitlab.tt.cc:30000/wangdd/omp.git (push) // 2 添加一个远程同步的上游仓库 ➜ omp git:(master) git remote add upstream http://gitlab.tt.cc:30000/fe/omp.git ➜ omp git:(master) git remote -v origin http://gitlab.tt.cc:30000/wangdd/omp.git (fetch) origin http://gitlab.tt.cc:30000/wangdd/omp.git (push) upstream http://gitlab.tt.cc:30000/fe/omp.git (fetch) upstream http://gitlab.tt.cc:30000/fe/omp.git (push) // 3 拉去上游分支到本地,并且会被存储在一个新分支upstream/master ➜ omp git:(master) git fetch upstream remote: Counting objects: 4, done. remote: Compressing objects: 100% (4/4), done....

2018-01-31 17:16:44 · 1 min · Eddie Wang

如何写好接口文档?

1. HTTP携带信息的方式 url headers body: 包括请求体,响应体 2. 分离通用信息 一般来说,headers里的信息都是通用的,可以提前说明,作为默认参数 3. 路径中的参数表达式 URL中参数表达式使用{}的形式,参数包裹在大括号之中{paramName} 例如: /api/user/{userId} /api/user/{userType}?age={age}&gender={gender} 4. 数据模型定义 数据模型定义包括: 路径与查询字符串参数模型 请求体参数模型 响应体参数模型 数据模型的最小数据集: 名称 是否必须 说明 “最小数据集”(MDS)是指通过收集最少的数据,较好地掌握一个研究对象所具有的特点或一件事情、一份工作所处的状态,其核心是针对被观察的对象建立起一套精简实用的数据指标。最小数据集的概念起源于美国的医疗领域。最小数据集的产生源于信息交换的需要,就好比上下级质量技术监督部门之间、企业与质量技术监督部门之间、质量技术监督部门与社会公众之间都存在着信息交换的需求。 一些文档里可能会加入字段的类型,但是我认为这是没必要的。以为HTTP传输的数据往往都需要序列化,大部分数据类型都是字符串。一些特殊的类型,例如枚举类型的字符串,可以在说明里描述。 另外:数据模型非常建议使用表格来表现。 举个栗子🌰: 名称 是否必须 说明 userType 是 用户类型。commom表示普通用户,vip表示vip用户 age 否 用户年龄 gender 否 用户性别。1表示男,0表示女 5. 请求示例 // general POST http://www.testapi.com/api/user // request payload { "name": "qianxun", "age": 14, "like": ["music", "reading"], "userType": "vip" } // response { "id": "asdkfjalsdkf" } 6. 异常处理 异常处理最小数据集...

2018-01-29 22:01:55 · 1 min · Eddie Wang

win7 ie11 开发者工具打开后一片空白

解决方法安装Windows7补丁:KB3008923; 下载地址: http://www.microsoft.com/en-us/download/details.aspx?id=45134 (32位) http://www.microsoft.com/zh-CN/download/details.aspx?id=45154 (64位)

2018-01-29 21:43:12 · 1 min · Eddie Wang

CSTA 呼叫模型简介

1. 内容概要 CSTA协议与标准概述 CSTA OpenScape 语音架构概述 2. CSTA协议标准 2.1. 什么是CSTA ? CSTA:电脑支持通讯程序(Computer Supported TelecommunicationsApplications) 基本的呼叫模型在1992建立,后来随着行业发展,呼叫模型也被加强和扩展,例如新的协议等等 CSTA是一个应用层接口,用来监控呼叫,设备和网络 CSTA创建了一个通讯程序的抽象层: CSTA并不依赖任何底层的信令协议 E.g.H.323,SIP,Analog,T1,ISDN,etc. CSTA并不要求用户必须使用某些设备 E.g.intelligentendpoints,low-function/stimulusdevices,SIPSignalingmodels-3PCC vs. Peer/Peer 适用不同的操作模式 第三方呼叫控制 一方呼叫控制 CSTA的设计目标是为了提高各种CSTA实现之间的移植性 规范化呼叫模型和行为 完成服务、事件定义 规范化标准 3. CSTA 标准的进化史 阶段1 (发布于 June ’92) 40 特性, 66 页 (服务定义) 专注于呼叫控制 阶段2 (发布于 Dec. ’94) 77 特性, 145 页 (服务定义) I/O & 语音单元服务, 更多呼叫控制服务 阶段3 - CSTA Phase II Features & versit CTI Technology 发布于 Dec. ‘98 136 特性, 650 页 (服务定义) 作为ISO 标准发布于 July 2000 发布 CSTA XML (ECMA-323) June 2004 发布 “Using CSTA with Voice Browsers” (TR/85) Dec....

2018-01-29 21:35:24 · 1 min · Eddie Wang

组织在召唤:如何免费获取一个js.org的二级域名

之前我是使用wangduanduan.github.io作为我的博客地址,后来觉得麻烦,有把博客关了。最近有想去折腾折腾。 先看效果:wdd.js.org 如果你不了解js.org可以看看我的这篇文章:一个值得所有前端开发者关注的网站js.org 1. 前提 已经有了github pages的一个博客,并且博客中有内容,没有内容会审核不通过的。我第一次申请域名,就是因为内容太少而审核不通过。 2. 想好自己要什么域名? 比如你想要一个:wdd.js.org的域名,你先在浏览器里访问这个地址,看看有没有人用过,如果已经有人用过,那么你就只能想点其他的域名了。 3. fork js.org的项目,添加自己的域名 1 fork https://github.com/js-org/dns.js.org 2 修改你fork后的仓库中的cnames_active.js文件,加上自己的一条域名,最好要按照字母顺序 如下图所示,我在第1100行加入。注意,不要在该行后加任何注释。 "wdd": "wangduanduan.github.io", 3 commit 4. 加入CNAME文件 我是用hexo和next主题作为博客的模板。其中我在gh-pages分支写博客,然后部署到master分支。 我在我的gh-pages分支的source目录下加入CNAME文件, 内容只有一行 wdd.js.org 将博客再次部署好,如果CNAME生效的话,你已经无法从原来的地址访问:wangduanduan.github.io, 这个博客了。 5. 向js.org项目发起pull-request 找到你fork后的项目,点击 new pull request, 向原来的项目发起请求。 然后你可以在js-org/dns.js.org项目的pull requests看到你的请求,当这个请求被合并时,你就拥有了js.org的二级域名。

2018-01-29 18:08:03 · 1 min · Eddie Wang

不常用却很有妙用的事件及方法

1. visibilitychange事件 触发条件:浏览器标签页被隐藏或显示的时候会触发visibilitychange事件. 使用场景:当标签页显示或者隐藏时,触发一些业务逻辑 document.addEventListener("visibilitychange", function() { console.log( document.visibilityState ); }); 2. storage事件 触发条件:使用localStorage or sessionStorage存储或者修改某个本地存储时 使用场景:标签页间通信 // AB页面同源 // 在A 页面 window.addEventListener('storage', (e) => {console.log(e)}) // 在B 页面,向120打个电话 localStorage.setItem('makeCall','120') // 然后可以在A页面间有输出, 可以看出A页面 收到了B页面的通知 ...key: "makeCall", oldValue: "119", newValue: "120", ... 3. beforeunload事件 触发条件:当页面的资源将要卸载(及刷新或者关闭标签页前). 当页面依然可见,并且该事件可以被取消只时 使用场景:关闭或者刷新页面时弹窗确认,关闭页面时向后端发送报告等 window.addEventListener("beforeunload", function (e) { var confirmationMessage = "\o/"; e.returnValue = confirmationMessage; // Gecko, Trident, Chrome 34+ return confirmationMessage; // Gecko, WebKit, Chrome <34 }); 4....

2018-01-29 14:15:25 · 1 min · Eddie Wang