文章:A Brief History of Windows Programming Revolutions(Windows程式設計的革命簡史)
日期:2009.12.01
作者:Ron Burk
作者的部落格:Ron Burk - Programming, psychology, and "stuff".
作者簡介:
曾擔任Windows Developer's Journal的編輯職務;正在寫一本書,書名為"The Pop Psychology of Programming";這裡有一段5分鐘的影片,Ron Burk講解三種computer programming的定義。
Windows程式設計的革命簡史
爬出DLL地獄──再一次
首先,我們有Windows API以及DLL地獄(DLL Hell),第一波的革命技術是DDE──還記得熱連結(hot links)讓我們可以產生出狀態列來顯示微軟股票目前價位嗎?
大約就在那時,微軟搞出了VERSIONINFO這玩意,用來揮除DLL地獄這夢靨,但微軟的另一個團隊發現DDE有一個致命性的缺陷:那不是他們發明的!
為了解決這個問題,他們創造出OLE(跟DDE差不多,看起來不同而已),而且我還深深記得在一場微軟討論會上,有位演講者公開聲明Windows API很快就會改寫成OLE API,螢幕上的每個控制元件將會變成OCX;OLE引進介面這玩意,用來跟DLL地獄說掰掰,還記得那"就地(in situ)"狂熱嗎,還記得那時我們幻想著有一天所有應用軟體通通內嵌在一支(很明顯地,非常大的一支)Word文件中嗎?
就在那時期左右,微軟改拜C++,MFC也出來了,再一次地解決老問題,但這一次有繼承(inheritance)這玩意,不過咧,OLE可不會坐著發呆,重新包裝後以COM之名現身,突然我們醒悟了,OLE(還是DDE啊?)才是王道啊──裡面包含了精心打造的元件版本系統,是用來避免陷入DLL地獄的,與此同時,微軟某搗蛋團隊發現MFC有一個致命性的缺陷:那不是他們發明的!
他們毫不猶豫地修正了那缺陷,創造出ATL,跟MFC差不多,看起來不同而已,並且試著把COM團隊費盡心思教會我們的技術細節通通藏起來,這可刺激到了COM團隊(還是OLE啊,搞不清楚?)重新改名為ActiveX後再出發,釋出數以百磅計的新介面(甚至有新的版本控管介面,用來防止DLL地獄的玩意),還有,讓我們的程式碼可經由瀏覽器來下載的能力,加上各種病毒(哈哈──想辦法跟上腳步吧,你們這群ATL傢伙們!);就像個被忽視沒人裡的小孩一樣,作業系統團隊大聲呼喊著看過來喔,"準備好等著迎接Cairo吧",ㄘㄟˊ,他們從來沒能好好解釋說明過那是啥東西,更別提出貨見人了,不過有一點功勞要算在他們身上,作業系統團隊確實導入了"系統檔案保護機制(System File Protection)",是用來遠離DLL地獄的玩意兒。
與此同時,微軟另一支團隊發現Java有一個致命性的缺陷:那不是他們發明的!怎麼補救呢?於是有了J、Jole、ActiveJ(老實說,我記不得名字了),跟Java差不多,看起來不一樣而已,很興奮吧;不過昇陽開始告微軟,用的是某古老的法條說一家公司不能在一年內放出太多的技術,很明顯地是在試著阻止微軟創造雷同但只是看起來不一樣的產品,結果是讓微軟有了全新的自由,可以把錢塞進國會議員的褲子裡;還記得J/Jole/ActiveJ的產品經理用他的鞋拍桌保證微軟絕對不會終止放棄他的產品嗎?傻孩子!這一切只代表了一件事──ActiveX(還是應該叫COM啊?)團隊得到的關愛眼神太少了,這一群身段柔軟的API打造者,以更強的姿態COM+(不是應該叫ActiveX+嗎?)還有MTS(我不懂,為什麼"MTS"裡沒有"COM"或"ActiveX"或"X"或"+"等字眼呢──這次我整個被他們嚇到了!)回來了,他們還威脅說不久之後就要在所有術語後面再加上一個"+";大約在那個時候,某人大聲嚷嚷著"Windows DNA"和"Windows Washboard"一段時間,不過在我搞懂之前就死掉出局了。
那時,微軟注視著網際網路(internet)的發展已有數年,越來越不安,他們發現,網際網路有個致命性的缺陷:哎呀呀,你大概知道我要說什麼了,於是把我們帶到.NET(唸起來像是"doughnut甜甜圈",看起來不一樣而已),跟網際網路雷同,只不過有著更多的文宣廣告與宣傳;讓我把一點說的非常非常清楚:.NET解掉了DLL地獄這個麻煩,.NET有一個新的程式語言,叫做C#(發現Active++Jspresso有個致命性的缺陷,所以下場是出局了),.NET包含一個虛擬執行機器,所有語言都在上面跑(發現依賴英代爾CPU有個致命性的缺陷),.NET只用一套登入系統(如果不把你所有的密碼都存放在微軟的主機上,那是有致命性的缺陷的),事實上,比較簡單的方式是把.NET沒有的東西列出來;毫無疑問的,.NET將會是Windows程式設計的革命性的徹底改革的新方式...到明年就不是了。
2010/09/07
翻譯:Windows程式設計的革命簡史(A Brief History of Windows Programming Revolutions) by Ron Burk
標籤: programming
2010/08/22
翻譯:C++的編譯速度(C++ Compilation Speed) by Walter Bright
文章:C++ Compilation Speed(C++的編譯速度)
日期:2010.08.17
作者:Walter Bright
作者的部落格:Walter Bright Home Page
作者簡介:
Walter Bright是位電腦程式設計師,是D語言的設計者,第一套C++原生編譯器的主要開發員,也就是Zortech C++(後來變成Symantec C++,現在是Digital Mars C++),在C++編譯器之前,他開發了Datalight C編譯器,先以Zorland C後以Zortech C之名販售。
C++的編譯速度
我常聽到有人抱怨說C++程式碼編譯速度很慢,有時候甚至要花上整夜的時間,編譯慢是exported templates這玩意的源由之一,甚至列在發展Go語言的理由清單上,這點確實是個問題;既然我身在C++編譯器的產業中,三不五時就會被問到這點。
為什麼C++編譯速度慢?一旦我們合理假設開發C++編譯器的人都擅長於寫出效能高的程式碼,那麼,一定有某個深植於C++語言本身的原因;的確,不同牌的C++編譯器速度快慢相差極大,但還沒完喔,其他語言通常能夠快上一整個等級,而且厲害的編譯器專家應該不會只為其他語言寫編譯器吧(!)。
我從1987就在寫C++編譯器了,對比今日想當年,電腦可是慢的不得了,所以我投注極大的精神讓編譯器能夠快一點,花上大把的時間做效能分析以及微調各個小地方來讓編譯器更快,我發現,語言本身的某些特性讓編譯速度快不了。
理由是:
1. 轉譯過程中有七個階段[1]。雖然有些可被合併處理,但在前端處理原始碼最少要有三個階段,至少我還沒找到降到三以下的法子。要快的話語言設計時就只能有一個階段,C++0x惡化了這點,居然要求trigraph轉換與行尾為\與下行接合這兩個功能要能夠支援string literals[2]。
2. 每個階段都相依於前一個階段,意思是,沒有可靠的方式可以做往前先看的動作,例如,往前先去找#include然後先去讀進檔案;編譯器沒辦法往前先看出是個string literal所以不要做trigraph轉換,必須先做trigraph轉換,但要做好回到上一步的準備;我從沒找出能夠平行編譯C++程式碼的方法,除了在make時加上-j參數這種很粗略的作法。
3. 因為#include是種文本逐字置入(textual insertion)的機制,而不是符號式(symbolic)的,當一個檔案被#include很多次,編譯器只能悲情地做白工地一再地處理,即使是被#ifndef包起來也一樣。(Kenneth Boyd跟我說,如果將標準文件讀的仔細一點,是有可能允許編譯器省略被#ifndef包起來的#include,但我不知道有哪一支編譯器利用了這點。)
4. 程式檔案中總是傾向於,通通#include進來就對了,當責任全部落在編譯器身上時,每一個.cpp檔通常都會連帶引出一拖拉庫的檔案要處理,在Ubuntu上,就算只把標準函式庫#include進來,居然需要處理74支檔案總共37,687行耶(不包括同支檔案被#include多次的情形);templates以及generic programming的興起更惡化了這點,而且,把更多的程式碼放進標頭檔(header files)中的壓力也逐漸升高,更是雪上加霜。
5. 語意上的與語法上的(不只是詞彙上的)處理單位依賴處在它之前的整個原始文本,意思是,沒有東西是上下文無關的;不把#include的東西先看一看,就不能正確地解析(parse)檔案,甚至是先做lex的動作也不行,標頭檔在第二次#include時可能含有不一樣的內容(事實上,確有標頭檔利用這點)。
譯註:語意上的 semantic,語法上的 syntactic,詞彙上的 lexical。
6. 因為第5點,編譯器在某個TU[3]所編譯的#include的結果,不能下一個TU共用,每個TU都必須從頭開始。
7. 因為不同的TU之間彼此不知道對方的存在,常用的templates在每個TU都會被產生出來,鏈結器(linker)會將重複的刪除,但當初所花的時間都白費了。
預先編譯標頭檔(precompiled headers)解決了一些問題,但那是對非標準的C++做出某些簡化後的假設,才可辦到,例如,標頭檔被#include還是會含有同樣的內容;所以你必須小心,不能違反這些假設。
想解決這些問題又要跟舊有的程式碼保持相容性,真是高難度的挑戰啊,我預期在C++0x之後,會有相當份量的心力花在這些問題上,但那至少是10年後了。
在那之前,並沒有哪個方法可稱得上是解答,exported templates被廢棄了,precompiled headers是不符合標準的,imports被踢出C++0x標準之外,以及往往你沒有選擇編譯器的權力,諸如此類的;現在來說,有效地使用make -j參數可算得上是最好的方法了。
我會再談談關於語言的設計,哪些特性能夠導致快速的編譯速度。
註解
[1] C++98標準文件的2.1章節, 七個階段是:
1. Trigraph與萬國碼轉換。
2. 行尾為\時接到下一行
3. 轉換成預先處理的標記(preprocessing tokens),標準文件註明說這是上下文相依的。
4. 預先處理的指令執行,展開巨集,#include的讀取以及再跑一次1到4。
5. 將原始碼中處在char與string literals的字元轉換成執行字元集(execution character set)。
6. string literal的接合。
7. 將預先處理的標記轉成C++的標記(C++ tokens)。
[2] 在C++0x標準文件中的例子在2.14.5-4:
const char *p = R"(a\
b
c)";
assert(std::strcmp(p, "a\\\nb\nc") == 0);
[3] 一個TU,也就是一個轉譯單位(Translation Unit),通常就是一支C++原始碼檔案,通常是以.cpp為副檔名,編譯一支TU會生出一個目的檔(object file),每個TU的編譯過程都與其他TU不相關,最後由鏈結器(linker)將目的檔整合成單一的執行檔。
感謝
感謝Andrei Alexandrescu、Jason House、Brad Roberts以及Eric Niebler給予這份文章草稿時的有用建議。
標籤: programming
2010/08/16
翻譯:Java簡史(A Brief History of Java) by Jeff Foster
文章:A Brief History of Java(Java簡史)
日期:2010.08.13
作者:Jeff Foster
作者的部落格:Fatvat : Exploring functional programming
Java簡史
話說當年1995之時,昇陽(Sun)公司釋出Java程式語言,做為整個Java平台策略的一部分,當初喊著“一次編寫,到處運行”的口號,要讓Java遍地開花,從腕錶到手機到筆電到超級電腦,隨處皆可運行。

