關(guān)于爛代碼的那些事( 上 )

1.摘要

最近寫了不少代碼烦粒,review了不少代碼蜡秽,也做了不少重構(gòu)瘸羡,總之是對(duì)著爛代碼工作了幾周漩仙。為了抒發(fā)一下這幾周里好幾次到達(dá)崩潰邊緣的情緒,我決定寫一篇文章談一談爛代碼的那些事犹赖。 這里是上篇队他,談一談爛代碼產(chǎn)生的原因和現(xiàn)象。

2.寫爛代碼很容易

剛?cè)氤绦騿T這行的時(shí)候經(jīng)常聽到一個(gè)觀點(diǎn):你要把精力放在ABCD(需求文檔/功能設(shè)計(jì)/架構(gòu)設(shè)計(jì)/理解原理)上峻村,寫代碼只是把想法翻譯成編程語言而已麸折,是一個(gè)沒什么技術(shù)含量的事情。

當(dāng)時(shí)的我在聽到這種觀點(diǎn)時(shí)會(huì)有一種近似于高冷的不屑:你們就是一群傻X粘昨,根本不懂代碼質(zhì)量的重要性垢啼,這么下去遲早有一天會(huì)踩坑,呸雾棺。

可是幾個(gè)月之后膊夹,他們似乎也沒怎么踩坑。而隨著編程技術(shù)一直在不斷發(fā)展捌浩,帶來了更多的我以前認(rèn)為是傻X的人加入到程序員這個(gè)行業(yè)中來放刨。

語言越來越高級(jí)、封裝越來越完善尸饺,各種技術(shù)都在幫助程序員提高生產(chǎn)代碼的效率进统,依靠層層封裝助币,程序員真的不需要了解一丁點(diǎn)技術(shù)細(xì)節(jié),只要把需求里的內(nèi)容逐行翻譯出來就可以了螟碎。

很多程序員不知道要怎么組織代碼眉菱、怎么提升運(yùn)行效率、底層是基于什么原理掉分,他們寫出來的是在我心目中爛成一坨翔一樣的代碼俭缓。

但是那一坨翔一樣代碼竟然他媽的能正常工作。

即使我認(rèn)為他們寫的代碼是坨翔酥郭,但是從不接觸代碼的人的視角來看(比如說你的boss)华坦,代碼編譯過了,測試過了不从,上線運(yùn)行了一個(gè)月都沒出問題惜姐,你還想要奢求什么?

所以椿息,即使不情愿歹袁,也必須承認(rèn),時(shí)至今日寝优,寫代碼這件事本身沒有那么難了条舔。

3.爛代碼終究是爛代碼

但是偶爾有那么幾次,寫爛代碼的人離職了之后乏矾,事情似乎又變得不一樣了逞刷。

想要修改功能時(shí)卻發(fā)現(xiàn)程序里充斥著各種無法理解的邏輯、改完之后莫名其妙的bug一個(gè)接一個(gè)妻熊,接手這個(gè)項(xiàng)目的人開始漫無目的的加班夸浅,并且原本一個(gè)挺樂觀開朗的人漸漸的開始喜歡問候別人祖宗了。

我總結(jié)了幾類經(jīng)常被艸祖宗的爛代碼:

3.1.意義不明

能力差的程序員容易寫出意義不明的代碼扔役,他們不知道自己究竟在做什么.

就像這樣:

public void save() {

for(int i=0;i<100;i++) {

//防止保存失敗,重試100次

document.save();

}

}

對(duì)于這類程序員亿胸,我一般建議他們轉(zhuǎn)行坯钦。

3.2.不說人話

不說人話是新手最經(jīng)常出現(xiàn)的問題,直接的表現(xiàn)就是寫了一段很簡單的代碼侈玄,其他人卻看不懂婉刀。

比如下面這段:

public boolean getUrl(Long id) {

UserProfile up = us.getUser(ms.get(id).getMessage().aid);

if (up == null) {

return false;

}

if (up.type == 4 || ((up.id >> 2) & 1) == 1) {

return false;

}

if(Util.getUrl(up.description)) {

return true;

} else {

return false;

}

}

很多程序員喜歡簡單的東西:簡單的函數(shù)名、簡單的變量名序仙、代碼里翻來覆去只用那么幾個(gè)單詞命名突颊;能縮寫就縮寫、能省略就省略、能合并就合并律秃。這類人寫出來的代碼里充斥著各種g/s/gos/of/mss之類的全世界沒人懂的縮寫爬橡,或者一長串不知道在做什么的連續(xù)調(diào)用。

