拷贝Vim中的文本到Mac OS X的系统粘贴板
:[range]w[rite] !pbcopy
比如:.w !pbcopy
把当前行写到系统粘贴板里,也就是复制当前行。
也可以选择文本后,再:w !pbcopy
。
:r !pbpaste
,粘贴。
另外,如果vim在编译时打开了+clipboard
,那么set clipboard=unnamed
之后,yy
之类的命令就可以直接复制到粘贴板了。
Spring MVC中的异常处理
Exception Handling in Spring MVC
详细地介绍了Spring MVC中的异常处理。
Per Exception
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="No such Order")
public class OrderNotFoundException extends RuntimeException { }
Per Controller
@Controller
public class ExceptionHandlingController {
@ResponseStatus(value=HttpStatus.CONFLICT,
reason="Data integrity violation") // 409
@ExceptionHandler(DataIntegrityViolationException.class)
public void conflict() {
}
}
Globally
可以用@ControllerAdvice
和HandlerExceptionResolver
。
REST API的错误处理
Spring MVC REST Exception Handling Best Practices (part 1)
文章推荐了一种REST API发生错误时HTTP body的格式。
{
"status": 404,
"code": 40483,
"message": "Oops! It looks like that file does not exist.",
"developerMessage": "File resource for path /uploads/foobar.txt does not exist. Please wait 10 minutes until the upload batch completes before checking again.",
"moreInfo": "http://www.mycompany.com/errors/40483"
}
status
的值就是HTTP status code。
code
是应用程序内部的错误代码。
表示错误的HTTP status code最多只有几十种,不能再细分到底是哪段业务逻辑发生了错误;而code
的值空间是无限的。
同时code
也方便后续在代码中定位错误。
message
是code
的具体描述信息。它(可以)和code
一一对应。
同一code的message在不同的locale下可以是不同的值。翻译的信息可以放在json或者XML文件里。
developerMessage
和moreInfo
相比之下没有那么重要。
实现时,可以设计一个异常类,BusinessException(HttpStatus status, String code)
;
然后实现一个HandlerExceptionResolver。
Java的finally是否一定会执行?
try {
return 1;
} catch (Exception ex) {
//...
} finally {
//...
return 2;
}
类似“try里的return语句会不会使得finally块被跳过”或者“到底是return 1还是return 2”之类的问题常常会在面试时被问到。 这篇Oracle的文档给出了答案,
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break.
意思是return
之类的关键字不会使得finally块的执行被跳过。
除非在执行try时JVM退出了(比如调用了System.exit()
);或者执行try的线程被中断或者杀死了。
If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.
用removeIf和Lambda更快更简洁地删除元素
Java 8的Collection
接口提供了一个新的删除元素的方法,boolean removeIf(Predicate<? super E> filter)
。
它可以接受一个Lambda做为参数。
用这个方法可以写出更简洁的代码。
用一行代码,items.removeIf(i -> isDeletable(i));
,就可以替代下面的代码。
for (Iterator it = items.iterator(); it.hasNext();) {
if (isDeletable(it.next())) {
it.remove();
}
}
另外,对于ArrayList
而言,使用removeIf
比传统的iterator方式更快。
传统的iterator方式,每删除一个元素E都要把E之后的所有元素往前移动一位。
如果ArrayList
的大部分元素都要被删除,那么时间复杂度会是O(n^2)级别。
(实际上,Collection
接口提供的默认removeIf
实现就是用iterator方式来做删除的。)
ArrayList
类override了removeIf
方法,提供了更高效的实现。
新的实现先用一个BitSet
在一趟循环中标记哪些元素需要删除(O(n)复杂度),然后再在一趟循环中移动要保留的元素(O(n)复杂度)。
Git in 2016
这篇文章回顾了Git的一些新功能。
Worktree
通过git worktree
,一个Git repository可以有多个工作目录。
如果一段时间内,需要同时工作在一个repository的多个分支上,那么使用worktree比反复切换branch要方便。
$ git worktree add -b hotfix/BB-1234 ../hotfix/BB-1234
Bisect
git bisect
不是一个特别新的功能。用它方便地定位出问题的commit(假设test case充足的话)。
$ git bisect start
$ git bisect good v2.0.0
$ git bisect bad master
$ git bisect run npm test
Autostash
$ git config --global rebase.autostash true
这样就不怕每次rebase前忘记git stash
了。
Simple Stash IDs
不需要输入git stash apply stash@{n}
,简单地输入git stash apply 1
就可以了。
更多的内容,请阅读原文。
日常开发中常用的一些Vim操作
允许鼠标操作
在.vimrc
文件里加上set mouse=a
。
移动光标到第一个非空格字符
^
,移动光标到当前行的第一个非空格字符。
另外,0
移动光标到行首。+
移动光标到下一行的第一个非空格字符,-
移动光标到上一行的第一个非空格字符。
删除一个函数
假设有如下函数,
int sum() {
int total = 0;
for (int i = 0; i < 42; i++) {
total += i;
}
return total;
}
使光标位于函数体内(且光标位于for循环体外),然后da}dd
。
da}
,删除当前光标所在”{}块”,此时函数只剩下了int sum()
行;然后,再通过dd
删除这一行。
删除函数体:使光标位于函数体内,然后di}
。操作完成之后,剩下的代码是int sum() {}
。
拷贝一个函数
假设函数还是如上所示。
使光标位于函数体内(且光标位于for循环体外),然后va}o0y
。
v
,进入visual mode。
a}
,选择当前的“{}块”。o
,改变visual mode中光标的移动方向。
0
,移动光标到行首。y
,拷贝。
如果函数的{
是另起新行的,比如,
Ruby on Rails上的一个多租户实现
Scale Out Multi-Tenant Apps based on Ruby on Rails
一些ORM框架,比如EclipseLink,自带了多租户的实现。 这篇文章介绍了一个在Rails ActiveRecord之上的多租户实现。
Asshole Driven Development
基本上,程序员们都听过TDD(Test Driven Development)、敏捷开发或者“简历驱动开发”。 这篇文章归纳总结了一些新的软件开发模式。比如,
ADD,Asshole Driven development
Any team where the biggest jerk makes all the big decisions is asshole driven development. All wisdom, logic or process goes out the window when Mr. Asshole is in the room…
CYAE,Cover Your Ass Engineering
The driving force behind most individual efforts is to make sure than when the shit hits the fan, they are not to blame.
Reddit的讨论里还有更多的吐槽。比如,“seagull management”,
Where the supposed leaders are totally uninvolved in the work, they just swoop down once in a while to shit all over everything “This is wrong, and this, and this looks bad” etc, before flying away again.
MVCC in Database
Multiversion concurrency control(MVCC)是数据库实现并发访问的一种方法。
在MVCC下一个row会有多个版本。
比如对一个row做UPDATE
操作时,不会修改原始的row,而是作用在这个row的一个新的拷贝上。
MVCC在实现并发时不需要引入锁。
读、写操作不会相互阻塞。
很多数据库都实现了MVCC,比如PostgreSQL和Oracle。
更多参考
Multiversion concurrency control