The two most important days in your life are the day you were born and the day you find out why. -Mark Twain

#84 程式設計的簡約格式 - 減少程式碼縮排


最近在 code review 的過程中,總是常常會看到一些令人驚喜的事情,其中一件事情和程式的寫法有關.有時候是邏輯可以在簡化,有時候是 coding style 上可以在簡化以便閱讀.首先來看 coding style 可以簡化的部份.在寫程式的過程中,有時會因為業務邏輯面的複雜而造成會寫出多個 nested if statements 的情況,如下面的例子

string GetVersionName(string revision, string version, string pass)
{
string versionName = string.Empty;
if (!string.IsNullOrEmpty(revision.Trim()) && revision.Trim().ToLower() != "n/a")
{
versionName = version + "," + revision + "," + pass;
}
else
{
if (!string.IsNullOrEmpty(pass.Trim()) && pass.Trim().ToLower() != "n/a")
{
versionName = version + "," + revision + "," + pass;
}
else
{
versionName = version;
}
}
return versionName;
}
view raw blog84-1 hosted with ❤ by GitHub


上面的程式碼其實沒錯,也算方便閱讀.也許是我個人的因素,遇到 nested if 的時候,我會儘量地朝向少點縮排的方式前進. 除此之外,第 7 行和第 13 行是回傳一樣的答案.在程式寫法上可以將他們結合在一起,因為那是一個 "業務邏輯",一般來說,我們希望同一件事情只要發生在一個地方.因此,可以將上述的程式碼改成如下:

string GetVersionName(string revision, string version, string pass)
{
if (!string.IsNullOrWhiteSpace(revision) && !string.Equals(revision, "n/a", StringComparison.OrdinalIgnoreCase)
|| (!string.IsNullOrWhiteSpace(pass) && !string.Equals(pass, "n/a", StringComparison.OrdinalIgnoreCase))
{
return version + "," + revision + "," + pass;
}
return version;
}
view raw blog84-2 hosted with ❤ by GitHub


一個 if 配合上多個檢查條件,我自己覺得這樣閱讀起來比上述的語法好些.

再來看另外一個例子.

原本的程式碼如下:

object GetColumnValue(SqlDataReader reader, PropertyInfo prop)
{
object target = null;
if (reader.ColumnExists(prop.Name))
{
if (reader[prop.Name] == DBNull.Value)
{
if (prop.PropertyType == typeof(string))
{
target = string.Empty;
}
else
{
if (prop.PropertyType.IsValueType)
{
target = Activator.CreateInstance(prop.PropertyType)
}
else
{
target = null;
}
}
}
else
{
target = reader[prop.Name];
}
}
return target;
}
view raw blog84-3 hosted with ❤ by GitHub


同樣的,這程式也沒錯.不過,閱讀起來有點 "階梯".因為當我們閱讀時,大腦會產生那種 "階梯",如果 if true part/false part 的內容物很多程式碼,我們還得仔細看縮排才知道下一行要跑到那繼續看.

其實,只要動一點腦筋想一下就可以把它寫的更簡單,如下

object GetColumnValue(SqlDataReader reader, PropertyInfo prop)
{
if (!reader.ColumnExists(prop.Name))
{
return null;
}
if (reader[prop.Name] != DBNull.Value)
{
return reader[prop.Name];
}
if (prop.PropertyType == typeof(string))
{
return string.Empty;
}
if (prop.PropertyType.IsValueType)
{
return Activator.CreateInstance(prop.PropertyType);
}
return null;
}
view raw blog84-4 hosted with ❤ by GitHub


這樣的寫法是一樣的邏輯,而且是不是覺得更方便閱讀呢 ?

在寫程式的過程式,會常用到 if..else.. 是很正常的事情,然後這也代表你的業務邏輯將分成兩塊,而這兩塊的內容是獨立而不會互相干擾的,所以這兩塊的內容基本上不會重覆.若有重覆,那就是一般所謂的 duplicated code bad smell.另外,利用減少 "縮排" (indentation) 的技巧也能讓程式碼達到更方便閱讀的地步.
Share:

Related Posts:

0 意見:

張貼留言