還有很多程序員喜歡復(fù)雜棒动,各種宏定義糙申、位運(yùn)算之類寫的天花亂墜,生怕代碼讓別人一下子看懂了會(huì)顯得自己水平不夠船惨。

簡單的說柜裸,他們的代碼是寫給機(jī)器的,不是給人看的粱锐。

3.3.不恰當(dāng)?shù)慕M織

不恰當(dāng)?shù)慕M織是高級(jí)一些的爛代碼粘室,程序員在寫過一些代碼之后,有了基本的代碼風(fēng)格卜范,但是對(duì)于規(guī)模大一些的工程的掌控能力不夠,不知道代碼應(yīng)該如何解耦鹿榜、分層和組織海雪。

這種反模式的現(xiàn)象是經(jīng)常會(huì)看到一段代碼在工程里拷來拷去;某個(gè)文件里放了一大坨堆砌起來的代碼舱殿;一個(gè)函數(shù)堆了幾百上千行奥裸;或者一個(gè)簡單的功能七拐八繞的調(diào)了幾十個(gè)函數(shù),在某個(gè)難以發(fā)現(xiàn)的猥瑣的小角落里默默的調(diào)用了某些關(guān)鍵邏輯沪袭。

這類代碼大多復(fù)雜度高湾宙,難以修改,經(jīng)常一改就崩冈绊;而另一方面侠鳄,創(chuàng)造了這些代碼的人傾向于修改代碼,畏懼創(chuàng)造代碼死宣,他們寧愿讓原本復(fù)雜的代碼一步步變得更復(fù)雜伟恶,也不愿意重新組織代碼。當(dāng)你面對(duì)一個(gè)幾千行的類毅该,問為什么不把某某邏輯提取出來的時(shí)候博秫,他們會(huì)說:

“但是,那樣就多了一個(gè)類了呀眶掌〉灿”

3.4.假設(shè)和缺少抽象

相對(duì)于前面的例子,假設(shè)這種反模式出現(xiàn)的場景更頻繁朴爬,花樣更多即寒,始作俑者也更難以自己意識(shí)到問題。比如:

public String loadString() {

File file = new File("c:/config.txt");

// read something

}

文件路徑變更的時(shí)候,會(huì)把代碼改成這樣:

public String loadString(String name) {

File file = new File(name);

// read something

}

需要加載的內(nèi)容更豐富的時(shí)候蒿叠,會(huì)再變成這樣:

public String loadString(String name) {

File file = new File(name);

// read something

}

public Integer loadInt(String name) {

File file = new File(name);

// read something

}

之后可能會(huì)再變成這樣:

public String loadString(String name) {

File file = new File(name);

// read something

}

public String loadStringUtf8(String name) {

File file = new File(name);

// read something

}

public Integer loadInt(String name) {

File file = new File(name);

// read something

}

public String loadStringFromNet(String url) {

HttpClient ...

}

public Integer loadIntFromNet(String url) {

HttpClient ...

}

這類程序員往往是項(xiàng)目組里開發(fā)效率比較高的人明垢,但是大量的業(yè)務(wù)開發(fā)工作導(dǎo)致他們不會(huì)做多余的思考,他們的口頭禪是:“我每天要做XX個(gè)需求”或者“先做完需求再考慮其他的吧”市咽。

這種反模式表現(xiàn)出來的后果往往是代碼很難復(fù)用痊银,面對(duì)deadline的時(shí)候,程序員迫切的想要把需求落實(shí)成代碼施绎,而這往往也會(huì)是個(gè)循環(huán):寫代碼的時(shí)候來不及考慮復(fù)用溯革,代碼難復(fù)用導(dǎo)致之后的需求還要繼續(xù)寫大量的代碼。

一點(diǎn)點(diǎn)積累起來的大量的代碼又帶來了組織和風(fēng)格一致性等問題谷醉,最后形成了一個(gè)新功能基本靠拷的遺留系統(tǒng)致稀。

3.5.還有嗎

爛代碼還有很多種類型,沿著功能-性能-可讀-可測試-可擴(kuò)展這條路線走下去俱尼,還能看到很多匪夷所思的例子抖单。

那么什么是爛代碼?個(gè)人認(rèn)為遇八,爛代碼包含了幾個(gè)層次:

