UDN-企业互联网技术人气社区

板块导航

浏览  : 474
回复  : 1

[资源分享] 从 MVC 到微服务,技术演变的必经之路

[复制链接]
舞操的头像 楼主
发表于 2016-8-11 19:17:02 | 显示全部楼层 |阅读模式
  写代码就像读书时候写作文一样,虽然试卷上没有要求字迹要多工整、篇幅要多具备艺术气息,但是不可否认的是,字迹工整、篇幅合理的作文总能拿较高的分数,屡试不爽。而好的代码规范能够提高工作效率,降低查找代码和团队交接的时间。如何让代码看起来很“养眼”呢?确切地说有三条原则:

  使用一致的布局

  让相似的代码看上去相似

  把相关的代码行分组,形成代码块

  举个坏掉的栗子:

  1.   class StatsKeeper{

  2.   public:

  3.   // A class for keeping track of a series of doubles

  4.   void Add(double d); // and methods for quick statistics about them

  5.   private: int count; /* how many so far

  6.   */private: double Average();

  7.   list

  8.   past_items

  9.   ;double maximum;

  10.   };
复制代码


  再举一个好的栗子:

  1.   // A class for keeping track of a series of doubles

  2.   // and methods for quick statistics about them

  3.   class StatsKeeper{

  4.   public:

  5.   void Add(double d);

  6.   double Average();

  7.   private:

  8.   list past_items;

  9.   int count; // how many so far

  10.   double minimum;

  11.   double maximum;

  12.   };
复制代码


  嗯,看到这里你应该才发现第一个例子中少写了一个double minimum;,下面是一些具体操作的要点。

  通过换行来保持一致和紧凑

  在需要时使用列对齐

  选一个有意义的顺序,并始终一致地使用

  把声明按块组织起来

  把代码分成段落

  用方法来整理不规则的东西

  个人风格与一致性

  1. 通过换行来保持一致和紧凑

  有的公司编码规范中有明确规定列字数限制,例如Google是80或100,超过规定都必须自动换行。但除此之外,还有一些没有超过的但也期望程序员能选择换行的情况。举个例子:

  1.   public class PerformanceTester{

  2.   public static final TcpConnectionSimulator wifi = new TcpConnectionSimulator(

  3.   500, /* kbps */

  4.   80, /*millisecs latency */

  5.   200, /* jitter */

  6.   1 /* packet loss % */ );

  7.   public static final TcpConnectionSimulator t3_fiber =

  8.   new TcpConnectionSimulator(

  9.   4500, /* kbps */

  10.   10, /*millisecs latency */

  11.   0, /* jitter */

  12.   0 /* packet loss % */ );

  13.   public static final TcpConnectionSimulator cell = new TcpConnectionSimulator(

  14.   100, /* kbps */

  15.   400, /*millisecs latency */

  16.   250, /* jitter */

  17.   5 /* packet loss % */ );

  18.   }
复制代码


  虽然都是定义一个TcpConnectionSimulator对象,但t3_fiber乍一看和它的邻居并不一样,这显然违反了“让相似的代码看上去相似”原则。修改过后是这样的:

  1.   public class PerformanceTester{

  2.   public static final TcpConnectionSimulator wifi =

  3.   new TcpConnectionSimulator(

  4.   500, /* kbps */

  5.   80, /*millisecs latency */

  6.   200, /* jitter */

  7.   1 /* packet loss % */ );

  8.   public static final TcpConnectionSimulator t3_fiber =

  9.   new TcpConnectionSimulator(

  10.   4500, /* kbps */

  11.   10, /*millisecs latency */

  12.   0, /* jitter */

  13.   0 /* packet loss % */ );

  14.   public static final TcpConnectionSimulator cell =

  15.   new TcpConnectionSimulator(

  16.   100, /* kbps */

  17.   400, /*millisecs latency */

  18.   250, /* jitter */

  19.   5 /* packet loss % */ );

  20.   }
