在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    再談為什么代碼需要注釋

    前言

    在上篇文章 要不要寫代碼注釋 中,我們闡述了為什么代碼需要注釋,但是在評(píng)論區(qū)中,有同學(xué)依然認(rèn)為簡(jiǎn)介明了的代碼不需要注釋。本篇文章,我們通過舉兩個(gè)例子探討為什么我們認(rèn)為寫代碼需要寫注釋,歡迎大家給出建議。

    例子一

    同樣的命名,在不同場(chǎng)景下,返回字段含義不同

    我司的業(yè)務(wù)系統(tǒng)中,會(huì)涉及到轉(zhuǎn)碼的業(yè)務(wù),將音視頻、PPT、Word、Excel等文件進(jìn)行轉(zhuǎn)碼,然后使用播放器進(jìn)行播放。在進(jìn)行首抽象時(shí),將轉(zhuǎn)碼后的資源統(tǒng)一抽象成了一個(gè)interface,代碼如下:

    <?phpinterface Resource{ public function getName(); public function getPlayUrl(); public function getType(); public function getLength(); // 其他接口}

    列出的三個(gè)接口,從命名角度上沒有問題,分別表達(dá)的是獲取資源的名稱、獲取資源的播放地址和獲取資源的長(zhǎng)度。

    但是在getLength這個(gè)接口的返回值上,是有歧義的,這個(gè)長(zhǎng)度指的是什么?

    如果是音視頻資源,我們很好理解,90%是指音視頻的時(shí)長(zhǎng),但是單位是秒還是分鐘,不確定。對(duì)于文檔類型的資源呢?首先,對(duì)于一個(gè)剛接觸這套系統(tǒng)的新人而言在不明白文檔資源到底被轉(zhuǎn)碼什么樣子的情況下,他是無法猜測(cè)其含義的,文檔有可能被轉(zhuǎn)成了視頻、圖片,再或者是其他格式。

    我們的系統(tǒng)會(huì)將文檔資源轉(zhuǎn)成圖片或者h(yuǎn)tml文件,一頁就是一張圖片或者一個(gè)html文件,這里的getLength,對(duì)于文檔資源來講,返回的是文檔資源的總頁數(shù)。

    這里可能有同學(xué)會(huì)質(zhì)疑,為什么不將文檔和音視頻抽象成兩個(gè)不同的資源,針對(duì)文檔類型的,提供getTotalPage接口,獲取頁數(shù),針對(duì)音視頻類型的,提供getLenght接口,并提取出公共方法抽象成基類?

    <?php// 針對(duì)不同資源進(jìn)行抽象接口示例interface BaseResource { public function getName(); public function getPlayUrl(); public function getType();}interface MediaResource extends BaseResource{ public function getLenght();}interface DocResource extends BaseResource{ public function getTotalPage();}

    原因很簡(jiǎn)單特別簡(jiǎn)單,抽象是為了把復(fù)雜的事情簡(jiǎn)單化,而不是把簡(jiǎn)單的事情復(fù)雜化!

    這個(gè)場(chǎng)景中,除了getLength接口的返回值有歧義,其他接口針對(duì)不同類型資源是沒有歧義的。如果我們分別進(jìn)行抽象,勢(shì)必會(huì)讓代碼更復(fù)雜,比如引入設(shè)計(jì)模式(工廠或策略,或者兩者皆有)。并且,調(diào)用資源的客戶端,也會(huì)引入條件分支,針對(duì)不同的資源類型,調(diào)用不同的方法。

    ‘MediaResource’, ‘doc’ => ‘DocResource’, ];public static function getResource($type, $resouceId) { if (!isset(self::$map[$type]) { throw new Exception(sprintf(‘Not support type %s’, $type)); } $resClass = self::$map($type); return new $resClass($resourceId); }}// Client端$res = ResourceFactory::getResource($resouceId);if (‘doc’ == $res->getType) {echo ‘資源頁數(shù)是:’ . $res->getTotalPage();} else { echo ‘音視頻長(zhǎng)度是:’ . $res->getLength() / 60 . ‘分鐘’;}

    本來,我們?cè)黾右痪渥⑨尶梢越鉀Q這個(gè)問題。

    <?phpinterface Resource{ public function getName(); public function getPlayUrl(); public function getType(); /** * 對(duì)于流媒體資源,入視頻、音頻等,返回時(shí)長(zhǎng),單位為秒; * 對(duì)于文檔類型資源,返回文檔的頁數(shù). * * @return int */ public function getLength(); // 其他接口}

    也有同學(xué)會(huì)說,我不搞復(fù)雜化,所有資源都是getLength接口,具體的返回值,可以看代碼實(shí)現(xiàn)。如果這樣的話,這就會(huì)有以下問題,一是違背了好命名的初衷,為什么我們要用好的方法名,就是為了一眼能看出函數(shù)的意圖,二是增加了他人的負(fù)擔(dān),閱讀實(shí)現(xiàn)代碼既費(fèi)時(shí)又痛苦,沒有隱藏細(xì)節(jié)(關(guān)于隱藏細(xì)節(jié)這個(gè)話題,我們會(huì)單獨(dú)寫一篇文章進(jìn)行介紹)。

    代碼無法表達(dá)一些隱藏的邏輯

    在接觸過的業(yè)務(wù)中,有一個(gè)學(xué)習(xí)平臺(tái)。對(duì)于課程的設(shè)計(jì)大概是這樣的:

    有一張課程表 course,用于記錄課程的基本信息

    有一張course_member表,用于記錄課程中的用戶,主要字段為課程id course_id和用戶id user_id。

    還有一張 course_learn_record表,用戶記錄用戶學(xué)習(xí)時(shí)長(zhǎng),包含課程id course_id字段、用戶id user_id字段 和學(xué)習(xí)時(shí)長(zhǎng)字段。

    在課程的業(yè)務(wù)中實(shí)現(xiàn)中,有一個(gè)方法,代碼如下

    getCourseMemberDao() ->findCourseMemberIds($courseId); return $this->getCourseLearnRecordDao() ->countLearnTimeByCourseIdAndMemberIds($courseId, $memberIds); } }

    該方法先從 course_member 表中查了一次課程下所有的用戶id,再根據(jù)課程id和用戶id去course_learn_record 表中統(tǒng)計(jì)學(xué)習(xí)時(shí)長(zhǎng)。

    為什么要先查一遍課程的用戶id,再把課程id和用戶id組成與關(guān)系,去course_learn_record表中統(tǒng)計(jì)數(shù)據(jù)呢?單通過課程id,也可以統(tǒng)計(jì)出課程下所有用戶的學(xué)習(xí)時(shí)長(zhǎng),為何多此一舉?

    原來,業(yè)務(wù)要求,課程的成員可以被移除、也允許被再次添加到課程;當(dāng)成員再次添加到課程的時(shí)候,需要保留之前的學(xué)習(xí)記錄。

    因此,這個(gè)方法統(tǒng)計(jì)的是 課程當(dāng)前成員的學(xué)習(xí)時(shí)長(zhǎng)。

    有同學(xué)會(huì)說,這明顯是方法命名不對(duì),那什么樣的命名可以體現(xiàn)出這個(gè)邏輯呢?

    我們內(nèi)部有同學(xué)提出了兩個(gè)命名:

    一是 countCourseCurrentMembersLearnTime, 直譯就是統(tǒng)計(jì)課程當(dāng)前成員的學(xué)習(xí)時(shí)長(zhǎng);

    另外一個(gè)是 countCourseValidLearnTime, 直譯是統(tǒng)計(jì)課程有效的學(xué)習(xí)時(shí)長(zhǎng);

    兩個(gè)命名都不好。首先,統(tǒng)計(jì)課程當(dāng)前成員的學(xué)習(xí)時(shí)長(zhǎng),這個(gè)“當(dāng)前”是怎么來的,為什么會(huì)有當(dāng)前成員這種說法,是否還有“非當(dāng)前”的成員存在,對(duì)于不熟悉業(yè)務(wù)的開發(fā)同學(xué)來講,是比較蒙的,可能要問一圈才知道為什么。同理,統(tǒng)計(jì)課程有效的學(xué)習(xí)時(shí)長(zhǎng),為什么要區(qū)分有效和無效,什么情況下有效,什么情況下無效?

    (PS: 如果你有更好的命名方式,可以貼在評(píng)論區(qū)微笑)

    如果我們給個(gè)注釋,情況就很明了:

    getCourseMemberDao() ->findCourseMemberIds($courseId); return $this->getCourseLearnRecordDao() ->countLearnTimeByCourseIdAndMemberIds($courseId, $memberIds); } }

    總結(jié)

    良好的命名能減少代碼對(duì)注釋的依賴,但仍有大量設(shè)計(jì)信息無法用代碼表示。

    鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場(chǎng),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系管理員(admin#wlmqw.com)刪除。
    上一篇 2022年6月21日 06:41
    下一篇 2022年6月21日 06:41

    相關(guān)推薦

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時(shí)間:周一至周五,10:30-18:30,節(jié)假日休息