代碼重構思路,代碼重構優化

本文目錄一覽:

Java代碼優化有哪些常用的方法

1、 盡量指定類的final修飾符 帶有final修飾符的類是不可派生的。

在Java核心API中,有許多應用final的例子,例如java.lang.String。為String類指定final防止了人們覆蓋length()方法。另外,如果指定一個類為final,則該類所有的方法都是final。Java編譯器會尋找機會內聯(inline)所有的final方法(這和具體的編譯器實現有關)。此舉能夠使性能平均提高50% 。

2、 盡量重用對象。

特別是String 對象的使用中,出現字元串連接情況時應用StringBuffer 代替。由於系統不僅要花時間生成對象,以後可能還需花時間對這些對象進行垃圾回收和處理。因此,生成過多的對象將會給程序的性能帶來很大的影響。

3、 盡量使用局部變數,調用方法時傳遞的參數以及在調用中創建的臨時變數都保存在棧(Stack)中,速度較快。

其他變數,如靜態變數、實例變數等,都在堆(Heap)中創建,速度較慢。另外,依賴於具體的編譯器/JVM,局部變數還可能得到進一步優化。請參見《儘可能使用堆棧變數》。

4、 不要重複初始化變數

默認情況下,調用類的構造函數時, Java會把變數初始化成確定的值:所有的對象被設置成null,整數變數(byte、short、int、long)設置成0,float和double變數設置成0.0,邏輯值設置成false。當一個類從另一個類派生時,這一點尤其應該注意,因為用new關鍵詞創建一個對象時,構造函數鏈中的所有構造函數都會被自動調用。

5、 在JAVA + ORACLE 的應用系統開發中,java中內嵌的SQL語句盡量使用大寫的形式,以減輕ORACLE解析器的解析負擔。

6、 Java 編程過程中,進行資料庫連接、I/O流操作時務必小心,在使用完畢後,即使關閉以釋放資源。

因為對這些大對象的操作會造成系統大的開銷,稍有不慎,會導致嚴重的後果。

7、 由於JVM的有其自身的GC機制,不需要程序開發者的過多考慮,從一定程度上減輕了開發者負擔,但同時也遺漏了隱患,過分的創建對象會消耗系統的大量內存,嚴重時會導致內存泄露,因此,保證過期對象的及時回收具有重要意義。

JVM回收垃圾的條件是:對象不在被引用;然而,JVM的GC並非十分的機智,即使對象滿足了垃圾回收的條件也不一定會被立即回收。所以,建議我們在對象使用完畢,應手動置成null。

8、 在使用同步機制時,應盡量使用方法同步代替代碼塊同步。

9、 盡量減少對變數的重複計算

例如:for(int i = 0;i list.size; i ++) {

}

應替換為:

for(int i = 0,int len = list.size();i len; i ++){

}

10、盡量採用lazy loading 的策略,即在需要的時候才開始創建。

例如: String str = 「aaa」;

if(i == 1) {

list.add(str);

}

應替換為:

if(i == 1) {

String str = 「aaa」;

list.add(str);

}

11、慎用異常

異常對性能不利。拋出異常首先要創建一個新的對象。Throwable介面的構造函數調用名為fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法檢查堆棧,收集調用跟蹤信息。只要有異常被拋出,VM就必須調整調用堆棧,因為在處理過程中創建了一個新的對象。 異常只能用於錯誤處理,不應該用來控制程序流程。

12、不要在循環中使用:

Try {

} catch() {

}

應把其放置在最外層。

13、StringBuffer 的使用:

StringBuffer表示了可變的、可寫的字元串。

有三個構造方法 :

StringBuffer (); //默認分配16個字元的空間

StringBuffer (int size); //分配size個字元的空間

StringBuffer (String str); //分配16個字元+str.length()個字元空間

你可以通過StringBuffer的構造函數來設定它的初始化容量,這樣可以明顯地提升性能。

這裡提到的構造函數是StringBuffer(int length),length參數表示當前的StringBuffer能保持的字元數量。你也可以使用ensureCapacity(int minimumcapacity)方法在StringBuffer對象創建之後設置它的容量。首先我們看看StringBuffer的預設行為,然後再找出一條更好的提升性能的途徑。