复制代码


  当然也可以把注释搬到上面去,毕竟同样的注释写了三遍就要考虑“重构”了。

  1.   public class PerformanceTester{

  2.   // TcpConnectionSimulator(thoughput, latency, jetter, packet_loss)

  3.   // [kbps] [ms] [ms] [percent]

  4.   public static final TcpConnectionSimulator cell =

  5.   new TcpConnectionSimulator(500,80, 200, 1);

  6.   public static final TcpConnectionSimulator cell =

  7.   new TcpConnectionSimulator(4500, 10, 0, 0);

  8.   public static final TcpConnectionSimulator cell =

  9.   new TcpConnectionSimulator(100, 400, 250, 5);

  10.   }
复制代码


  2.在需要的时候使用列对齐

  整齐的边和列让读者可更轻松的浏览文本,有时候可以选择借用“列对齐”来让代码易读。例如:

  1.   CherkFullName("Doug Adams" , "Mr. Douglas Adams" , "");

  2.   CherkFullName("Jake Brown" , "Mr. Jake Brown III" , "");

  3.   CherkFullName("No Such Guy", "" , "no match found");

  4.   CherkFullName("John" , "" , "more than one result");
复制代码


  就像Google的代码规范中并不提倡这样的写法一样,笔者也不建议使用这种风格,因为一旦方法中某个参数需要修改,那么你又要花很多时间去排序。但是下面的情况可适当使用:

  
  1. # Extract POST parameters to local variables

  2.   details = request.POST.get('details');

  3.   location = request.POST.get('location');

  4.   phone = equest.POST.get('phone');

  5.   email = request.POST.get('email');

  6.   url = request.POST.get('url');
复制代码


  Wait!第四行是不是少了点什么???

  3. 选一个有意义的顺序,始终一致地使用

  在很多时候,代码的顺序不会影响其正确性,例如上文五个变量的定义可以写成任意顺序。在这种情况下,不要随机排序,把他们按有意义的方式排序会有帮助。以下是一些排序的原则:

  让变量的顺序与对应的HTML表单中字段的顺序相匹配。

  从“最重要”到“最不重要”排序。

  按字母顺序排序

  一旦你采用了某种排序规则,就要在代码中始终如一的遵循它。

  4.把声明按块组织起来

  由于大脑会很自然地按照分组和层次结构来思考,因此可以通过按块组织方式来使读者更快速的理解你的代码。

  举个例子:

  1.   class FrontendServer{

  2.   public:

  3.   FrontendServer();

  4.   void ViewProfile(HttpRequest* request);

  5.   void OpenDatabase(String location, String user);

  6.   void SaveProfile(HttpRequest* request);

  7.   String ExtractQueryParam(HttpRequest* request, String param);

  8.   void ReplyOk(HttpRequest* request, String html);

  9.   void FindFriends(HttpRequest* request);

  10.   void ReplyNotFound(HttpRequest* request, String error);

  11.   void CloseDatabase(String location);

  12.   ~FrontendServer();

  13.   }
复制代码


  作为读者,要想读懂代码,恐怕你会选择先把它们分成不同的组,所以写这段代码的程序员不妨先将它们按块组织在一起,并加上适当的注释,这样代码的可读性将大大提高。

 
  1.  class FrontendServer{

  2.   public:

  3.   FrontendServer();

  4.   ~FrontendServer();

  5.   // Handlers

  6.   void ViewProfile(HttpRequest* request);

  7.   void SaveProfile(HttpRequest* request);

  8.   void FindFriends(HttpRequest* request);

  9.   // Request/Reply Utilities

  10.   String ExtractQueryParam(HttpRequest* request, String param);

  11.   void ReplyOk(HttpRequest* request, String html);

  12.   void ReplyNotFound(HttpRequest* request, String error);

  13.   //Database Helpers

  14.   void OpenDatabase(String location, String user);

  15.   void CloseDatabase(String location);

  16.   }
