国产精品免费无遮挡无码永久视频-国产高潮视频在线观看-精品久久国产字幕高潮-国产精品99精品无码视亚

優秀代碼的格式準則

發布時間:2016-9-21 13:45    發布者:designapp
關鍵詞: 代碼
  這篇文章將與大家一起聊一聊,書寫代碼過程中一些良好的格式規范。
  一、引言
  以下引言的內容,有必要伴隨這個系列的每一次更新,這次也不例外。
  《代碼整潔之道》這本書提出了一個觀點:代碼質量與其整潔度成正比,干凈的代碼,既在質量上可靠,也為后期維護、升級奠定了良好基礎。書中介紹的規則均來自作者多年的實踐經驗,涵蓋從命名到重構的多個編程方面,雖為一“家”之言,然誠有可資借鑒的價值。
  但我們知道,很多時候,理想很豐滿,現實很骨感,也知道人在江湖,身不由己。因為項目的緊迫性,需求的多樣性,我們無法時時刻刻都寫出整潔的代碼,保持自己輸出的都是高質量、優雅的代碼。
  但若我們理解了代碼整潔之道的精髓,我們會知道怎樣讓自己的代碼更加優雅、整潔、易讀、易擴展,知道真正整潔的代碼應該是怎么樣的,也許就會漸漸養成持續輸出整潔代碼的習慣。
  而且或許你會發現,若你一直保持輸出整潔代碼的習慣,長期來看,會讓你的整體效率和代碼質量大大提升。
  二、本文涉及知識點思維導圖
  國際慣例,先放出這篇文章所涉及內容知識點的一張思維導圖,就開始正文。大家若是疲于閱讀文章正文,直接看這張圖,也是可以Get到本文的主要知識點的大概。
  


  三、優秀代碼的書寫格式準則
  1 像報紙一樣一目了然
  想想那些閱讀量巨大的報紙文章。你從上到下閱讀。在頂部,你希望有個頭條,告訴你故事主題,好讓你決定是否要讀下去。第一段是整個故事的大綱,給出粗線條概述,但隱藏了故事細節。接著讀下去,細節漸次增加,直至你了解所有的日期、名字、引語、說話及其他細節。
  優秀的源文件也要像報紙文章一樣。名稱應當簡單并且一目了然,名稱本身應該足夠告訴我們是否在正確的模塊中。源文件最頂部應該給出高層次概念和算法。細節應該往下漸次展開,直至找到源文件中最底層的函數和細節。
  2 恰如其分的注釋
  帶有少量注釋的整潔而有力的代碼,比帶有大量注釋的零碎而復雜的代碼更加優秀。
  我們知道,注釋是為代碼服務的,注釋的存在大多數原因是為了代碼更加易讀,但注釋并不能美化糟糕的代碼。
  另外,注意一點。注釋存在的時間越久,就會離其所描述的代碼的意義越遠,越來越變得全然錯誤,因為大多數程序員們不能堅持(或者因為忘了)去維護注釋。
  當然,教學性質的代碼,多半是注釋越詳細越好。
  3 合適的單文件行數
  盡可能用幾百行以內的單文件來構造出出色的系統,因為短文件通常比長文件更易于理解。當然,和之前的一些準則一樣,只是提供大方向,并非不可違背。
  例如,《代碼整潔之道》第五章中提到的FitNess系統,就是由大多數為200行、最長500行的單個文件來構造出總長約5萬行的出色系統。
  4 合理地利用空白行
  古詩中有留白,代碼的書寫中也要有適當的留白,也就是空白行。
  在每個命名空間、類、函數之間,都需用空白行隔開(應該大家在學編程之初,就早有遵守)。這條極其簡單的規則極大地影響到了代碼的視覺外觀。每個空白行都是一條線索,標識出新的獨立概念。
  其實,在往下讀代碼時,你會發現你的目光總停留于空白行之后的那一行。用空白行隔開每個命名空間、類、函數,代碼的可讀性會大大提升。
  5 讓緊密相關的代碼相互靠近
  如果說空白行隔開了概念,那么靠近的代碼行則暗示了他們之間的緊密聯系。所以,緊密相關的代碼應該相互靠近。
  舉個反例(代碼段1):
  [csharp] view plain copy print?
  public class ReporterConfig
  {
  /**
  * The class name of the reporter listener
  */
  private String m_className;
  /**
  * The properties of the reporter listener
  */
  private List
m_properties = new ArrayList
();

  public void addProperty(Property property)
  {
  m_properties.add(property);
  }
  }
  再看個正面示例(代碼段2):
  [cpp] view plain copy print?
  public class ReporterConfig
  {
  private String m_className;
  private List
m_properties = new ArrayList
();

  public void addProperty(Property property)
  {
  m_properties.add(property);
  }
  }
  以上這段正面示例(代碼段2)比反例(代碼段1)中的代碼好太多,它正好一覽無遺,一眼就能看這個是有兩個變量和一個方法的類。而再看看反例,注釋簡直畫蛇添足,隔斷了兩個實體變量間的聯系,我們不得不移動頭部和眼球,才能獲得相同的理解度。
  6 基于關聯的代碼分布
  關系密切的概念應該相互靠近。對于那些關系密切、放置于同一源文件中的概念,他們之間的區隔應該成為對相互的易懂度有多重要的衡量標準。應該避免迫使讀者在源文件和類中跳來跳去。變量的聲明應盡可能靠近其使用位置。
  對于大多數短函數,函數中的本地變量應當在函數的頂部出現。例如如下代碼中的is變量的聲明:
  [cpp] view plain copy print?
  private static void readPreferences()
  {
  InputStream is= null;
  try
  {
  is= new FileInputStream(getPreferencesFile());
  setPreferences(new Properties(getPreferences()));
  getPreferences().load(is);
  }
  catch (IOException e)
  {
  DoSomeThing();
  }
  }
  而循環中的控制變量應該總在循環語句中聲明,例如如下代碼中each變量的聲明:
  [cpp] view plain copy print?
  public int countTestCases()
  {
  int count = 0;
  for (Test each : tests)
  count += each.countTestCases();
  return count;
  }
  在某些較長的函數中,變量也可能在某代碼塊的頂部,或在循環之前聲明。例如如下代碼中tr變量的聲明:
  [cpp] view plain copy print?
  ...
  for (XmlTest test : m_suite.getTests())
  {
  TestRunner tr = m_runnerFactory.newTestRunner(this, test);
  tr.addListener(m_textReporter);
  m_testRunners.add(tr);
  invoker = tr.getInvoker();
  for (ITestNGMethod m : tr.getBeforeSuiteMethods())
  {
  beforeSuiteMethods.put(m.getMethod(), m);
  }
  for (ITestNGMethod m : tr.getAfterSuiteMethods())
  {
  afterSuiteMethods.put(m.getMethod(), m);
  }
  }
  ...
  另外,實體變量應當在類的頂部聲明(也有一些流派喜歡將實體變量放到類的底部)。
  若某個函數調用了另一個,就應該把它們放到一起,而且調用者應該盡量放到被調用者上面。這樣,程序就有自然的順序。若堅定地遵守這條約定,讀者將能夠確信函數聲明總會在其調用后很快出現。
  概念相關的代碼應該放到一起。相關性越強,則彼此之間的距離就該越短。
  這一節的要點整理一下,大致就是:
  變量的聲明應盡可能靠近其使用位置。
  循環中的控制變量應該在循環語句中聲明。
  短函數中的本地變量應當在函數的頂部聲明。
  而對于某些長函數,變量也可以在某代碼塊的頂部,或在循環之前聲明。
  實體變量應當在類的頂部聲明。
  若某個函數調用了另一個,就應該把它們放到一起,而且調用者應該盡量放到被調用者上面。
  概念相關的代碼應該放到一起。相關性越強,則彼此之間的距離就該越短。
  7 團隊遵從同一套代碼規范
  一個好的團隊應當約定與遵從一套代碼規范,并且每個成員都應當采用此風格。我們希望一個項目中的代碼擁有相似甚至相同的風格,像默契無間的團隊所完成的藝術品,而不是像一大票意見相左的個人所堆砌起來的殘次品。
  定制一套編碼與格式風格不需要太多時間,但對整個團隊代碼風格統一性的提升,卻是立竿見影的。
  記住,好的軟件系統是由一系列風格一致的代碼文件組成的。盡量不要用各種不同的風格來構成一個項目的各個部分,這樣會增加項目本身的復雜度與混亂程度。
  四、范例代碼
  和上篇文章一樣,有必要貼出一段書中推崇的整潔代碼作為本次代碼書寫格式的范例。書中的這段代碼采用java語言,但絲毫不影響使用C++和C#的朋友們閱讀。
  [cpp] view plain copy print?
  public class CodeAnalyzer implements JavaFileAnalysis
  {
  private int lineCount;
  private int maxLineWidth;
  private int widestLineNumber;
  private LineWidthHistogram lineWidthHistogram;
  private int totalChars;
  public CodeAnalyzer()
  {
  lineWidthHistogram = new LineWidthHistogram();
  }
  public static List findJavaFiles(File parentDirectory)
  {
  List files = new ArrayList();
  findJavaFiles(parentDirectory, files);
  return files;
  }
  private static void findJavaFiles(File parentDirectory, List files)
  {
  for (File file : parentDirectory.listFiles())
  {
  if (file.getName().endsWith(".java"))
  files.add(file);
  else if (file.isDirectory())
  findJavaFiles(file, files);
  }
  }
  public void analyzeFile(File javaFile) throws Exception
  {
  BufferedReader br = new BufferedReader(new FileReader(javaFile));
  String line;
  while ((line = br.readLine()) != null)
  measureLine(line);
  }
  private void measureLine(String line)
  {
  lineCount++;
  int lineSize = line.length();
  totalChars += lineSize;
  lineWidthHistogram.addLine(lineSize, lineCount);
  recordWidestLine(lineSize);
  }
  private void recordWidestLine(int lineSize)
  {
  if (lineSize > maxLineWidth)
  {
  maxLineWidth = lineSize;
  widestLineNumber = lineCount;
  }
  }
  public int getLineCount()
  {
  return lineCount;
  }
  public int getMaxLineWidth()
  {
  return maxLineWidth;
  }
  public int getWidestLineNumber()
  {
  return widestLineNumber;
  }
  public LineWidthHistogram getLineWidthHistogram()
  {
  return lineWidthHistogram;
  }
  public double getMeanLineWidth()
  {
  return (double)totalChars / lineCount;
  }
  public int getMedianLineWidth()
  {
  Integer[] sortedWidths = getSortedWidths();
  int cumulativeLineCount = 0;
  for (int width : sortedWidths)
  {
  cumulativeLineCount += lineCountForWidth(width);
  if (cumulativeLineCount > lineCount / 2)
  return width;
  }
  throw new Error("Cannot get here");
  }
  private int lineCountForWidth(int width)
  {
  return lineWidthHistogram.getLinesforWidth(width).size();
  }
  private Integer[] getSortedWidths()
  {
  Set widths = lineWidthHistogram.getWidths();
  Integer[] sortedWidths = (widths.toArray(new Integer[0]));
  Arrays.sort(sortedWidths);
  return sortedWidths;
  }
  }
  五、小結:讓代碼不僅僅是能工作
  代碼的格式關乎溝通,而溝通是專業開發者的頭等大事,所以良好代碼的格式至關重要。
  或許之前我們認為“讓代碼能工作”才是專業開發者的頭等大事。然而,《代碼整潔之道》這本書,希望我們能拋棄這個觀點。
  讓代碼能工作確實是代碼存在的首要意義,但作為一名有追求的程序員,請你想一想,今天你編寫的功能,極可能在下一版中被修改,但代碼的可讀性卻會對以后可能發生的修改行為產生深遠影響。原始代碼修改之后很久,其代碼風格和可讀性仍會影響到可維護性和擴展性。即便代碼已不復存在,你的風格和律條仍影響深遠。
  “當有人在閱讀我們的代碼時,我們希望他們能為其整潔性、一致性和優秀的細節處理而震驚。我們希望他們高高揚起眉毛,一路看下去,希望他們感受能到那些為之勞作的專業人士們的優秀職業素養。但若他們看到的只是一堆由酒醉的水手寫出的鬼畫符,那他們多半會得出結論——這個項目的其他部分應該也是混亂不堪的。”
  所以,各位,在開發過程中請不要僅僅是停留在“讓代碼可以工作”的層面,而更要注重自身輸出代碼的可維護性與擴展性。請做一個更有追求的程序員。
  六、本文涉及知識點提煉整理
  整潔代碼的書寫格式,可以遵從如下幾個原則:
  第一原則:像報紙一樣一目了然。優秀的源文件也要像報紙文章一樣,名稱應當簡單并且一目了然,名稱本身應該足夠告訴我們是否在正確的模塊中。源文件最頂部應該給出高層次概念和算法。細節應該往下漸次展開,直至找到源文件中最底層的函數和細節。
  第二原則:恰如其分的注釋。帶有少量注釋的整潔而有力的代碼,比帶有大量注釋的零碎而復雜的代碼更加優秀。
  第三原則:合適的單文件行數。盡可能用幾百行以內的單文件來構造出出色的系統,因為短文件通常比長文件更易于理解。
  第四原則:合理地利用空白行。在每個命名空間、類、函數之間,都需用空白行隔開。
  第五原則:讓緊密相關的代碼相互靠近。靠近的代碼行暗示著他們之間的緊密聯系。所以,緊密相關的代碼應該相互靠近。
  第六原則:基于關聯的代碼分布。
  變量的聲明應盡可能靠近其使用位置。
  循環中的控制變量應該在循環語句中聲明。
  短函數中的本地變量應當在函數的頂部聲明。
  對于某些長函數,變量也可以在某代碼塊的頂部,或在循環之前聲明。
  實體變量應當在類的頂部聲明。
  若某個函數調用了另一個,就應該把它們放到一起,而且調用者應該盡量放到被調用者上面。
  概念相關的代碼應該放到一起。相關性越強,則彼此之間的距離就該越短。
  第七原則:團隊遵從同一套代碼規范。一個好的團隊應當約定與遵從一套代碼規范,并且每個成員都應當采用此風格。
本文地址:http://m.4huy16.com/thread-174303-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • “芯”光璀璨,鵬城共賞——2025 Microchip中國技術精英年會深圳站回顧
  • 電動兩輪車設計生態系統
  • 常見深度學習模型介紹及應用培訓教程
  • Microchip第22屆中國技術精英年會——采訪篇
  • 貿澤電子(Mouser)專區

相關視頻

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表