StringBuffer在內部維護一個字元數組,當你使用預設的構造函數來創建StringBuffer對象的時候,因為沒有設置初始化字元長度,StringBuffer的容量被初始化為16個字元,也就是說預設容量就是16個字元。當StringBuffer達到最大容量的時候,它會將自身容量增加到當前的2倍再加2,也就是(2*舊值+2)。如果你使用預設值,初始化之後接著往裡面追加字元,在你追加到第16個字元的時候它會將容量增加到34(2*16+2),當追加到34個字元的時候就會將容量增加到70(2*34+2)。無論何事只要StringBuffer到達它的最大容量它就不得不創建一個新的字元數組然後重新將舊字元和新字元都拷貝一遍――這也太昂貴了點。所以總是給StringBuffer設置一個合理的初始化容量值是錯不了的,這樣會帶來立竿見影的性能增益。StringBuffer初始化過程的調整的作用由此可見一斑。所以,使用一個合適的容量值來初始化StringBuffer永遠都是一個最佳的建議。

14、合理的使用Java類 java.util.Vector。

簡單地說,一個Vector就是一個java.lang.Object實例的數組。Vector與數組相似,它的元素可以通過整數形式的索引訪問。但是,Vector類型的對象在創建之後,對象的大小能夠根據元素的增加或者刪除而擴展、縮小。請考慮下面這個向Vector加入元素的例子:

Object bj = new Object();

Vector v = new Vector(100000);

for(int I=0;

I100000; I++) { v.add(0,obj); }

除非有絕對充足的理由要求每次都把新元素插入到Vector的前面,否則上面的代碼對性能不利。在默認構造函數中,Vector的初始存儲能力是10個元素,如果新元素加入時存儲能力不足,則以後存儲能力每次加倍。Vector類就對象StringBuffer類一樣,每次擴展存儲能力時,所有現有的元素都要複製到新的存儲空間之中。下面的代碼片段要比前面的例子快幾個數量級:

Object bj = new Object();

Vector v = new Vector(100000);

for(int I=0; I100000; I++) { v.add(obj); }

同樣的規則也適用於Vector類的remove()方法。由於Vector中各個元素之間不能含有「空隙」,刪除除最後一個元素之外的任意其他元素都導致被刪除元素之後的元素向前移動。也就是說,從Vector刪除最後一個元素要比刪除第一個元素「開銷」低好幾倍。

假設要從前面的Vector刪除所有元素,我們可以使用這種代碼:

for(int I=0; I100000; I++)

{

v.remove(0);

}

但是,與下面的代碼相比,前面的代碼要慢幾個數量級:

for(int I=0; I100000; I++)

{

v.remove(v.size()-1);

}

從Vector類型的對象v刪除所有元素的最好方法是:

v.removeAllElements();

假設Vector類型的對象v包含字元串「Hello」。考慮下面的代碼,它要從這個Vector中刪除「Hello」字元串:

String s = “Hello”;

int i = v.indexOf(s);

if(I != -1) v.remove(s);

這些代碼看起來沒什麼錯誤,但它同樣對性能不利。在這段代碼中,indexOf()方法對v進行順序搜索尋找字元串「Hello」,remove(s)方法也要進行同樣的順序搜索。改進之後的版本是:

String s = “Hello”;

int i = v.indexOf(s);

if(I != -1) v.remove(i);

這個版本中我們直接在remove()方法中給出待刪除元素的精確索引位置,從而避免了第二次搜索。一個更好的版本是:

String s = “Hello”; v.remove(s);

最後,我們再來看一個有關Vector類的代碼片段:

for(int I=0; I++;I v.length)

如果v包含100,000個元素,這個代碼片段將調用v.size()方法100,000次。雖然size方法是一個簡單的方法,但它仍舊需要一次方法調用的開銷,至少JVM需要為它配置以及清除堆棧環境。在這裡,for循環內部的代碼不會以任何方式修改Vector類型對象v的大小,因此上面的代碼最好改寫成下面這種形式:

int size = v.size(); for(int I=0; I++;Isize)

雖然這是一個簡單的改動,但它仍舊贏得了性能。畢竟,每一個CPU周期都是寶貴的。

15、當複製大量數據時,使用System.arraycopy()命令。

int[] src={1,3,5,6,7,8};

int[] dest = new int[6];

System.arraycopy(src, 0, dest, 0, 6);

src:源數組; srcPos:源數組要複製的起始位置;

dest:目的數組; destPos:目的數組放置的起始位置;

length:複製的長度.

注意:src and dest都必須是同類型或者可以進行轉換類型的數組.

16、代碼重構:增強代碼的可讀性。

public class ShopCart {

private List carts ;

public void add (Object item) {

if(carts == null) {

carts = new ArrayList();

}

crts.add(item);

}

public void remove(Object item) {

if(carts. contains(item)) {

carts.remove(item);

}

}

public List getCarts() {

//返回只讀列表

return Collections.unmodifiableList(carts);

}

//不推薦這種方式

//this.getCarts().add(item);

}

