为什么 C+标准每三年发布一次?
?
譯者丨平川
每到這個時候,WG21 的工作人員總會遇到來自外界的疑問,“為什么 C++ 標準的發布時間這么嚴格?”。甚至許多新的委員會成員,他們對 WG21 的歷史和這樣做的原因同樣并不了解。眾所周知,WG21 有一個嚴格的時間表,按照這份時間表,機構每三年發布一次標準,從不會推遲。因此,在 7 月 5 日科隆大會之前的行政電話會議上,本文作者 Herb Sutter 在其他委員會主席的鼓勵下,回應了采用這一方式的原因及背后的歷史,該修訂版在科隆大會的會議郵件中發布。本文是是面向感興趣的公眾發布的副本,希望能對你理解 C++ 標準的發布有所啟發。
在科隆大會之前,如果標準中有 Bug,WG21 會推遲 C++ 20 嗎?
當然不會。我們正在按計劃進行,修復 Bug 是最后一年的目標。這也是時間表在“19”(科納)的早期凍結了 C++“20”的特性,留出一年的時間來修復 Bug 的原因,包括今年夏天開展一輪國際討論。我們必須在 2020 年初(三個會議:科隆、貝爾法斯特和布拉格)采用評審反饋、任何其他問題的解決方案以及 Bug 修復。
如果還有一兩個會議,就可以添加幾乎已經準備好的特性,那么 WG21 是否會推遲發布 C++ 20 呢?
當然不會。只能再等幾次會議(布拉格大會之后),C++ 23 正式對外開放,可以將該特性作為 C++ 23 工作草案的第一項內容。例如,對于 concept,我們就是這樣做的。它還沒有完全準備好從 TS 直接進入 C++ 17,所以按照投票,其核心功能會在 C++ 20 的首次會議(多倫多)時加入 C++ 20 草案,留下足夠的時間來完善,采用 TS 中余下的有爭議的部分,稍微多花些時間準備(非“模板”的語法),并在第二年(圣地亞哥)采用。現在我們擁有了整個特性。
這聽起來太嚴格了。為什么我們每三年發布標準 ?
因為它是發布 C++ 標準僅有的兩個項目管理選項之一,經驗表明它比另一個選項更好。
發布 C++ 標準的兩個項目管理選項是什么?
對于發布目標,有兩個基本選擇:特性和發布時間。無論選擇哪一個,都意味著放棄對另一項的控制。具體來說:
(1)、“What”:選擇特性。準備好了再發布,即放棄對發布時間的控制。
如果你發現標準草案中的某個特性需要更長的準備時間,那么就推遲到它完成。你可以使一個版本大到足以涵蓋必要的開發時間,從而開發需要花費多年時間的重要特性,然后設法停止開發新特性,穩定這一版本。
這是 C++ 98(最初預計在 1994 年左右發布。Bjarne 最初表示,如果它不能在 1994 年前后發布,那么它將是一個失敗)和 C++ 11(稱為 0x,因為 x 預計在 7 左右)的模型。該模型“將病人公開”,時間的不確定導致了集成測試和發布延遲。這導致了巨大的市場不確定性,人們會想,委員會什么時候發布下一個標準,或者他們是否會發布(在社區中,實施者,甚至委員會內部的一些人嚴重懷疑在 1996 年和 2009 年我們是否會發布相應的版本)。在這段時間內,大多數編譯器通常都是晚幾年實現標準。因為沒有人知道,委員會在修補版本時還會做多少不兼容的修改,或者什么時候發布,這導致社區可用的編譯器對 C++ 的支持存在廣泛的差別和分化。
為什么我們這樣做,我們是傻瓜嗎?不是。只是沒有經驗以及……“樂觀態度”,心懷最大的善意想要打下良好的基礎。在 1994 年 5 月 6 日,還有 2007 年 8 月 9 日,我們真的相信,如果延期到下次會議或者推遲兩三次會議,我們就可以完成。但每次我們都最終推遲了四年,我們已經吸取了教訓,沒有所謂的推遲一兩年。幸運的是,有了選項(2),這種情況已經改變。
(2)、“When”:選擇發布時間。交付準備好的特性,不去選擇功能集。
如果你發現實現標準草案中的一個特性需要更多的準備時間,那么你就把它從此次發布中去掉,只交付準備好的東西。你仍可以跨越多個版本的開發時間開發重要特性,只要把它放到“分支”里去進行,并在準備就緒時把它們合并到主干標準。你一直都在開發特性,因為每一個特性的開發在準備好之前,都和具體的交付很好地解耦了。
本模型自 2012 年以來一直在使用,我們不想回去。該模型會定期“把病人關起來”,為了維持較高的質量,強制進行定期集成,在達到相當的穩定程度之前不合并到標準草案中,通常是在一個特性分支上。它還創建了一個可預測的交付周期,供行業參考和規劃。在這段時間里,每次標準發布后,編譯器越來越早地交付了符合標準的實現(這在以前從未發生過)。2020 年,我們希望多個完全符合標準的實現在同一年發布(這在以前從未發生過)。這對整個市場——實現者、用戶、教育工作者以及所有人來說都是好事。
此外,請注意,由于我們采用了方式(2),我們還交付了更多(以大 / 中 / 小特性計數)質量更高的特性,而交付的是任何準備好的東西(如果沒有準備好就推遲)。
我們對(2)有多嚴肅?如果由一名重要的委員會成員所主導的主要特性“幾乎準備好了”……我們會等待,不是嗎?
A:不會。我們有歷史數據:2016 年在杰克遜維爾,在 C++ 特性截止日,Bjarne Stroustrup 在全體會議上呼吁在 C++17 中包含 concept,而人們未能達成共識。因此,有人直接問他是否愿意讓 C++ 17 推遲一年,加入 concept。Stroustrup 說“不”,沒有任何的猶豫或遲疑,并補充說,沒有 concept 的 C++ 17 比有 concept 的 C++ 18 甚或 C++ 19 更重要,盡管 Stroustrup 從事 concept 特性的開發已有 15 年。
真正的選擇是:(2)發布沒有 concept 的 C++ 17,然后在 C++ 20 包含 concept(我們就是這樣做的)。或者(1)把 C++ 17 重命名為 C++ 20,這就等同于(2)跳過 C++ 17,并且不發布已經準備好的 C++ 17。
介于(1)和(2)之間的東西呢,比如,基本上采用(2)的做法,但計劃有“一點”靈活性,當我們覺得需要穩定一個特性時,就額外花“少許”時間?
不會,因為那就成(1)了。Fred Brooks 在《人月神話》中解釋了“神秘的小偏差(mythical small slip)”,并得出結論:“避免小偏差。”
現在,想象一下,C++ 20 稍微延期了。現實情況是,我們將從(2)切換到(1),無論我們怎么試圖否認它,都沒有任何實際的好處。如果我們為了完整度而決定推遲 C++ 20,我們至少要將標準延期兩年。一旦我們延期至少兩年,C++ 20 會變為 C++ 22,甚至 C++ 23……但我們已經準備交付 C++ 23!所以不管是哪個計劃,我們仍然是交付 C++ 23。唯一的區別在于,我們在此期間沒有交付 C++ 20,完全準備就緒的工作多了許多,而世人則多等了三年。這沒有理由,因為延遲不會造福那些未完全準備就緒的特性,大部分或全部都是如此。
所以,這個建議相當于“讓我們把 C++ 20 變成 C++ 22 或 C++ 23”。而答案很簡單,“是的,我們會有 C++ 23,但是在 C++ 20 之外,而不是取代 C++ 20。“推遲 C++ 20 實際上意味著跳過 C++ 20,而不是發布已經穩定而且準備就緒的工作,這樣做沒有好處。
特性 X 被破壞了,需要時間修復,而 C++20 中剩余的修復時間不夠用了,怎么辦?
A:沒問題!我們去掉它!在這種情況下,有人就需要寫文章向 EWG 或 LEWG(酌情)說明問題,并提出從標準草案中去掉它的建議。這些組織就會考慮,如果他們確定該特性被破壞了(全體同意),這很好,該 C++ 特性將推遲到下一個版本。對于 C++ 0x 的 concept,我們已經這樣做過。但是,按照計劃(1),我們會延期,不僅那個特性,C++ 20 的整個特性集都會被納入 C++ 23,那就太過分了。
(2)意味著“大 / 小”版本嗎?
不是。(2)僅僅意味著你不選擇特性集,甚至是以“大 / 小”版本的粒度。簡單地說,模型(2)是“準備好了就交付”。這使得發布具有以下特點:
對于“較小”的特性,大小類似(通常為中等大小),因為它們的提前期往往比較短(每個小于 3 年),所以一般每次發布時我們看到的特性數量差不多;
對于“較大”的特性,大小變化較大,它們需要更長的提前期(大于 3 年),每次標準發布時會使任何在標準時間窗口內已經成熟的特性做好合并準備,所以有時會比其他的版本多。
所以,C++ 14 和 C++ 17 相對較小,因為在此期間,許多標準化工作都是在提案文件(如 contract)和 TS“特性分支”(如 concept)的重要特性中進行的。
那么,我們沒有在 C++ 20 的三年周期中塞入很多東西嗎?
沒有。C++ 20 的變化比較大,不是因為我們在這三年做了更多的工作,而是因為許多重要項目(至少有兩個自 2012 年以來就一直以它們當前的形式開展工作,它們是 P-proposals 和 TS“分支”)正好成熟,并且人們達成共識要在同一個發布周期內將其合并進草案。
開發重大特性需要多年的時間,這幾乎一直是事實。C++ 98 和 C++ 11 采用的方案(1)和現在的方案(2)之間的主要區別在于,我們直到標準準備就緒才發布,現在,對于那些大特性,我們仍然是準備好再發布。但與此同時,我們也會發布其他準備好的特性,而不是完全停止任何發布。
C++ 20 與 C++ 14,C++ 17 的周期相同,都是 3 年。這不是說我們在這三年的時間里比前面的兩個三年周期做得更多,只是有更多的重要特性要準備好合并。如果真的沒準備好,我們可以再去掉它們,讓它們為 C++ 23 做好準備。
事實上,我認為正確的思考方法是,C++14+17+20 作為一個整體是我們的第三個九年周期(2011-2020),在 C++ 98(1989-1998)和 C++ 11(2002-2011)之后。但是,因為我們現在采用方案(2),我們也會發布在第 3 年、第 6 年準備好的部分。
在產品開發過程中發現 Bug 不是比在發布給客戶之后發現更好嗎?
當然。但如果我們談論的是推遲發布 C++ 標準的理由,那么這個問題意味著兩個錯誤的前提:(a)假設特性在標準尚未發布之前就已經發布和使用(已經有許多生產使用經驗);(b)假設所有的特性都可以在標準發布之前一起使用(它們不能)。具體來說:
對于(a):本質上,C++ 20 最主要的特性至少在一個發布編譯器中按照當前的標準草案形式實現了。實際上,在大多數情況下已經實際用于生產代碼(已經發布給客戶,而且客戶非常滿意)。例如,協程(截至本文寫作的時候采用僅僅五個月)被用于 MSVC 生產代碼已經兩年,在 Clang 中使用已經至少一年,像 Azure、Facebook 等大規模使用的客戶都非常滿意。
對于(b):事實上,我們不會發現多少特性交互問題,直到用戶在生產中使用它們,這通常意味著直到標準發布之后,因為實施者通常會等到標準發布之后才實現大多數東西。這就是為什么當我們對何時發布表現出任何的不確定性時,通常會發生的是,實施者會等待——他們將實現一些東西,但暫停實現整個東西,直到他們知道我們已經準備好。問下“最喜歡的編譯器”團隊,當他們在標準發布之前實現重要特性會發生什么。在許多情況下,他們必須實現不止一次,并不止一次地給客戶造成破壞。因此,實施者等待委員會發布是合理的。
最后,不要忘記特性交互問題。除了在準備好時發布,發布后,我們也需要時間查找和修復特性之間交互的問題,添加特性交互支持。在這些新特性被廣泛使用之前,我們通常都不知道這些交互。無論我們的標準推遲多久,都會有交互直到很久以后才被我們發現。關鍵是借助設計的靈活性來管理風險,以兼容的方式調整特性,而不是等到所有風險都消除。
標準從來都不是完美的,難道我們不會把錯誤發布出去嗎?
是的。如果我們看到一個特性還沒準備好,我們應該去掉它。如果我們看到一個特性可以更好,但我們知道,修改可以用向后兼容的方式完成,這不是一個現在不發布它的理由,那可以在 C++ 的下一個版本中作為一個擴展。我們會特地發布計劃進一步改進的特性,只要我們有足夠的信心用向后兼容的方式完成。
難道不應該以交付錯誤最小化為目標嗎?
是的,我們應該以此為目標。然而,我們的目標不在于消除所有風險。不發布我們認為已經準備好的東西既有風險,也有(機會)成本。到目前為止,我們大部分時間都是正確的。
你確定現在的質量比采用方案(1)時更好嗎?
是的。借助客觀的指標,特別是國家機構的評論和問題報告,C++ 14 和 C++ 17 一直是最穩定的版本。對于這些指標,它們每一個都比 C++ 98 或 C++ 11 好三至四倍。原因是我們定期發布,并優先將大特性放入 TS 分支(包括如何與主干標準整合的完整說明),在知道它們準備好之后將它們合并。
事實上,自 2012 年以來的核心標準始終保持“接近交付(near-ship-ready)”的狀態(所以,即使是我們的工作草案,其質量也不亞于 C++ 98 和 C++ 11 標準)。在 2012 年之前,這從未發生過,我們常常“將病人公開”,問題列表很長,我們打算很快就安回去的器官散落在周圍。如果我們想要,我們現在就可以交付 CD,沒有科隆會議也可以,而且仍然比 C++ 98 或 C++ 11 的 CD 質量更高。考慮到 C++ 98 和 C++ 11 的成功,我們認識到,現在的質量比過去任何時候都要高,這意味著我們處于一個非常好的位置。
(2)是否允許基于特性的目標,如 P0592 對于 C++next?
A:當然!只要它不包含“必須包括這些特性”這樣的說法,因為這就成方案(1)了。瞄準一組特性,給予它們比其他特性更高的優先級,這就成了一個優先次序的問題。我們還是只接受準備好的特性,但我們肯定可以更有意識地優先考慮先做什么,這樣它就有最好的機會盡快做好準備。
https://herbsutter.com/2019/07/13/draft-faq-why-does-the-c-standard-ship-every-three-years/
總結
以上是生活随笔為你收集整理的为什么 C+标准每三年发布一次?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用pip3 install --upg
- 下一篇: MIT发布“全球最快AutoML”,刷新