【置顶】个人阶段性学习和规划总结(技能树)

  本人专注后台服务端开发一晃已经好久了,自我感觉上不仅经验增加了很多,同时接触到的东西确实不少,在增加见识的同时博文也批量更新了很多。大多人看来内容很多很杂,此处做一阶段性整理和总结吧,给自己也梳理梳理一下。
  其实不仅仅是后台服务端开发这个方向,就整个软件开发来说,其知识构成也是有所层次的。个人毕竟不是正规计算机科班出身,也就是大家所说的半路出道、自学成才的野程序员,优点就是不会被那些所谓正规计算机教育的所束缚禁锢住,但是很多时候感觉自己的知识构成还是有所缺陷。既然励志要靠撸代码吃饭养家,那么长痛不如短痛,晚补不如早补,该学的终究跑不掉!

【置顶】博客资源收录大全

  虽然当下微信公众号席卷自媒体市场之势如火如荼,但是针对文章展示的话个人还是偏向于独立博客的形式,主要是因为个人可控制化的东西比较多。我想,在被条条框框束缚的无以喘息的情况下,这个时代没有什么比个性和自由更为重要的了吧。
  下面是一些网络知名人士的博客,以及平时在搜索资料过程中遇到的好站点,都被一一记录下来了,真心喜欢的话可以用RSS订阅这些站点,其中很多都是全文输出的。因为个人的兴趣取向问题,除了将不感兴趣的前端、移动端外,过于偏向于Java/Nodejs等语言化的博客也被KO了(即使编程思想是独立于语言而存在的),希望平时没事多看看吧!

【置顶】架构师成长之路

  上个月公司组织我和另外一个同事有幸参加了每年一度的全球架构师峰会,姑且算是架构师们的一场盛宴吧,不过确实感觉这个峰会挺水的,和自己当初的期望相差甚远。虽然近一百多个场次中零星夹杂着一些产品、质量方面的主题,但是绝大多数会场都是架构师在秀技术,当然这也折射出来:在国内,架构师常常被狭隘成技术能力强的那一拨人群。
  虽然不知道国外的架构师是否真如书本上说的那样,是一个偏向技术族的高端(几近全能)管理型人才,但是理想总需要有的,而且我觉得能做到那种标准的人肯定是企业稀缺的人才。这就整理收集了一些所谓架构师的职责和所需技能,就置顶当做自己努力的目标吧,希望能早日实现梦想!

1. 系统架构师是技术领导
  这意味着架构师除了需要有技术能力,同时还必须有领导能力。在项目中架构师具有做出技术方面决策的权力,相比而言项目经理则更加注重于在资源、排期、成本方面的规划和跟踪。
  架构师还需要参与到架构团队的组织管理,除了在较高层次设计系统架构外还,需要对各种工作和活动做出策划,因为架构实现最终会被落实分解成一个个的任务去执行。团队的质量对整个架构的成败有至关重要的影响,所以架构师还最好参与到团队员工的培养和新员工的面试选拔上去。
  架构师的领导力还体现在和团队成员的沟通交互上面,给员工的工作方向做出指引,给予他们充分明确的信息,并在需要的时候能够做出样例师范。成功的架构师都是以人为本的,每个架构师都会作为导师、教练的角色来带领团队的成员,成员的成长进步会推动项目的顺利进行,同时也让员工自身、整个团队、整个项目大大获益;同时架构师还需要发掘团队中各个成员的长处优势,鼓励大家相互分享相互学习。
  架构师在技术角度上要是整个项目推动的驱动力,架构师必须能够适时做出决策,并且保证这些决策能够被充分的讨论和论证,内容明确,最终落实实现下来。
  架构师需要和不同领域的人协同工作,需要对商务环境、需求的变更做出快速的响应,所以架构师的压力回是比较大的,需要寻求方式来释放消极情绪,努力使自身和团队成员积极向上的工作态度。

