ο缶幊蹋簭哪_本到工程的關(guān)鍵一躍)
簡(jiǎn)介本資源為2021年出版的《Python Object-Oriented Programming》第四版英文原版PDF由Steven F. Lott與Dusty Phillips合著面向希望系統(tǒng)掌握Python面向?qū)ο缶幊痰拈_發(fā)者。全書依照“類與對(duì)象基礎(chǔ)—封裝與繼承—多態(tài)與特殊方法—設(shè)計(jì)模式—測(cè)試與維護(hù)”的脈絡(luò)展開既覆蓋OOP核心概念也給出構(gòu)建健壯應(yīng)用和可維護(hù)Python庫(kù)的實(shí)際方法適合從入門到進(jìn)階的Python工程師及教學(xué)參考。資源共1個(gè)文件為PDF格式壓縮包大小約6.51MB便于在線閱讀或?qū)牍P記工具。目前已有43人學(xué)習(xí)下載。相比零散教程這份完整英文原版能幫助讀者建立面向?qū)ο笤O(shè)計(jì)思維同時(shí)理解異常處理、單元測(cè)試、版本控制與依賴管理等工程實(shí)踐細(xì)節(jié)適合作為長(zhǎng)期案頭參考書。1. 先搞懂一個(gè)概念面向?qū)ο蟛皇切W(xué)是組織代碼的思維剛學(xué)Python的朋友都有過(guò)這種遭遇寫幾十行小腳本順順利利程序長(zhǎng)到上千行就一團(tuán)亂麻——改一個(gè)小功能崩了三個(gè)地方。這時(shí)候需要的不是更多技巧而是更好的組織代碼的方式。面向?qū)ο缶幊叹褪沁@種更好的方式它不玄。核心一句話把數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)打包成獨(dú)立的小單元叫作對(duì)象。每個(gè)對(duì)象各管一攤協(xié)作時(shí)通過(guò)明確的接口說(shuō)話。好比餐廳廚師炒菜、服務(wù)員傳菜、收銀員結(jié)賬各司其職?!禤ython面向?qū)ο缶幊痰谒陌妗氛侵v這件事從類與對(duì)象講到繼承、異常、數(shù)據(jù)類、設(shè)計(jì)模式再到測(cè)試與并發(fā)適合一寫復(fù)雜程序就發(fā)怵的初學(xué)者。2. 為什么必學(xué)面向?qū)ο髲哪_本到工程的關(guān)鍵一躍2.1 先看一個(gè)失控的例子加功能的腳本如何變成亂麻先復(fù)制一個(gè)很常見(jiàn)的場(chǎng)景。你接了個(gè)小任務(wù)統(tǒng)計(jì)班里同學(xué)的成績(jī)。第一版很快就寫完了students [(A同學(xué), 85), (B同學(xué), 92), (C同學(xué), 58)] total sum(score for _, score in students) print(平均分:, total / len(students))一個(gè)列表、一行統(tǒng)計(jì)、一個(gè)打印干凈利落。然后需求來(lái)了要標(biāo)出不及格的同學(xué)要按分?jǐn)?shù)排序要按成績(jī)段統(tǒng)計(jì)人數(shù)還要知道誰(shuí)比平均分低。你開始一個(gè)接一個(gè)地往里塞函數(shù)def print_failed(students): for name, score in students: if score 60: print(f{name} 不及格) def sort_by_score(students): return sorted(students, keylambda x: x[1], reverseTrue) def grade(score): if score 90: return 優(yōu) if score 80: return 良 if score 60: return 及格 return 不及格這段代碼現(xiàn)在還能看懂但隱患已經(jīng)埋下了所有函數(shù)都在操作同一個(gè)列表誰(shuí)都能隨時(shí)改它。某天你決定在列表里加一項(xiàng)數(shù)據(jù)比如“班級(jí)”把原來(lái)的二元組變成三元組上面每個(gè)函數(shù)就都得跟著改漏改一個(gè)程序跑出來(lái)的結(jié)果就是錯(cuò)的。更折磨的是這個(gè)列表被十個(gè)函數(shù)傳來(lái)傳去你想找“到底是誰(shuí)改了里面的數(shù)據(jù)”只能靠肉眼逐行讀。這就是面向過(guò)程腳本的典型困境數(shù)據(jù)是“光著”的在任何地方都可能被改動(dòng)功能一多你就像同時(shí)維護(hù)十根纏在一起的毛線。程序不是一下子爛掉的是每一行新代碼都在上面打了個(gè)結(jié)。2.2 對(duì)象幫你做了什么把數(shù)據(jù)和操作鎖進(jìn)同一個(gè)盒子里面向?qū)ο蟮乃悸吠耆珦Q了個(gè)問(wèn)法這個(gè)系統(tǒng)里最核心的“東西”是什么是學(xué)生。那就建一個(gè)“學(xué)生”類把學(xué)生自己的數(shù)據(jù)姓名、成績(jī)和所有針對(duì)這些數(shù)據(jù)的操作判斷是否及格、計(jì)算等級(jí)都放進(jìn)同一個(gè)定義里class Student: def __init__(self, name: str, score: int) - None: self.name name self.score score def is_pass(self) - bool: return self.score 60 def grade(self) - str: if self.score 90: return 優(yōu) if self.score 80: return 良 if self.score 60: return 及格 return 不及格改動(dòng)體現(xiàn)在哪里數(shù)據(jù)的存儲(chǔ)格式name、score兩個(gè)字段被固定在這個(gè)類的內(nèi)部。外面想操作一個(gè)學(xué)生不需要直接碰它的內(nèi)部而是通過(guò)is_pass()、grade()這兩個(gè)方法。以后如果要在 Student 里加一個(gè)“班級(jí)”字段受影響的地方被限制在類的內(nèi)部外面調(diào)用is_pass()和grade()的代碼一行都不用動(dòng)。這就是面向?qū)ο笞顦闼氐暮锰幱辛诉吔绺膭?dòng)才不會(huì)到處漏。2.3 你其實(shí)每天都在用面向?qū)ο髢?nèi)置類型就是對(duì)象有一個(gè)很多人沒(méi)意識(shí)到的點(diǎn)你早就天天在用面向?qū)ο笾皇菦](méi)意識(shí)到而已。Python 里的一切都是對(duì)象。字符串有.strip()、.lower()方法列表有.append()、.sort()方法字典有.keys()、.values()方法。這些“點(diǎn)出來(lái)的函數(shù)”就是對(duì)象的方法text Hello, Python .strip().lower() print(text) # 輸出: hello, python你不需要知道字符串內(nèi)部是怎么存字符的只需要知道strip()能去掉空格、lower()能轉(zhuǎn)小寫。這種“別人把內(nèi)部藏好只給你幾個(gè)操作入口”的設(shè)計(jì)就是面向?qū)ο罄镎f(shuō)的封裝。學(xué) OOP 不是學(xué)一門離你很遠(yuǎn)的新東西而是把你天天在用的東西從“會(huì)調(diào)用”升級(jí)成“會(huì)自己造”。2.4 主流庫(kù)都在講 OOP看不懂文檔的真正原因打開 pandas 的文檔你會(huì)看到 DataFrame、Series 這些“類”打開 Django 文檔你會(huì)看到 Model、View 這些“類”打開機(jī)器學(xué)習(xí)庫(kù)的文檔你會(huì)看到 estimator、transformer 這些“對(duì)象”概念。如果不懂類、實(shí)例、繼承、方法這些詞讀任何主流庫(kù)的文檔都像在看天書。學(xué)完面向?qū)ο笾竽銜?huì)發(fā)現(xiàn)文檔里翻來(lái)覆去說(shuō)的就是那幾件事這個(gè)類有哪些屬性有哪些方法我要怎么創(chuàng)建實(shí)例怎么調(diào)用方法。這套思維一旦打通再接觸任何新庫(kù)學(xué)習(xí)成本都會(huì)直線下降。這也是為什么幾乎所有 Python 進(jìn)階路線都會(huì)把面向?qū)ο蠓旁谧钋懊妗钦麄€(gè) Python 生態(tài)的地基。3. 第一個(gè)例子跑起來(lái)寫一個(gè)學(xué)生成績(jī)管理類3.1 類就是一張圖紙先定義一個(gè)空殼子第 2 章的 Student 類也許讓你覺(jué)得“這不就是把函數(shù)塞進(jìn) class 里嗎”。別急跟著我一步一步寫你會(huì)看到這樣做的價(jià)值。先打開你的編輯器或者打開 Jupyter、IDLE 都行敲下第一行class Student: pass這里的pass是 Python 的占位符表示“代碼塊還沒(méi)寫先讓語(yǔ)法通過(guò)”。運(yùn)行之后你會(huì)得到一個(gè)叫 Student 的類型但它目前什么都沒(méi)有。不過(guò)已經(jīng)可以靠它創(chuàng)建對(duì)象了s1 Student() s2 Student() print(s1 is s2) # 輸出 False說(shuō)明是兩個(gè)完全獨(dú)立的實(shí)例Student()這個(gè)寫法叫“實(shí)例化”——按圖紙?jiān)斐鲆粋€(gè)具體的學(xué)生。類本身是圖紙圖紙上畫著“學(xué)生都有哪些特征、哪些動(dòng)作”實(shí)例是根據(jù)圖紙?jiān)斐鰜?lái)的每一份真實(shí)對(duì)象。s1 和 s2 互不干擾。類只定義一次實(shí)例可以造無(wú)數(shù)個(gè)。3.2 給類加上“出生初始化”init登場(chǎng)一個(gè)真正有用的學(xué)生得有自己的姓名和成績(jī)。我們希望在創(chuàng)建實(shí)例的時(shí)候直接傳入這兩個(gè)值這時(shí)就要用到__init__方法。它在對(duì)象剛被創(chuàng)建時(shí)自動(dòng)執(zhí)行專門負(fù)責(zé)給新對(duì)象灌入初始數(shù)據(jù)class Student: def __init__(self, name: str, score: int) - None: self.name name self.score score這里有三點(diǎn)要講清楚。第一__init__里的self是 Python 自動(dòng)傳入的它指向“當(dāng)前正在創(chuàng)建的這個(gè)實(shí)例”。self.name name的意思是把這個(gè)新實(shí)例的名字設(shè)為傳入的 name。第二name: str和score: int是類型注解書上叫 type hints它不會(huì)在運(yùn)行時(shí)報(bào)錯(cuò)但讓讀代碼的人一眼就知道該傳什么類型IDE 還能自動(dòng)提示。第三- None表示這個(gè)方法不返回值。創(chuàng)建對(duì)象的方式也隨之變了s Student(A同學(xué), 85) print(s.name) # 輸出: A同學(xué) print(s.score) # 輸出: 85現(xiàn)在 s 這個(gè)實(shí)例已經(jīng)帶著自己的姓名和成績(jī)了。每個(gè)通過(guò) Student 創(chuàng)建的實(shí)例都有一份獨(dú)立的 name 和 score——改 s1 不會(huì)碰 s2。這是“實(shí)例屬性”與后面要說(shuō)的“類屬性”最大的區(qū)別也是新手最容易繞暈的地方。3.3 寫方法讓對(duì)象會(huì)判斷、會(huì)說(shuō)話類里不能只有數(shù)據(jù)還得有行為。比如判斷一個(gè)學(xué)生是否及格給它寫一個(gè)方法class Student: def __init__(self, name: str, score: int) - None: self.name name self.score score def is_pass(self) - bool: 成績(jī)大于等于60分視為通過(guò) return self.score 60 def introduce(self) - str: return f我是{self.name}成績(jī)是{self.score}分調(diào)用方式非常直白s.is_pass()返回 True 或 Falses.introduce()返回一句話。不需要往方法里傳 self——Python 調(diào)用時(shí)自動(dòng)把 s 自己傳進(jìn)去了。這跟前面字符串的lower()是同一套邏輯對(duì)象本身就是數(shù)據(jù)方法就是對(duì)象能做的動(dòng)作。特別提醒方法內(nèi)部想使用實(shí)例自己的數(shù)據(jù)必須通過(guò)self.xxx去取。如果直接在方法里寫scorePython 會(huì)認(rèn)為那是一個(gè)不存在的局部變量當(dāng)場(chǎng)報(bào)錯(cuò)。這本書反復(fù)強(qiáng)調(diào)這一點(diǎn)因?yàn)樗切率肿畛R?jiàn)的認(rèn)知斷層。3.4 類型注解、docstring 與模塊組織讓代碼像文檔一樣清楚剛才的代碼里出現(xiàn)了- bool和- str這是方法的返回類型注解。加上之后代碼的可讀性明顯提升不用讀方法體光看簽名就知道is_pass返回布爾值、introduce返回字符串。這本書更推薦把 docstring 也寫上一句話說(shuō)清楚“這個(gè)方法負(fù)責(zé)什么”class Student: def __init__(self, name: str, score: int) - None: 創(chuàng)建一個(gè)學(xué)生實(shí)例。 參數(shù) name: 學(xué)生姓名 score: 成績(jī)0~100 self.name name self.score score很多新手覺(jué)得寫 docstring 是浪費(fèi)時(shí)間但等你三個(gè)月后回來(lái)看自己寫的代碼或者別人要接手你的代碼時(shí)這段文字的價(jià)值立刻超過(guò)代碼本身。這不是儀式感是血淚經(jīng)驗(yàn)。當(dāng)類慢慢變多你就要注意組織方式了。一個(gè)良好習(xí)慣是一個(gè)類放一個(gè)文件。比如把 Student 存成student.py在另一個(gè)main.py里寫from student import Student然后再創(chuàng)建實(shí)例。這樣你的項(xiàng)目不再是“一個(gè)大腳本”而是一個(gè)結(jié)構(gòu)清晰的包。書里用了一整節(jié)講模塊和包的拆法新手階段記住“按類拆文件”就夠用了。4. 新手避坑指南5個(gè)最常見(jiàn)的面向?qū)ο蠓嚞F(xiàn)場(chǎng)4.1 坑一方法定義忘了寫 self現(xiàn)象class Student: def __init__(self, name): self.name name def introduce(): # 忘了寫 self return f我是{self.name} # 這里直接報(bào)錯(cuò)一調(diào)用s.introduce()就會(huì)報(bào)錯(cuò)TypeError: introduce() takes 0 positional arguments but 1 was given。原因Python 調(diào)用實(shí)例方法時(shí)會(huì)自動(dòng)把實(shí)例本身作為第一個(gè)參數(shù)傳入。方法定義里一個(gè)參數(shù)都沒(méi)留自然就裝不下了。這是零基礎(chǔ)學(xué) OOP 的第一大坑幾乎每個(gè)人都會(huì)踩一次。解決實(shí)例方法的第一個(gè)參數(shù)寫self就這一個(gè)名字這是規(guī)范。把定義改成def introduce(self):方法體里用self.name問(wèn)題立刻消失。4.2 坑二把可變列表放在類屬性里現(xiàn)象你想給所有學(xué)生共享一個(gè)“班級(jí)名單”于是在類的內(nèi)部寫了classmates []。然后發(fā)現(xiàn) A 同學(xué)往名單里加了一個(gè)人B 同學(xué)身上的名單也跟著多了這個(gè)人。原因類屬性是所有實(shí)例共享的。當(dāng)你寫self.classmates.append(...)時(shí)列表是類的那一份所有實(shí)例都在往同一個(gè)列表里塞東西——你以為是每個(gè)人的其實(shí)是大家的。解決不要在類定義里放可變對(duì)象。把可變數(shù)據(jù)放在__init__里用self.classmates []新建一份實(shí)例專屬的列表。類屬性只放那些“所有學(xué)生都一樣”的常量比如max_score 100。4.3 坑三為了復(fù)用代碼強(qiáng)行用繼承現(xiàn)象你的項(xiàng)目里“狗”和“車”都要“啟動(dòng)”功能于是寫了一個(gè) Base 類讓兩個(gè)類都繼承它。后來(lái)發(fā)現(xiàn)狗和車的啟動(dòng)邏輯根本不同到處都在重寫父類方法最后只能把 Base 改得面目全非。原因繼承表達(dá)的是“is-a”關(guān)系比如“學(xué)生”是一種“人”。為了省幾行代碼硬套繼承等于把兩個(gè)不相干的東西綁在一起后面的維護(hù)全是債。解決先問(wèn)自己A 是不是 B 的一種如果不是優(yōu)先用組合——一個(gè)類里持有另一個(gè)類的實(shí)例比如 Car 類里有一個(gè) Engine 類的屬性。這本書第 1 章專門講了這個(gè)取舍建議多看兩遍。4.4 坑四異常捕獲后直接吞掉現(xiàn)象代碼里寫著try: ... except: pass程序跑起來(lái)不報(bào)錯(cuò)但結(jié)果卻是錯(cuò)的查了半天才發(fā)現(xiàn)某個(gè)異常被靜默吃掉了。原因except Exception: pass讓你永遠(yuǎn)看不到發(fā)生了什么。表面安靜實(shí)際上把問(wèn)題藏進(jìn)了黑匣子出了故障完全無(wú)從下手。解決至少用 logging 記錄錯(cuò)誤或者讓異常自然地拋出讓調(diào)用者知道出了問(wèn)題import logging try: score int(input(請(qǐng)輸入成績(jī): )) except ValueError: logging.error(用戶輸入的不是數(shù)字) raise4.5 坑五可變默認(rèn)參數(shù)現(xiàn)象你定義了一個(gè)方法def add_tag(self, tags[]):每次調(diào)用不傳 tags結(jié)果上一次調(diào)用留下的內(nèi)容還在列表里越積越多。原因默認(rèn)參數(shù)是在函數(shù)定義時(shí)創(chuàng)建一次的默認(rèn)的[]是一個(gè)共享對(duì)象所有實(shí)例都往同一個(gè)列表里追加。解決默認(rèn)值寫None函數(shù)體內(nèi)再創(chuàng)建新列表def add_tag(self, tagsNone): if tags is None: tags [] tags.append(新手) return tags這五條是新手階段最常遇到的坎每一條我都親眼見(jiàn)過(guò)身邊的朋友踩過(guò)。提前知道它們能省下不少排查時(shí)間。5. 再往前走一步異常、數(shù)據(jù)類與測(cè)試的實(shí)戰(zhàn)用法5.1 異常處理讓程序出錯(cuò)時(shí)也“有尊嚴(yán)”程序一定會(huì)出錯(cuò)用戶輸入了非法值、文件不存在、網(wǎng)絡(luò)斷了。面向?qū)ο蟮某绦虿蛔非蟆坝肋h(yuǎn)不出錯(cuò)”而是追求“出錯(cuò)時(shí)能給個(gè)明白話”。Python 的try/except用起來(lái)非常自然try: user_input input(請(qǐng)輸入成績(jī)) score int(user_input) if score 0 or score 100: raise ValueError(成績(jī)必須在0-100之間) except ValueError as e: print(輸入不合法, e)這里的raise ValueError(...)是自己主動(dòng)拋出異常。更進(jìn)一步你可以定義自己的異常類讓調(diào)用者能精確捕獲class ScoreError(Exception): 成績(jī)不合法時(shí)拋出的異常 def set_score(student, score): if score 0 or score 100: raise ScoreError(f成績(jī)必須在0-100之間收到{score}) student.score score自定義異常讓錯(cuò)誤信息帶著業(yè)務(wù)含義而不是籠統(tǒng)的ValueError。在長(zhǎng)期維護(hù)的項(xiàng)目里這種明確性非常重要排查問(wèn)題時(shí)能省下大量時(shí)間。5.2 數(shù)據(jù)類一行解決掉大量重復(fù)代碼寫一個(gè)類最煩的就是__init__、__repr__、__eq__這些模板代碼。Python 3.7 加入的 dataclass數(shù)據(jù)類用裝飾器自動(dòng)生成它們from dataclasses import dataclass dataclass class Student: name: str score: int graduated: bool False就這幾行你自動(dòng)獲得了__init__按 name、score、graduated 順序接收參數(shù)、__repr__打印出一行易讀的文字和__eq__兩個(gè)學(xué)生姓名成績(jī)相同即為相等。不用再手寫一堆模板代碼字段一目了然。書里第 7 章詳細(xì)對(duì)比了普通類、namedtuple 和 dataclass 的適用場(chǎng)景新手階段記住“需要可變數(shù)據(jù)結(jié)構(gòu)的首選 dataclass”就夠了。5.3 給代碼上保險(xiǎn)用 pytest 寫最小測(cè)試程序越寫越大手動(dòng)測(cè)試已經(jīng)不夠。這時(shí)你需要一個(gè)極簡(jiǎn)的工具pytest。安裝之后pip install pytest寫一個(gè)測(cè)試文件from student import Student def test_is_pass(): s Student(A同學(xué), 85) assert s.is_pass() is True def test_is_pass_low_score(): s Student(B同學(xué), 59) assert s.is_pass() is False在終端里運(yùn)行pytest它會(huì)自動(dòng)發(fā)現(xiàn)test_開頭的函數(shù)并執(zhí)行。輸出綠點(diǎn)就是全過(guò)紅色就是某個(gè)斷言失敗還會(huì)告訴你具體哪一行出了問(wèn)題。給每個(gè)方法寫兩三個(gè)這樣的測(cè)試功能回歸的恐懼感會(huì)大大降低。5.4 一個(gè)設(shè)計(jì)模式速覽抽象基類書里后面幾章講設(shè)計(jì)模式先帶你瞥一眼最有用的一個(gè)抽象基類ABC。它適合做“接口約定”——規(guī)定所有子類必須實(shí)現(xiàn)哪些方法from abc import ABC, abstractmethod class Distance(ABC): abstractmethod def compute(self, p1, p2) - float: 計(jì)算兩點(diǎn)的距離 class EuclideanDistance(Distance): def compute(self, p1, p2) - float: return ((p1[0] - p2[0]) ** 2 (p1[1] - p2[1]) ** 2) ** 0.5好處很明顯任何繼承 Distance 的類如果忘了實(shí)現(xiàn)compute一運(yùn)行就會(huì)報(bào)錯(cuò)。這等于把“必須實(shí)現(xiàn)某個(gè)方法”的約定寫進(jìn)了代碼本身而不是寫在開發(fā)者的備忘錄里。理解抽象基類讀很多框架源碼時(shí)會(huì)豁然開朗。6. 下一步學(xué)什么從這本書走向獨(dú)立寫項(xiàng)目6.1 給零基礎(chǔ)的你一條不太費(fèi)力的路《Python面向?qū)ο缶幊痰谒陌妗芬还?14 章新手不需要從頭到尾一口氣啃完。我建議按這條路徑走階段建議目標(biāo)第1階段第1~3章面向?qū)ο笤O(shè)計(jì)基礎(chǔ)、Python類語(yǔ)法、繼承能把普通腳本改寫成類第2階段第4~5章異常、何時(shí)用OOP寫出健壯的輸入校驗(yàn)第3階段第7章數(shù)據(jù)類、字典、列表、集合、隊(duì)列選對(duì)數(shù)據(jù)結(jié)構(gòu)第4階段第13章pytest測(cè)試養(yǎng)成測(cè)試習(xí)慣第5階段第8~9章字符串、序列化、文件路徑處理真實(shí)數(shù)據(jù)文件第 6、10、11、12 章可以先翻一翻不必深究。等你寫的程序開始超過(guò)兩千行再回來(lái)精讀設(shè)計(jì)模式和并發(fā)部分會(huì)有完全不同的收獲。6.2 一個(gè)親測(cè)有效的技巧跟緊書里的 k-NN 案例這本書最妙的設(shè)計(jì)是從第 1 章開始埋了一個(gè)貫穿全書的案例一個(gè) k 近鄰k-NN機(jī)器學(xué)習(xí)小項(xiàng)目。每一章都會(huì)給這個(gè)案例增加一部分功能比如第 1 章做整體設(shè)計(jì)、第 3 章實(shí)現(xiàn)距離計(jì)算、第 7 章處理數(shù)據(jù)、第 13 章補(bǔ)測(cè)試。我第一次學(xué)的時(shí)候被這個(gè)案例從“設(shè)計(jì)思路”到“可跑代碼”的完整推進(jìn)震撼到了。強(qiáng)烈建議不要把各章當(dāng)獨(dú)立文章看而是跟著案例走一遍——每個(gè)階段都實(shí)際運(yùn)行書里的代碼。你會(huì)發(fā)現(xiàn)前面學(xué)的概念在后一章都變成了某個(gè)真實(shí)功能的構(gòu)件這種“概念落地”的循環(huán)比單獨(dú)記知識(shí)點(diǎn)有效十倍。6.3 一點(diǎn)過(guò)來(lái)人的教訓(xùn)我剛開始學(xué) OOP 時(shí)總覺(jué)得自己寫的腳本挺順的不屑于用類。結(jié)果半年后回來(lái)維護(hù)自己的舊代碼錯(cuò)改了三處才跑起來(lái)那叫一個(gè)后悔。從那以后我每次寫新項(xiàng)目都強(qiáng)制自己先走一遍“這個(gè)系統(tǒng)里有哪些對(duì)象、各自管什么數(shù)據(jù)”的思考再動(dòng)手敲 class。這套流程已經(jīng)變成了肌肉記憶省下了大量返工時(shí)間。如果你拿到了這本書的電子文檔我建議先從第 1 章的案例看起不要從目錄開始硬啃。希望這本書的方法論也能幫你少走這樣一圈彎路希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取