这份列表从前端开始,然后是后端API和数据库,最后是工程最佳实践/流程。
经验总结
CSSSpecificity
组件层次结构中的设计状态
后端编程中的面条式代码、千层饼式代码和馄饨式代码
生产中的Postgres
欲速则不达
投资自动化
掌握你的工具
最小可行性产品(MinimumViableProduct,MVP)
研究支持开发
科学调试
1CSSSpecificity
错误:我的CSS不适用。我要用!important。
教训:应该为特殊情况保留使用!important,因为它们破坏了整个CSS层次结构,并强制使用特定样式。所以,你有必要了解CSSSpecificity。
CSSspecificity是浏览器应用的一组规则,用来确定哪个CSS样式更specific。你可以将其视为基于点的系统,它决定哪种CSS样式获得优先权,并最终应用于DOM元素。
如果你想知道,为什么你的CSS没有被应用,这与CSSspecificity有关。在大型项目中,这是一个很常见的问题,在这类项目中,像SCSS这样的预处理程序与复杂的CSS层次结构一起使用。了解CSSspecificity将有助于你保留使用!important,仅在极罕见的覆盖情况下使用,例如,当你想要覆盖CSS库或让iframe覆盖主机站点样式时。
本质上,优先顺序是这样:IDselectors>Classselectors>Typeselectors。!important和内联style属性会覆盖所有的CSS。
对于应用于元素的每个CSS,你都可以轻松确定哪种样式将生效。例如,如果你加载上面的HTML代码:
在本例中,IDselector优先级高于typeselector。如果冲突的CSS选择器具有相同的优先级,那么将选择CSS文件中的最后一个。
最后,ChromeDevTools将会显示如上图所示的specificity顺序。如果你无法使用CSS,请查看Chrome使用的specificity顺序,然后添加一个更具体的选择器(如ID选择器、类选择器、类型选择器),让你的CSS更特定,并指示浏览器选择它。
如果你不想这么做,请看看这个specificity计算器
2组件层次结构的设计状态
错误:我需要添加这个新状态。我只需要将它放到这个reducer中,但不确定为什么这个reducer还有这么多其他状态?
教训:管理不当的redux状态会在开发人员中造成混乱,并导致bug。如果用react和redux来构建前端应用程序,那么你可以考虑使用这种可视化技术,从用户界面组件层次结构中构建状态和reducer层次结构。从零到统一的组件状态层次结构有三个步骤:
在线框图(wireframe)将用户界面进行可视化
将状态层次结构进行可视化以反映用户界面
构建reducer层次结构以反映状态层次结构
让我们来看一个例子。在这个例子中,我们构建一个博客网站,它有两个页面,一个页面用于博客列表,另一个页面用于个人博客:
第一步:在线框图中将用户界面进行可视化
主页和个人博客页面
第二步:将状态层次结构进行可视化以反映用户界面
相应的状态层次结构图如下所示:
状态层次结构
请注意,公共Header状态是如何被拉到根状态的。类似的,任何共享状态都可以在层次结构中“冒泡”,因此很明显,子组件共享该状态。
第三步:构建reducer层次结构以反映状态层次结构
reducer层次结构
这是一个简单而强大的例子,展示了如何构造状态和reducer层次结构来匹配用户界面。这一过程可以轻松扩展到复杂的应用程序和大型团队。最后,你可以在这个结构上构建操作和表示层。
3后端编程中的面条式代码、千层饼式代码和馄饨式代码
错误:这个代码库是如何组织的?也许我可以在这里添加这个文件,就像所有其他仓库代码一样。
教训:我写过三种“意大利面条式代码”。说实话,我觉得在“馄饨式代码”里放上“迷你千层饼式代码”也许是个好办法。组织和培训所有开发人员以这种方式构建代码库,可以保持代码的可维护性、可测试性,最重要的是能保持敏捷性。你能在不影响其他功能的情况下,轻松修改特定的“馄饨式代码”(也就是功能)的实现细节。
“千层饼式代码”是:
分层架构
架构整洁
外层是I/O,内层是纯数据结构
依赖关系向内注入
内层不依赖于外层
优先考虑组合,而非继承
“馄饨式代码”是:
Screamingarchitecture
切片与分层
文件夹和文件的空间位置
可以是微服务形式
4生产中的Postgres
错误:为什么这个查询速度这么慢?我认为是因为Postgres很慢的缘故。我需要切片,或者我认为这是ORM,或者,我需要一个不同的数据库,Postgres并不适合我。
教训:如果你在生产环境中运行Postgres,那么你将会遇到查询缓慢、表锁、无限等待迁移和错误的问题。如果不是这样,那么对你有好处,你又是怎么做到的?这并不意味着Postgres不再是正确工具,而是意味着你需要揭开帷幕,看看下面发生了什么。
截至目前,我发现的最好工具是pgbadger。你可以用它解决几乎所有的Postgres问题。
这是一个Perl命令行工具,它将Postgres(如果你使用AWS的话,就是RDS)日志作为输入,并输出报告。该报告的好坏取决于你在Postgres上启用的日志。因此,在第一步时你可能需要启用这些日志:
log_checkpoints=onlog_connections=onlog_disconnections=onlog_lock_waits=onlog_temp_files=0log_autovacuum_min_duration=0log_error_verbosity=defaultlog_min_duration_statement=1s
此外,你可能还需要启用pg_stat_statements语句来实时分析查询,并启用auto_explain来自动解释日志中运行缓慢的查询。
运行报告:
pgbadger--prefix'%m%u@%d%p%r%a:'/pglog/postgresql.log
该报告将汇总数据,并提供有关Postgres所做工作的大量信息。你可以找到关于错误、最慢查询、等待最长查询、获取的锁类型、临时文件是否用于排序、检查点运行的频率、真空运行的频率以及其他类似信息。有了这些数据,你就可以识别和修复运行缓慢的查询,并通过调优提高Postgres的性能。
你可以持续运行此报告(CLI支持增量模式),从而随时掌握新问题。
另外,如果你想理解解释输出,可以用这款工具。
该工具将解释JSON和原始查询作为输入,并将在如下所示的可视化树形图中对解释输出进行解释:
正如你所见,节点将有最大、最慢、最贵等标签。这将帮助你根据Postgres的执行方式来优化查询。
最后,如果在Postgres中建立能力不可行,我建议你问问像Percona这样的数据库咨询公司。
5欲速则不达
错误:看起来不错嘛,让我们交付吧!
教训:
在这个快速行动、打破常规的时代,这似乎不是最受欢迎的建议,但是“慢慢来”会有回报的。与其快速发布糟糕的代码,还不如有条不紊地来,发布几乎没有生产bug的代码。
优秀工程师会考虑到软件系统的所有问题。
他们不仅关心代码覆盖率,还关心可能破坏相同代码路径的奇怪输入。通过分层架构,它们可以实现模拟层,并只测试所考虑的层。他们不仅实现单元测试,而且还实现了集成和功能测试。如果你的团队还有QA工程师,就与他们一起测试这些用例。
子曰:“无欲速,无见小利。欲速则不达,见小利则大事不成。”
6在自动化上投资
错误:我们手动部署到staging和沙箱,是临时的。生产也是手工部署,但每天执行一次。
教训:拥有一个CI/CD系统管理部署意味着更可预测的结果。软件以促销策略在pipeline中移动,而临时部署则被降级到特殊情况下。这可以确保你正交付软件的稳定性和可靠性,这是工程团队的主要责任。
投资:
培训团队成员学习如何进行代码审查。你的团队成员可能有各种各样的技能,但不是每个人都知道如何进行更好的codereview。因此,你应在学习和教授codereview的最佳实践上进行投资。
使用像peril和hound这样的自动化codereview系统。Peril可以检查代码更改,并根据预先配置的设置,标记警告和构建失败。例如,如果数据库迁移文件缺少statement_timeout或包含不必要的DEFAULTNULL,则pullrequest可能失败。你可以编写许多这样的检查和特定于团队的规则,并让Peril成为更改的“看门人”。HoundCI可以做类似的事情,而且规则是完全可配置的。
7掌握你的工具
错误:我需要找到这个实现接口,先搜索一下。我记得它以前就在这个文件夹里,现在却不见了?在那个文件夹里找找,我还是问问别人吧!
教训:不知道如何使用你的工具,这会让你效率变低。你能想象一个邋遢的裁缝使用缝纫机的样子吗?这不仅关系到代码结果,还关系到构建软件的效率。
了解你的工具,掌握捷径。代码编辑器可能是你要掌握的第一个工具。你应该知道如何设置选项卡的排序、打开最后的编辑文件、显示调用图等。如果你使用基于文本的编辑器,而不是图形用户界面,这也可行。类似Vim这样的编辑器,有很多实用技巧。
请注意手动执行的常见操作,并学习如何通过快捷键来执行这些操作。要做到这点,一个简单的方法是先记住5条捷径,并熟练掌握它们,然后再记住5个捷径。
全栈工程师每天接触的其他常用工具有终端、docker、tableplus/pgadmin/一些其他数据库客户端用户界面、Chrome开发工具等。
8最小可行性产品(MVP)
错误:我觉得这个功能会很有用。我要使用分布式容错复制高可用数据存储。我还要构建一个基于插件的架构,使这个软件具有超强的可扩展性。
教训:在构建某个东西前,请确保它是你要构建的正确的东西。这就是MVP的用武之地。
理想的最小可行性产品(MinimumViableProduct,MVP)应该尽可能少地触及所有层面,而不仅仅是一个层。这是降低风险的一种做法。最好是最低限度地构建所有层,而不是完善单个层。最小可行性产品并不意味着技术债、糟糕的代码或缺乏测试。它不是抛弃型代码(throw-awaycode)。
奥卡姆剃刀:在其他一切同等的情况下,较简单的解释普遍比较复杂的好。
9研究支持开发
错误:我(工程师)认为这是我们应该构建的。
教训:在开发前,应该先进行大量的研究以佐证。与其跟随你的直觉,不如进行一项用户研究。要了解用户需求,可以亲自或者通过视频采访,进行调查、查看日志等。这将帮助你更好地了解用户。然后,你可以提出一个假设并进行实验。当形成一个假设时,请使用反演来驳斥自己的主张。
在一个A/B测试框架上投资,可以让你进行实验。
10科学的调试
错误:有一个bug。我想是因为代码改变所致。让我看看这个文件。没准也许是内存问题所致。或者这两个原因都有可能。
教训:作为一名工程师,无论是作为事件一部分,还是在本地环境中,你都将调试软件中的问题。如果不是通过结构化推理来完成的话,调试可能会非常痛苦、缓慢。
我们如何系统找出程序失败的原因?如果没有“直觉”、“敏锐思维”等模糊的概念,我们又该怎样才能做到这一点?我们想要找到一种查找失败原因的方法——这种方法:
不需要先验知识
是有系统的
我们可以确定找到根本原因,并随意复制
将科学方法应用于调试问题,是发展失败理论的公正方法。科学调试的步骤如下:
观察事实(彻底读取日志、错误跟踪等)
在日志中明确地陈述假设,而不是在心里做假设
如果你发现程序中的某部分存在错误,使用结构化方法来缩小错误范围,如二分搜索
测试假设:使用日志、断点、断言
如果通过验证,应用修复并确保没有新错误
如果无效,请重复步骤3到步骤6
对简单的调试情况来说,这可能看起来有点过头。但是,对于涉及多个团队的复杂分布式系统而言,一个系统科学的调试过程为消除模糊性提供必要的结构。
11额外福利
优秀的行为是帮助他人成长。当你需要用别人能理解的方式来解释某事时,你对事情的理解会更清晰。
通过这样做,你可以为自己打造个人品牌,从而获得职业资本。研究表明,那些拥有强大个人品牌、网络形象和帮助他人的记录的人,会取得成功,更重要的是,还会拥有令人满意的职业生涯。
2.塑造自己的世界
你无需接受这一现实世界。你可以通过坐在驾驶座上,塑造你所感知的世界。
这可能意味着在设计讨论和codereviews期间发表意见,或者修复关键的不稳定的测试(flakytest)。很多人会告诉你要多发言,提高知名度,以便在公司内部发展,但他们却从来不告诉你怎样才能做到这一点。要做到这一点,最好的方法是拥有坚定的观点和信心,将人们拉向你的方向。不要畏惧组建小型团队来构建/改进事物。不要屈服于你的恐惧。要大声说出来,只要不是无礼的,你都可以说出来。
负面情绪是改变的巨大动力。如果有问题让你感到困扰,你要扪心自问,并想出该如何进行改变。如果你将每一天都当作成长的途径,那么生活就会成为一种锻炼。
3.结识朋友
如果你像我一样,想弄清楚什么对你真正重要,那就去结识许多朋友吧,尤其是那些让你感兴趣的人。这可能意味着去参加会议、参加在线社区或者在黑客松活动和项目上进行合作。这种接触会帮你弄清楚你想要做什么。这样,你就可以对那些无关紧要的事说“No”,并抓住对你来说重要的那些机会。
通过这样做,我发现我更喜欢的是广度而不是深度,更看重创造力和自由,喜欢多样化和非正式的关系。我不适合从事结构化的重复性工作、例行公事、稳定和安全的事情。