MySQL查询语句EXPLAIN解析

  从MySQL服务器获取正确结果可能会有不止一种方法,但是这些方法所花费的代价很可能是不同的,在MySQL中为了找出这种花费最少、效率最高的方法肯定是大家最希望的。相比于传统基于规则的优化,MySQL和现代绝大多数数据库都是实现基于代价的优化方式,他们在处理查询的时候会创建多种可用方法,然后参考各种处理的消耗信息以及目标数据库表的统计分布信息,计算各个执行计划的代价,从中选择代价最小的计划去执行,所以找到最优的执行计划就是优化器所要负责的功能。
  通过EXPLAIN命令可以查看SQL语句的执行计划,后面直接跟SELECT语句即可,如果想看DML语句的执行计划,则可以先将其转换成带WHERE条件的SELECT语句,再使用EXPLAIN分析即可,然后执行完EXPLAIN后会返回一个包含执行计划信息的相关表格,不过据称新版本的MySQL已经提供了直接通过EXPLAIN分析INSERT、UPDATE等操作的执行计划了。

1. id (query id)

  如果一个SELECT查询包含有多个子查询语句,则EXPLAIN返回的信息表会将每个子查询都赋予不同的ID列并显示出来,同时还包括子查询需要创建临时表的情况。如果一个SELECT语句需要连接多个数据表,执行计划把连接的表都进行显示,并且把他们都赋予相同的ID列值,即ID值不会增加。

1
2
SELECT e.emp_no, e.first_name, s.from_date, s.salary FROM employees e, salaries s
WHERE e.emp_no = s.emp_no LIMIT 10;

  信息表越显示在上方的结果,也就是ID值越小的结果,表示越为查询的外部、或越先访问的数据表;相反越显示在下方的记录,即ID值越大的结果,则为越是查询的内部、或越是后访问的数据表。

软件设计模式中应该遵守的SOLID原则

  《敏捷软件开发:原则、模式与实践》和可能又是一本极易被埋没的面向对象软件设计的经典之作,本人也是在闲暇时候逛论坛偶然看见有人倾力推荐后才主动了解到它的,而之所以说容易被埋没,是因为这本书的名字很容易让别人感觉是一本专门讲授敏捷开发的知识,而大家心里其实都很清楚:敏捷开发在中国这种大量民工级别的程序员参与开发的形式下是很难实施的。曾记得在2012年我在公司实习的时候,公司总部就部署各个分舵组织学习Agile和看板这些开发和管理技术,不过形式上走过场之后就没有然后了,根本无法实施。
  言归正题,这本书还是说了不少敏捷开发、测试驱动开发的相关知识和案例演示,但目前为止最吸引我的是里面罗列的面向对象软件设计原则和各种设计模式的灵活运用,总体来说比GoF的经典《设计模式》要容易消化接收一些,书中的样例很多都是使用C++实现的,尽管也有一些是使用Java实现的,不过这两种语言基本同根,所以理解起来也不是特别的费劲。总体评价是:这是一本很值得慢慢研磨品味的书。
  下面的内容是介绍面向对象软件设计中所需要遵守的五个原则,他们有时候也被统称为S.O.L.I.D原则,分别是:单一功能原则、开闭原则、里氏替换原则、接口隔离原则和依赖翻转原则。如果说设计模式是软件开发中小巧灵活、功能实用的瑞士军刀,那么这里的软件设计原则就是军刀的灵魂。而且Uncle Bob也在书中说到,经验丰富的开发者遇到一个场景的时候很可能立马熟悉的设计模式就复现在脑海中了,其实有时候也不必一定要寻找某个设计模式来套当前的项目,而是朝着软件的需求方向,按照面向对象软件设计的原则去不断重构、演化项目的代码,那么最后的可能会发现模块自然而然地就会演化接近某一个设计模式了,毕竟那些设计模式也是从实践中提炼出来的,实践开发中也应该回归设计模式。