如果只是一個(gè)人維護(hù)的代碼矛绘,滿足功能和性能要求倒也足夠了。

如果在一個(gè)團(tuán)隊(duì)里工作,那就必須易于理解和測試,讓其它人員有能力修改各自的代碼对途。

同時(shí),越是處于系統(tǒng)底層的代碼囚玫,擴(kuò)展性也越重要。

所以读规,當(dāng)一個(gè)團(tuán)隊(duì)里的底層代碼難以閱讀抓督、耦合了上層的邏輯導(dǎo)致難以測試、或者對(duì)使用場景做了過多的假設(shè)導(dǎo)致難以復(fù)用時(shí)束亏,雖然完成了功能本昏,它依然是坨翔一樣的代碼。

3.6.夠用的代碼

而相對(duì)的枪汪,如果一個(gè)工程的代碼難以閱讀涌穆,能不能說這個(gè)是爛代碼?很難下定義雀久,可能算不上好宿稀,但是能說它爛嗎?如果這個(gè)工程自始至終只有一個(gè)人維護(hù)赖捌,那個(gè)人也維護(hù)的很好祝沸,那它似乎就成了“夠用的代碼”矮烹。

很多工程剛開始可能只是一個(gè)人負(fù)責(zé)的小項(xiàng)目,大家關(guān)心的重點(diǎn)只是代碼能不能順利的實(shí)現(xiàn)功能罩锐、按時(shí)完工奉狈。

過上一段時(shí)間,其他人參與時(shí)才發(fā)現(xiàn)代碼寫的有問題涩惑,看不懂仁期,不敢動(dòng)。需求方又開始催著上線了竭恬,怎么辦跛蛋?只好小心翼翼的只改邏輯而不動(dòng)結(jié)構(gòu),然后在注釋里寫上這么實(shí)現(xiàn)很ugly痊硕,以后明白內(nèi)部邏輯了再重構(gòu)赊级。

再過上一段時(shí)間,有個(gè)相似的需求岔绸,想要復(fù)用里面的邏輯理逊,這時(shí)才意識(shí)到代碼里做了各種特定場景的專用邏輯,復(fù)用非常麻煩盒揉。為了趕進(jìn)度只好拷代碼然后改一改晋被。問題解決了,問題也加倍了预烙。

幾乎所有的爛代碼都是從“夠用的代碼”演化來的,代碼沒變道媚,使用代碼的場景發(fā)生變了扁掸,原本夠用的代碼不符合新的場景,那么它就成了爛代碼最域。

4.重構(gòu)不是萬能藥

程序員最喜歡跟程序員說的謊話之一就是:現(xiàn)在進(jìn)度比較緊谴分,等X個(gè)月之后項(xiàng)目進(jìn)度寬松一些再去做重構(gòu)。

不能否認(rèn)在某些(極其有限的)場景下重構(gòu)是解決問題的手段之一镀脂,但是寫了不少代碼之后發(fā)現(xiàn)牺蹄,重構(gòu)往往是程序開發(fā)過程中最復(fù)雜的工作”〕幔花一個(gè)月寫的爛代碼沙兰,要花更長的時(shí)間、更高的風(fēng)險(xiǎn)去重構(gòu)翘魄。

曾經(jīng)經(jīng)歷過幾次忍無可忍的大規(guī)模重構(gòu)鼎天,每一次重構(gòu)之前都是找齊了組里的高手,開了無數(shù)次分析會(huì)暑竟,把組內(nèi)需求全部暫停之后才敢開工斋射,而重構(gòu)過程中往往哀嚎遍野,幾乎每天都會(huì)出上很多意料之外的問題,上線時(shí)也幾乎必然會(huì)出幾個(gè)問題罗岖。

從技術(shù)上來說涧至,重構(gòu)復(fù)雜代碼時(shí),要做三件事:理解舊代碼桑包、分解舊代碼南蓬、構(gòu)建新代碼。而待重構(gòu)的舊代碼往往難以理解捡多;模塊之間過度耦合導(dǎo)致牽一發(fā)而動(dòng)全身蓖康,不易控制影響范圍;舊代碼不易測試導(dǎo)致無法保證新代碼的正確性垒手。

這里還有一個(gè)核心問題蒜焊,重構(gòu)的復(fù)雜度跟代碼的復(fù)雜度不是線性相關(guān)的。比如有1000行爛代碼科贬,重構(gòu)要花1個(gè)小時(shí)泳梆,那么5000行爛代碼的重構(gòu)可能要花2、3天榜掌。要對(duì)一個(gè)失去控制的工程做重構(gòu)优妙,往往還不如重寫更有效率。