17、不用new關鍵詞創建類的實例

用new關鍵詞創建類的實例時,構造函數鏈中的所有構造函數都會被自動調用。但如果一個對象實現了Cloneable介面,我們可以調用它的clone()方法。clone()方法不會調用任何類構造函數。

在使用設計模式(Design Pattern)的場合,如果用Factory模式創建對象,則改用clone()方法創建新的對象實例非常簡單。例如,下面是Factory模式的一個典型實現:

public static Credit getNewCredit() {

return new Credit();

}

改進後的代碼使用clone()方法,如下所示:

private static Credit BaseCredit = new Credit();

public static Credit getNewCredit() {

return (Credit) BaseCredit.clone();

}

上面的思路對於數組處理同樣很有用。

18、乘法和除法

考慮下面的代碼:

for (val = 0; val 100000; val +=5) {

alterX = val * 8; myResult = val * 2;

}

用移位操作替代乘法操作可以極大地提高性能。下面是修改後的代碼:

for (val = 0; val 100000; val += 5) {

alterX = val 3; myResult = val 1;

}

修改後的代碼不再做乘以8的操作,而是改用等價的左移3位操作,每左移1位相當於乘以2。相應地,右移1位操作相當於除以2。值得一提的是,雖然移位操作速度快,但可能使代碼比較難於理解,所以最好加上一些注釋。

19、在JSP頁面中關閉無用的會話。

一個常見的誤解是以為session在有客戶端訪問時就被創建,然而事實是直到某server端程序調用HttpServletRequest.getSession(true)這樣的語句時才被創建,注意如果JSP沒有顯示的使用 關閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的session對象的來歷。由於session會消耗內存資源,因此,如果不打算使用session,應該在所有的JSP中關閉它。

對於那些無需跟蹤會話狀態的頁面,關閉自動創建的會話可以節省一些資源。使用如下page指令:%@ page session=”false”%

20、JDBC與I/O

如果應用程序需要訪問一個規模很大的數據集,則應當考慮使用塊提取方式。默認情況下,JDBC每次提取32行數據。舉例來說,假設我們要遍歷一個5000行的記錄集,JDBC必須調用資料庫157次才能提取到全部數據。如果把塊大小改成512,則調用資料庫的次數將減少到10次。

21、Servlet與內存使用

許多開發者隨意地把大量信息保存到用戶會話之中。一些時候,保存在會話中的對象沒有及時地被垃圾回收機制回收。從性能上看,典型的癥狀是用戶感到系統周期性地變慢,卻又不能把原因歸於任何一個具體的組件。如果監視JVM的堆空間,它的表現是內存佔用不正常地大起大落。

解決這類內存問題主要有二種辦法。第一種辦法是,在所有作用範圍為會話的Bean中實現HttpSessionBindingListener介面。這樣,只要實現valueUnbound()方法,就可以顯式地釋放Bean使用的資源。

另外一種辦法就是儘快地把會話作廢。大多數應用伺服器都有設置會話作廢間隔時間的選項。另外,也可以用編程的方式調用會話的setMaxInactiveInterval()方法,該方法用來設定在作廢會話之前,Servlet容器允許的客戶請求的最大間隔時間,以秒計。

22、使用緩衝標記

一些應用伺服器加入了面向JSP的緩衝標記功能。例如,BEA的WebLogic Server從6.0版本開始支持這個功能,Open Symphony工程也同樣支持這個功能。JSP緩衝標記既能夠緩衝頁面片斷,也能夠緩衝整個頁面。當JSP頁面執行時,如果目標片斷已經在緩衝之中,則生成該片斷的代碼就不用再執行。頁面級緩衝捕獲對指定URL的請求,並緩衝整個結果頁面。對於購物籃、目錄以及門戶網站的主頁來說,這個功能極其有用。對於這類應用,頁面級緩衝能夠保存頁面執行的結果,供後繼請求使用。

23、選擇合適的引用機制

在典型的JSP應用系統中,頁頭、頁腳部分往往被抽取出來,然後根據需要引入頁頭、頁腳。當前,在JSP頁面中引入外部資源的方法主要有兩種:include指令,以及include動作。

include指令:例如%@ include file=”copyright.html” %。該指令在編譯時引入指定的資源。在編譯之前,帶有include指令的頁面和指定的資源被合併成一個文件。被引用的外部資源在編譯時就確定,比運行時才確定資源更高效。