复制代码


  5. 把代码分成段落

  字面文字分成段落是由于以下几个原因:

  它是一种把相似的想法放在一起并与其他想法分开的方法。

  它提供了可见的“脚印”,如果没有它,会很容易找不到你读到哪里了。

  它便于段落之间的导航。

  出于同样的原因,代码也应该分段,并为每一个段落加上一条总结性的注释。

  1.   def suggust_new_friends(user, emaii_password):

  2.   # Get the user's friends' email addresses

  3.   friends = user.friends();

  4.   friend_emails = set(f.email for f in frends)

  5.   # Import all email addresses from this user's email account.

  6.   contacts = import_contacts(user.email, email_password)

  7.   contact_emails = set(c.email for c in contracts)

  8.   # Find matching users that they aren't aleady friends with.

  9.   non_friend_emails = contact_email - friend_emails

  10.   suggested_friends = User.object.select(email_in = non_friend_emails)

  11.   # Display these lists on the page

  12.   display['user'] = user

  13.   display['friends'] = friends

  14.   display['suggested_friends'] = suggested_friends

  15.   return render("suggested_friends.html", display)
复制代码


  6. 用方法来整理不规则的东西

  假设有一个个人数据库,它提供了下面这个函数:

 
  1.  // Turn a partial_name like "Doug Adams " into "Mr. Douglas Adams".

  2.   // If not possible, 'error' is filled with an explannation.

  3.   String ExpandFullName(DatabaseConnection dc, String patial_name, String* error);
复制代码


  并且提供一系列的例子来测试:

  1.   DatabaseConnection database_connection;

  2.   string error;

  3.   assert(ExpandFullName(database_connection, "Doug Adams", &error) == "Mr. Douglas Adams");

  4.   assert(error == "");

  5.   assert(ExpandFullName(database_connection, "Jake Brown", &error) == "Mr. Jacob Brown III");

  6.   assert(error == "");

  7.   assert(ExpandFullName(database_connection, "No Such Guy", &error) == "");

  8.   assert(error == "no match found");

  9.   assert(database_connection, "John", &error) == "");

  10.   assert(error == "more than one result");
复制代码


  这段代码其实看起来并不“养眼”,因为它没有换行,也没有一致的风格。但更大的问题在于有很多重复的串,例如“assert(ExpandFullName(database_connection,…”, 其中还有很多“error”。要想改进这段代码,可以为它们添加一个辅助方法。就像:

 
  1.  CherkFullName("Doug Adams", "Mr. Douglas Adams", "");

  2.   CherkFullName("Jake Brown", "Mr. Jake Brown III", "");

  3.   CherkFullName("No Such Guy", "", "no match found");

  4.   CherkFullName("John", "", "more than one result");
复制代码


  很明显这里有4个测试,每个使用了不同的参数,并把所有的“脏活”都放在CherkFullName()中:

  1.   void CherkFullName(String partial_name,

  2.   String expected_full_name,

  3.   String expected_error) {

  4.   //database_connection is now a class member

  5.   String error;

  6.   String full_name = ExpandFullName(database_connection, partial_name, &error);

  7.   assert(error == expected_error);

  8.   assert(full_name == expected_full_name);

  9.   }
复制代码


  7. 个人风格与一致性

  最后想说的是一些个人的编程风格,例如大括号该放在哪里:

  1.   public void function

  2.   {

  3.   …

  4.   }
复制代码


  还是:

 
  1.  public void function {

  2.   …

  3.   }
复制代码


  又比如说"Tabs versus Space" ,笔者的建议是按照团队定好的风格来写,只采取一种,至于是采取哪一种,那就见仁见智了。

原文作者:Misa527528  来源:开发者头条

相关帖子

发表于 2016-8-12 11:47:26 | 显示全部楼层
写代码就像读书时候写作文一样,虽然试卷上没有要求字迹要多工整、篇幅要多具备艺术气息,但是不可否认的是,字迹工整、篇幅合理的作文总能拿较高的分数,屡试不爽
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部