Menu Home

标准GNU命令行的格式

我们每天都在Terminal下面运行很多命令,但是,你了解一条命令的标准格式吗?对于我来说,以前并没怎么关心过,都是拿来就用,不会就google。这几天继续看《Build Awesome Command-Line Applications in Ruby 2》,其中讲到了GNU规定的命令行的格式,看完以后有种恍然大悟的感觉,才发现原来一条命令还有一个标准格式的,有了这个格式,很多东西都不用记了,一个命令用起来就觉得有章可循了,对一个不熟悉的命令,也更容易猜到,或是找到使用的方法。 废话不多说,一个GNU规定的命令行的格式如下图所示: 一个完整的Terminal命令主要由4部分组成: 命令名(Executable): git 子命令(Command): push 选项(Options): –no-pager 和 -v都是 参数(arguments): origin和master 这里重点是选项(Options)的一些格式规定。 选项根据形式分类 从形式上来说,Options有两种形式:简短形式和完整形式。 简短形式一般由一个连接符“-”后面跟一个字母组成: ls -l -a -t # -l, -a, -t都是简短形式的Option 其实,几个简短形式的options可以合并写成一个: ls -lat 效果等同于 ls -l -a -t 完整形式的则一般由两个连接符“–”开头,接着是一个或多个完整的单词,如果有多个单词,那么中间用一个连接符连接,如上面的“–no-pager”。 选项根据功能分类 从功能上来讲,Options一般有两种。一种的是“switch”(开关),用来enable或者是disable(一般以“–no”开头)一些feature,如上面的–no-pager,就是用来disable pager这个feature的。除此之外的另外一种是flag。switch一般没有参数,flag则一般有参数。 如果一个flag有参数,那么一般简短形式的flag跟它的参数之间由一个空格分开。而完整形式的flag则用一个“=”连接它的参数,如: curl -X POST http://www.google.com #POST是-X的参数 curl […]

什么叫"功能单一"

昨天开始看《Build Awesome Command-Line Applications in Ruby 2》这本书,看完第一章。其中提到一个Awesome的Command,应该是功能单一(single-purpose)的,但是具体什么叫功能单一呢?为了解释这个问题,书中举了两个反例,来解释什么不是功能单一。 第一个例子是一个备份数据库的脚本。其中需要备份的数据库有两个,这个脚本一次性把两个脚本都备份了,脚本大概是这么写的: #!/usr/bin/env ruby # File: db_backup.rb #两个数据库的信息 databases = { big_client: { database: ‘big_client’, username: ‘big’, password: ‘big’, }, small_client: { database: ‘small_client’, username: ‘small’, password: ‘p@ssWord!’, } } databases.each do |name,config| #依次备份每个数据库 #… end 使用的时候,只需要运行一个这个命令就好了。但是这个脚本的结构其实并不好,也并不是"功能单一",之所以这么说,是因为它一次性备份了两个数据库,而不是一个。试想一下,如果后来又有一个数据库需要备份,那么就得改这个脚本,修改上面databases这个Hash(Map、Dictionary,whatever)。这个可不是一个好主意,如果别人给你一个备份数据库的脚本,然后你说要再备份一个数据库,结果他说你要改那个脚本,这时候你的感觉可不会太好,如果这个人离职了呢?如果他用的是一门你不熟悉的语言写的呢?如果他用的是write-only的perl写的呢? 所以对于这个脚本,更好的组织方式是,脚本本身只备份一个数据库,并且需要的数据库信息是从外面传进来的。 比如可以这样写: #!/usr/bin/env ruby # File: db_backup.rb […]

Rails Authentication From Scratch