include動作:例如jsp:include page=”copyright.jsp” /。該動作引入指定頁面執行後生成的結果。由於它在運行時完成,因此對輸出結果的控制更加靈活。但時,只有當被引用的內容頻繁地改變時,或者在對主頁面的請求沒有出現之前,被引用的頁面無法確定時,使用include動作才合算。

24、及時清除不再需要的會話

為了清除不再活動的會話,許多應用伺服器都有默認的會話超時時間,一般為30分鐘。當應用伺服器需要保存更多會話時,如果內存容量不足,操作系統會把部分內存數據轉移到磁碟,應用伺服器也可能根據「最近最頻繁使用」(Most Recently Used)演算法把部分不活躍的會話轉儲到磁碟,甚至可能拋出「內存不足」異常。在大規模系統中,串列化會話的代價是很昂貴的。當會話不再需要時,應當及時調用HttpSession.invalidate()方法清除會話。HttpSession.invalidate()方法通常可以在應用的退出頁面調用。

25、不要將數組聲明為:public static final 。

26、HashMap的遍歷效率討論

經常遇到對HashMap中的key和value值對的遍歷操作,有如下兩種方法:

MapString, String[] paraMap = new HashMapString, String[]();

//第一個循環

SetString appFieldDefIds = paraMap.keySet();

for (String appFieldDefId : appFieldDefIds) {

String[] values = paraMap.get(appFieldDefId);

……

}

//第二個循環

for(EntryString, String[] entry : paraMap.entrySet()){

String appFieldDefId = entry.getKey();

String[] values = entry.getValue();

…….

}

第一種實現明顯的效率不如第二種實現。

分析如下 SetString appFieldDefIds = paraMap.keySet(); 是先從HashMap中取得keySet

代碼如下:

public SetK keySet() {

SetK ks = keySet;

return (ks != null ? ks : (keySet = new KeySet()));

}

private class KeySet extends AbstractSetK {

public IteratorK iterator() {

return newKeyIterator();

}

public int size() {

return size;

}

public boolean contains(Object o) {

return containsKey(o);

}

public boolean remove(Object o) {

return HashMap.this.removeEntryForKey(o) != null;

}

public void clear() {

HashMap.this.clear();

}

}

其實就是返回一個私有類KeySet, 它是從AbstractSet繼承而來,實現了Set介面。

再來看看for/in循環的語法

for(declaration : expression)

statement

在執行階段被翻譯成如下各式

for(IteratorE #i = (expression).iterator(); #i.hashNext();){

declaration = #i.next();

statement

}

因此在第一個for語句for (String appFieldDefId : appFieldDefIds) 中調用了HashMap.keySet().iterator()

而這個方法調用了newKeyIterator()

IteratorK newKeyIterator() {

return new KeyIterator();

}

private class KeyIterator extends HashIteratorK {

public K next() {

return nextEntry().getKey();

}

}

所以在for中還是調用了

在第二個循環for(EntryString, String[] entry : paraMap.entrySet())中使用的Iterator是如下的一個內部

private class EntryIterator extends HashIteratorMap.EntryK,V {

public Map.EntryK,V next() {

return nextEntry();

}

}

此時第一個循環得到key,第二個循環得到HashMap的Entry效率就是從循環裡面體現出來的第二個循環此致可以直接取key和value值而第一個循環還是得再利用HashMap的get(Object key)來取value值現在看看HashMap的get(Object key)方法

public V get(Object key) {

Object k = maskNull(key);

int hash = hash(k);

int i = indexFor(hash, table.length); //Entry[] table

EntryK,V e = table;

while (true) {

if (e == null)

return null;

if (e.hash == hash eq(k, e.key))

return e.value;

e = e.next;

}

}

其實就是再次利用Hash值取出相應的Entry做比較得到結果,所以使用第一中循環相當於兩次進入HashMap的Entry

中而第二個循環取得Entry的值之後直接取key和value,效率比第一個循環高。其實按照Map的概念來看也應該是用第二個循環好一點,它本來就是key和value的值對,將key和value分開操作在這裡不是個好選擇。

27、array(數組) 和 ArryList的使用

array([]):最高效;但是其容量固定且無法動態改變;

ArrayList:容量可動態增長;但犧牲效率;

基於效率和類型檢驗,應儘可能使用array,無法確定數組大小時才使用ArrayList!

ArrayList是Array的複雜版本

