阿里云主機(jī)推薦碼,可以打九折8C0BAY 有效期 11-30號(hào)
posted @
2015-10-15 18:13 hellxoul 閱讀(198) |
評(píng)論 (0) |
編輯 收藏
摘要:
閱讀全文
posted @
2015-01-05 11:52 hellxoul 閱讀(315) |
評(píng)論 (0) |
編輯 收藏
如果不配置其他參數(shù),大致相當(dāng)于以下的配置文件(參考自org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser)
1 <!-- 配置路徑擴(kuò)展名映射的媒體類(lèi)型 -->
2 <bean name="pathExtensionContentNegotiationStrategy"
3 class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
4 <constructor-arg>
5 <props>
6 <!-- if romePresent -->
7 <prop key="atom">application/atom+xml</prop>
8 <prop key="rss">application/rss+xml</prop>
9 <!-- endif -->
10 <!-- if jackson2Present || jacksonPresent -->
11 <prop key="json">application/json</prop>
12 <!-- endif -->
13 <!-- if jaxb2Present -->
14 <prop key="xml">application/xml</prop>
15 <!-- endif -->
16 </props>
17 </constructor-arg>
18 </bean>
19
20 <!-- 配置映射媒體類(lèi)型的策略 -->
21 <bean name="mvcContentNegotiationManager"
22 class="org.springframework.web.accept.ContentNegotiationManager">
23 <constructor-arg>
24 <list>
25 <ref bean="pathExtensionContentNegotiationStrategy" />
26 </list>
27 </constructor-arg>
28 </bean>
29
30 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
31 <property name="order" value="0"/>
32 <property name="removeSemicolonContent" value="false"/>
33 <property name="contentNegotiationManager" ref="mvcContentNegotiationManager"/>
34 </bean>
35
36 <!-- 配置數(shù)據(jù)轉(zhuǎn)換服務(wù),默認(rèn)使用格式化數(shù)據(jù)轉(zhuǎn)換服務(wù),可以對(duì)日期和數(shù)字進(jìn)行格式化 -->
37 <bean name="conversionService"
38 class="org.springframework.format.support.DefaultFormattingConversionService">
39 <constructor-arg index="0">
40 <null/>
41 </constructor-arg>
42 <constructor-arg index="1" value="true"/>
43 </bean>
44
45 <bean name="validator"
46 class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
47
48 <!-- 配置數(shù)據(jù)綁定,通過(guò)轉(zhuǎn)換服務(wù)實(shí)現(xiàn)綁定,如果包含jsr303實(shí)現(xiàn)還將進(jìn)行校驗(yàn) -->
49 <bean name="webBindingInitializer"
50 class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
51 <property name="conversionService" ref="conversionService" />
52 <!-- if jsr303Present -->
53 <property name="validator" ref="validator" />
54 <!-- endif -->
55 </bean>
56
57 <bean name="byteArrayHttpMessageConverter"
58 class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
59
60 <bean name="stringHttpMessageConverter"
61 class="org.springframework.http.converter.StringHttpMessageConverter">
62 <property name="writeAcceptCharset" value="false" />
63 </bean>
64
65 <bean name="resourceHttpMessageConverter"
66 class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
67 <bean name="sourceHttpMessageConverter"
68 class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
69 <bean name="allEncompassingFormHttpMessageConverter"
70 class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
71 <bean name="atomFeedHttpMessageConverter"
72 class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"/>
73 <bean name="rssChannelHttpMessageConverter"
74 class="org.springframework.http.converter.feed.RssChannelHttpMessageConverter"/>
75 <bean name="jaxb2RootElementHttpMessageConverter"
76 class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
77 <bean name="mappingJacksonHttpMessageConverter"
78 class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
79
80 <!-- 配置@RequestBody,@ResponseBody注解可用的轉(zhuǎn)換器 -->
81 <util:list id="messageConverters"
82 list-class="org.springframework.beans.factory.support.ManagedList">
83 <ref bean="byteArrayHttpMessageConverter" />
84 <ref bean="stringHttpMessageConverter" />
85 <ref bean="resourceHttpMessageConverter" />
86 <ref bean="sourceHttpMessageConverter" />
87 <ref bean="allEncompassingFormHttpMessageConverter" />
88 <!-- if romePresent -->
89 <ref bean="atomFeedHttpMessageConverter" />
90 <ref bean="rssChannelHttpMessageConverter" />
91 <!-- endif -->
92 <!-- if jaxb2Present -->
93 <ref bean="jaxb2RootElementHttpMessageConverter" />
94 <!-- endif -->
95 <!-- if jacksonPresent -->
96 <ref bean="mappingJacksonHttpMessageConverter" />
97 <!-- endif -->
98 </util:list>
99
100 <!-- 將任意類(lèi)型的Controller適配為Handler -->
101 <bean name="requestMappingHandlerAdapter"
102 class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
103 <property name="contentNegotiationManager" ref="mvcContentNegotiationManager" />
104 <property name="webBindingInitializer" ref="webBindingInitializer" />
105 <property name="messageConverters" ref="messageConverters" />
106 </bean>
107
108 <!-- 這個(gè)攔截器暴露轉(zhuǎn)換器服務(wù)讓spring:bind和spring:eval標(biāo)簽可用 -->
109 <bean name="csInterceptor"
110 class="org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor">
111 <constructor-arg index="0" ref="conversionService"/>
112 </bean>
113
114 <!-- 現(xiàn)在所有攔截器都必須設(shè)定響應(yīng)的路徑映射 -->
115 <bean name="mappedCsInterceptor"
116 class="org.springframework.web.servlet.handler.MappedInterceptor">
117 <constructor-arg index="0">
118 <null/>
119 </constructor-arg>
120 <constructor-arg index="1" ref="csInterceptor"/>
121 </bean>
122
123 <!-- 使用@ExceptionHandler注解的方法來(lái)處理Exception,優(yōu)先級(jí)為0(最高) -->
124 <bean name="exceptionHandlerExceptionResolver"
125 class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
126 <property name="contentNegotiationManager" ref="mvcContentNegotiationManager" />
127 <property name="messageConverters" ref="messageConverters" />
128 <property name="order" value="0" />
129 </bean>
130
131 <!-- 如果拋出的Exception類(lèi)帶有@ResponseStatus注解,響應(yīng)返回該注解的Http狀態(tài)碼,優(yōu)先級(jí)為1 -->
132 <bean name="responseStatusExceptionResolver"
133 class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver">
134 <property name="order" value="1" />
135 </bean>
136
137 <!-- SpringMvc內(nèi)部異常處理 -->
138 <bean name="defaultExceptionResolver"
139 class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver">
140 <property name="order" value="2" />
141 </bean>
142
posted @
2014-08-03 22:35 hellxoul 閱讀(2899) |
評(píng)論 (1) |
編輯 收藏
HeadFirst Servlet/JSP 學(xué)習(xí)筆記
1.容器加載類(lèi),調(diào)用servlet的無(wú)參構(gòu)造方法,并調(diào)用servlet的init()方法,從而初始化servlet。
2.init()在servlet一生中只調(diào)用一次,往往在servlet為客戶(hù)請(qǐng)求提供服務(wù)之前調(diào)用。
3.init()方法使servlet可以訪(fǎng)問(wèn)ServletConfig和ServletContext對(duì)象,servlet需要從這些對(duì)象得到有關(guān)servlet配置和web應(yīng)用的信息。
4.容器通過(guò)調(diào)用servlet的destroy()方法來(lái)結(jié)束servlet的生命
5.servlet一生的大多時(shí)間都是在為某個(gè)客戶(hù)端請(qǐng)求運(yùn)行service()方法
6.對(duì)servlet的每個(gè)請(qǐng)求都在一個(gè)單獨(dú)的線(xiàn)程中運(yùn)行,任何特定servlet類(lèi)都只有一個(gè)實(shí)例。
posted @
2014-07-05 15:21 hellxoul 閱讀(270) |
評(píng)論 (0) |
編輯 收藏
轉(zhuǎn)自:
http://www.cnblogs.com/peida/p/Guava_Ordering.html
Ordering是Guava類(lèi)庫(kù)提供的一個(gè)犀利強(qiáng)大的比較器工具,Guava的Ordering和JDK Comparator相比功能更強(qiáng)。它非常容易擴(kuò)展,可以輕松構(gòu)造復(fù)雜的comparator,然后用在容器的比較、排序等操作中。
本質(zhì)上來(lái)說(shuō),Ordering 實(shí)例無(wú)非就是一個(gè)特殊的Comparator 實(shí)例。Ordering只是需要依賴(lài)于一個(gè)比較器(例如,Collections.max)的方法,并使其可作為實(shí)例方法。另外,Ordering提供了鏈?zhǔn)椒椒ㄕ{(diào)用和加強(qiáng)現(xiàn)有的比較器。
下面我們看看Ordering中的一些具體方法和簡(jiǎn)單的使用實(shí)例。
常見(jiàn)的靜態(tài)方法:
natural():使用Comparable類(lèi)型的自然順序, 例如:整數(shù)從小到大,字符串是按字典順序;
usingToString() :使用toString()返回的字符串按字典順序進(jìn)行排序;
arbitrary() :返回一個(gè)所有對(duì)象的任意順序, 即compare(a, b) == 0 就是 a == b (identity equality)。 本身的排序是沒(méi)有任何含義, 但是在VM的生命周期是一個(gè)常量。
簡(jiǎn)單實(shí)例:
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
public class OrderingTest {
@Test
public void testStaticOrdering(){
List<String> list = Lists.newArrayList();
list.add("peida");
list.add("jerry");
list.add("harry");
list.add("eva");
list.add("jhon");
list.add("neron");
System.out.println("list:"+ list);
Ordering<String> naturalOrdering = Ordering.natural();
Ordering<Object> usingToStringOrdering = Ordering.usingToString();
Ordering<Object> arbitraryOrdering = Ordering.arbitrary();
System.out.println("naturalOrdering:"+ naturalOrdering.sortedCopy(list));
System.out.println("usingToStringOrdering:"+ usingToStringOrdering.sortedCopy(list));
System.out.println("arbitraryOrdering:"+ arbitraryOrdering.sortedCopy(list));
}
}
輸出:
list:[peida, jerry, harry, eva, jhon, neron]
naturalOrdering:[eva, harry, jerry, jhon, neron, peida]
usingToStringOrdering:[eva, harry, jerry, jhon, neron, peida]
arbitraryOrdering:[neron, harry, eva, jerry, peida, jhon]
操作方法:
reverse(): 返回與當(dāng)前Ordering相反的排序:
nullsFirst(): 返回一個(gè)將null放在non-null元素之前的Ordering,其他的和原始的Ordering一樣;
nullsLast():返回一個(gè)將null放在non-null元素之后的Ordering,其他的和原始的Ordering一樣;
compound(Comparator):返回一個(gè)使用Comparator的Ordering,Comparator作為第二排序元素,例如對(duì)bug列表進(jìn)行排序,先根據(jù)bug的級(jí)別,再根據(jù)優(yōu)先級(jí)進(jìn)行排序;
lexicographical():返回一個(gè)按照字典元素迭代的Ordering;
onResultOf(Function):將function應(yīng)用在各個(gè)元素上之后, 在使用原始o(jì)rdering進(jìn)行排序;
greatestOf(Iterable iterable, int k):返回指定的第k個(gè)可迭代的最大的元素,按照這個(gè)從最大到最小的順序。是不穩(wěn)定的。
leastOf(Iterable<E> iterable,int k):返回指定的第k個(gè)可迭代的最小的元素,按照這個(gè)從最小到最大的順序。是不穩(wěn)定的。
isOrdered(Iterable):是否有序,Iterable不能少于2個(gè)元素。
isStrictlyOrdered(Iterable):是否嚴(yán)格有序。請(qǐng)注意,Iterable不能少于兩個(gè)元素。
sortedCopy(Iterable):返回指定的元素作為一個(gè)列表的排序副本。

package com.peidasoft.guava.base;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
public class OrderingTest {
@Test
public void testOrdering(){
List<String> list = Lists.newArrayList();
list.add("peida");
list.add("jerry");
list.add("harry");
list.add("eva");
list.add("jhon");
list.add("neron");
System.out.println("list:"+ list);
Ordering<String> naturalOrdering = Ordering.natural();
System.out.println("naturalOrdering:"+ naturalOrdering.sortedCopy(list));
List<Integer> listReduce= Lists.newArrayList();
for(int i=9;i>0;i--){
listReduce.add(i);
}
List<Integer> listtest= Lists.newArrayList();
listtest.add(1);
listtest.add(1);
listtest.add(1);
listtest.add(2);
Ordering<Integer> naturalIntReduceOrdering = Ordering.natural();
System.out.println("listtest:"+ listtest);
System.out.println(naturalIntReduceOrdering.isOrdered(listtest));
System.out.println(naturalIntReduceOrdering.isStrictlyOrdered(listtest));
System.out.println("naturalIntReduceOrdering:"+ naturalIntReduceOrdering.sortedCopy(listReduce));
System.out.println("listReduce:"+ listReduce);
System.out.println(naturalIntReduceOrdering.isOrdered(naturalIntReduceOrdering.sortedCopy(listReduce)));
System.out.println(naturalIntReduceOrdering.isStrictlyOrdered(naturalIntReduceOrdering.sortedCopy(listReduce)));
Ordering<String> natural = Ordering.natural();
List<String> abc = ImmutableList.of("a", "b", "c");
System.out.println(natural.isOrdered(abc));
System.out.println(natural.isStrictlyOrdered(abc));
System.out.println("isOrdered reverse :"+ natural.reverse().isOrdered(abc));
List<String> cba = ImmutableList.of("c", "b", "a");
System.out.println(natural.isOrdered(cba));
System.out.println(natural.isStrictlyOrdered(cba));
System.out.println(cba = natural.sortedCopy(cba));
System.out.println("max:"+natural.max(cba));
System.out.println("min:"+natural.min(cba));
System.out.println("leastOf:"+natural.leastOf(cba, 2));
System.out.println("naturalOrdering:"+ naturalOrdering.sortedCopy(list));
System.out.println("leastOf list:"+naturalOrdering.leastOf(list, 3));
System.out.println("greatestOf:"+naturalOrdering.greatestOf(list, 3));
System.out.println("reverse list :"+ naturalOrdering.reverse().sortedCopy(list));
System.out.println("isOrdered list :"+ naturalOrdering.isOrdered(list));
System.out.println("isOrdered list :"+ naturalOrdering.reverse().isOrdered(list));
list.add(null);
System.out.println(" add null list:"+list);
System.out.println("nullsFirst list :"+ naturalOrdering.nullsFirst().sortedCopy(list));
System.out.println("nullsLast list :"+ naturalOrdering.nullsLast().sortedCopy(list));
}
}
//============輸出==============
list:[peida, jerry, harry, eva, jhon, neron]
naturalOrdering:[eva, harry, jerry, jhon, neron, peida]
listtest:[1, 1, 1, 2]
true
false
naturalIntReduceOrdering:[1, 2, 3, 4, 5, 6, 7, 8, 9]
listReduce:[9, 8, 7, 6, 5, 4, 3, 2, 1]
true
true
true
true
isOrdered reverse :false
false
false
[a, b, c]
max:c
min:a
leastOf:[a, b]
naturalOrdering:[eva, harry, jerry, jhon, neron, peida]
leastOf list:[eva, harry, jerry]
greatestOf:[peida, neron, jhon]
reverse list :[peida, neron, jhon, jerry, harry, eva]
isOrdered list :false
isOrdered list :false
add null list:[peida, jerry, harry, eva, jhon, neron, null]
nullsFirst list :[null, eva, harry, jerry, jhon, neron, peida]
nullsLast list :[eva, harry, jerry, jhon, neron, peida, null]

posted @
2014-07-03 10:48 hellxoul 閱讀(395) |
評(píng)論 (0) |
編輯 收藏
摘要: centos 6.5 安裝rabbitmq
閱讀全文
posted @
2014-06-25 22:23 hellxoul 閱讀(2260) |
評(píng)論 (0) |
編輯 收藏
轉(zhuǎn)自:http://singo107.iteye.com/blog/1175084
數(shù)據(jù)庫(kù)事務(wù)的隔離級(jí)別有4個(gè),由低到高依次為Read uncommitted 、Read committed 、Repeatable read 、Serializable ,這四個(gè)級(jí)別可以逐個(gè)解決臟讀 、不可重復(fù)讀 、幻讀 這幾類(lèi)問(wèn)題。
√: 可能出現(xiàn) ×: 不會(huì)出現(xiàn)
| 臟讀 | 不可重復(fù)讀 | 幻讀 |
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable read | × | × | √ |
Serializable | × | × | × |
注意:我們討論隔離級(jí)別的場(chǎng)景,主要是在多個(gè)事務(wù)并發(fā) 的情況下,因此,接下來(lái)的講解都圍繞事務(wù)并發(fā)。
Read uncommitted 讀未提交
公司發(fā)工資了,領(lǐng)導(dǎo)把5000元打到singo的賬號(hào)上,但是該事務(wù)并未提交,而singo正好去查看賬戶(hù),發(fā)現(xiàn)工資已經(jīng)到賬,是5000元整,非常高 興。可是不幸的是,領(lǐng)導(dǎo)發(fā)現(xiàn)發(fā)給singo的工資金額不對(duì),是2000元,于是迅速回滾了事務(wù),修改金額后,將事務(wù)提交,最后singo實(shí)際的工資只有 2000元,singo空歡喜一場(chǎng)。

出現(xiàn)上述情況,即我們所說(shuō)的臟讀 ,兩個(gè)并發(fā)的事務(wù),“事務(wù)A:領(lǐng)導(dǎo)給singo發(fā)工資”、“事務(wù)B:singo查詢(xún)工資賬戶(hù)”,事務(wù)B讀取了事務(wù)A尚未提交的數(shù)據(jù)。
當(dāng)隔離級(jí)別設(shè)置為Read uncommitted 時(shí),就可能出現(xiàn)臟讀,如何避免臟讀,請(qǐng)看下一個(gè)隔離級(jí)別。
Read committed 讀提交
singo拿著工資卡去消費(fèi),系統(tǒng)讀取到卡里確實(shí)有2000元,而此時(shí)她的老婆也正好在網(wǎng)上轉(zhuǎn)賬,把singo工資卡的2000元轉(zhuǎn)到另一賬戶(hù),并在 singo之前提交了事務(wù),當(dāng)singo扣款時(shí),系統(tǒng)檢查到singo的工資卡已經(jīng)沒(méi)有錢(qián),扣款失敗,singo十分納悶,明明卡里有錢(qián),為 何......
出現(xiàn)上述情況,即我們所說(shuō)的不可重復(fù)讀 ,兩個(gè)并發(fā)的事務(wù),“事務(wù)A:singo消費(fèi)”、“事務(wù)B:singo的老婆網(wǎng)上轉(zhuǎn)賬”,事務(wù)A事先讀取了數(shù)據(jù),事務(wù)B緊接了更新了數(shù)據(jù),并提交了事務(wù),而事務(wù)A再次讀取該數(shù)據(jù)時(shí),數(shù)據(jù)已經(jīng)發(fā)生了改變。
當(dāng)隔離級(jí)別設(shè)置為Read committed 時(shí),避免了臟讀,但是可能會(huì)造成不可重復(fù)讀。
大多數(shù)數(shù)據(jù)庫(kù)的默認(rèn)級(jí)別就是Read committed,比如Sql Server , Oracle。如何解決不可重復(fù)讀這一問(wèn)題,請(qǐng)看下一個(gè)隔離級(jí)別。
Repeatable read 重復(fù)讀
當(dāng)隔離級(jí)別設(shè)置為Repeatable read 時(shí),可以避免不可重復(fù)讀。當(dāng)singo拿著工資卡去消費(fèi)時(shí),一旦系統(tǒng)開(kāi)始讀取工資卡信息(即事務(wù)開(kāi)始),singo的老婆就不可能對(duì)該記錄進(jìn)行修改,也就是singo的老婆不能在此時(shí)轉(zhuǎn)賬。
雖然Repeatable read避免了不可重復(fù)讀,但還有可能出現(xiàn)幻讀 。
singo的老婆工作在銀行部門(mén),她時(shí)常通過(guò)銀行內(nèi)部系統(tǒng)查看singo的信用卡消費(fèi)記錄。有一天,她正在查詢(xún)到singo當(dāng)月信用卡的總消費(fèi)金額 (select sum(amount) from transaction where month = 本月)為80元,而singo此時(shí)正好在外面胡吃海塞后在收銀臺(tái)買(mǎi)單,消費(fèi)1000元,即新增了一條1000元的消費(fèi)記錄(insert transaction ... ),并提交了事務(wù),隨后singo的老婆將singo當(dāng)月信用卡消費(fèi)的明細(xì)打印到A4紙上,卻發(fā)現(xiàn)消費(fèi)總額為1080元,singo的老婆很詫異,以為出 現(xiàn)了幻覺(jué),幻讀就這樣產(chǎn)生了。
注:Mysql的默認(rèn)隔離級(jí)別就是Repeatable read。
Serializable 序列化
Serializable 是最高的事務(wù)隔離級(jí)別,同時(shí)代價(jià)也花費(fèi)最高,性能很低,一般很少使用,在該級(jí)別下,事務(wù)順序執(zhí)行,不僅可以避免臟讀、不可重復(fù)讀,還避免了幻像讀。
posted @
2014-06-15 15:15 hellxoul 閱讀(237) |
評(píng)論 (0) |
編輯 收藏
在上一篇文章中提到過(guò),我已經(jīng)不在Google工作了。我還沒(méi)有想清楚應(yīng)該去哪里—有兩三個(gè)非常好的工作機(jī)會(huì)擺在我面前。因?yàn)樵谶@段做決定時(shí)間里,我不再受雇于任何人,我想可以寫(xiě)一些專(zhuān)業(yè)性的東西,一些很有趣,但也會(huì)在同事和管理工作中導(dǎo)致關(guān)系緊張的東西。Google是一個(gè)非常優(yōu)秀的公司。他們做出了很多令人稱(chēng)贊的東西—既是公司外部,人們可以看到的東西,也是公司內(nèi)部。有一些在公司內(nèi)部并不屬于保密的事情,在外部并沒(méi)有給予足夠廣泛的討論。這就是我今天要說(shuō)的。
讓Google的程序如此優(yōu)秀的一個(gè)最重要的事情看起來(lái)是非常的簡(jiǎn)單:代碼審查。并不是只有Google做這個(gè)事情—代碼審查已經(jīng)被廣泛的認(rèn)可為一種非常好的做法,很多人都在這樣做。但我還沒(méi)有看到第二家這樣大的公司能把這種事情運(yùn)用的如此普遍。在Google,沒(méi)有程序,任何產(chǎn)品、任何項(xiàng)目的程序代碼,可以在沒(méi)有經(jīng)過(guò)有效的代碼審查前提交到代碼庫(kù)里的。
所有人都要經(jīng)過(guò)代碼審查。并且很正規(guī)的:這種事情應(yīng)該成為任何重要的軟件開(kāi)發(fā)工作中一個(gè)基本制度。并不單指產(chǎn)品程序——所有東西。它不需要很多的工作,但它的效果是巨大的。
從代碼審查里能得到什么?
很顯然:在代碼提交前,用第二群眼睛檢查一遍,防止bug混入。這是對(duì)其最常見(jiàn)的理解,是對(duì)代碼審查的好處的最廣泛的認(rèn)識(shí)。但是,依我的經(jīng)驗(yàn)來(lái)看,這反倒是它最不重要的一點(diǎn)。人們確實(shí)在代碼審查中找到了bug。可是,這些在代碼審查中能發(fā)現(xiàn)的絕大部分bug,很顯然,都是微不足道的bug,程序的作者花幾分鐘的時(shí)間就能發(fā)現(xiàn)它們。真正需要花時(shí)間去發(fā)現(xiàn)的bug不是在代碼審查里能找到的。
代碼審查的最大的功用是純社會(huì)性的。如果你在編程,而且知道將會(huì)有同事檢查你的代碼,你編程態(tài)度就完全不一樣了。你寫(xiě)出的代碼將更加整潔,有更好的注釋?zhuān)玫某绦蚪Y(jié)構(gòu)——因?yàn)槟?strong style="border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; background: transparent;">知道,那個(gè)你很在意的人將會(huì)查看你的程序。沒(méi)有代碼審查,你知道人們最終還是會(huì)看你的程序。但這種事情不是立即發(fā)生的事,它不會(huì)給你帶來(lái)同等的緊迫感,它不會(huì)給你相同的個(gè)人評(píng)判的那種感受。
還有一個(gè)非常重要的好處。代碼審查能傳播知識(shí)。在很多的開(kāi)發(fā)團(tuán)隊(duì)里,經(jīng)常每一個(gè)人負(fù)責(zé)一個(gè)核心模塊,每個(gè)人都只關(guān)注他自己的那個(gè)模塊。除非是同事的模塊影響了自己的程序,他們從不相互交流。這種情況的后果是,每個(gè)模塊只有一個(gè)人熟悉里面的代碼。如果這個(gè)人休假或——但愿不是——辭職了,其他人則束手無(wú)策。通過(guò)代碼審查,至少會(huì)有兩個(gè)人熟悉這些程序——作者,以及審查者。審查者并不能像程序的作者一樣對(duì)程序十分了解——但他會(huì)熟悉程序的設(shè)計(jì)和架構(gòu),這是極其重要的。
當(dāng)然,沒(méi)有什么事情能簡(jiǎn)單的做下來(lái)的。依我的經(jīng)驗(yàn),在你能正確的進(jìn)行代碼審查前,你需要花時(shí)間鍛煉學(xué)習(xí)。我發(fā)現(xiàn)人們?cè)诖a審查時(shí)經(jīng)常會(huì)犯一些錯(cuò)誤,導(dǎo)致不少麻煩——尤其在一些缺乏經(jīng)驗(yàn)的審查者中經(jīng)常的出現(xiàn),他們給了人們一個(gè)很遭的代碼審查的體驗(yàn),成為了人們接受代碼審查制度的一個(gè)障礙。
最重要的一個(gè)原則:代碼審查用意是在代碼提交前找到其中的問(wèn)題——你要發(fā)現(xiàn)是它的正確。在代碼審查中最常犯的錯(cuò)誤——幾乎每個(gè)新手都會(huì)犯的錯(cuò)誤——是,審查者根據(jù)自己的編程習(xí)慣來(lái)評(píng)判別人的代碼。
對(duì)于一個(gè)問(wèn)題,通常我們能找出十幾種方法去解決。對(duì)于一種解決方案,我們能有百萬(wàn)種編碼方案來(lái)實(shí)現(xiàn)它。作為一個(gè)審查者,你的任務(wù)不是來(lái)確保被審查的代碼都采用的是你的編碼風(fēng)格——因?yàn)樗豢赡芨銓?xiě)的一樣。作為一段代碼的審查者的任務(wù)是確保由作者自己寫(xiě)出的代碼是正確的。一旦這個(gè)原則被打破,你最終將會(huì)倍感折磨,深受挫折——這可不是我們想要的結(jié)果。
問(wèn)題在于,這種錯(cuò)誤是如此的普遍而易犯。如果你是個(gè)程序員,當(dāng)你遇到一個(gè)問(wèn)題,你能想到一種解決方案——你就把你想到的方案作為標(biāo)準(zhǔn)答案。但事情不是這樣的——作為一個(gè)好的審查者,你需要明白這個(gè)道理。
代碼審查的第二個(gè)易犯的毛病是,人們覺(jué)得有壓力,感覺(jué)非要說(shuō)點(diǎn)什么才好。你知道作者用了大量的時(shí)間和精力來(lái)實(shí)現(xiàn)這些程序——不該說(shuō)點(diǎn)什么嗎?
不,你不需要。
只說(shuō)一句“哇,不錯(cuò)呀”,任何時(shí)候都不會(huì)不合適。如果你總是力圖找出一點(diǎn)什么東西來(lái)批評(píng),你這樣做的結(jié)果只會(huì)損害自己的威望。當(dāng)你不厭其煩的找出一些東西來(lái),只是為了說(shuō)些什么,被審查人就會(huì)知道,你說(shuō)這些話(huà)只是為了填補(bǔ)寂靜。你的評(píng)論將不再被人重視。
第三是速度。你不能匆匆忙忙的進(jìn)行一次代碼審查——但你也要能迅速的完成。你的同伴在等你。如果你和你的同事并不想花太多時(shí)間進(jìn)行代碼復(fù)查,你們很快的完成,那被審查者會(huì)覺(jué)得很沮喪,這種代碼審查帶來(lái)的只有失望的感覺(jué)。就好象是打攪了大家,使大家放下手頭的工作來(lái)進(jìn)行審查。事情不該是這樣。你并不需要推掉手頭上的任何事情來(lái)做代碼審查。但如果中途耽誤了幾個(gè)小時(shí),你中間還要休息一會(huì),喝杯茶,沖個(gè)澡,或談會(huì)兒閑話(huà)。當(dāng)你回到審查現(xiàn)場(chǎng),你可以繼續(xù)下去,把事情做完。如果你真是這樣,我想沒(méi)有人愿意在那干等著你。
posted @
2014-06-06 10:04 hellxoul 閱讀(221) |
評(píng)論 (0) |
編輯 收藏
wps只有32位的,因此要安裝wps必須安裝32位的支持庫(kù),按照網(wǎng)上的教程先安裝32位的一些依賴(lài)庫(kù)
因?yàn)橐呀?jīng)安裝了libfreetype,網(wǎng)上也說(shuō)64位的安裝32位的libfreetype 會(huì)有問(wèn)題,同時(shí),自己系統(tǒng)也裝不上32位的libfreetype 總是提示沖突。
沒(méi)辦法強(qiáng)制安裝
sudo dpkg -i --force-all --ignore-depends=libfreetype6:i386 --ignore-depends=libfontconfig1:i386 wps-office_8.1.0.3724~b1p2_i386.deb
搞定
posted @
2014-04-20 21:40 hellxoul 閱讀(1498) |
評(píng)論 (0) |
編輯 收藏