一、单一职责原则 (Single Responsibility Principle, SRP)

  就一个类而言应该仅有一个引起它变化的原因。
  因为类的职责会随着需求的变化而发生变化,同时每一个职责都是变化的一个轴线,如果一个类承担的职责过多,那么这些职责就会被耦合在一起,一个职责的变化可能会削弱甚至抑制这个类完成其他职责的能力。
  在SRP中将“引起变化的原因”定义为职责。在现实中,我们通常习惯于以组的形式(而不是变化的原因)去考虑职责进行归类,比如通常会将Modem的所有接口组合起来放在一起,因为他们都和Modem相关,不过这个Modem具有连接管理、数据通信两个职责,后续会因为两者中的任意一个发生变化都,则所有依赖这两个职责中的任何一个都迫使我们需要进行代码审查、测试验证、部署等操作,在用户的角度看来这两个职责被耦合在了一起。不过该原则需要预先推断出变化的情况,如果不会发生变化,或者应用程序的变化总是导致两个职责同时发生变化,那么就没有必要分离他们了。
  还有一种违反SRP的是经常变动的职责和不会频繁(甚至不会)变动的模块混合在一起的情形,比如业务模块和持久化子系统就是典型的变化频率和原因不相同的模块,这个时候就推荐使用FACADE或者PROXY模式重构分离两个职责。

关于转行互联网的一些想法

  身处一家所谓互联网公司,在面试的时候发现相当一部分应聘求职者是从事传统行业经验的,比如不仅仅是世界五百强的HW,还有我的前东家TP,以及当前深圳很多小微智能设备创业公司的工作背景……每当面试开始的时候我都会问他们为什么要转行互联网?大部分都回答说行业前景不好、没有挑战性等,当然也有给我回答说互联网企业工资比较高,虽然大家现在都是面向工资编程,这种回答让我很欣赏他们的诚实,但是如此露骨也让人感觉很尴尬啊。
  因为我也是一个从传统设备行业转行互联网的先驱,算是亲身经历了转行的种种辛酸不易。至少转行也就意味着之前的工作经验(主要是技术方面)都被失效了,而面对新行业的知识经验尚处一片空白,也就是和学校应届毕业生再次处于同一起跑线了,其中的阵痛也只有经受过的人才能深切体会。不过让人感到安慰的是,很多互联网公司还是比较开明的,他们还是会给这样一批人公平的面试机会,只要有机会就意味着还是有希望的。打铁还需自身硬,所以转行的重点还是在于求职者要做好步入互联网行业的充足准备,只要让面试官相信你在新的岗位上能够做事,出现问题能够快速有效解决,我想任何一个正常的企业都是没有理由拒绝这类有价值的人才的。
  以我的亲身经历来说,只要脸皮厚、肯吃苦,就一定能成功,虽然这两条法则放到任何一个事情上都没错……
  首先,如果决定要转战互联网,就要有破釜沉舟的勇气和决心。不要在求职意向上表现出互联网行业和老本行的职业都看,这种犹豫的不仅不能表现在简历上,更要在思想上保持坚定。然后求职简历上尽量多描述一些对意向工作有用的专业技能,行业无关的工作项目经验不必描述的过于详细。我面试一些嵌入式工程师的时候,会问一些嵌入式开发相关的技术细节,即使求职者在简历上没有把嵌入式的项目写的很详细的情况下也是这样,主要是考查这个员工分析解决问题的能力和手段,以及从事上一份工作时候的投入和钻研精神;不过如果面试官没有这方面的经历和背景,对着密密麻麻的嵌入式工作经验,面试官不问你会觉得面试官不够尊重你,问你的话也不知道从何入手,岂不尴尬了。

《Effective STL》读摘

  Scott Meyers大神的Effective C++系列自然是让不少C++爱好者顶礼膜拜的经典之作,读完之后C++的使用技能瞬间飙升好几个档次,其实他还有一本《Effective STL》也是值得品读学习的,可能大家觉得熟悉一些常用的容器基本就足够使用了,所以对STL这个话题也关注的较少。
  也的确,平时在面试别人的时候问熟不熟悉STL?各个容器的特点及查找、修改元素的复杂度是什么?容器的内部用什么数据结构实现的?再深一点的时候顺带问一下迭代器失效的问题。除此之外好像也没什么可以深度问下去的了,比如STL的算法函数基本都没有人说用过。不过STL中的容器和基本算法作为最基础的开发组件可以说是将效率优化到极致了的,而对用户而言不同的用法带来的效果可能会相差甚远,而且用STL常常可以用更简洁、更可维护的方式实现业务需求,所以只有彻底熟悉STL才能真正发挥它的强大优势,这就是我读完这本书的感受。
  虽然这本书出版的较早,而且很久没有更新了,不过对比新标准的STL实现,对用户来说使用方式基本没有太大的差异,所以这里的知识基本不会太过时。