剛開始時Java的接受度有高有低,當出現Java力有未逮之處,就會有福音天使出來保證這技術將會改變世界,你看,靠Java運作的烤吐司機就在不遠的角落了。
隨著時間演進,為了守住“一次編寫,到處運行”的承諾,Java也逐漸背上更多的負擔,標記為廢棄的方法(deprecated methods)到處可見,但昇陽必須留下這些功能來保持向後相容性;java.util.DateTime此套件變成了劣質設計的同義字,差勁的命名規則總是在修正中(叫它size好還是length好呢?)。
微軟(Microsoft) 的.NET開始蠶食Java的領地,微軟團隊導入delegates,一種有做型別確認的函式指標,使得事件處理(event handling)變得容易許多;Java要趕快反擊,所以在版本1.1時,Java生出了inner classes,能夠有類似的效用,但以一種較有限制與用起來較麻煩的方式出現,一份Java白皮書斷定地說『bound method references是不必要的東西....這玩意減損了Java語言的簡單性與一致性』,但與此同時,將bound method references放進Java裡的勢力從沒消失過。
當Java到了版本1.4時,為了對抗微軟的.NET,昇陽決定要有一套新的策略手段,思索良久之後,昇陽將版本1.4改成“5”,試圖一舉超前.NET的2.0。
同時間附帶了另一個決策,實作generics,一種能夠有額外的型別安全檢查的技術,不幸的是,隨型別安全而來的代價是要多打字,工程師引入generics後,每次又要寫一遍
List<Foo> foos = new ArrayList<Foo>敘述時,就會常被聽到咒罵聲。
大學很快地就接納了Java;學生們不再需要學習手動記憶體管理與指標的種種艱澀難懂的奧祕,反之,他們可以依賴Java來做這些苦功夫,集中精神在解決問題上,不幸的是,這也導致一批同等級的開發者,被稱作“設計模式使徒(Patternistas)”,手上只有鎚子且把所有問題都看做釘子去敲,在他們的領導下,Java命名規則越來越可笑,當這種類別名“RequestProcessorFactoryFactory”成為一種常態時,一些開發人員開始質疑無限制地構築抽象化高塔是否真為明智之舉。
當開發人員意識到他們終日所為僅是把數千行的程式碼搬來搬去而已,他們需要一個字眼來辯護他們的存在意義,那個字就是“重構(refactoring)”,所有的設計模式使徒欣喜不已;他們不但能運用工廠的工廠模式(factory factories)、獨身模式(singletons)與訪問者模式(visitors)來解決問題,而且還能朝三暮四改變心意,並用個時髦字眼來正當合理化!
整個產業的演進方向只是為了滿足設計模式使徒們而已,跟別人與別的語言比起來,老鳥們覺得Java越來越弱,所以新型開發環境出現了,IntelliJ與Eclipse的目標是將開發人員受的傷害最小化,靠著極佳的程式碼自動補足機制(code completion)與重構功能,只需按幾個鍵而不用輸入一長串的程式碼來達到那想要卻沒有的語言功能。