而拋開具體的重構(gòu)方式憎账,從受益上來說套硼,重構(gòu)也是一件很麻煩的事情:它很難帶來直接受益,也很難量化胞皱。這里有個(gè)很有意思的現(xiàn)象邪意,基本關(guān)于重構(gòu)的書籍無一例外的都會(huì)有獨(dú)立的章節(jié)介紹“如何向boss說明重構(gòu)的必要性”。

重構(gòu)之后能提升多少效率反砌?能降低多少風(fēng)險(xiǎn)雾鬼?很難答上來,爛代碼本身就不是一個(gè)可以簡單的標(biāo)準(zhǔn)化的東西宴树。

舉個(gè)例子策菜,一個(gè)工程的代碼可讀性很差,那么它會(huì)影響多少開發(fā)效率酒贬?

你可以說:之前改一個(gè)模塊要3天又憨,重構(gòu)之后1天就可以了。但是怎么應(yīng)對(duì)“不就是做個(gè)數(shù)據(jù)庫操作嗎為什么要3天”這類問題锭吨?爛代碼“爛”的因素有不確定性竟块、開發(fā)效率也因人而異,想要證明這個(gè)東西“確實(shí)”會(huì)增加兩天開發(fā)時(shí)間耐齐,往往反而會(huì)變成“我看了3天才看懂這個(gè)函數(shù)是做什么的”或者“我做這么簡單的修改要花3天”這種神經(jīng)病才會(huì)去證明的命題浪秘。

而另一面蒋情,許多技術(shù)負(fù)責(zé)人也意識(shí)到了代碼質(zhì)量和重構(gòu)的必要性,“那就重構(gòu)嘛”耸携,或者“如果看到問題了棵癣,那就重構(gòu)”。上一個(gè)問題解決了夺衍,但實(shí)際上關(guān)于重構(gòu)的代價(jià)和收益仍然是一筆糊涂賬狈谊,在沒有分配給你更多資源、沒有明確的目標(biāo)沟沙、沒有具體方法的情況下河劝,很難想象除了有代碼潔癖的人還有誰會(huì)去執(zhí)行這種莫名其妙的任務(wù)。

于是往往就會(huì)形成這種局面:

不寫代碼的人認(rèn)為應(yīng)該重構(gòu)矛紫,重構(gòu)很簡單赎瞎,無論新人還是老人都有責(zé)任做重構(gòu)。

寫代碼老手認(rèn)為應(yīng)該遲早應(yīng)該重構(gòu)颊咬,重構(gòu)很難务甥,現(xiàn)在湊合用,這事別落在我頭上喳篇。

寫代碼的新手認(rèn)為不出bug就謝天謝地了敞临,我也不知道怎么重構(gòu)。

5.寫好代碼很難

與寫出爛代碼不同的是麸澜,想寫出好代碼有很多前提:

理解要開發(fā)的功能需求挺尿。

了解程序的運(yùn)行原理。

做出合理的抽象炊邦。

組織復(fù)雜的邏輯编矾。

對(duì)自己開發(fā)效率的正確估算。

持續(xù)不斷的練習(xí)铣耘。

寫出好代碼的方法論很多洽沟,但我認(rèn)為寫出好代碼的核心反而是聽起來非常low的“持續(xù)不斷的練習(xí)”以故。這里就不展開了蜗细,留到下篇再說。

很多程序員在寫了幾年代碼之后并沒有什么長進(jìn)怒详,代碼仍然爛的讓人不忍直視炉媒,原因有兩個(gè)主要方面:

環(huán)境是很重要的因素之一,在爛代碼的熏陶下很難理解什么是好代碼昆烁,知道的人大部分也會(huì)選擇隨波逐流吊骤。

還有個(gè)人性格之類的說不清道不明的主觀因素,寫出爛代碼的程序員反而都是一些很好相處的人静尼,他們往往熱愛公司團(tuán)結(jié)同事平易近人工作任勞任怨–只是代碼很爛而已白粉。

而工作幾年之后的人很難再說服他們?nèi)ヌ岣叽a質(zhì)量传泊,你只會(huì)反復(fù)不斷的聽到:“那又有什么用呢?”或者“以前就是這么做的把及汀眷细?”之類的說法。