一、容器

  通常STL容器可以分为连续内存容器基于节点的容器连续内存容器包括vector、string、deque,节点类型容器包括链表类的list、slist(forward_list)和关联类型的容器。这两种类型的容器除了涉及到在中间插入、删除元素的复杂性,元素的排列是否是有序等常见差异外,他们的差异性还表现在迭代器、引用的有效性问题:
  序列容器支持随机访问,只要没有删除操作发生而且插入操作只发生在容器的末尾,则指向数据的指针、引用就不会失效。任何的push操作都会导致deque的所有迭代器失效,不过指针和引用仍然会保持有效。对于vector如果插入节点导致容器重排,则所有的迭代器、指针、引用都会失效,末尾删除元素不会导致迭代器失效。
  节点容器是让迭代器、指针、引用失效次数最小的容器,这类容器的插入、删除操作从来不会使别的迭代器、指针、引用失效,除了直接操作的那个元素之节点。

function和bind真的是C++的救赎

  最近整理了以前收藏的那些优秀文章,又发现了孟岩老师的那篇《function/bind的救赎(上)》。曾记得当年读这篇文章的时候硬是没明白啥意思,不过可能随着一些开发经验的积累,经历到的事情也多了,现在也越来越觉得这篇文章真是点中了C++的要害之处。想当初在学校的时候老师们、多少本教材满怀信心地告诉我们:携C++之重器、怀面向对象之思想,仿佛大千世界尽皆可以被这个语言所描述和创造,但是等到真正上船后才发现,不仅C++语言像架波音747一样,非超凡的智慧和丰富的经验不能驾驭,而且蹊跷晦涩的语言特性、一些怪异的语法规则更是暗坑密布,所以业界对这个语言阴暗面的诟病也从未停止。
  不过读过C++之父《C++语言的设计与演化》的人就能理解,C++如此的怪异也是跟其历史来由密切相关的。C++当初为了从C语言那边策反一批用户,坚持高度兼容C语言的抉择不但把C语言的毛病全给沾染了,而且背负着这个沉重的历史包袱也导致C++的发展如同戴着脚镣在艰难的前行着,C++的标准规范的许多例外也都像是一个个的补丁一样那么的扎眼(比如当C++分析语法得到歧义的时候,规定优先将其看做一个声明语句),整体看上去是那么的不和谐。
  其实C++在当初设计的时候如果不是努力维护着和C语言的高度兼容性,以Bjarne的才华,肯定可以把C++设计的远比现在更简洁优雅。不过说实话,让C++既可以像C语言一样可以极为底层的方式高效操作资源,也可以实现面向对象方式的高级抽象,中间还得兼容C语言面向过程的编程手法,其复杂度可想而知,也就必然会造成很多的瑕疵和不完美的地方。而且C++为不完美的C也提供了很多改良性的措施,比如:namespace解决名字冲突,引用代替指针解决指针的种种陷阱,以xxxx_cast的转换语法保证转换操作既安全又方便查找和调试,语言级原生支持多态而不用像在C中使用指针强制转换来模拟多态特性,RAII避免资源潜在泄漏的危险,模板和STL让我们不用一次次的纠结数据结构和算法……上面的这些知识点也告诉我们:我们固然可以用写C的思路去写C++,但是要想写出高效、安全、可维护的代码,那么还是建议认真系统的学习一下C++,善用C++的特性去解决问题。说据实话,越来越感觉Bjarne爷爷真是神人一般的厉害,他在C++的设计演化中恪守着许多哲学和原则,并且始终坚持C++的发展以实用为准则,才使得C++在没有花哨地营销情况下,尽管不够完美也逐渐被大众所接受,而且在工业界占据着极为重要的地位。记得他老人家还开玩笑的表示,如果C++不这么的难以驾驭,老板哪肯给你们多付点薪水呢?
  话题扯远了。孟岩老师只写了个上篇就撒手不管了的节奏,广大C++爱好者在评论下面苦苦央求了快十年,也没有等到后续的更新,但是从其最初的标题也可以猜测出来了:对于C++静态消息分发不灵活的缺陷,需要使用bind和function机制来解决。下面允我先将这篇文章的主题描述下来。

