读书摘要,Hackable Projects
完整读完Google的三篇谈Hackable Projects的文章,以及一篇从Test Pyramid看UnitTest的比重、一篇谈Optimal Logging的文章,感觉这5篇在测试、日志两个方面对工程的速度、大小、解耦三个方面做了深入而系统的解读,非常值得一看,专业的测试角度剖析工程,有一种解剖学的感觉,这刷新了我对测试的理解,我估计职业的开发工程师里能有这么全面的视角的估计比例本就不高。此处简要摘录做个笔记,结合自己的经验体会,在这方面会有系统化的视角。
Hackable Projects - Pillar 1: Code Health
- Readable Code
- Code Style: google code style guid
- Code Review
- Presubmit Test
- Single Branch And Reducing Risk
- Loose Couping
- SOLID
- Aggressively Reduce Technical Debt
- dependency enforcement
Hackable Projects - Pillar 2: Debuggability
- Principle
- Debuggability means being able to easily find what’s wrong with a piece of software
- through logs, statistics or debugger tools
- Debuggability doesn’t happen by accident: you need to design it into your product
- Debuggability means being able to easily find what’s wrong with a piece of software
- Running on Localhost
- need some kind of script that brings up your server stack on localhost
- Debugging Mobile Apps
- mobile is hard
- unit tests are great for hackability here
- Test-Drive Your Android Code:Robolectric
- Android Testing Support Library:Espresso test
- Create and run unit tests, performance tests, and UI tests for your Xcode project: XCTest
- iOS UI Automation Test Framework:EarlGrey
- When Debugging gets Tricky
- debugging flags and instructions
- you need to build these kinds of things into your product
- Proper Logging
- It’s hackability to get the right logs when you need them
- Logs are also useful for development
- Optimal Logging
- Monitoring and Statistics
- System Under Test (SUT) Size
Hackable Projects - Pillar 3: Infrastructure
- Build Systems Speed
- Replace make with ninja
- Use the gold linker instead of ld
- Detect and delete dead code in your project
- Reduce the number of dependencies
- enforce dependency rules so new ones are not added lightly
- Give the developers faster machines
- Use distributed build, which is available with many open-source continuous integration systems
- feedback cycles kill hackability, for many reasons:
- Build and test times longer than a handful of seconds cause many developers’ minds to wander, taking them out of the zone.
- Excessive build or release times* makes tinkering and refactoring much harder.
- The main axes of improvement are:
- Reduce the amount of code being compiled.
- Replace tools with faster counterparts.
- Increase processing power, maybe through parallelization or distributed systems.
- Continuous Integration and Presubmit Queues
- You should build and run tests on all platforms you release on.
- At a minimum, you should build and test on all platforms, but it’s even better if you do it in presubmit.
- Chromium:It has developed over the years so that a normal patch builds and tests on about 30 different build configurations before commit.
- Test Speed:
- if it takes more than a minute to execute, its value is greatly diminished
- Sharding and parallelization.
- Continuously measure how long it takes to run one build+test cycle in your continuous build, and have someone take action when it gets slower.
- Remove tests that don’t pull their weight.
- If you have tests that bring up a local server stack, for instance inter-server integration tests, making your servers boot faster is going to make the tests faster as well.
- Workflow Speed
- You need to keep track of your core workflows as your project grows.
- Your version control system may work fine for years, but become too slow once the project becomes big enough.
- Release Often
- It aids hackability to deploy to real users as fast as possible.
- Easy Reverts:
- If you look in the commit log for the Chromium project, you will see that a significant percentage of the commits are reverts of a previous commits.
- Performance Tests: Measure Everything:
- Is it critical that your app starts up within a second?
- Should your app always render at 60 fps when it’s scrolled up or down?
- Should your web server always serve a response within 100 ms?
- Should your mobile app be smaller than 8 MB?
Just Say No to More End-to-End Tests
Good ideas often fail in practice, and in the world of testing, one pervasive good idea that often fails in practice is a testing strategy built around end-to-end tests.
What Went Wrong for End-to-End test:
- The team completed their coding milestone a week late (and worked a lot of overtime).
- Finding the root cause for a failing end-to-end test is painful and can take a long time.
- Partner failures and lab failures ruined the test results on multiple days.
- Many smaller bugs were hidden behind bigger bugs.
- End-to-end tests were flaky at times.
- Developers had to wait until the following day to know if a fix worked or not.
The True Value of Tests:
- A failing test does not directly benefit the user.
- A bug fix directly benefits the user.
Building the Right Feedback Loop:
- It's fast
- It's reliable(smaller)
- It isolates failures
Think Smaller, Not Larger
Unit Test
Unit tests take a small piece of the product and test that piece in isolation.
- Unit tests are fast.
- Unit tests are reliable.
- Unit tests isolate failures.
Writing effective unit tests requires skills in areas:
- dependency management
- mocking
- hermetic testing
With end-to-end tests, you have to wait: first for the entire product to be built, then for it to be deployed, and finally for all end-to-end tests to run.
Although end-to-end tests do a better job of simulating real user scenarios, this advantage quickly becomes outweighed by all the disadvantages of the end-to-end feedback loop:
- NOT fast
- NOT Reliable
- NOT Isolates Failures
Integration Tests
Unit tests do have one major disadvantage: even if the units work well in isolation, you do not know if they work well together.
But even then, you do not necessarily need end-to-end tests. For that, you can use an integration test.
An integration test takes a small group of units, often two units, and tests their behavior as a whole, verifying that they coherently work together.
Testing Pyramid
Even with both unit tests and integration tests, you probably still will want a small number of end-to-end tests to verify the system as a whole.
To find the right balance between all three test types, the best visual aid to use is the testing pyramid:

As a good first guess, Google often suggests a 70/20/10 split: 70% unit tests, 20% integration tests, and 10% end-to-end tests.
Optimal Logging
Channeling Goldilocks:
Massive, disk-quota burning logs are a clear indicator that little thought was put in to logging.
- Never log too much:
Goals of logging:
- help with bug investigation
- event confirmation
If your log can’t explain the cause of a bug or whether a certain transaction took place, you are logging too little.
- The only thing worse than logging too much is logging too little.
Good things to log:
- Important startup configuration
- Errors
- Warnings
- Changes to persistent data
- Requests and responses between major system components
- Significant state changes
- User interactions
- Calls with a known risk of failure
- Waits on conditions that could take measurable time to satisfy
- Periodic progress during long-running tasks
- Significant branch points of logic and conditions that led to the branch
- Summaries of processing steps or events from high level functions - Avoid logging every step of a complex process in low-level functions.
Bad things to log:
- Function entry - Don’t log a function entry unless it is significant or logged at the debug level.
- Data within a loop - Avoid logging from many iterations of a loop. It is OK to log from iterations of small loops or to log periodically from large loops.
- Content of large messages or files - Truncate or summarize the data in some way that will be useful to debugging.
- Benign errors - Errors that are not really errors can confuse the log reader. This sometimes happens when exception handling is part of successful execution flow.
- Repetitive errors - Do not repetitively log the same or similar error. This can quickly fill a log and hide the actual cause. Frequency of error types is best handled by monitoring. Logs only need to capture detail for some of those errors.
There is More Than One Level
Test logs should always contain:
- Test execution environment
- Initial state
- Setup steps
- Test case steps
- Interactions with the system
- Expected results
- Actual results
- Teardown steps
Conditional Verbosity With Temporary Log Queues
to create temporary, in-memory log queues. Throughout processing of a transaction, append verbose details about each step to the queue. If the transaction completes successfully, discard the queue and log a summary. If an error is encountered, log the content of the entire queue and the error.
Failures and Flakiness Are Opportunities
If you have a hard time determining the cause of an error, it's a great opportunity to improve your logging. Before fixing the problem, fix your logging so that the logs clearly show the cause.
Might As Well Log Performance Data
Logged timing data can help debug performance issues.
Following the Trail Through Many Threads and Processes
You should create unique identifiers for transactions that involve processing across many threads and/or processes
Monitoring and Logging Complement Each Other
a monitoring alert is simply a trigger for you to start an investigation. Monitoring shows the symptoms of problems. Logs provide details and state on individual transactions
读书摘要,Hackable Projects的更多相关文章
- 《Effective C++》读书摘要
http://www.cnblogs.com/fanzhidongyzby/archive/2012/11/18/2775603.html 1.让自己习惯C++ 条款01:视C++为一个语言联邦 条款 ...
- 读书摘要:第七章 闩Suan锁和自旋锁
摘要: 1.闩锁就像是内存上的锁,随着越来越多的线程参与进来,他们争相访问同一块内存,导致堵塞.2.自旋锁就是闩锁,不同之处是如果访问的内存不可用,它将继续检查轮询一段时间.3.拴锁和自旋锁是我们无法 ...
- JAVA 技术手册 卷1 第十四章『多线程』 读书摘要
什么是线程 进程受CPU时间片的轮转调度,进而予人多任务并发的感觉. 线程在更低层次上扩展多任务概念,一个进程通常包含多个线程. 进程各自数据独立,而线程共享数据. 数据独立使进程相互通信变得繁难,共 ...
- 读书摘要,一种新的黑客文化:programming is forgetting
http://opentranscripts.org/transcript/programming-forgetting-new-hacker-ethic/ 这篇文章非常有意思,作者是一个计算机教师, ...
- 《Java多线程核心技术》读书摘要
Chapter1: 进程是操作系统管理的基本单元,线程是CPU调到的基本单元. 调用myThread.run()方法,JVM不会生成新的线程,myThread.start()方法调用两次JVM会报错. ...
- Java设计模式(Design Patterns In Java)读书摘要——第1章 绪论
为何需要模式 模式是做事的方法,是实现目标,研磨技术的方法.通俗点说,模式是为了解决某个行业的某个问题的有效的方法或技艺. 为何需要设计模式 为了提升代码的水准,是代码变得简洁而易用.模式是一种思想, ...
- JAVA设计模式(DESIGN PATTERNS IN JAVA)读书摘要 第1部分接口型模式——第4章 外观(Facade)模式
外观模式就类似于一个工具包,一个类对应一个功能. 外观模式的意图是为子系统提供一个接口,便于它的使用. 书中给出的例子是画一个哑弹的飞行路径, 初始的类的设计是这样的,看下图, ShowFlight类 ...
- HeadFirst SQL 读书摘要
数据库都是用 圆柱形表示的. 数据库中包含表 表中包含行和列 行又叫记录record, 列又叫 字段field 创建数据库 create database mypipe_l; 选择数据库 use m ...
- Tomcat权威指南-读书摘要系列10
Tomcat集群 一些集群技术 DNS请求分配 TCP网络地址转换请求分配 Mod_proxy_balance负载均衡与故障复原 JDBC请求分布与故障复原
随机推荐
- iOS 导航栏实现总结
目标: 在UI界面中实现 整体效果的导航栏, 比如1 首页无导航条,次页有导航条, 2 导航条中不包含下方不包含黑边 3 导航条包含多个筛选项 等等 问题: 用系统带的NavigateBar 来实现时 ...
- Hello BIEE
这篇文章提供了一个Hello World式的例子,讲述如何创建一个最简单的BIEE资料库.本文使用的示例数据可以在从此链接下载:http://www.zw1840.com . 目录 创建资料库 创 ...
- MySQL数据类型——数值类型
1.1.1 整型 整型 占用字节 范围 范围 tinyint 1 -27~27-1 -128~127 smallint 2 -215~215-1 -32768~32767 mediumint 3 -2 ...
- C#正则表达式开源工具,为.net开源绵尽薄力
先交代一下背景,最近工作中经常用到正则表达式,而正则表达式这个东西我个人觉得很鸡肋,不用吧,有些功能实现起来会很麻烦.用吧,又不是说工作中经常用到,只是有时候有些需要求用到而已.但是正则表达式只要一段 ...
- Linux下GitLab的快速安装以及备份
源码安装 GitLab 步骤繁琐:需要安装依赖包,Mysql,Redis,Postfix,Ruby,Nginx……安装完毕还得一个个手动配置这些软件,容易出错 一.安装 在Ubuntu 14上 修改/ ...
- HBase 高性能获取数据(多线程批量式解决办法) + MySQL和HBase性能测试比较
摘要: 在前篇博客里已经讲述了通过一个自定义 HBase Filter来获取数据的办法,在末尾指出此办法的性能是不能满足应用要求的,很显然对于如此成熟的HBase来说,高性能获取数据应该不是问题. ...
- iOS 判断内容是否是中文,两种实现
用category实现 新建类别文件,代码 .h文件 #import <Foundation/Foundation.h> @interface NSString (Valid) - (BO ...
- AIR ANE(本机扩展)使用中的一些问题(Android平台)
关于如何写ANE,就不说了,用关键字,Android ANE 开发,会搜索到N多. 下面写一下碰到的问题,和一些别人可能没有说清的地方 1. 生成的ANE是直接拷到lib里使用吗?A:这个一定不要直接 ...
- python paramiko
paramiko 遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接,可以实现远程文件的上传,下载或通过ssh远程执行命令. 项目地址:https://github.com/paramik ...
- Objective-C基础数据类型-NSSet[转]
转自GISerYang 集合: 集合(NSSet)和数组(NSArray)有相似之处,都是存储不同的对象的地址:不过NSArray是有序的集合,NSSet是无序的集合. 集合是一种哈希表,运用散列算法 ...