【轉(zhuǎn)】編寫函數(shù)的一些提議

原文出處

傻瓜都能寫出計算機可以讀懂的代碼,只有優(yōu)秀的程序員才能寫出人能讀懂的代碼二跋!

函數(shù)編寫木人,可讀性放在第一位麸锉。而函數(shù)可讀性的最關(guān)鍵點在于函數(shù)的輸入?yún)?shù)钠绍。

1. 不要出現(xiàn)和業(yè)務(wù)無關(guān)的參數(shù)

函數(shù)參數(shù)里面不要出現(xiàn)local,messagesource花沉,request柳爽,response這些參數(shù),第一非常干擾閱讀碱屁,一堆無關(guān)的參數(shù)把業(yè)務(wù)代碼都遮掩住了磷脯,第二導致你的函數(shù)不好測試,如你要構(gòu)建一個request參數(shù)來測試娩脾,還是有一定難度的赵誓。

干凈清爽的參數(shù),寫測試代碼非常舒服柿赊,如我們編寫一些Service的測試代碼:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml",
        "file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml" })
@WebAppConfiguration
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CongfigServiceTest {

    @Autowired
    ConfigService configService;

    /**
     * 初始化信息
     */
    @Before
    public void init() {
        System.out.println("------------init-----------");
        UserUtil.setLocale("en");
        UserUtil.setUser("測試的用戶");
    }

    @Test
    public void test01Full() {
        Config config = new Config();

        config.setName("配置項名稱");
        config.setValue("配置項值");

        // 新增測試
        long newId = configService.add(config);
        assertTrue(newId > 1);

        // 查詢測試
        Collection<Config> all = configService.getAll();
        assertTrue(all.size() == 1);

        // 刪除測試
        boolean result = configService.delete(newId);
        assertTrue(result);
    }
}

2. 避免使用復雜的數(shù)據(jù)對象作為參數(shù)和結(jié)果

輸入輸出參數(shù)都應該盡量避免出現(xiàn)Map俩功,Json這種“黑箱子”參數(shù)。這種參數(shù)碰声,你只有通讀代碼诡蜓,才知道里面究竟放了什么。

錯誤代碼范例:

/**
 * R忍簟B!椿肩!錯誤代碼示例
 * 1. 和業(yè)務(wù)無關(guān)的參數(shù)locale,messagesource
 * 2. 輸入輸出都是map脚粟,根本不知道輸入了什么覆旱,返回了什么
 * 
 * @param params
 * @param local
 * @param messageSource
 * @return
 */
public Map<String, Object> addConfig(Map<String, Object> params, 
    Locale locale, MessageSource messageSource) {

  Map<String, Object> data = new HashMap<String, Object>();

  try {
    String name = (String) params.get("name");
    String value = (String) params.get("value");

    //示例代碼,省略其他代碼
  }
  catch (Exception e) {
    logger.error("add config error", e);

    data.put("code", 99);
    data.put("msg", messageSource.getMessage("SYSTEMERROR", null, locale));
  }

  return data;
}

3. 有明確的輸入輸出和方法名

盡量有清晰的輸入輸出參數(shù)核无,使人一看就知道函數(shù)做了啥。舉例:

public void updateUser(Map<String, Object> params){
  long userId = (Long) params.get("id");
  String nickname = (String) params.get("nickname");

  //更新代碼
}

上面的函數(shù)藕坯,看函數(shù)定義你只知道更新了用戶對象团南,但你不知道更新了用戶的什么信息。建議寫成下面這樣:

public void updateUserNickName(long userId, String nickname){
  //更新代碼
}

就算不看方法名炼彪,只看參數(shù)就能知道這個函數(shù)只更新了nickname一個字段吐根。

4. 把可能變化的地方封裝成函數(shù)

編寫函數(shù)的總體指導思想是抽象和封裝,需要把代碼的邏輯抽象出來封裝成為一個函數(shù)辐马,以應對將來可能的變化拷橘。以后代碼邏輯有變更的時候,單獨修改和測試這個函數(shù)即可喜爷。

如何識別可能變的地方冗疮,多思考一下就知道了,隨著工作經(jīng)驗的增加識別起來會越來越容易檩帐。比如术幔,開發(fā)初期,業(yè)務(wù)說只有管理員才可以刪除某個對象湃密,你就應該考慮到后面可能除了管理員诅挑,其他角色也可能可以刪除,或者說對象的創(chuàng)建者也可以刪除泛源,這就是將來潛在的變化拔妥,你寫代碼的時候就要埋下伏筆,把是否能刪除做成一個函數(shù)达箍。后面需求變更的時候没龙,你就只需要改一個函數(shù)。