读《哲学家们都干了些什么》摘

  这算是除了《苏菲的世界》之外读的第二本哲学入门书籍了。虽然里面涉及到的那些专业知识没搞懂的终究还是没有搞懂,一看到那些不知所云的字眼就犯迷糊,不过书中描述到的整个哲学的发展史跟之前读《苏菲的世界》的感觉还是一致的:一方面现代人都已经有了一定的科学素养,所以对牛顿时代之前的哲学观都感觉比较天真甚至有些幼稚;然而整个人类发展征途漫漫,除了要同饥饿、疾病做斗争之外,还不断尝试着去解释自然和精神、平静心灵获得快乐和幸福感(而且那些哲学大师普遍生活的比较贫穷和痛苦,但是操心的是整个人类的精神生活和幸福),并试图建立一套套完美的学说和理论体系,意图可以一劳永逸地解释整个世界和万物根本。
  除了脉络清晰的哲学发展史,配合较为专业的哲学知识之外,书中也穿插了不少有趣的故事和名人八卦,使其不像其他哲学书那样显得古板而且晦涩难读,整体看起来还是津津有味的,比如死于爱问问题的苏格拉底、康德怪异的生活癖好、牛顿的人品说、复杂透顶的罗素情史……实在是饭后闲聊杂谈的好话题啊。同时,哲学的左右也总是伴随着宗教和科学的存在,由此也可以从另外的角度窥视欧洲的发展历史,从雅典、亚历山大帝国、罗马帝国、日耳曼名族这个流程看待整个欧洲文化特性和历史渊源,还比如欧洲教皇可以凌驾于所有王权之上,比如宗教鼎盛的时候欧洲王室的登基都需要得到教皇的册封,而且王室还需要每年给教皇捐税,这些事情真的让东方人匪夷所思,因为在中国历史上,宗教要么是鼓励出世的(远离政权),要么是作为皇权的附庸形式(入世)存在的,宗教从来都不会有这么大的权利存在着。
philosopher

Nagle和Delayed ACK优化算法合用导致的死锁问题

  前面说了TIME_WAIT的问题,这里再讨论网络开发中另外一个常见的奇怪现象——Nagle算法和Delayed ACK相互作用产生“死锁”导致网络性能下降的问题。这个问题算是网络服务器开发中较容易遇同时又十分严重的问题,会严重影响服务的响应时间和吞吐量,之前在网上看一些博客文章,发现连续好几篇都是描述这类问题的文章,Google两个关键字也会发现相关文章和解决方法大把大把的,他们描述问题的现象基本表现为规律性的几十到几百毫秒的确认延时。
  其实,这两种机制原本的初衷都是为了优化TCP传输效率、减少网络中低有效负载的小包数量的,减少网络拥塞提高传输效率的。这两种算法是由两个独立的团队在几乎相近的时间,分别从发送端和接收端的角度提出的优化机制,但是如果两者同时使用常常就会出现上面提到的问题。

一、算法介绍

1. Nagle算法

  Nagle算法的初衷是从发送端解决网络传输小数据包问题的,目的就是为了解决像Telnet这类应用程序性能而进行的优化。因为一个TCP数据包的传输至少需要固定的40字节头部信息(20字节TCP + 20字节IP),如果数据包实际负载都比较小的话,那么传输的效率就非常低,但是如果将这些小包的负载都尽量集中起来,封装到一个TCP数据包中进行传输,那么传输效率势必将会大大提高。此处我们再次强调,TCP传输的是一个字节流,本身不存在所谓的离散形式的数据包的概念,协议可以任意组合、拆分每次调用实际传输的数据长度。
  在Nagle算法中参数MSS(maximum segment size,IPv4默认值是576-20-20 = 536)扮演者重要的作用,其算法流程也简洁明了:
nagle
  概括地说来,其流程表述为:(a)不考虑窗口流量控制的限制,一旦累积的数据达到MSS就立即执行传输;(b)否则如果当前有未ACK的数据,就将数据堆积到发送队列里延迟发送;(c)如果没有待需要ACK的数据,就立即发送。简单说来,就是在数据没有累积到MSS的大小情况下,整个连接中允许有未ACK的数据。