ArrayList內部封裝了一個Object類型的數組,從一般的意義來說,它和數組沒有本質的差別,甚至於ArrayList的許多方法,如Index、IndexOf、Contains、Sort等都是在內部數組的基礎上直接調用Array的對應方法。

ArrayList存入對象時,拋棄類型信息,所有對象屏蔽為Object,編譯時不檢查類型,但是運行時會報錯。

註:jdk5中加入了對泛型的支持,已經可以在使用ArrayList時進行類型檢查。

從這一點上看來,ArrayList與數組的區別主要就是由於動態增容的效率問題了

28、盡量使用HashMap 和ArrayList ,除非必要,否則不推薦使用HashTable和Vector ,後者由於使用同步機制,而導致了性能的開銷。

29、StringBuffer 和StringBuilder的區別:

java.lang.StringBuffer線程安全的可變字元序列。一個類似於 String 的字元串緩衝區,但不能修改。

StringBuilder。與該類相比,通常應該優先使用 java.lang.StringBuilder類,因為它支持所有相同的操作,但由於它不執行同步,所以速度更快。為了獲得更好的性能,在構造 StirngBuffer 或 StirngBuilder 時應儘可能指定它的容量。當然,如果你操作的字元串長度不超過 16 個字元就不用了。 相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%-15% 左右的性能提升,但卻要冒多線程不安全的風險。而在現實的模塊化編程中,負責某一模塊的程序員不一定能清晰地判斷該模塊是否會放入多線程的環境中運行,因此:除非你能確定你的系統的瓶頸是在 StringBuffer 上,並且確定你的模塊不會運行在多線程模式下,否則還是用 StringBuffer 吧。

30、盡量避免使用split

除非是必須的,否則應該避免使用split,split由於支持正則表達式,所以效率比較低,如果是頻繁的幾十,幾百萬的調用將會耗費大量資源,如果確實需要頻繁的調用split,可以考慮使用apache的 StringUtils.split(string,char),頻繁split的可以緩存結果。

其他補充:

1、及時清除不再使用的對象,設為null

2、儘可能使用final,static等關鍵字

3、儘可能使用buffered對象

如何優化代碼使JAVA源文件及編譯後CLASS文件更小

1 盡量使用繼承,繼承的方法越多,你要寫的代碼量也就越少

2 打開JAVA編譯器的優化選項: javac -O 這個選項將刪除掉CLASS文件中的行號,並能把

一些private, static,final的小段方法申明為inline方法調用

3 把公用的代碼提取出來

4 不要初始化很大的數組,儘管初始化一個數組在JAVA代碼中只是一行的代碼量,但

編譯後的代碼是一行代碼插入一個數組的元素,所以如果你有大量的數據需要存在數組

中的話,可以先把這些數據放在String中,然後在運行期把字元串解析到數組中

5 日期類型的對象會佔用很大的空間,如果你要存儲大量的日期對象,可以考慮把它存儲為

long型,然後在使用的時候轉換為Date類型

6 類名,方法名和變數名盡量使用簡短的名字,可以考慮使用Hashjava, Jobe, Obfuscate and Jshrink等工具自動完成這個工作

7 將static final類型的變數定義到Interface中去

8 算術運算 能用左移/右移的運算就不要用*和/運算,相同的運算不要運算多次

2. 不要兩次初始化變數

Java通過調用獨特的類構造器默認地初始化變數為一個已知的值。所有的對象被設置成null,integers (byte, short, int, long)被設置成0,float和double設置成0.0,Boolean變數設置成false。這對那些擴展自其它類的類尤其重要,這跟使用一個新的關鍵詞創建一個對象時所有一連串的構造器被自動調用一樣。

3. 在任何可能的地方讓類為Final

標記為final的類不能被擴展。在《核心Java API》中有大量這個技術的例子,諸如java.lang.String。將String類標記為final阻止了開發者創建他們自己實現的長度方法。

更深入點說,如果類是final的,所有類的方法也是final的。Java編譯器可能會內聯所有的方法(這依賴於編譯器的實現)。在我的測試里,我已經看到性能平均增加了50%。

9. 異常在需要拋出的地方拋出,try catch能整合就整合

try {

some.method1(); // Difficult for javac

} catch( method1Exception e ) { // and the JVM runtime

// Handle exception 1 // to optimize this

} // code

try {

some.method2();

} catch( method2Exception e ) {

// Handle exception 2

}

try {

some.method3();

} catch( method3Exception e ) {

// Handle exception 3

}

已下代碼 更容易被編譯器優化

