if (clubs[i].members[j] == users[k]) => (clubs[ci].members[mi] == users[ui]
这样更不容易取错值。
delay → delay_secs password → plaintext_password5.匈牙利命名法(PS.现在不多见了)
8.不同命名形式代表不同的变量“类别”,例如 const 全大写,类用帕斯卡,普通变量用驼峰
limit 是否包含边界值容易引起误解,建议使用 max,同理还有 min
.特定语言有特定含义的的方法需要注意,如 get()、size()
// 外形不同 public class PerformanceTester { public static final TcpConnectionSimulator wifi = new TcpConnectionSimulator( 500, /* Kbps */ 80, /* millisecs latency */ 200, /* jitter */ 1 /* packet loss % */); public static final TcpConnectionSimulator t3_fiber = new TcpConnectionSimulator( 45000, /* Kbps */ 10, /* millisecs latency */ 0, /* jitter */ 0 /* packet loss % */); public static final TcpConnectionSimulator cell = new TcpConnectionSimulator( 100, /* Kbps */ 400, /* millisecs latency */ 250, /* jitter */ 5 /* packet loss % */); } // 外形相同 public class PerformanceTester { public static final TcpConnectionSimulator wifi = new TcpConnectionSimulator( 500, /* Kbps */ 80, /* millisecs latency */ 200, /* jitter */ 1 /* packet loss % */); public static final TcpConnectionSimulator t3_fiber = new TcpConnectionSimulator( 45000, /* Kbps */ 10, /* millisecs latency */ 0, /* jitter */ 0 /* packet loss % */); public static final TcpConnectionSimulator cell = new TcpConnectionSimulator( 100, /* Kbps */ 400, /* millisecs latency */ 250, /* jitter */ 5 /* packet loss % */); } // 堆代码 duidaima.com // 另一种注释方法 public class PerformanceTester { // TcpConnectionSimulator(throughput, latency, jitter, packet_loss) // [Kbps] [ms] [ms] [percent] public static final TcpConnectionSimulator wifi = new TcpConnectionSimulator(500, 80, 200, 1); public static final TcpConnectionSimulator t3_fiber = new TcpConnectionSimulator(45000, 10, 0, 0); public static final TcpConnectionSimulator cell = new TcpConnectionSimulator(100, 400, 250, 5); }.保持固定的顺序(PS. Vue 的官方 option 顺序)
# remove everything after the second '*' name = '*'.join(line.split('*')[:2])不要为了注释而注释:
// Find the Node in the given subtree, with the given name, using the given depth. Node* FindNodeInSubtree(Node* subtree, string name, int depth);尝试写添加实现细节:
// Find a Node with the given 'name' or return NULL. // If depth <= 0, only 'subtree' is inspected. // If depth == N, only 'subtree' and N levels below are inspected. Node* FindNodeInSubtree(Node* subtree, string name, int depth);PS.go 语言就是强迫你为 export 的函数写注释,千万不要为了写而写呀,可以参考下标准库的注释:https://golang.org/pkg/#stdlib
// Surprisingly, a binary tree was 40% faster than a hash table for this data. // The cost of computing a hash was more than the left/right comparisons.有些地方看似可以优化,但是自己已经实践得出并不能优化的结论,那就加上注释避免别人浪费时间。
// TODO(dustin): handle other image formats besides JPEG还有这些类型:
TODO: Stuff I haven’t gotten around to yet FIXME: Known-broken code here HACK: Admittedly inelegant solution to a problem XXX: Danger! major problem here这些注释同样应该遵循统一风格,这样全局搜索就能轻易找到不同类型的问题。
// Impose a reasonable limit - no human can read that much anyway. const int MAX_RSS_SUBSCRIPTIONS = 1000;想象读者需要知道什么
.用回车和注释将代码划分成块(PS.与代码美学讲的重复了)
// This class contains a number of members that store the same information as in the // database, but are stored here for speed. When this class is read from later, those // members are checked first to see if they exist, and if so are returned; otherwise the // database is read from and that data stored in those fields for next time. // 其实就是 ↓ // This class acts as a caching layer to the database.简化逻辑
while (bytes_received < bytes_expected)作者推荐把变量放在左边,这样比较符合人类语言习惯,例如:接受长度小于某个特定的值,而不是某个特定的值大于等于接受长度。
exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent)就不要用三元运算。
public boolean Contains(String str, String substr) { if (str == null || substr == null) return false; if (substr.equals("")) return true; // ... }最小化嵌套
if (user_result == SUCCESS) { if (permission_result != SUCCESS) { reply.WriteErrors('error reading permissions') reply.Done() return } reply.WriteErrors('') } else { reply.WriteErrors(user_result) } reply.Done()上面的代码很可能是分两次编写的,最初的需求只有判断 user_result,后来新增需求判断 permission_result。其实这样的写法并不好理解,在处理新需求时,你可以尝试不要跟随以前的思路,从新的角度思考 if 条件怎么写:
if (user_result != SUCCESS) { reply.WriteErrors(user_result) reply.Done() return } if (permission_result != SUCCESS) { reply.WriteErrors(permission_result) reply.Done() return } reply.WriteErrors('') reply.Done()
德摩根定律 !(a||b) 等于 !a&&!b,!(a&&b) 等于 !a||!b
var remove_one = function(array, value_to_remove) { var index_to_remove = null for (var i = 0; i < array.length; i += 1) { if (array[i] === value_to_remove) { index_to_remove = i break } } if (index_to_remove !== null) { array.splice(index_to_remove, 1) } }缩减作用域
class LargeClass { string str_; void Method1() { str_ = ...; Method2(); } void Method2() { // Uses str_ } // Lots of other methods that don't use str_ ... };把 str_ 提取到被需要的最小范围:
class LargeClass { void Method1() { string str = ...; Method2(str); } void Method2(string str) { // Uses str } // Now other methods can't see str. };另外还提到了 C 的 if 作用域和 JavaScript 的 IIFE,都是控制作用域范围的方法。
var vote_changed = function(old_vote, new_vote) { var score = get_score() if (new_vote !== old_vote) { if (new_vote === 'Up') { score += old_vote === 'Down' ? 2 : 1 } else if (new_vote === 'Down') { score -= old_vote === 'Up' ? 2 : 1 } else if (new_vote === '') { score += old_vote === 'Up' ? -1 : 1 } } set_score(score) }但是如果不根据前后状态直接混在一起处理可以吗?可以,这就是所谓“每次做一件事”。我们把单个操作的变化抽离成函数,然后先减去旧的状态,再加上新的状态:
var vote_value = function(vote) { if (vote === 'Up') { return +1 } if (vote === 'Down') { return -1 } return 0 } var vote_changed = function(old_vote, new_vote) { var score = get_score() score -= vote_value(old_vote) // remove the old vote score += vote_value(new_vote) // add the new vote set_score(score) }想法化为代码
$is_admin = is_admin_request(); if ($document) { if (!$is_admin && ($document['username'] != $_SESSION['username'])) { return not_authorized(); } } else { if (!$is_admin) { return not_authorized(); } }相信看了上面优化逻辑的话应该不会写出这样的代码了,在这章作者再解释了一次怎么修改这种代码:
if (is_admin_request()) { // authorized } elseif ($document && ($document['username'] == $_SESSION['username'])) { // authorized } else { return not_authorized(); } // continue rendering the page ...如果你发现很难描述你的问题或者代码……那可能你的代码逻辑存在一些问题,那更好了,再深度思考一下业务逻辑会不会有什么不对的地方吧。这事情做起来和 rubber ducking(也就是“小黄鸭调试法”)差不多,不难做到,却十分有效,十分推荐大家尝试。