舉例幻梯,刪除配置項的邏輯兜畸,判斷一下只有是自己創(chuàng)建的配置項才可以刪除,一開始代碼是這樣的:

/**
 * 刪除配置項
 */
@Override
public boolean delete(long id) {
  Config config = configs.get(id);

  if(config == null){
    return false;
  }

  // 只有自己創(chuàng)建的可以刪除
  if (UserUtil.getUser().equals(config.getCreator())) {
    return configs.remove(id) != null;      
  }

  return false;
}

這里我們會識別一下碘梢,是否可以刪除這個地方就有可能會變化咬摇,很有可能以后管理員就可以刪除任何人的,那么這里就抽成一個函數(shù):

/**
 * 刪除配置項
 */
@Override
public boolean delete(long id) {
  Config config = configs.get(id);

  if(config == null){
    return false;
  }

  // 判斷是否可以刪除
  if (canDelete(config)) {
    return configs.remove(id) != null;      
  }

  return false;
}

/**
 * 判斷邏輯變化可能性大煞躬,抽取一個函數(shù)
 * 
 * @param config
 * @return
 */
private boolean canDelete(Config config) {
  return UserUtil.getUser().equals(config.getCreator());
}

后來想了一下肛鹏,沒有權(quán)限應該拋出異常逸邦,再次修改為:

/**
 * 刪除配置項
 */
@Override
public boolean delete(long id) {
  Config config = configs.get(id);

  if (config == null) {
    return false;
  }

  // 判斷是否可以刪除
  check(canDelete(config), "no.permission");

  return configs.remove(id) != null;
}

這就是簡單的抽象和封裝的思想。把可能變化的點封裝成可以獨立測試的函數(shù)在扰,我們編碼過程中就會少了很多“需求變更”缕减。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市芒珠,隨后出現(xiàn)的幾起案子桥狡,更是在濱河造成了極大的恐慌,老刑警劉巖皱卓,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裹芝,死亡現(xiàn)場離奇詭異,居然都是意外死亡娜汁,警方通過查閱死者的電腦和手機嫂易,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掐禁,“玉大人怜械,你說我怎么就攤上這事「凳拢” “怎么了缕允?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長享完。 經(jīng)常有香客問我灼芭,道長,這世上最難降的妖魔是什么般又? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任彼绷,我火速辦了婚禮,結(jié)果婚禮上茴迁,老公的妹妹穿的比我還像新娘寄悯。我一直安慰自己,他們只是感情好堕义,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布猜旬。 她就那樣靜靜地躺著,像睡著了一般倦卖。 火紅的嫁衣襯著肌膚如雪洒擦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天怕膛,我揣著相機與錄音熟嫩,去河邊找鬼。 笑死褐捻,一個胖子當著我的面吹牛掸茅,可吹牛的內(nèi)容都是我干的椅邓。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼昧狮,長吁一口氣:“原來是場噩夢啊……” “哼景馁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起逗鸣,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤合住,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后撒璧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體聊疲,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年沪悲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阱表。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡殿如,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出最爬,到底是詐尸還是另有隱情涉馁,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布爱致,位于F島的核電站烤送,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏糠悯。R本人自食惡果不足惜帮坚,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望互艾。 院中可真熱鬧试和,春花似錦、人聲如沸纫普。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昨稼。三九已至节视,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間假栓,已是汗流浹背寻行。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留但指,地道東北人寡痰。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓抗楔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拦坠。 傳聞我的和親對象是個殘疾皇子连躏,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 假期馬上到了晓铆,有很多人開始計劃著去哪兒旅游或者回老家看看勺良,一些腸道功能不佳或脾胃虛弱的人,突然進入新的環(huán)境并改變原...
    熊俊容閱讀 240評論 0 0
  • 其實只有自己知道骄噪,正如廣大雞湯愛好者所說尚困,這個年紀誰都不會誰的一生,所以我原諒你的中途怯懦链蕊。 我自己知道我本身的缺...
    南風呀閱讀 258評論 0 0
  • 我和一個長有尾巴的女子做了愛事甜,事實上,她身后確實長著一條棕色的滔韵,三十厘米長的尾巴逻谦,然而,我們還是做了陪蜻,在夏...
    阿洛Peter閱讀 634評論 0 0
  • 周末啊邦马,只想宅在家里做做飯,曬曬太陽宴卖,看看書滋将,追追劇
    一路李花開閱讀 170評論 0 0