try {

some.method1(); // Easier to optimize

some.method2();

some.method3();

} catch( method1Exception e ) {

// Handle exception 1

} catch( method2Exception e ) {

// Handle exception 2

} catch( method3Exception e ) {

// Handle exception 3

}

10. For循環的優化

Replace…

for( int i = 0; i collection.size(); i++ ) {

}

with…

for( int i = 0, n = collection.size(); i n; i++ ) {

}

5、 在JAVA + ORACLE 的應用系統開發中,java中內嵌的SQL語句盡量使用大寫的形式,以減輕ORACLE解析器的解析負擔。

10、盡量採用lazy loading 的策略,即在需要的時候才開始創建。

例如: String str = 「aaa」;

if(i == 1) {

list.add(str);

}

應替換為:

if(i == 1) {

String str = 「aaa」;

list.add(str);

}

12、不要在循環中使用:

Try {

} catch() {

}

應把其放置在最外層

java 代碼重用 真么體現的? 重構和重用是一個意識嗎?

重構可以說是覆蓋,用覆蓋一詞來講就比較清楚。

在面向對象的一個特性–繼承中就表現出重構的意思。

重構,就是繼承於父類方法的子類將子類的方法重寫,方法名及參數完全相同.

重用是繼承了就可以用父類定義的方法和變數,不用再定義一次。

比如說

class B {

public void see(){

System.out.println(“this is b”);

}

}

public class A extends B{

public void see() {

System.out.println(“this is a”);

}

public static void main(String[] args) {

B b=new A();

b.see();

}

}

這是重構的意思。

class B {

public void see(){

System.out.println(“this is b”);

}

}

public class A extends B{

public static void main(String[] args) {

B b=new A();

b.see();

}

}

這是重用的意思

編程好的思路。

我認為編程,重要的不是如何華麗的代碼,而是能夠將用戶需求轉化為機器語言的能力

你的很多思想,是剛開始做程序員的普遍想法,開始思考通過模塊化設計能夠更省力,更快捷的完成工作,程序運行效率還要高。

如果你在大軟體公司工作過,就不會有這種困惑了。因為對於具有一定規模的軟體公司,已經在相當的時間內積累起很豐富的模塊和庫資源,程序員們只需要根據項目的不同象選擇自助餐一樣給拼接到一起,就有了基本框架。

最重要的還是做好用戶需求到需求說明,再到系統框架設計這個工作,會少走很多彎路。

細化到編寫程序,我覺得很重要的一點就是要求公司裡面的程序員要有絕對規範的編程習慣,不然在團隊協作的時候會出很多問題,做出來的基礎庫也經不起時間的考驗。

還有就是你說的模塊化的東西不是萬能的,和你經常從事的項目領域密切相關,你用著很順手,別人可能用不了。比如你是做信息系統的,那麼一個好的查詢分析模塊很多地方都能用,用戶信息管理就要根據複雜程度做幾套,比如能夠定期更換密碼的,比如許可權是要細化到列的,比如只是一個簡單的用戶密碼。根據項目的不同選用。

有些人鼓吹自動化編程,利用商業化的系統模板進行配置。我認為對於企業應用還是可以的,但是對於軟體開發就不可取了。因為提供模板的單位水平如何你並不知道,裡面是否存在大量bug你也不清楚,只是演示做的漂亮。一旦你用了這個東西,在你的項目中出現問題,你debug是查不到具體原因的,苦果只能自己吃,這是個建議,有點離題,但是怕你思路到了一定程度就推崇這種方法。

最後一點,大部分的項目都是需要資料庫作為後台支持的,一定要注意處理好資料庫設計的問題,不然很容易因為庫設計的不合理造成程序複雜,或者是在使用一段時間後效率嚴重降低,造成程序重新返工,就說這麼多,希望你能有所收穫

如何重構代碼