那么從源頭入手鹃祖,提高招人時(shí)對(duì)代碼的質(zhì)量的要求怎么樣溪椎?

前一陣面試的時(shí)候增加了白板編程、最近又增加了上機(jī)編程的題目恬口。發(fā)現(xiàn)了一個(gè)現(xiàn)象:一個(gè)人工作了幾年校读、做過很多項(xiàng)目、帶過團(tuán)隊(duì)祖能、發(fā)了一些文章歉秫,不一定能代表他代碼寫的好;反之芯杀,一個(gè)人代碼寫的好端考,其它方面的能力一般不會(huì)太差。

舉個(gè)例子揭厚,最近喜歡用“寫一個(gè)代碼行數(shù)統(tǒng)計(jì)工具”作為面試的上機(jī)編程題目却特。很多人看到題目之后第一反映是,這道題太簡單了筛圆,這不就是寫寫代碼嘛裂明。

從實(shí)際效果來看,這道題識(shí)別度卻還不錯(cuò)太援。

首先闽晦,題目足夠簡單,即使沒有看過《面試寶典》之類書的人也不會(huì)吃虧提岔。而題目的擴(kuò)展性很好仙蛉,即使提前知道題目,配合不同的條件碱蒙,可以變成不同的題目荠瘪。比如要求按文件類型統(tǒng)計(jì)行數(shù)、或者要求提高統(tǒng)計(jì)效率赛惩、或者統(tǒng)計(jì)的同時(shí)輸出某些單詞出現(xiàn)的次數(shù)哀墓,等等。

從考察點(diǎn)來看喷兼,首先是基本的樹的遍歷算法篮绰;其次有一定代碼量,可以看出程序員對(duì)代碼的組織能力季惯、對(duì)問題的抽象能力吠各;上機(jī)編碼可以很簡單的看出應(yīng)聘者是不是很久沒寫程序了臀突;還包括對(duì)于程序易用性和性能的理解。

最重要的是贾漏,最后的結(jié)果是一個(gè)完整的程序惧辈,我可以按照日常工作的標(biāo)準(zhǔn)去評(píng)價(jià)程序員的能力,而不是從十幾行的函數(shù)里意淫這個(gè)人在日常工作中大概會(huì)有什么表現(xiàn)磕瓷。

但即使這樣盒齿,也很難拍著胸脯說,這個(gè)人寫的代碼質(zhì)量沒問題困食。畢竟面試只是代表他有寫出好代碼的能力边翁,而不是他將來會(huì)寫出好代碼。

6.悲觀的結(jié)語

說了那么多硕盹,結(jié)論其實(shí)只有兩條符匾,作為程序員:

不要奢望其他人會(huì)寫出高質(zhì)量的代碼

不要以為自己寫出來的是高質(zhì)量的代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瘩例,隨后出現(xiàn)的幾起案子啊胶,更是在濱河造成了極大的恐慌,老刑警劉巖垛贤,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焰坪,死亡現(xiàn)場離奇詭異,居然都是意外死亡聘惦,警方通過查閱死者的電腦和手機(jī)某饰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來善绎,“玉大人黔漂,你說我怎么就攤上這事≠鹘矗” “怎么了炬守?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長剂跟。 經(jīng)常有香客問我减途,道長,這世上最難降的妖魔是什么浩聋? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任观蜗,我火速辦了婚禮臊恋,結(jié)果婚禮上衣洁,老公的妹妹穿的比我還像新娘。我一直安慰自己抖仅,他們只是感情好坊夫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布砖第。 她就那樣靜靜地躺著,像睡著了一般环凿。 火紅的嫁衣襯著肌膚如雪梧兼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天智听,我揣著相機(jī)與錄音羽杰,去河邊找鬼。 笑死到推,一個(gè)胖子當(dāng)著我的面吹牛考赛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播莉测,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼颜骤,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了捣卤?” 一聲冷哼從身側(cè)響起忍抽,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎董朝,沒想到半個(gè)月后鸠项,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡子姜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年锈锤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闲询。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡久免,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扭弧,到底是詐尸還是另有隱情阎姥,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布鸽捻,位于F島的核電站呼巴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏御蒲。R本人自食惡果不足惜衣赶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望厚满。 院中可真熱鬧府瞄,春花似錦、人聲如沸碘箍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至货邓,卻和暖如春秆撮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背换况。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國打工职辨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人戈二。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓拨匆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親挽拂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惭每,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

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