这是一个对railscast250的学习笔记,所有copyright belongs to Railscast作者 Ryan Bates ### 1. 创建User Model rails g resource user email password_digest 这里有两点说明,一是关于rails g resource,你可能对rails g scaffold熟悉,那resource是什么呢?在这里,scaffold和resource都是rails generator,就是可以帮你自动生成很多琐碎的东西的助手,这样你就不用自己一遍一遍写类似的东西了。resource跟scaffold最主要的不同是,resource不会帮你生成对应的controller里面的任何个action以及他们对应的任何view;第二点需要说明的是“password_digest”这个字段,这个字段比较关键,因为接下来我们要用到rails为我们提供的has_secure_password这个helper method,这个method默认需要用到这个字段。 ### 2. Migrate database 在命令行执行rake db:migrate创建你的database ### 3. 打开model里面的user.rb,加上 has_secure_password class User < ActiveRecord::Base has_secure_password end has_secure_password这个方法我们前面提到过,它的作用是,利用前面提到的password_digest字段,给你提供password 和password_confirmation两个字段,并帮你做一些常见的validation,比如:密码不能为空,长度必须小于72字符,把password和password_confirmation两个字段进行对比,确保他们相等,等等。 ### 4. 安装bcrypt gem 前面提到的has_secure_password这个方法需要用到一个gem叫bcrypt,这个gem在你创建project的时候默认已经加到你的Gemfile里面去了,只不过默认被注释掉了。我们打开Gemfile,找到那一行并uncomment掉。接着执行 bundle install 进行安装,安装完这个gem以后,重启rails server让它生效。 […]

安卓单元测试(十一):异步代码怎么测试

这是被问得最多的问题之一。。。 ## 问题 今天讲一个我们讨论群里面被问得最多的一个问题:怎么测试异步操作。问题很明显,测试方法跑完了的时候,被测代码可能还没跑完,这就有问题了。比如下面的类: public class RepoModel { private Handler mUiHandler = new Handler(Looper.getMainLooper()); public void loadRepos(final RepoCallback callback) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); final List<Repo> repos = new ArrayList<>(); repos.add(new Repo("android-unit-testing-tutorial", "A repo that demos how to do android unit testing")); […]

Android单元测试(十):DaggerMock:The Power of Dagger2, The Ease of Mockito

## The Old Way 我们在系列的第六篇文章前面介绍了Dagger2在单元测试里面的使用姿势。大致过程是这样的,首先,你要mock出一个Module,让它的某个Provider方法在被调用的时候,返回你想到的mock的Dependency。然后使用这个mock的module来build出一个Component,再把这个Component放到你的ComponentHolder。举个例子说明一下,假设你有一个LoginActivity,里面有一个LoginPresenter,是通过Dagger2 inject进去的,如下: public class LoginActivity extends AppCompatActivity { @Inject LoginPresenter mLoginPresenter; @Override protected void onCreate(Bundle savedInstanceState) { //…other code ComponentHolder.getAppComponent().inject(this); } } //对应的Test类如下: @RunWith(RobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class, sdk = 21) public class LoginActivityTest { @Test public void testLogin() { AppModule mockAppModule = Mockito.mock(AppModule.class); LoginPresenter mockLoginPresenter = […]

安卓单元测试(九):使用Mockito Annotation快速创建Mock

注: 如果你还不了解Mock的概念或Mockito框架的使用,请先看这篇文章。 ### @Mock的基本用法 如果你follow了这个安卓单元测试系列文章,那么到现在为止,你应该很清楚mock的概念和使用了,创建Mock的方法我们都知道: YourClass yourInstance = Mockito.mock(YourClass.class); 比如: public class LoginPresenterTest { @Test public void testLogin() { UserManager mockUserManager = mock(UserManager.class); PasswordValidator mockValidator = mock(PasswordValidator.class); Mockito.when(mockValidator.verifyPassword("xiaochuang is handsome")).thenReturn(true); LoginPresenter presenter = new LoginPresenter(mockUserManager, mockValidator); presenter.login("xiaochuang", "xiaochuang is handsome"); verify(mockUserManager).performLogin("xiaochuang", "xiaochuang is handsome"); } } 虽然很简单,但是如果一个测试类里面很多测试方法都要用到mock,那写起来就会有点麻烦,这时候我们可以写一个@Before方法来作这个setup工作: public class LoginPresenterTest […]

安卓单元测试(八):Junit Rule的使用