先從接觸過的幾個老項目經歷來談談,對於老項目來說,大家在初步接觸的過程中,大多總是抱著抵觸的情緒,甚至有些是蔑視。總喜歡對以前的代碼挑出一大堆的問題,接著就開始抱怨代碼、抱怨以前的開發人員,經過一段時間鬱悶的抱怨階段後,處於職業的責任心,就很想去改變這一切,希望把自己認為好的方式給帶進來,於是接下來的工作就是重構代碼了。 這也許大多數開發人員都經歷過,這種經歷是辛酸的(因為重構工作雖然重要,但是得不到過多的認可,目前國內關注的是可用性,對於代碼質量並沒有得到應有的重視),也是甜蜜的(風雨之後總會有彩虹)。對於年輕的開發人員來說,見到彩虹的過程是痛苦、漫長地。他們都是在失敗中成長,這些失敗除了經驗外,主要是由於太急功儘力了,盲目的重構! 盲目主要體現在: 1、在還沒有對系統整體架構有個清晰認識的時候,就想用自認為新的技術或架構來替換。 2、根本不分析現有系統架構或程序存在的弊端,只是一味地談設計模式,以設計模式中固有的一套來重構(在重構中,它只作為一個參考,而不是一個依據。) 3、重構比較隨性,每個版本的開發都跳出架構之外隨意帶入新的設計思想 這種盲目重構後給系統會帶來更多問題: 你會發現當你重構完後你的系統運行效率變低了, 系統中同時存在多種思想,新加入人員更難接手, 由於你沒有完全了解系統,反而在你的重構當中帶來了很多重複代碼, 最悲劇的是你重構後的代碼也被其他人當成垃圾,而進行重構。 那麼我們怎麼消除盲目呢!? 首先,了解目前項目是否存在問題,存在什麼問題,這些問題是否能通過重構來解決,如果能,才進行重構,你的重構時間是需要公司給的,老闆不會因為你說依賴性強偶合性低就同意的,你必須要通過問題來讓他認識,關鍵的是只有通過問題才能得到重構時間和資源,並且你的工作才能得到認可,這是一個很現實的情況。 接下來,你要確定重構的對象,是針對架構還是局部代碼,並且去設定一個理想的目標(為什麼是理想的?因為我們不可能一步到位,理想和現實是有差距的,但是我們要做的是儘力去往理想上靠攏)。 如果是針對架構進行重構,那麼這可不是一件輕鬆的事情,再真正開始之前需要做到以下幾點: 1、全面的了解系統的過去,包括以前的架構/技術背景、業務需求 2、分析以前架構的問題,例如:可維護性低、在哪個方面已經不滿足現有需求等等 3、查看至少80%的核心代碼,最好有一定時間的真實在以前代碼基礎上編碼的經歷 做到上面幾點就是為了保證你能有一個清晰的認識,做到知己知彼。接下來可以進入實質階段了嗎?不行,還少了一個很重要的東西,重構計劃! 這種大範圍的重構,在真實情況下,一般老闆給予的時間和重構真正所需用的時間相差很大,所以重構的工作是需要往後延遲的,那麼就會出現又要重構又要進行新需求的開發;還有這項工作不是一個人的事情,是一個團對,既然涉及到多人合作,除了共同的目標外,還需要有一定的評審機制,這是為了保證重構的方向一致,等等,在這些因素下要做好重構,就是需要重構計劃的理由。 針對局部代碼進行重構來說,也許會簡單的許多,不過需要注意的地方是,你一定要符合現有架構的思想,在它的範圍之內去思考。 其實這種方式的重構大多就是提取方法,或者是以真實業務流程的思路去重構現有的代碼執行流程,以便易於理解,或者是降低程序之間的依賴性。要做到這些有個很重要的思維方式: 1、善於從某個事物中分析出什麼是事物的本質和什麼是事物的外部環境。 2、從很多不同事物中去發現共同點,並對這些共同點進行抽象化(舉個簡單的例子:對於寶馬和奧迪,你應該把他們抽象化為汽車)。 為什麼這樣說,因為這些能帶來重構代碼所需要的: 1、在寫代碼過程中降低了依賴性, 2、抽象化的事物復用性更強 做好上述的所有就表示重構完成了嗎!不可能,這只是一個好的開始而已,我們要做到持續重構,就像敏捷中提到的。 也許有的人認為不現實,因為項目經理不會在每個版本周期內給出這個時間,其實,我就納悶了,為什麼不給?!不給的原因一定在你,如果你期望是一周或者更久,那麼誰都不會同意,一周的時間都基本都能做完一個版本的設計了,重構還需要這麼久,如果真的需要就說明你前期的設計很差!我所希望的時間是兩天左右,因為這隻局限於很小範圍內的變動。 如果你們很好的做這些,那麼你的項目可維護性一定很好,並且加入你的項目會是一件愉快的事情,這並不是什麼理想的事情,只要你持之以恆地去做,實現起來其實很簡單。 架構重構:1、重構計劃代碼重構:2、提取獲取交集的演算法3、簡單、靈活地實現對象複製

單片機、OpenGL、matlab、C++、VB、java、Delphi、CPLD等編程思路編程好的思路。

複製、粘貼這麼強的功能你竟然沒寫。多閱讀別人的代碼,把一些你不知道的功能的代碼或演算法,給複製、粘貼過來,保存好;然後也可以按照你的12條整理成庫,也可以整理成「類」。

