轉眼間第三次做業了,彷佛須要說點啥,那就說點。java
說到這個,不得不提一下軟件開發的發展史。git
早在上世紀50年代,就已經有早期的編程語言出現,也開始有一些程序編寫者出現(多爲資深電子工程師,和半路出家的數學家)。程序員
然而那個時代,軟件開發基本侷限於本身或本身部門內部的使用,需求並無不少,也並不複雜(或者說人們並無意識到有那麼多事情能夠經過軟件解決)。因此基本都是靠早期的程序猿們的自由開發,也並無現代代碼規範的概念。github
然而等到了60到70年代,隨着硬件技術和工業界思想的進步,軟件層面上的需求愈來愈多,愈來愈雜,且再也不侷限於本身的使用,開始有了各種外包的需求(早期的軟件做坊、外包公司)。這時候,人們發現代碼規模一上來,工程質量將再也不那麼可控。不只開發成本隨規模急劇上升,且開發過程當中的人員與工程管理也出現了很大的麻煩。失敗的案例不在少數,工期拖延數月甚至數年的也經常發生,並且還頗有可能沒法知足用戶的需求或者可靠性極差。軟件工程迎來了一個動亂的年代。正則表達式
1968年,北大西洋公約組織的計算機科學家在聯邦德國召開的國際學術會議上第一次提出了「軟件危機」(software crisis)這個名詞。算法
歸納來講,軟件危機包含兩方面問題:編程
1968年秋季,NATO的科技委員會召集了近50名一流的編程人員、計算機科學家和工業界巨頭,討論和制定擺脫「軟件危機」的對策。在那次會議上第一次提出了軟件工程(software engineering)這個概念。軟件工程正式被列爲工程的一種,並開始走向專業化系統化,以全新的面貌從新步入工業界。數組
現代的軟件工程是一門研究如何用系統化、規範化、數量化等工程原則和方法去進行軟件的開發和維護的學科。經過前人的不斷努力,人們逐漸解決了軟件危機,並認識到規格化設計的重要性,在此期間,一些重要的文檔格式的標準被肯定下來,包括變量、符號的命名規則以及源代碼的規範式。後來隨着發展,這些規範逐漸造成了軟件開發中的規格化設計,而且因爲其高效性與高可靠性,愈來愈受到軟件開發人員的重視。架構
結合我我的嘛,其實也是能說上一些的。因爲筆者在早年長期處於自由成長階段,因此其實不少發展歷程,和歷史的進程十分類似。編程語言
筆者從2年級初學編程(2005年,豆腐塊+win2000的年代),最初寫的都是一些很小的程序(基本不存在超過100行的狀況),用的是面向過程語言和原始的面嚮對象語言。(Pascal、VB6,後來進階VB.NET)
說實話,筆者之因此喜歡編程,喜歡計算機,很大程度上喜歡的是創造的快感,尤爲是計算機這種低成本高回報即刻見效的創造。因而呢,筆者逐漸在試着編寫規模更大程序,來知足一些更加實際的需求。在那個階段,筆者的開發徹底是怎麼順手怎麼來,畢竟急於得到那種看到成果的快感,且尚未造成工程的思惟(和不少同窗現階段的狀態相似)。
然而,筆者在初中那會就發現了一件很頭疼的事情——但凡程序超過500行,不管再簡單的需求,再明確的目的,本身都會開始控制不住局面。具體的表現爲,只要規模一上去,哪怕本來早就想清楚了一切,在debug的時候仍是不是這裏出錯就是那裏出錯,甚至自覺得改好了一邊,而後另外一邊又被帶出毛病的狀況也時有發生。
那個階段,能夠說,筆者本身軟件開發的投入成本隨代碼量上升而上升的幅度是指數級別的。
筆者曾經被這個問題困擾了很是久,一直處於這樣的一個瓶頸期,難以突破。
直到高中,接觸了github,上去看了一些各個語言的開源代碼以後,才恍然大悟。筆者發現:
1:1
),說明相關位置的功能與需求。(相似於規格的requires和effects)a
、b
、b
、d
,其餘變量都亂用單個字母)因而,解決方案就很是明顯了——代碼規範化。由於,多花這些時間作好這些工做,對於全局而言,實際上並不下降效率,正所謂磨刀不誤砍柴工。
當筆者得到進一步能力提高以後,就開始開發更大規模的程序。
然而,當正式步入工業界時,另外一個很現實的問題產生了——對於上層的工程師或架構師,該如何對全局化系統化地設計一個系統?
親手碼代碼顯然速度太慢,且只能一我的幹,不具有可合做性,沒法發揮並行優點。然而設計不實現好的話,又該如何描述設計?
答曰——規格。架構師只須要將各個部分的規格設計好,規定好出入口條件等信息,由下位程序猿進行完成便可。既準確描述需求又提供了測試根據,一箭雙鵰。
筆者未被報過規格錯誤。
筆者
在第十一次做業中,被友善好心素質優良情商天下第一的測試者找到了bug,分別是:
map.txt
內的空白字符lights.txt
內的空白字符很明顯,這三個均不是內部功能性上的錯誤。
能夠說是筆者的需求分析失誤。(前兩個隱藏在指導書上的一個角落中,後一個隱藏在第十次做業的issue區。)
因爲筆者未被報過規格錯誤,且bug均爲需求研究層面上的疏漏,故不存在相關性。
筆者認爲,實際上,只要搞清楚規格的做用與意義,不少問題就應該迎刃而解,無需舉過多的例子。
說到規格的一些不太好的用法,其實最典型的有如下幾種
字面意思,有些很好用布爾表達式表達的卻恰恰用了天然語言
/** * @requires: true; * @modifies: None; * @effects: result will be the equation between a and b; */
應該改成
/** * @requires: true; * @modifies: None; * @effects: \result == (a == b); */
規格,講究的是個對於局部抽象功能的描述。說白了,它只關心這個方法或者類應該實現什麼樣的一個功能,而不關內心頭具體是怎麼實現的,同時,給出的規格條件必須具有可斷定性。
例如程序(GenericPair爲泛型二元對類):
public static GenericPair<Integer, Integer> whatCanYouSee(int a, int b) { int c = a + b; b = c - b; a = c - a; return new GenericPair<>(a, b); }
仔細看的話,應該不難發現其實功能是交換了a
和b
的順序後存入了GenericPair
內。
然而規格很容易被寫成以下的形式:
/** * @requires: true; * @modifies: None; * @effects: * c == (\old(a) + \old(b)); * b == (c - \old(b)); * a == (c - \old(a)); * result will be new GenericPair<>(a, b); */
而正確的應該是改成先後置約束條件。
/** * @requires: true; * @modifies: None; * @effects: (\result.first == b) && (\result.second == a); */
實際上,筆者見過一些同窗,在初學階段把局部變量的修改也寫入了modifies。相似這樣:
/** * @requires: true; * @modifies: z; * @effects: * z = x * y; * \result == (z + x + y); * */ public static void privateVariableSample(int x, int y) { int z = x * y; return z + x + y; }
不過,仍是那句話——規格只關心這個方法或者類應該實現什麼樣的一個功能,而不關內心頭具體是怎麼實現的。
局部變量徹底是屬於方法內部的東西,並不屬於外部設計者須要關心的範疇。因此,不該寫在modifies內,與之相關的表達式在effects關鍵字中也應該展開表達。
/** * @requires: true; * @modifies: None; * @effects: * \result == (x * y + x + y); */ public static void privateVariableSample(int x, int y) { int z = x * y; return z + x + y; }
其實,這一點是ppt上的錯誤示範致使的。筆者在第十次做業報了對方一個這樣的JSF錯誤,然而鑑於對方認爲ppt上有相似的格式,因此筆者只好先選擇了仲裁。
實際上,JSF這樣的東西,從一設計,就是要面向自動化的,同時繼承了doclet(筆者有幸閱讀過JSF源代碼),就是爲了完美兼容和擴展javadoc。而違反javadoc基本格式規範的行爲,顯然與這一設計初衷不符。建議課程組看到以後對相關部分進行全面的修改。
錯誤示範一(第九次PPT,P16):
javadoc基本格式中間行開頭都是須要*
的,且首行(兩個*
的行)不要寫東西。開頭的*
也最好嚴格對齊。
錯誤示範二(第十次PPT,P9):
理由同上
相似這樣的錯誤示範還有很是多。
此外,其實關於javadoc的格式,在idea(或者說jetbrains系列IDE)中,直接鍵入/**
並回車便可生成正確規範的格式。
其實,根據筆者的瞭解,嚴格工程開發是這樣的一個流程:
能夠看出,規格、不變式在開發、測試環節中扮演了至關重要的角色:
固然,實際上,在一些非高度嚴格的工程代碼中,甚至不寫規格也是很常見的。例如筆者參與過的創業公司內的開發,多爲敏捷開發,且攻城獅開發經驗均較爲老道,徹底有能力緊緊掌握全局。
不過,敏捷開發對攻城獅自身素養要求是很高的。而若是想普遍地擴大生產力,則這樣子成本無疑太高。
這時候,強類型面嚮對象語言、代碼規範、文檔規範、規格就得以體現其做用:
生產力決定生產關係,生產力量變引起社會質變,這樣的結論在計算機行業同樣適用。由於,工業界,其終極目標永遠只有一個——創造更多價值。
JSF根據筆者瞭解,彷佛是之前的某位學姐的畢業論文。以及,彷佛課程組對這樣一個東西情有獨鍾。
咱們先來看看JSF爲人稱道的地方:
看似,的確是個好東西,並且理論上確實如此。然而,理論和實際老是存在着不可忽視的差距的:
verilog
似的表達出來?)這麼看下來,彷佛惟一還能夠的地方就是javadoc的兼容性設計了。
JSF的設計宗旨是爲自動化提供可能,而且具有輕量級特性。然而就目前的JSF而言,能夠說是很是尷尬的存在——本是追求自動化的,但是自動化卻作得侷限這麼大,作得這麼不到位,並且實際寫起來對用戶要求還極高,和天然語言比起來體驗只差很差。
綜上,筆者以爲,若是JSF不良好的解決自動化問題,或者從新對這種工具進行需求定位的話,這樣的東西將不存在實際應用到工業界的可能性。(筆者也對這種東西的前景持消極態度)
emmm。。。說在前面,若是讀者您看不懂這段話在說啥的話,那說明不是寫給您的,您能夠直接跳至下一個段落,感激涕零 。
我相信您老人家此次必定又在看個人博客。嘛。。。本菜的博客有您這樣的粉絲,實屬蓬蓽生輝。
以前已經給您寫了一些話,我已經深入沉痛深切地檢討了個人過錯,還望大佬您海涵。
做爲本菜對友善好心素質優良情商天下第一的大佬您的賠禮道歉,我爲大佬送上一句大佬本身說出來的金句——「對了,情商是個好東西」。
emmm。。。筆者認爲,對於這樣的大佬這一句還不夠,那麼,再來兩句——「種瓜得瓜種豆得豆」、「己所不欲勿施於人」。
其餘更多的話,本菜坐臥不安,不敢多言。由於您這樣神通常的大佬哪裏是我這樣的人能夠教育的了的呢。
好的,可愛的筆者抽風完畢。接下來正文繼續。
其實,規格的意義與重要性,筆者在上面均已經進行了論述。這一點絲絕不值得懷疑。
可是,這樣的制度直接照搬進了一個面向小白的OO課程,並且還如此草率地歸入互測考覈,真的合適麼?
筆者給出的答案是否認的。
首先,在目前這樣的課程制度設計下,徹底不能體現規格的重要性。最典型的一點,就是先寫程序後寫規格。這顯然是錯誤的作法,然而,這樣作的不只僅是大部分同窗們,還包括課程的設計——出租車做業第一次並不要求規格,從第二次纔開始要求。這意味着什麼?這意味着你們第二次出租車做業將花費大量的時間補第一次的規格(甚至花在這上面的時間遠遠多於正確使用規格的時間)。給第一次接觸規格的同窗們上來就是這樣的徹底錯誤的引導,顯然是不合適的。
其次,JSF的各類槽點,上面已經吐槽過了,用戶體驗至關差,此處再也不贅述。並且當JSF歸入考覈以後,因爲不得不使用部分天然語言,而致使你們都使用天然語言描述的狀況不斷地發生,然後課程組還給出了require必須布爾表達式的要求,然而根據筆者的調查和了解,並無起到預期的效果。能夠說,JSF的強行推廣是至關失敗的。
不只如此,咱們來回想一下,JSF互測,評判者都是些什麼人——同樣還沒有造成工程思惟,同樣不熟悉規格設計的小白同窗。把這樣的東西的評價權力直接交給自顧不暇的初學者,或者說得更直接點,讓不懂工程的人強行評判工程的好壞,這樣的作法顯然很荒唐。這樣只會致使測試者無從下手(甚至乾脆選擇不講道理亂扣分),而被測試者的公平與利益毫無保障。
不一樣於BUG互測(實際上筆者支持保留BUG的互測),JSF這東西不少同窗都是第一次接觸,工程思惟不少同窗都尚未造成。也許對於職業攻城獅和其餘從業人員而言,他們內心都一把評判的尺子,也具有最最基本的職業道德和職業素養。可是對於初學階段,各方面水準參差不齊的學生而言,這樣的作法顯然太過於理想化了。
此外,課程組還彷佛單純的想依靠高傷害和仲裁機制來保證你們的重視與制度的公平性。可是,在目前這樣雙方都一臉迷茫的情況下,這樣是毫無效果的(甚至能夠說弊遠遠大於利)。盲目的高傷害只會致使你們愈來愈沒有努力的動力(由於再努力再踏實也沒有有些良心歷來不會痛的投機分子過得舒服,本身的努力在高傷害面前一文不值),而滯後至關嚴重的仲裁製度更是致使你們再也不那麼相信正義的存在,可謂雪上加霜(遲來的正義,經常和沒來沒有區別)。
然而,據筆者所知,課程組彷佛在根據經過這樣收集到的數據來進行數據分析,並且彷佛還分析了與bug的相關性,不只如此,甚至還得出了同窗們不夠重視JSF的結論。對此,我只想說,這樣的數據,與其說是JSF評判的最終結果,倒不如說是博弈的最終結果,公平性真實性根本保證不了。用了個錯誤的前提條件,獲取了所謂預期的分析結果,是毫無心義的。
綜上,筆者以爲不該該在使用互測制度來考覈JSF,而應該將評價權交給更加專業的人士。一方面保證同窗們能受到正確的引導,另外一方面也保證制度的公平與合理,此外,也保證數據收集工做真正的客觀性與有效性。