Java開始向企業端進攻,招攬了一些有領導地位的的架構大師,打造出一套會造成典範轉移的協同式架構方法來建置企業軟體,其結果不小於一場革命;爪哇豆(beans)現身了,Beans顯然是一種伺服端的元件架構,用來當企業應用軟體的建構基本模組。
使用generics所帶來的角括號障礙一旦減低之後,Java邁步向前跳上了XML的列車,藉由使用XML,開發人員就能將簡單明瞭的概念表達成一整個龐大囉嗦的角角惡夢,好處是XML檔案(不同於其他檔案類型)可以輕易地被電腦看懂處理,至於對人難以閱讀這種小代價是值得的,像是Ant和JBoss這些軟體都是由可執行的XML所建構出來的。
與此同時,在這些架構大師的宇宙之外,一群新種程式員認為將該死的工作完成遠比一整天都花在打字重要,這種想法誕生出一些框架,例如Rails,設計的重點在於不擋路讓你能解決真正的問題,其中心思路以“約定俗成先於設定(convetion over configuration)”之名廣為人知,Rails獲得正面的迴響,而且至少有一些Java信徒轉投向Ruby的陣營;Java不再能緊抓人心的第一個徵兆開始浮上檯面。
2006年8月,Java 7計畫啟動,很多開發人員都要求一個叫做lambda expressions的功能,毫無疑問地會簡化很多原先Java搞的很痛苦的撰碼作業,可惜,Java委員會四年後還在為這項功能的細微差別爭辯不休,而且有可能會被排除掉,Java 7的無作為引出了新一代更迷人的語言,例如Clojure和Scala,設計在Java環境中運行,但不需要Java語言。
2009年4月,甲骨文(Oracle)公司宣布計畫將收購昇陽,此乃敲下棺材釘的最後一鎚,由“黑暗王子拉瑞”所領軍的甲骨文是一部併購機器,擅長於企業軟體與賺進大筆鈔票,當甲骨文的律師們了解一份份的軟體專利文件,他們會挑個大目標然後引起戰鬥,而還有哪個目標比谷歌(Google)更大呢(一家網路廣告的領導品牌),所以甲骨文的律師猛撲而出,戰爭就此展開。
這會給Java帶來什麼後果呢?從15年前的小小開端起,在昇陽的領導下,Java爬上了最熱門的程式語言的頂端,而在甲骨文的控制下,不但到底會不會有下一版的Java情況不明,更別提開發人員渴望許久的功能了,這是Java的新開始還是結束呢?
標籤: programming