不過你這12條對我也很有幫助;

你這裡除了第5條外其它的都是自己干,要麼自己寫,要麼自己整理。沒想過參考別人的?我們程序員不是代碼工人。像一些無腦的,或者很好理解的代碼,簡單的。讓別人去想就好了。我們用現成的。

關於這段C#代碼有人有好的重構的思路嗎?

題主, 咱們一句一句看,從第一句開始 你這個代碼不能這樣寫,會導致邏輯隱患,

!(transitSpanTypeList.Contains(“1”) stopTransferTotelMins = 0 stopTransferTotelMins 240)

這一句 你前面加了個! , !的意思是非

如果我transitSpanTypeList.Contains(“1”) stopTransferTotelMins 為 241

也是 滿足第一個條件,並且後面兩個條件也都滿足,因為你在前面加了個非

這個非表示不和條件一致時 執行,

就拿第三個條件來說

transitSpanTypeList.Contains(“3”) stopTransferTotelMins在480和720之間

但是你前面加了個非

那麼我transitSpanTypeList.Contains(“1”) stopTransferTotelMins 為 241 其實在邏輯上也是滿足你第三個條件的,不信的話 你把屬性值設置死,然後調試一下試試,

本人建議你先把邏輯修改一下,然後再去寫這個邏輯語句

如不太明白,建議反覆閱讀,

謝謝, 望採納。

原創文章,作者:CQSA,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/134694.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
CQSA的頭像CQSA
上一篇 2024-10-04 00:07
下一篇 2024-10-04 00:07

相關推薦

  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • Python字元串寬度不限制怎麼打代碼

    本文將為大家詳細介紹Python字元串寬度不限制時如何打代碼的幾個方面。 一、保持代碼風格的統一 在Python字元串寬度不限制的情況下,我們可以寫出很長很長的一行代碼。但是,為了…

    編程 2025-04-29
  • Python基礎代碼用法介紹

    本文將從多個方面對Python基礎代碼進行解析和詳細闡述,力求讓讀者深刻理解Python基礎代碼。通過本文的學習,相信大家對Python的學習和應用會更加輕鬆和高效。 一、變數和數…

    編程 2025-04-29
  • Python滿天星代碼:讓編程變得更加簡單

    本文將從多個方面詳細闡述Python滿天星代碼,為大家介紹它的優點以及如何在編程中使用。無論是剛剛接觸編程還是資深程序員,都能從中獲得一定的收穫。 一、簡介 Python滿天星代碼…

    編程 2025-04-29
  • 倉庫管理系統代碼設計Python

    這篇文章將詳細探討如何設計一個基於Python的倉庫管理系統。 一、基本需求 在著手設計之前,我們首先需要確定倉庫管理系統的基本需求。 我們可以將需求分為以下幾個方面: 1、庫存管…

    編程 2025-04-29
  • 寫代碼新手教程

    本文將從語言選擇、學習方法、編碼規範以及常見問題解答等多個方面,為編程新手提供實用、簡明的教程。 一、語言選擇 作為編程新手,選擇一門編程語言是很關鍵的一步。以下是幾個有代表性的編…

    編程 2025-04-29
  • Python實現簡易心形代碼

    在這個文章中,我們將會介紹如何用Python語言編寫一個非常簡單的代碼來生成一個心形圖案。我們將會從安裝Python開始介紹,逐步深入了解如何實現這一任務。 一、安裝Python …

    編程 2025-04-29
  • 怎麼寫不影響Python運行的長段代碼

    在Python編程的過程中,我們不可避免地需要編寫一些長段代碼,包括函數、類、複雜的控制語句等等。在編寫這些代碼時,我們需要考慮代碼可讀性、易用性以及對Python運行性能的影響。…

    編程 2025-04-29
  • Python愛心代碼動態

    本文將從多個方面詳細闡述Python愛心代碼動態,包括實現基本原理、應用場景、代碼示例等。 一、實現基本原理 Python愛心代碼動態使用turtle模塊實現。在繪製一個心形的基礎…

    編程 2025-04-29
  • 北化教務管理系統介紹及開發代碼示例

    本文將從多個方面對北化教務管理系統進行介紹及開發代碼示例,幫助開發者更好地理解和應用該系統。 一、項目介紹 北化教務管理系統是一款針對高校學生和教職工的綜合信息管理系統。系統實現的…

    編程 2025-04-29

發表回復

登錄後才能評論