JUnit Rule是什么 一个JUnit Rule就是一个实现了TestRule的类,这些类的作用类似于@Before、@After,是用来在每个测试方法的执行前后执行一些代码的一个方法。 如果你不清楚@Before、@After这些Annotation的意思,Chances are你还不了解Junit的使用,建议先看这篇文章。 那为什么不直接用这些annotation呢?这是因为它们都只能作用于一个类,如果同一个setup需要在两个类里面同时使用,那么你就要在两个测试类里面定义相同的@Before方法,然后里面写相同的代码,这就造成了代码重复。有的人说你可以用继承啊,首先我想说,我很讨厌继承这个东西,所以如果可以不用继承的话,我就不会用;再次我想说,如果你不讨厌继承的话,从现在开始,你也应该慢慢的讨厌它了。 此外,JUnit Rule还能做一些@Before这些Annotation做不到的事情,那就是他们可以动态的获取将要运行的测试类、测试方法的信息。这个在接下来的一个例子里面可以看到。 怎么用JUnit Rule? 使用框架自带的Rule 很多测试框架比如JUnit、Mockito自带给我们很多已经实现过好了的JUnit Rule,我们可以直接拿来用。比如Timeout,TemporaryFolder,等等。这些Rule的使用方法非常简单。定义一个这些类的public field,然后用@Rule修饰一下就好了。比如 public class ExampleTest { @Rule public Timeout timeout = new Timeout(1000); //使用Timeout这个 Rule, @Test public void testMethod1() throws Exception { //your tests } @Test public void testMethod2() throws Exception { //your tests2 } //other test […]

RxJava源码分析(一):Observable的几种创建方式

相信写Android的,写Java的人应该都听说过RxJava这个革命性的东西了,很多人也了解这个东西怎么使用。网上也有很多优秀的介绍性的文章,如果你还不了解这个东西,或者是不熟悉它的用法的话,我会建议先看这个系列的文章,然后再看这篇。尤其是后者绝对强烈推荐,其实我个人对RxJava的看法,刚开始只是觉得这个东西写起来语法非常简洁,非常优雅,可以在很大程度上面减少一些外部变量的使用,非常Functional。但是等到我看了那篇文章以后,我才发现,我只是发挥了RxJava不到一成的功力,获得了它不到一成的优点。它还有那么强大的力量,隐藏在冰山水下。另外,国内也有广受好评的扔物线写的给Android开发者的RxJava详解。这些足够让你对RxJava有一个比较深入的了解,此外,扔物线的文章也有一定程度的原理讲解和源码分析,可谓真正的深入浅出。 Anyway,这里我们就不介绍RxJava的用法和特点了,我们简单看看它的源代码。 先看第一部分,Observable的创建。现在大部分介绍RxJava的文章、尤其是介绍RxJava在Android上面的使用的文章,都往往会结合第三方的library,比如Retrofit。里面介绍Observable的使用方式是通过Retrofit的返回结果来获得一个Observable,再操作这个Observable。这容易给我们一种错觉,就好像我们自己从来不用,也不能创建Observable一样。然后其实不是这样的,我们完全可以自己创建Observable。常见的创建Observable的方式有以下几种: Observable.just(…) 比如: Observable.just("xiaochuang"); //Create an Observable that has only one item: "xiaochuang" Observable.just("xiaochuang", "handsome"); //Create an Observable that has 2 items: "xiaochuang" and "handsome" Observable.just("xiaochuang", "is", "handsome"); //Create an Observable that has 3 items: "xiaochuang", "is" and "handsome" //…you can pass in up to 10 items Observable.from(an_array_or_iterable); […]

《Working Effectively with Legacy Code》阅读分享(一)

端午节开始看这本编程领域经典的书《Working Effectively with Legacy Code》,中文版叫《修改代码的艺术》。英文原版豆瓣评分9分,中文版8.2分。Amazon.com评分9.2分。 从评分上看,这是一本质量非常不错的书。中文版的书名翻译虽然少了点感觉,多了点俗气——现在书名动不动什么什么艺术,什么什么之道,甚至什么什么之禅,真是让人不知道该作何感想。但应该说,这个书名翻译得还是很准确的。因为这本书讲的就是如何修改代码! 书的开篇讲了修改代码的四种原因: Adding a feature Fixing a bug Improving the design Optimising resource usage 对于前两种原因来说,改代码自然是理直气壮,没什么可以商量的余地。然而,对于后两种原因,通常就不是那么肯定了,甚至还有种policy叫做“If it’s not broke, don’t fix it”。这种policy之所以会出现,自然是有它的原因的。最大的原因,往往不是因为改代码需要时间,而是因为更改是有风险的,这种风险就是,你不知道你的更改是不是对的,更要命的是,你不知道你的更改会影响到其它的什么地方,会后带来什么后果。出于这种恐惧的心理,我们往往倾向于不到非不得已,就不去改代码。而这里所说的非不得已,就是添加feature和fix bugs。 然而遗憾的是,这种policy被一次又一次的证明,是行不通的,因为很快你会发现,你的每个类会写得越来越大,每个方法越来越长,结构越来越复杂,越来越难以理解,每次加一个新feature,fix一个bug都越来越困难。于是到了某个点,所有东西都必须推倒重写。这种事情在历史上发生了一次又一次。那怕不会到那一步,烂代码和烂结构也会严重的拖后正常的工作进程。 这种结局是应该被避免的,也是可以被避免的,怎么避免?那就是不要只顾着add feature和fix bugs,也要及时的“Improve the design”,也就是传说中的重构。但是话说回来,重构就会有上面提到的那些风险,说得更具体点,我们需要解决好以下三个问题: What changes do we have to make? How will we know that we’ve done them correctly? How […]

关于安卓单元测试,你需要知道的一切

单元测试是个技术活,它有自己的一套知识体系,要做好单元测试,的确是需要学习和不断的在实践中练习的。好消息是,这套知识体系的范围相对来说是有限的,因此,只要耐心的学习和练习一段时间,就可以做好日常大多数的需求。然后国内这大环境和氛围,大家都清楚,大部分时候大家都在赶feature,赶上线,以至于单元测试这件事情,往往被忽略,甚至从来没考虑过,而这一点在移动开发上面则更加严重。这导致的结果就是,网上很难找到比较系统的关于单元测试各个方面的文章。这就让有些童鞋那怕有做单元测试的想法,却不知道从何下手,因此导致一个恶性循环。 出于这点原因,我根据自己的一些经验和想法,写了一个系列的文章,至此为止写了7篇,然而经常发现有朋友对前面的一些概念不是很清楚,从网站或公众号找之前的一些文章又不是很方便,因此整理了这样一篇汇总性的文章,希望能让大家对此有个更整体化的了解,如果某一方面的东西不是很清楚,也能很快找到参考。 以下文章是这个系列文章的总结。 什么是单元测试:介绍了什么是单元测试,里面澄清了一个最常见的误解,同时介绍了有返回值和没有返回值两种不同的函数——对于OO来说,应该叫“方法”,但是中文里面“方法”这个词太容易产生误解了,因此我这里用函数来代替,这就是翻译尴尬的地方。所以很多时候我建议不如直接用英文单词本身,而不是非要硬生生翻译过来。 为什么要做单元测试:对于什么要做单元测试的个人之见。 JUnit单元测试框架的使用:介绍了题目中说的内容,JUnit是最基础的一个单元测试框架。 Mock以及Mockito的使用:mock自古以来就是单元测试不可分割的一部分,这篇介绍了mock的概念和使用。 依赖注入,将mock方便的用起来:为了将mock更方便简洁优雅的用起来,我们需要用到依赖注入。这篇文章介绍了依赖注入的概念和使用。 使用dagger2来做依赖注入,以及在单元测试中的应用:上一篇文章讲了依赖注入,而Dagger2能让我们易如反掌的使用依赖注入的模式,代码的耦合度变得非常低。 Robolectric,在JVM上调用安卓的类:解决在JVM上做单元测试的时候,无法调用和测试安卓的类的问题。 其它的一些文章: Android单元测试在蘑菇街支付金融部门的实践:这个是在InfoQ的移动前线学习分享群里面作的一个分享,首发于”移动开发前线”公众号,也在InfoQ网站上发表过,讲了的单元测试在蘑菇街支付金融部门的实践。 MDay上的分享-关于安卓单元测试的一切:这是在MDay第五季作的一次分享,有PPT和视频,不过视频暂时还没有公开,如果公开了会第一时间更新过来。 安卓单元测试是不是只有这些东西?当然不是,只不过,主要的概念和框架都在这了。剩下的相对来说更多是一些具体的技巧、解决某个具体问题的方法等等。对于这些东西,以后也会有文章介绍,敬请关注。 最后,如果你对安卓单元测试感兴趣,欢迎加入我们的交流群,因为群成员超过100人,没办法扫码加入,请关注下方公众号获取加入方法。 以上,希望能帮助到你。如果觉得有用,请分享一下,以便帮助到其它人。分享是一种美德,这也是我坚持写作的初衷。 (如果提示群满了,请关注一下公众号,在公众号的菜单有加入方法)