看板 Soft_Job 關於我們 聯絡資訊
其實這要看你的抽象化程度 一般在閱讀程式的時候除非有必要,否則都不會追究到程式架構的最底端 我們都會在抽象化程度偏高的地方瀏覽,真的有需要才會再往下一層去檢視實作 如果你的程式會讓閱讀者想要看裡面的實作通常代表 1. 你的設計沒辦法交代清楚它到底確切在做什麼?需要什麼?使用時機?使用限制?… … 一些慣例(命名慣例,design patterns…)可以讓閱讀者一眼就取得這些隱含的資訊 2. 這個東西的功能太神奇了(程式行為超出預期),超出一般人的預期 像是 qt 的 signal slot 機制就會讓第一次接觸的人摸不著頭腦 因為它用名稱來配對 signal slot 的做法不是標準的 c++ 語言可以做到的 3. 底層程式有蟲,要抓蟲啦 4. 你的 code 很漂亮,很能夠引人入勝,讓人家很想一直繼續往下看 XD 所以說,要是有一個好的設計 那麼閱讀者根本就不需要去看那些效率取向的,最佳化過後的難懂的實作 因為你的設計就已經提供給閱讀者他想要的所有資訊 根本不需要自己去閱讀實作慢慢推敲啊 以上是對於提升整個系統整體的可讀性,如果是要考慮實作本身的可讀性的話 那麼重點就會放在職責的切割和分配 最快最有效率的檢查方式就是看在同一個 block 內的 code 的抽象化程度是否差不多 要是上一行是系統頂層的操作,下一行又是底層的東西,看起來一定很痛苦吧 而且這樣把兩個不同階層的東西綁在一起就是在製造多餘的相依性 回到原 po 演算法取捨的問題,我會推 policy based design 它不但保留了程式的擴充性,又不損失效能,超美的 XD ※ 引述《gitignore (git)》之銘言: : 最近上班在思考這問題 : 假如今天有個 O(log n) 的方法可以寫出一個東西 : 但是程式碼無法簡化 以後維護的人應該也會很痛苦 : 因為不直觀 : 另一個就是程式碼非常簡潔 但就一定是O(n) 甚至 O(n^2) : 不知道大家會傾向於哪種? : 我個人是比較喜歡clean code 因為過一陣字自己回來維護也比較快上手 : 但是感覺在學校學這麼多 就是要能寫出效率較好的程式碼 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 49.217.64.252 ※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1464373625.A.CE0.html ※ 編輯: CoNsTaR (49.217.64.252), 05/28/2016 02:29:15
wesley234: 觀念正確,腦袋清楚05/28 08:07
wesley234: 除非人家想要改Code,否則對於一個呼叫者來說05/28 08:09
wesley234: 根本懶得看細節05/28 08:09
wesley234: 人與人之間是合作整合的關係,各自負責不同的部分05/28 08:11
wesley234: 不是都做一樣的事,然後相互比較看誰強,這跟學校不同05/28 08:12
wesley234: Code太髒,苦的是接手的人,或者是未來的自己05/28 08:13
comesuck: 不是每個人的心態都這麼健康的...05/28 10:48
comesuck: 聽不懂抽象化是什麼的比想像中的多...05/28 10:57
GoalBased: 聽不懂又整天掛在嘴上講的可怕05/28 11:29
abc0922001: 看別人的Code,起手勢不是「寫這麼爛都看不懂」05/28 13:25
sunsamy: 請問policy based design的overloading的Template泛型05/28 20:44
sunsamy: 最終runtime實現方式也是一堆case或if else在那比對?05/28 20:44
sunsamy: 這樣效率會好嗎?不曉得我認知有沒有錯?05/28 20:45
要是每種 policy 的組合都有可能在執行時期用到的話 就會像你說的 要選擇用哪個特化版勢必要一堆 if else switch 不過要是你能夠忍受整個程式除了 main 以外所有函數都是 function template 的話 把目前的組合當作 template parameter 就不必一直重複判斷 整個程式可以只出現一次 switch XD 不過這種需要"組合搭配"的 本來就不會選擇用 policy based 這種情況下多型會適合很多
kiwatami: 可是瑞凡 在接維護的人難免都會需要改程式05/28 21:41
kiwatami: 這個時候就需要看程式碼05/28 21:41
kiwatami: 你這篇的角度比較像是 api 使用者05/28 21:41
其實我覺得會需要"改程式"(而非只改功能) 就是有太多不該有的相依性 也就是職責的切割和分配一定出了問題 例如用你想要 增加/刪除/替換 某功能當例子好了 1. 假設你想增加某功能 會發現找不到一個適合的坑把新功能加進去 因為另一個佔著同一個坑的程式片段還負責了其他事情 所以如果你也想佔這個坑 勢必得一併把這些"其他事情"也寫進你的東西裡 否則塞不進這 個坑 2. 假設你想移掉一個功能 結果你發現你需要往下一層看實作 那通常代表你想移掉的功能可能又順便做了一點點其他事情 (它可能負責提供介面也負責做事,這聽起來沒什麼大問題,但是如果你把它直接刪掉, 那少了這個介面,上下就兜不起來了,如果一開始就把介面分開寫,你就可以直接刪掉原 本的功能,然後提供一個什麼都不做的版本銜接介面,介面再銜接上下) 或者是它本來就光明正大的被包含在一個負責不只一件事情的東西裡 所以你沒辦法直接移除它 不是要去修改實作就是要自己再寫另一份取代原本的 3. 替換同刪掉 不過這都只是我自己的想法 因為我根本還沒有工作過 唯一的合作夥伴就是自己 所以也不知道外面業界到底生態如何(我還只有大一)所以這些還是看看就好 XDD ※ 編輯: CoNsTaR (163.18.32.152), 05/29/2016 08:14:01
kiwatami: 其實有時候只是老闆希望產生的結果從 a 改成 b 05/29 09:04
kiwatami: 而這個演算法剛好是產生結果的核心部分05/29 09:04
kiwatami: 這樣不管怎麼抽離都會需要改程式碼05/29 09:04
kiwatami: 所以程式的可讀性與文件才會這麼重要05/29 09:04
kiwatami: 這也是為什麼我覺得你的說法比較接近 api 使用者05/29 09:04
comesuck: kiwatami 你指的應該是BO(or DAL)使用者吧05/29 10:29
comesuck: 只要當初寫code的人體質很差,很容易就會維護到這種三四05/29 10:32
comesuck: 個功能都擠到一個function裡做 05/29 10:32
comesuck: 但這些問題會一直累積到要改「機制」or「規則」的那個人 05/29 10:39
comesuck: 身上05/29 10:39
comesuck: 不用在意業界生態如何,用對的方式寫code就好05/29 10:50
comesuck: 不要被「實務上」魔人牽著走;因為我認為「因為我不懂,05/29 10:57
comesuck: 所以不這樣做」不等於「實務上」05/29 10:57
comesuck: 情境大致上是這樣:「為什麼不畫Uml?」、「為什麼不用de 05/29 11:02
comesuck: legate?」、「為什麼function一次做五件事?」答案開頭05/29 11:02
comesuck: 都會是「實務上沒人這樣做...」05/29 11:02
comesuck: 最後一個問題改成「為什麼function做五件事不拆出來?」05/29 11:04
kiwatami: 我指的 api 使用者其實就是一般開發者05/29 11:10
kiwatami: 通常不需要管原始碼 只要負責呼叫 method 就好 05/29 11:10
kiwatami: 這樣才符合原 po 提到的 1234點05/29 11:10
kiwatami: 接維護的人不太可能不需要讀原始碼05/29 11:10
kiwatami: 差別在於讀的範圍多寡而已05/29 11:10
kiwatami: 其實就算只有一個功能 複雜的演算法閱讀起來也很花時間 05/29 11:10
kiwatami: 如果改動幅度很大或是牽扯到資料來源內容的變更05/29 11:10
kiwatami: 這樣想不讀都不行 因為要評估重寫的可行性05/29 11:10
kiwatami: 以及是不是有把握重寫後的效能可以接近或是超過原本的05/29 11:10
kiwatami: 在這種情況下不論原本的架構有多好 都需要去讀原始碼05/29 11:10
comesuck: 原po針對的是演算法的部分;架構切割不完全(沒有各自負05/29 12:19
comesuck: 責功能的class or method)05/29 12:19
comesuck: 只要開發者開始負責某功能,而資料存取不是透過外部(ex 05/29 12:32
comesuck: :http api)取得,那所有這個功能相關的演算法、資料存 05/29 12:33
comesuck: 取 source code他都必須trace 一遍05/29 12:33
comesuck: 至於演算法複不複雜,算其次;這個演算法符不符合需求do05/29 12:37
comesuck: main的情境,才是維護的人該注意的05/29 12:37
comesuck: 跟需求落差很大的source code,對使用者來講毫無用處05/29 12:43
comesuck: 甚至會誤導方向 05/29 12:45
kiwatami: 接維護通常是驗收後的程式了05/29 22:22
kiwatami: 怎麼會有跟需求落差很大這種東西...?05/29 22:22
kiwatami: 原po第一段提到為什麼要閱讀 但接維護沒有為什麼05/29 22:22
kiwatami: 要改功能就是要讀 要修 bug 就是要讀05/29 22:22
kiwatami: 所以才說原 po 是從一般使用者的角度 才有所謂要不要讀 05/29 22:22
kiwatami: 第二段其實有點偏離主題 因為通通寫在一起不會跑比較快05/29 22:22
kiwatami: 同理功能分離效能也差不了幾微秒05/29 22:22
kiwatami: 所以效能問題不太會牽扯到這個東西05/29 22:22
kiwatami: 這反而是開發速度與維護速度的問題 05/29 22:22
kiwatami: 而 原原 po 要探討的就是高效能複雜的演算法05/29 22:22
kiwatami: 以及普通效能但可讀性高的演算法該如何選擇05/29 22:22
kiwatami: 也就是未來的可維護性 怎麼複雜度反而變成其次考量呢?05/29 22:22
kiwatami: 是瓶頸的不管多複雜都要用 但解法不一定只有一種05/29 22:22
kiwatami: 這反而是寫程式最花時間的時候 選擇使用哪一種方法解05/29 22:22
kiwatami: 以及評估各方法間的效能差異05/29 22:22
kiwatami: 為了解決問題 就算接手的人要花一個月才看得懂 05/29 22:22
kiwatami: 也得硬著頭皮寫下去 註解超多行 文件超厚也得寫 05/29 22:22
kiwatami: 反之就盡量維持高可讀性 因為不是重點05/29 22:22
kiwatami: 其實 原 po 說的並沒有甚麼不對的地方05/29 22:22
kiwatami: 只是出發點跟原原 po 要探討的有點不同而已05/29 22:22
comesuck: 可能最後有點扯遠了XD,但「驗收過」不等於「功能符合05/29 23:17
comesuck: 需求」(起碼要有9成才算);但經驗遇過的很多都是功能 05/29 23:17
comesuck: 「部分符合」(5成),驗收先過,之後再補。05/29 23:17
comesuck: 至於功能通通寫在一起,影響最大的不會是效能;影響最大05/29 23:21
comesuck: 的會是可讀性與可擴充性;class功能職責區分不明確,新05/29 23:21
comesuck: 功能程式碼找不到地方擺,就必須先重構05/29 23:21
comesuck: 對,原po一開始確實針對原原po的問題回應(開發);只是 05/29 23:32
comesuck: 後來的推文、編輯回文,情境轉成維護;是兩個討論主題05/29 23:32
可能是我沒有表達清楚 orz 我想說的是 不論想要對程式做什麼改動 不外乎是 增加 & 刪除 這兩個動作 我們想做到的 就是讓使用者、維護者etc...可以針對“功能”下手 而不需要針對“實作”下手 不論維護、閱讀、使用 都是以“功能”為單位 例如現在假設老闆希望產生的結果從 a 改成 b 好了 要是是介面不合需求了 我只需要製作一個新的介面取代原本的就好了 (取代 也就是刪除->增加 而且要以功能為單位才好) 要是是演算法不符合需求了 我一樣只要重寫新的算法 然後塞進原本的坑裡就好了 一樣也是以功能為單位的增加&刪除 只要每個程式片段都有相對應的抽象化概念 我只需要針對這些概念下手 這樣我根本就不需要真的去看原本程式的實作了 而這時候 1. 要如何利用抽象化的概念和設計來精確的表達出實作的確切資訊 (ex 行為、需求、特性、限制 etc...) 2. 把功能切割到不能再切割 就會是很重要的議題了 先討論 1 因為現在我們假設不從實作取得任何相關資訊 我們必須做到讓使用者、閱讀者、維護者都能夠絕對相信這些表面的資訊能夠代表實作真 正的行為 而且要盡可能地表達清楚、詳盡 而想要精準地描述程式確切的資訊 最棒的方法就是利用慣例 因為寫文件很累寫註解又很醜 XD 而且這些外加的描述也是麻煩的相依性 我更新程式 這些東西不就也要一併更新? 但是如果用慣例來表達 就沒有這種相依性的問題了 例如我一看到 singleton 就會知道這個東西一定有哪些哪些特性 或是看到 static const constexpr member 而非 enum 就知道設計者一定是因為考慮到了什麼什麼原因才這樣設計 再來是 2 最重要也最基本的責任的切割和分配 為什麼要把功能切割到不能再切割?因為你有可能會說 把產生的結果從 a -> b 只需要改原本算法的其中一部分就好了 我為什麼要重寫一個新的?那其實就是這個算法還可以再被分割 我覺得一個程式就像是一棵樹 兄弟代表不同功能 父子代表同功能不同抽象化階層 責任的分割就是在規劃兄弟節點 而責任的分配則是在規劃父子節點 一開始所有東西都混雜在一起 接著只要一直不斷地把程式碼從這個節點分離出去 能夠分割的就變成兄弟 能夠往下放的就變成父子 完成後再一次考慮所有節點的切割(兄弟)、分配(父子) 一直到無法再分離了 就完成了責任的切割和分配 接著就可以開始考慮每個節點的命名、要不要套用什麼模式、語言上的考慮和選擇 (ex 要用 function object 或是 lambda) 這樣你就完成了一個程式的架構設計 接著就是把實作填進架構裡 最無聊的工作 最後就是一些小調整 像是 for + if 可以用 find 取代之類的比較無關緊要的小改動 這樣就完成了架構設計 當然 系統設計又是另外一個故事了 orz 我們來重新整理一下好了 1. 以功能為本的設計 優點:利於對程式的修改和理解 只需對功能下手 前提:好的責任切割、分配 否則更改程式時一樣會難以下手 2. 用抽象化的概念代表一個程式片段 優點:不需要閱讀實作 只要看名稱、找慣例就可以取得行為和其他資訊 前提:好的責任切割、分配 否則命名名不副實、慣例難以套用 3. 責任切割、分配 優點:擴充性 前提:這個程式片段有變動的可能 另外 我會推 policy based design 就是因為 它需要把一個概念分解成好幾個不同的 policy (責任切割、分配) 然後需要為每個 policy 取適當的名字 (抽象化的概念代表程式片段) 而且它被提出時就是為了達到"以功能為本"這個目的 XDD 所以要是懂了 policy based 這些問題也可以很容易解開了 當然 這些都是我自己的方法 我會說不瞭解外面的生態就是因為 我知道在外面一定已經有一套開發流程 這是我還要去和外面磨合的 我不可能都自己工作不管別人 總是要和別人合作的嘛 但是我相信雖然這不是業界人家在用的流程 但是一定還是可以從裡面看出一些端倪的~ ※ 編輯: CoNsTaR (101.12.225.17), 05/30/2016 05:46:18
ripple0129: 差不多是這樣,一開始就看原始碼我也覺得不如ㄧ開始05/30 08:36
ripple0129: 先寫測試程式,結果都如預期事實上原始碼可以跳過。一05/30 08:36
ripple0129: 些pattern的用意也是讓你可以不用管底層實作05/30 08:36
kiwatami: 驗收過待補不會交維護 而且那也是整體功能有缺05/30 10:26
kiwatami: 怎麼可能有演算法跟需求落差很大這種事?05/30 10:26
kiwatami: 那寫這個演算法出來是練打字嗎?05/30 10:26
kiwatami: 演算法他就是一個完整的功能05/30 10:26
kiwatami: 他不會只有一個 method 也不會有什麼架構問題05/30 10:26
kiwatami: 也不需要考慮介面什麼的05/30 10:26
kiwatami: 執行緒可能也不只一條05/30 10:26
kiwatami: 純粹就是為了解決問題所以邏輯上比較複雜05/30 10:26
kiwatami: 這種演算法怎麼可能說重寫就重寫05/30 10:26
kiwatami: 要修改的部分也可能是其中的好幾個地方05/30 10:26
kiwatami: 而在這樣的過程中完全不用讀程式碼?05/30 10:26
kiwatami: 還是說只有讀到int a = b; 才算"讀"程式碼?05/30 10:26
kiwatami: 你說的比較像是各功能間配合的"開發模式"05/30 10:26
kiwatami: 說到後來反而像是在教人寫程式該怎麼寫才漂亮05/30 10:26
kiwatami: 不太像是原原 po 主要探討的議題05/30 10:26
kiwatami: 就像我們在討論烤雞翅要這樣調烤肉醬才好吃05/30 10:26
kiwatami: 你卻在說烤肉架最好用精工牌的 a5 型號烤起來最好吃05/30 10:26
kiwatami: 雖然最後都會影響到好吃程度 05/30 10:26
kiwatami: 可是醬料該怎麼調 跟烤肉架用哪牌是兩個不同的層級05/30 10:26
kiwatami: 不是說你推薦的烤肉架不好用 而是醬料才是靈魂啊!05/30 10:26
真的 我回答的不是原原 po 問的問題 可是他問的根本就不成問題啊… orz 演算法的難易度和 clean code 其實根本就沒什麼關係 所以我才會直接推薦 clean code 畢竟使用什麼演算法常常是效率考量優先 怎麼可能因為好讀就改用慢的算法? 除非是在一些效率無關緊要的地方 那在這種地方也不會需要讓你去仔細鑽研算法 只要知道行為(功能/輸入輸出/限制/需求 etc...)就可以了 相比之下 程式碼的可讀性更大的掌握在你的設計 再來來討論下你講的 那麼這個算法的“核心部分”(指的應該是直接決定外顯結果的部分?) 是不是也可以抽離出來? 改它發現不好改 難讀 邏輯複雜 是不是因為該分步驟的沒有分 該抽象化給名稱的沒有做 所以使用者才需要這樣閱讀源碼推敲行為? 一個算法當然可以再拆成更多不同的算法 像是你講的單緒多緒 就可以拆成不同的 policy 來實作 就算一開始功能比較陽春 先求有 我只實作了單緒 但是我一樣會把所有以後有可能改動的地方 或是有可能需要不同行為/結果的地方都預先做好準備 讓之後需要改程式行為的時候可以直接有個坑可以塞 (那種永遠不可能改的地方我才不理它勒 XDD 根本不會有動機去做那些東西的擴充性) MCD 裡面剛好就有把單緒多緒做成各種不同的 policy 的範例 (singleton 實作那章) 因為我不知道你是用什麼演算法舉的例子 所以我就隨便舉個例子吧 像是基因演算法好了 或許你會說 基因演算法就是基因演算法 我整個程式他媽就是一個基因演算法 我想要改程式的行為 當然一定要直接對實作下手 啊不就基因演算法 哪還有什麼架構不架構的問題 可是一樣是基因演算法 你的配對池可以有很多種不一樣的實作/行為 你的 randomizer 也可以有很多種不同的實作/行為 單緒多緒、配對方法、變異方法、發散收斂的控制、優化的方法…… 通通都是可以分開單獨討論的算法 要是發明基因演算法的人沒有把基因演算法區分成這些概念/步驟 它不也是一個"單純邏輯複雜步驟很多難以理解"的算法? 要是一開始就把可能變動的地方做好準備該抽象化的抽象化該獨立的獨立出來 這樣子我在改程式的時候不就可以針對功能下手了嗎? 所以才說責任的分割很重要 一定要考慮到不能再分割為止 如果考慮到擴充性可能影響效能的話一定選擇 policy based 就算沒有效率問題 選它的機率也還是很高的 XD 因為可讀性本來就不取決於演算法的難易度 不懂算法是使用者自己的問題 就像你不會因為初學者不懂 pointers 就不用 pointers 一樣 與其用一堆簡單的初學者都會的語法加上一堆說明/文件來降低難度 不如用好的寫法 不懂的自己學完再來 因為我的對象本來就是已經會的人 這裡也一樣 與其用簡單的算法來增加那些微的可讀性(真的會增加嗎) 還不如直接增加可讀性 你還可以選用更好的算法
comesuck: 認為演算法跟需求落差很大是罕事,我沒意見;只是在一05/30 12:56
comesuck: 個常態使用合約裡空泛的幾句話去定義一個功能scope的大05/30 12:56
comesuck: 環境底下,出現演算法與需求的落差,機率應該頗大吧?05/30 12:56
comesuck: 對,假設原原po的情境是:a要調出好吃的烤肉醬把烤肉烤05/30 13:05
comesuck: 好;那原po的情境比較像是:烤肉的任務a進行到一半,烤05/30 13:05
comesuck: 肉醬的材料切好了,現在換成b來接手,b憑經驗把材料組好05/30 13:05
comesuck: 變成烤肉醬,再完成烤肉任務。期間,只要換口味了,那就05/30 13:05
comesuck: 會發生醬料不符合口味的情境。05/30 13:05
comesuck: 至於不同廠牌的烤肉架,比較像是決定實作的framework或05/30 13:08
comesuck: 語言05/30 13:08
comesuck: 掌廚的人跟醬料會是勝負的關鍵05/30 13:09
comesuck: 我在講什麼...05/30 13:10
XDD 被你們講得我都想揪一個烤肉團了啦~~~ 端午節就是要烤肉啊!!! ※ 編輯: CoNsTaR (163.18.32.152), 05/30/2016 14:30:44
comesuck: 咦?XD05/30 14:42
※ 編輯: CoNsTaR (163.18.32.152), 05/30/2016 15:40:06
GoalBased: 假設情境是,bubble sort比quick sort容易讀,但quick05/30 18:56
GoalBased: sort比bubble sort還快,那要選哪個呢?05/30 18:57
GoalBased: 原PO的問題比較像是這樣吧...05/30 18:57
ripple0129: 會用quick sort然後做成api出來是要的結果就好了,裡05/31 02:01
ripple0129: 面的東西不用讀了,知道怎麼用即可XD。我是覺得樓主 05/31 02:01
ripple0129: 說的很清楚了,大概就類似這樣的做法。除非是演算法出 05/31 02:01
ripple0129: 問題不得不進來讀原始碼吧。 05/31 02:01
樓上真知我者也 我不想再打長長一大篇了 好浪費時間 不過我還是會盡力回的
kiwatami: 演算法跟需求落差很大驗收還會過 05/31 10:21
kiwatami: 那我乾脆寫個假結果給他驗收就好啦... 05/31 10:21
kiwatami: 何必寫什麼複雜的運算結果還是錯的 05/31 10:21
kiwatami: 不是效能瓶頸的地方當然不需要用複雜演算法 05/31 10:21
kiwatami: 因為提升的效能很有限05/31 10:21
kiwatami: 再來不管你分割的多清楚 你就是得讀原始碼05/31 10:21
是的 每個階層其實都是上個階層的“原始碼”
kiwatami: 難道原本只需要改迴圈的數量就好也要重寫嗎?05/31 10:21
kiwatami: 沒有讀過怎麼會知道要改迴圈的數量呢? 05/31 10:21
對啊先想想為什麼需要改迴圈的數量 迴圈的數量是由什麼控制的 控制迴圈數量的那個數字應該要叫做什麼 抽象化出來之後該放在哪裡? data member ? function parameter ? 或是要用別的資結來儲存?
kiwatami: 難道名稱是 loop3times 嗎?不然只看名稱怎麼知道?05/31 10:21
最無腦就 loop<N>() 供參考 或是你也可以想 那個 "loop" 實際上是在幹嘛 總不可能只是純粹 loop 什麼事都不做吧 那跑幾遍這個“數字”的意義是什麼? 把它變成 parameter 傳進去 或是把它變成 member 數字可以從其他地方控制 還有 lambda 的 closure 可以用 這也可以隱含的 close 變數
kiwatami: 知道怎麼用不需要讀裡面的就是一般使用者的情境05/31 10:21
kiwatami: 維護人員一定需要讀裡面的東西05/31 10:21
kiwatami: 難道你讀程式碼的定義是我沒有讀完全部就不算讀嗎?05/31 10:21
有種東西叫做測試 通通綠棒 就可以下一個了
kiwatami: 我只讀了三分之一 只讀了其中的幾個 method 就不算讀?05/31 10:21
kiwatami: 再提一個更簡單的例子05/31 10:21
kiwatami: 假設今天某個變數在運算過程中要多加一個常數05/31 10:21
kiwatami: 難道你事先知道這邊要這樣改嗎?05/31 10:21
kiwatami: 還是說每個計算不管多簡單 就算只是指定變數值05/31 10:21
kiwatami: 也要切出來?為了所謂的預防萬一以後要改?05/31 10:21
kiwatami: 難道不可能會有以上這種情況發生?05/31 10:21
我覺得你搞錯了 這些東西不是要拿來背或是拿來遵守的定死的規則 如果你是程式作者 你在寫程式的時候一定很瞭解自己的程式吧 我會在自己最瞭解這個程式的當下就想到我之後回來還能不能看懂 我會為自己留下一條先開闢好的道路 以免以後回來什麼屁都要重新開始
kiwatami: 維護要改的東西什麼都有可能什麼都不奇怪 05/31 10:21
kiwatami: 更何況有些時候算法是要一直調整的 05/31 10:21
沒錯啊 這些想法本來就是為了以後需要“一直調整”“什麼事都會發生”而出現的 所以才要避免寫死 抽象化不就是為了保留最大的兼容性嗎? 回到問題 調整什麼?用參數可以解決嗎? 既然這個算法是容易一直變動的 那為什麼當初對這一點沒有防範? 難道是寫 code 的人對這個算法的用途不瞭解?
kiwatami: 還是說在你的理論裡不會有開發到一半離職的情形?05/31 10:21
kiwatami: 還是說接手的不管如何就是重寫尚未完成的部分?05/31 10:21
kiwatami: 如果不是的話你要怎麼知道他寫到什麼程度?05/31 10:21
一開始閱讀 後來 api 使用者 再來維護者 現在變接手作者了 寫這篇好命苦啊 每個角色都要輪一遍 QQ
kiwatami: 靠名稱?靠慣例?靠心電感應?(喵喵)05/31 10:21
kiwatami: 用一個開發模式就號稱以後完全不需要動原始碼05/31 10:21
當然人非聖賢 不可能做到完美 但是差別只在有沒有被雷過(自己、別人)的經驗 知不知道哪邊需要注意 就像打電動 不就時時刻刻在注意 哪邊要小心 哪邊要怎樣 當遇到什麼什麼情況 你還是會跟新手說 那個牆角要注意 你現在從這邊…… 不是嗎 那麼你覺得如果他回答你 你講的又不一定每次都這樣 還有可能會怎樣怎樣啊 怎麼可能按照你說的做 就可以躺著把這個遊戲打到完美 我才不要用你這些規則 你會跟他說什麼
kiwatami: 這不太可能 不管你切的多細多完美05/31 10:21
kiwatami: 影響到的只有讀的範圍多寡而已 而不是"不用讀"05/31 10:21
是的 但是這樣會比原本改善很多 可能不只很多 是很多很多 而且我們的目的並不是讓你的程式變成沒人讀的程式 而是希望讀對的地方讀有意義 可以快速傳達概念的地方 當然不可能完美 但是沒有人會因此就不做
kiwatami: 原 po 假設的情況太過於完美 而現實的瑕疵太多了05/31 10:21
遇到現實問題而不知道如何用知識解決的時候 我的第一反應也是認為唉 知識就只是知識 太理論化了 現實無用 等到有一天經驗累積了 我自己體會這些知識之後 才開始覺得之前怎麼沒有好好讀懂它真正的意思 理論都不是表象看到的那樣 它一定有它適用的時機 也有不適用的時候 它達到的目的或許不是你眼前想要的 就覺得它是屁 等需要之後才發現它的好
kiwatami: 是瓶頸的部分不管你演算法多複雜都要寫05/31 10:21
kiwatami: 這我應該提到幾次了 簡單的算法也不是只有初學者的語法05/31 10:21
kiwatami: 而是不用過於特殊的方法去解決問題05/31 10:21
kiwatami: 可讀性的意義跟簡單完全是兩回事 風馬牛不相及05/31 10:22
我知道 我是舉例 你不會為了讓初學者看懂你的程式 就用簡單的語法 那你也不會為了某些人看不懂你寫的困難的演算法 而不用它
comesuck: 會有這種結果,就不懂軟工啊;使用者只看ui;與修改中的05/31 12:10
comesuck: 功能相關的class,只要用到的method都要讀(只用到兩個05/31 12:10
comesuck: ,你沒必要把20個全看完,但看懂是其次,意不意會的到05/31 12:10
comesuck: 它有沒有符合情境才是關鍵);今天不會莫名其妙加常數,05/31 12:10
comesuck: 決定加一定是因為有需求、有情境、經過討論後才決定修05/31 12:10
comesuck: 改抽象化與實作;ok,程式碼開發到一半人員離職怎麼辦?05/31 12:10
comesuck: 看你如何降低程式碼與開發者的耦合,對我來講,就是畫UM05/31 12:10
comesuck: L把抽象化概念拉出來討論(畫到sequence diagram 就可以05/31 12:10
comesuck: 收斂大部份的方向了);開發者按圖施工,就算你寫到一半05/31 12:10
comesuck: 閃了,也不會出現不知道抽象化怎麼做下去的窘境;05/31 12:10
comesuck: 切function愛怎麼切看開發者,好或壞由維護的人定奪;05/31 12:17
comesuck: 但記得稟持童子軍的精神05/31 12:17
我知道我們這些想法對一些很聰明的人來說不太能有共鳴 因為對那種人來說我們覺得麻煩需要思考的東西 他們都覺得沒什麼困難啊 不就這樣 所以對我們來說好維護好讀是重點 但是他們沒那需求 因為他們的大腦能負荷 可能要等他們真的被一個複雜到爆又亂七八糟的系統搞死之後才會回來注意這些東西吧 反正人各有志 道不同不相為謀 每個人都有自己的路 ※ 編輯: CoNsTaR (163.18.32.152), 05/31/2016 16:34:30
comesuck: 做認為是對的事就對了~ 05/31 16:46
viper9709: 推這篇~觀念正確 05/31 23:57
kiwatami: 我從來不認為你說的是屁 一直都很讚同你說的 06/01 10:10
kiwatami: 也沒有說不要用你的方法去實作 06/01 10:10
kiwatami: 只是你的角度與原原 po 要討論的不同啊... 06/01 10:10
嗯…我有說過了 因為他在糾結不該糾結的東西 所以我跟他說 要是你的設計夠好 那根本連實作都不用看(翻譯是 人家根本連實作都不想看)
kiwatami: 你說這樣的寫法不需要讀 所以我回應你說不可能不用讀 06/01 10:10
kiwatami: 你說這樣的寫法不需要改 只要重寫06/01 10:10
kiwatami: 但很多時候不可能重寫就好06/01 10:10
你有想過前提嗎 我說不用讀不用改的前提是什麼?
kiwatami: 所以舉例了一堆情況 06/01 10:10
kiwatami: 為什麼有算法需要調整?因為這個算法可能是顧問提供的06/01 10:10
kiwatami: 算出結果後發現有偏差於是需要調整 06/01 10:10
這樣不能算在有 bug 裡面嗎? 而且行為和預期也不同啊 命名名不符實不也想傳達類似的概念嗎? 再來要是實作得夠好 你能不能把“需要改的地方”給個名字 然後從實作裡面找到和這個名子一樣概念的元件 然後替換掉它? 要是可以 那不就是以元件為單位的修改? 要是不行 那是不是他的實作不夠親和? 要是找到之後 不能確定是不是你想改的 那不就是概念沒有傳達好? 該怎麼傳達更好?難道叫你去讀實作? 要是你找到了 但是發現還是得看實作 那是不是代表你切得太大了 找到的是需要修改的元件的上層?(切割到不能再切割) 這些你有想過嗎?還是覺得這應該是我有義務交代給大家的部分?
kiwatami: 因為這一大堆情況都需要"讀" "改" 程式碼06/01 10:10
kiwatami: 而你一再強調不需要讀 也只需要重寫06/01 10:10
事實上真的如此 在你的 code 體質好的前提下 不要再拿那些體質不好的 code 來反駁了 orz 這篇不適用那些情況
kiwatami: 我反駁的從頭到尾都是這點 但你最後的回應06/01 10:10
kiwatami: 搞得好像我反駁的是你提倡的開發模式06/01 10:10
kiwatami: 也似乎忘了你一開始一直堅持的不用改不用讀06/01 10:10
我並沒有堅持什麼 (苦笑
kiwatami: 甚至連註解跟文件都不用寫不是嗎?06/01 10:10
我不是這樣說的嗎: 假設現在我們無法從實作取得資訊 而想要利用命名/慣例…來讓使用者取得所有資訊 要是你真的做到了 你就不需要 註解/文件 了 因為註解ooo文件xxx反正就是不喜歡 你真的有認真看完我想表達的東西嗎?我寫得很認真欸 你給我的感覺只是一直想找碴 or z
kiwatami: 從頭到尾你觀念錯誤的地方從來就不是開發模式06/01 10:10
kiwatami: 而是你把接手人員的情況想得過於簡單06/01 10:10
不要再拿體質不好的 code 來說了 更大的問題是出在體質不好 不是在接手 而且你要自己想想前提是什麼 適用的時機是什麼 什麼時後情況如何啊! 我把最精華的部份交給你 那個濃淡你要自己調啊! 我沒辦法在這裡把所有情況一一列出來 所以只能把最沒有其他因素的拿出來 難道我該找一個已經被很多因素影響之後的例子來舉例嗎?這樣能夠幫助新手抓到重點嗎 ? 學校教的理論不也都是這樣 純理論和應用之間的銜接不應該是大家都已經駕輕就熟的嗎 ?
kiwatami: 把這個開發模式想得過於強大06/01 10:10
kiwatami: 好像用了這個開發模式一切都不會有問題06/01 10:10
kiwatami: 我反駁的是這個過於天真的想法06/01 10:10
kiwatami: 把我打成一個異教徒並沒辦法掩蓋這個事實06/01 10:10
kiwatami: 為什麼討論到後來總是變成在酸人 亂扣帽子06/01 10:10
kiwatami: 最後連自己當初堅持的想法都忘記了?06/01 10:10
kiwatami: 要不要回頭看看你說的東西 再看看你最後的回覆?06/01 10:10
kiwatami: 完全像是兩個不同立場的人在說話06/01 10:10
kiwatami: 最後那段酸文對討論又有什麼幫助?06/01 10:10
上面這段太偏激了 不回 反正說到最後就是在炮我表達上的問題 但是我真的努力了好嗎 我有錯 可能是因為我想要讓原原 po 很有感覺 所以才在前面講得誇張了點 但是每個結論都有適用和不適用的地方 這是每個人要靠自己去判斷的 我在這邊能做的 就是提供我的“萃取濃縮精華” 因為這種高濃度的東西才容易讓新手直接抓到重點 至於要在哪邊稀釋或是哪邊適用不適用 就靠每個人自己去體會了 我沒有必要在這邊回原原 po 的時候把所有場合的輕重緩急都描述得清清楚楚吧 一個已經對這些概念有足夠經驗的人在看的時候 會自己知道每句話實際上代表的輕重 看起來應該是很有感覺的 而不會把其中一句話當作最極端的例子或是想出各種立場來對這個概念反覆驗證 只有新手在對一個新東西的運作不太有信心 想要更了解它的底限在哪時才會這麼做 不知道你同不同意 如果你發現你對理論不是很有共鳴 覺得它施的力沒有打到痛處 那麼你要讀的是 註 不是 經 我記得 Gof 的那本設計模式在網路上評價不高 還被網友評“虛無縹緲”“不切實際” 有一本設計模式的書介紹裡有講 Gof 是設計模式的提出者 其他設計模式的書都像是在為 它做註 雖然其他本評價較高 但我個人還是最喜歡 Gof 那本 現在偶爾還會打開翻翻 我不是說我講的東西多高級 而是當你無法和純理論描述對頻的時候就該去看註 因為經惜字如金 有太多情況沒辦法一一說明的 就只講最精華的 共通的地方 還有 我沒有把你當成異教徒啦 XDDDD 和你討論之後 我也冒出了很多新的想法等待驗證 很多地方也表達得更清楚了啊 還是很感謝你的啦! 至於你說酸文 不知道是誰先開始的 我當下覺得你很盧 又沒有把我講的看清楚 又要一直 曲解硬套一句話來鬧 而且感覺對我們討論的東西也不是很了解(你講的那些問題點真的都 只是我們平常一直在做的事 都好好的 真的沒什麼問題) 如果你是新手不瞭解這樣很正常 但是你明明就不是新手 讓我不知道你想幹嘛 不過既然我已經懂你的立場了 如果你需要的話我還是在這裡和你說聲抱歉 orz 啊啊啊啊啊啊啊啊啊啊 如果你說的酸文是指 回 c 大的那一段 那個不是酸文啊!!! 就算酸 也是我內心的辛酸啊 (誤 那真的沒酸啦 QQ
comesuck: 他提倡較好讀較好改...沒有到不用讀不用改吧06/01 12:47
※ 編輯: CoNsTaR (163.18.32.152), 06/01/2016 15:44:49 ※ 編輯: CoNsTaR (163.18.32.152), 06/01/2016 17:14:41 ※ 編輯: CoNsTaR (163.18.32.152), 06/01/2016 18:09:51
kiwatami: 原 po 第一段提到"程式為什麼讓人想看裡面的實作" 06/02 09:34
kiwatami: 沒有為什麼 要改就是要看 這4點只符合一般使用者 06/02 09:34
kiwatami: 並不符合一般接手程式的情況 06/02 09:34
kiwatami: 但之後原 po 又說其實要讀 只是範圍小了點 06/02 09:35
kiwatami: 這不是完全跟你前面幾次回覆要說的完全不同了嗎? 06/02 09:35
kiwatami: 之後原 po 又提到"要是演算法不合需求了 重寫就好" 06/02 09:35
kiwatami: "也不需要看程式內的實作" 06/02 09:35
kiwatami: "要表達程式資訊最棒的方法是使用慣例" 06/02 09:35
kiwatami: "因為註解文件又累又醜" 06/02 09:35
kiwatami: 並不是炮你表達 而是以上這些觀念都是不對的 06/02 09:35
kiwatami: 原原 po 的問題不成立是因為該寫的地方不用考慮複雜度 06/02 09:35
kiwatami: 而不是你說的"只要架構夠好根本不需要讀" 06/02 09:35
kiwatami: 這不是表達的問題 這是你真的這樣認為才會這樣說 06/02 09:35
kiwatami: 因為你覺得這個開發模式太美妙 想推廣給大家 06/02 09:35
kiwatami: 但不得不承認的是很多情況並不是開發模式可以解決的 06/02 09:35
kiwatami: 但你又堅持可以 只是對方貫徹的不夠徹底 06/02 09:35
kiwatami: 你最後也說很多結論有適用與不適用的地方 06/02 09:35
kiwatami: 但我提出了不適用的地方 你卻一直反駁這其實適用 06/02 09:35
kiwatami: 無法接受這個事實的不就是你自己嗎? 06/02 09:35
kiwatami: 不是體質不夠好 就算體質再好你還是要讀 06/02 09:35
kiwatami: 這這是我一直想告訴你的 但你一直不接受 06/02 09:35
kiwatami: 最後你的回覆不就是我前面一直想說的嗎? 06/02 09:35
kiwatami: 但你又把我打成了你的方法無用論者 06/02 09:35
kiwatami: 明眼人都看得出來很聰明那段是在酸人寫 code 架構差 06/02 09:35
kiwatami: 又死腦筋不願改進 06/02 09:35
kiwatami: 我只是覺得這對討論一點幫助也沒有 06/02 09:35
kiwatami: 這不是誇張了點 這是誇大成效 你要做的不是描述各種眉 06/02 09:35
kiwatami: 角 06/02 09:35
kiwatami: 而是忠實傳述這個開發模式的優點與目的就好 06/02 09:35
kiwatami: 不用讀 不用改 不用註解與文件云云根本是多餘又錯誤的 06/02 09:35
kiwatami: 可以的話請你回頭看看我在14樓回你什麼 06/02 09:35
kiwatami: 是不是就是你說的某些不適用的情況? 06/02 09:35
kiwatami: 但結果呢?你不接受 才有了這一大篇最後都歪樓的討論 06/02 09:35
kiwatami: 但最後你又接受了... 卻又說我在鑽牛角尖 06/02 09:35
kiwatami: 但我要表達的就是你最後結論提到的 06/02 09:35
kiwatami: 有適用與不適用的情況 這點而已 06/02 09:35
kiwatami: 也是你一開始堅持絕對沒有的東西 06/02 09:35
CoNsTaR: 嗯…很好啊 戰鬥力滿分 繼續保持…… 06/02 22:12