卷2:第9章 ITK

2018-02-24 15:55 更新

原文鏈接:http://www.aosabook.org/en/itk.html

作者:Luis Ibanez 和 Brad King

譯按:原文的二級和三級標題并無章節(jié)號,只有字號區(qū)別。

9.1 ITK是什么?

ITK,又名Insight Toolkit,是一種用于圖像分析的庫,它由美國國家醫(yī)學(xué)圖書館(US National Libraray of Medicine)發(fā)起并資助開發(fā)的。ITK可以看作是一個方便使用的圖像分析算法百科全書,特別是它包含了圖像濾波、圖像分割和圖像配準。該庫由一個大學(xué)和商業(yè)公司組成的聯(lián)合組織、以及來自世界各地的代碼提交者共同開發(fā)。ITK的開發(fā)工作始于1999年,在其最近的十周年紀念過后不久,全庫經(jīng)歷了一次重構(gòu)過程,這次重構(gòu)旨在去除代碼庫中的頑固代碼;并對其重塑,以適應(yīng)下一個十年的發(fā)展。

9.2 架構(gòu)特性

軟件工具箱與他們的社區(qū)有一種密切的關(guān)系。他們以一個持續(xù)迭代的周期塑造彼此。軟件被持續(xù)改進,直到它能滿足社區(qū)的需要,與此同時,社區(qū)基于軟件準許或者約束他們要怎樣做來制約他們自身的行為。因此,為了更好地理解ITK架構(gòu)的天性,了解ITK社區(qū)經(jīng)常提出何種問題,以及他們?nèi)绾沃纸鉀Q這些問題,是非常有用的。

9.2.1 野獸的天性

如果你不了解野獸的天性,那這就對理解它們解剖結(jié)構(gòu)的機制毫無用處。
--?Dee Hock, One from Many: VISA and the Rise of Chaordic Organization

一個典型的圖像分析問題中,研究者或者工程師會取一個輸入圖像,通過降噪或是提高對比度來改善圖像的某些特性,然后進行處理以辨別圖像中的某些特征,比如拐角和強邊緣。這種類型的處理很自然地符合一種數(shù)據(jù)管線架構(gòu),如圖9.1所示。

圖9.2:MRI腦部圖像,中值濾波器,邊緣檢測濾波器

對于圖中的每一項任務(wù),圖像處理社區(qū)都已經(jīng)開發(fā)出了各種算法,并且繼續(xù)開發(fā)新的算法。為什么他們繼續(xù)做這些?你可能會問,答案就是圖像處理是一種科學(xué)、工程、藝術(shù)、以及“烹飪”技術(shù)的組合。公然宣稱某種算法組合對于一個圖像處理任務(wù)來說是“對的”無異于類似宣布正餐上要備“對的”巧克力甜點一樣的誤導(dǎo)。不是追求完美,社區(qū)奮力制造出豐富的工具來確保在面對一項挑戰(zhàn)性的圖像處理任務(wù)時,不會出現(xiàn)可選項的短缺。當然,事情發(fā)展的狀態(tài)是要付出代價的。代價就是圖像分析人員有一個困難的任務(wù),就是在從幾十個不同工具中選擇可用的不同組合,而這些組合可以得出類似的結(jié)果。

圖像分析社區(qū)與研究社區(qū)聯(lián)系緊密。某一個研究小組與某一個算法群相關(guān)聯(lián)是尋常現(xiàn)象。“品牌命名”的風(fēng)俗,以及某種程度的“市場化”,導(dǎo)致了一種這樣的情況:軟件工具箱可以盡可能好地為社區(qū)提供一個非常完整的算法實現(xiàn)集,然后將之混合并匹配,以創(chuàng)建一個滿足社區(qū)需要的菜譜。

為什么ITK要被設(shè)計并實現(xiàn)成一個巨大的某種程度獨立、且有條理的工具——圖像濾波器——的原因有很多,多數(shù)濾波器用于解決類似的問題。在本文中,某種程度的“冗余”——打個比方,提供高斯濾波器的三種不同實現(xiàn)方法——這不應(yīng)該被看做是問題,而應(yīng)該是一種有價值的特性,因為不同的實現(xiàn)可以可交換地使用,以滿足約束并且發(fā)掘與圖像尺寸、處理器數(shù)量、以及可能與某個給定圖像處理應(yīng)用程序中的特定高斯核尺度相關(guān)的效率潛能。

該工具箱還被創(chuàng)建成一個成長的、不斷更新自身的資源,因為新的算法和更好的實現(xiàn)出現(xiàn)了,取代了現(xiàn)有的;還因為為了應(yīng)對不斷涌現(xiàn)的新的醫(yī)學(xué)影像處理技術(shù)而開發(fā)的新工具。

快速了解了ITK社區(qū)中的圖像分析人員的每日例行公事,我們現(xiàn)在開始深入架構(gòu)的主要特性:

  • 模塊化
  • 數(shù)據(jù)管線
  • 工廠
  • IO工廠
  • 可復(fù)用性
  • 可維護性

9.2.2 模塊化

模塊化是ITK的主要特性之一。這個需求源于圖像分析社區(qū)的人們解決問題時的工作方式。大多數(shù)圖像分析問題將一幅或多幅輸入圖像放入處理濾波器的組合中,這些濾波器用于增強或是提取圖像中的某些特定的信息片段。因此這中間就沒有大的處理對象,而是許多小的。邏輯上講,這種圖像處理問題的結(jié)構(gòu)性本質(zhì)特征意味著要實現(xiàn)一個由許多圖像處理濾波器組成的軟件,這些濾波器就可以以不同的方式組合使用了。

將某些特定的處理濾波器聚合為一個家族也是如此,其中的某些實現(xiàn)上的特性可以被分解。這就導(dǎo)致圖像濾波器自然分組為模塊以及模塊群。

至此,模塊化存在于ITK中的三個自然層次上:

  • 濾波器層次
  • 濾波器家族層次
  • 濾波器家族群層次

在圖像濾波器層次上,ITK大約擁有700個濾波器??紤]到ITK是以C++實現(xiàn)的,這個層次中的每一個濾波器都是以C++類輔以面向?qū)ο蟮脑O(shè)計模式來實現(xiàn)的。在濾波器家族層次上,ITK根據(jù)濾波器進行處理時的方式將其分組。例如,所有與傅里葉變換有關(guān)的濾波器將會放入同一個模塊。在C++層次上,模塊映射于源代碼文件樹,并且映射于軟件編譯成二進制形式后的庫文件。ITK擁有120個這種模塊。每個模塊包含:

  • 屬于該家族的圖像濾波器的源代碼。
  • 一些描述該模塊如何構(gòu)建并列出該模塊與其他模塊之間依賴關(guān)系的配置文件。
  • 對應(yīng)于每個濾波器的一組單元測試。

圖9.4:ITK中50個最大的模塊的大小分布,單位:字節(jié)

ITK中的模塊化也應(yīng)用于其中的第三方庫,這些庫并不是工具箱的直接組成部分,但是工具箱依賴它們,因此將這些第三方庫與工具箱中的其余代碼一起發(fā)行,以方便使用者。尤其是圖像文件格式庫:HDF5、PNG、TIFF、JPEG、OpenJPEG等。這里強調(diào)第三方庫是因為約占ITK總大小的56%。這一點反映了開源應(yīng)用建立在現(xiàn)有平臺之上的自然特征。第三方庫的大小分布固然不能反映ITK的組織架構(gòu),因為我們采用了這些有用的庫,僅僅是由于它們屬于上游開發(fā)產(chǎn)物。然而, 第三方庫的代碼與工具箱一并發(fā)行、并且將之分割,是模塊化過程的關(guān)鍵驅(qū)動因素之一。

這里給出模塊大小的分布,因為它是一種代碼合理模塊化的量度??梢园汛a的模塊化看做是一個連續(xù)譜,分布于從只有一個巨大的、單體的模塊的一端,到將代碼分割成許多相等大小的模塊的另一端。大小分布是一種工具,它用于顯示模塊化過程的進展,尤其是確保同一個模塊中沒有大塊的代碼,除非有真實的邏輯依賴關(guān)系需要這樣的分組。

ITK的模塊化架構(gòu)使下面的事項成為可能或有助于它們實現(xiàn):

  • 減少和澄清交叉依賴關(guān)系
  • 采用社區(qū)貢獻的代碼
  • 評估各模塊的質(zhì)量指標(如:代碼覆蓋率)
  • 構(gòu)建工具箱的某個子集
  • 將工具箱的某個子集打包用于再發(fā)行
  • 通過添加新的模塊來維持持續(xù)成長

模塊化過程使顯式地辨別并聲明工具箱中不同部分的依賴關(guān)系成為可能,當然,這些不同的部分是要放在模塊中的。在許多情況下,這種做法暴露了做作的以及不正確的依賴關(guān)系,隨著時間的變化,這些依賴關(guān)系被引入工具箱,當大多數(shù)代碼被放入一些大的家族群中的時候,這些依賴關(guān)系就會被忽視。

評估各模塊的質(zhì)量指標的用處是雙重的。首先,它使開發(fā)者對其維護的模塊負責(zé)變得容易。其次,它使得參與由若干開發(fā)者集中短期時間來提高某個特定模塊的質(zhì)量的清理行動成為可能。當集中精力于工具箱的一小部分的時候,它使我們更容易看到我們的努力、并且更容易地保持開發(fā)者的參與、受到激勵。

對于重新迭代,我們發(fā)現(xiàn)工具箱架構(gòu)反映了社區(qū)的組織,以及在有些情況下,被用于軟件的持續(xù)成長和質(zhì)量控制的過程。

9.2.3 數(shù)據(jù)管線

多數(shù)圖像分析任務(wù)具有的階段性特征很自然地導(dǎo)致我們選擇了數(shù)據(jù)管線架構(gòu)作為數(shù)據(jù)處理的基礎(chǔ)設(shè)施。數(shù)據(jù)管線是下列成為可能:

  • 濾波器串聯(lián):若干圖像濾波器可以一個接一個的串聯(lián)起來,組成一個處理鏈,它可以對輸入圖像進行一系列的操作。
  • 參數(shù)探測:一旦處理鏈組合在一起,改變鏈中任何一個濾波器的參數(shù)就會很容易,并且可以探測改變參數(shù)會對最終的輸出圖像產(chǎn)生什么影響。
  • 內(nèi)存動態(tài)載入:數(shù)據(jù)量大的圖像可以通過每次只處理該圖像的一部分來管理。利用這種方法,處理數(shù)據(jù)量大的圖像就成為可能,否則,這種圖像將無法載入內(nèi)存。

圖9.1和9.2已經(jīng)從圖像處理的角度展示了一種數(shù)據(jù)管線的簡化表示。圖像濾波器一般都具有數(shù)值型參數(shù),用于調(diào)整濾波器的行為。每次有參數(shù)發(fā)生變更,數(shù)據(jù)管線就會將其輸出標記為“臟的”,并且知道這個濾波器及其下游使用它的輸出的各濾波器應(yīng)該重新執(zhí)行。管線設(shè)施的特性減少了探測參數(shù)空間的困難,同時為實驗中的各個示例分配最少的處理能力。

更新管線的過程可以通過每次只處理圖像的一部分的方式來驅(qū)動。這是一種對于支持動態(tài)載入處理功能來說很有必要的機制。實踐中,該過程被一種從一個RequestedRegion規(guī)范的內(nèi)部傳遞所控制,這種傳遞過程將規(guī)范從下游的濾波器傳向其上游的濾波器。這種通信過程是通過一個內(nèi)部API來實現(xiàn)的,并且可供應(yīng)用程序開發(fā)者直接調(diào)用。

舉一個更具體些的例子,如果一個高斯模糊圖像濾波器以一幅由中值濾波器處理過的100×100像素的圖像作為輸入,那么該模糊濾波器可以向中值濾波器請求只處理原圖像的四分之一,也就是說,一個大小為100×25像素的圖像區(qū)域。該請求還會繼續(xù)向上游傳播,同時警告沿途各濾波器為了生成請求中規(guī)定大小的圖像區(qū)域,將不得不向圖像區(qū)域的尺寸附加邊界。后面還將講述更多關(guān)于數(shù)據(jù)流的內(nèi)容。

不論是對給定濾波器的參數(shù)做出的改變,還是該濾波器所要處理的特定請求區(qū)域所做的改變,都會將管線標記為“臟的”、并提示管線的下游濾波器需要重新執(zhí)行。

9.2.3.1 過程與數(shù)據(jù)對象

有兩種主要的對象類型被設(shè)計用于存儲管線的基本結(jié)構(gòu)。它們是DataObjectProcessObject。DataObject是承載數(shù)據(jù)的類的抽象;例如:圖像和幾何網(wǎng)格。ProcessObject為處理上述數(shù)據(jù)的圖像濾波器和網(wǎng)格濾波器提供抽象。ProcessObjectDataObject為輸入,并對其進行某種算法變換,例如圖9.2中的那些。

DataObject是由ProcessObject生成的。這個鏈條通常自從磁盤讀取DataObject開始,例如通過使用一種ProcessObject類型的ImageFileReader。唯一能夠修改某個DataObject的就是生成該DataObjectProcessObject。輸出的DataObject一般連入管線中下游的濾波器作為它們的輸入。

圖9.5:ProcessObjectDataObject之間的關(guān)系

這種序列關(guān)系如圖9.5所示。同一個DataObject可能會傳給多個ProcessObject作為它們的輸入,如圖中所示,DataObject由管線開端的文件reader生成。在這種特定情況下,文件reader是ImageFileReader的實例,而它所生成的、作為其輸出的DataObjectImage類的一個實例。某些濾波器需要兩個DataObject作為輸入也是很平常的現(xiàn)象,比如上圖中右半部出現(xiàn)的相減濾波器就是這樣的例子。

ProcessObjectDataObject連接起來 構(gòu)建管線的副作用。從應(yīng)用程序開發(fā)者的角度來看,管線是通過涉及到一連串的調(diào)用連接起來的,如:

writer->SetInput(canny->GetOutput());
canny->SetInput(median->GetOutput());
median->SetInput(reader->GetOutput());

然而在內(nèi)部,連接在一起的并非以這中一連串的ProcessObject,而是下游的ProcessObject與其上游ProcessObject生成的DataObject。

管線內(nèi)部的鏈條結(jié)構(gòu)通過三種類型的連接維持在一起:

  • ProcessObject保有一系列指向其輸出的DataObject的指針。ProcessObject擁有并控制著其生成的DataObject。
  • ProcessObject保有一系列指向作為其輸入的DataObject的指針。輸入的DataObject由上游的ProcessObject擁有。
  • DataObject保有指向生成它的ProcessObject的指針。該ProcessObject正好還擁有和控制著這個DataObject。

這些內(nèi)部鏈接隨后被用于在管線內(nèi)部向上游或下游傳遞調(diào)用信息。在所有這些互動過程中,ProcessObject都保持對其所生成的DataObject的控制和所有權(quán)。下游的濾波器通過指針的鏈接來獲得對一個給定DataObject的信息的訪問權(quán)限,這種鏈接是由一連串的對SetInput()GetOutput()的調(diào)用建立起來的,它甚至無需獲得對輸入數(shù)據(jù)的控制。出于實踐的目的,濾波器應(yīng)當將其各自的輸入數(shù)據(jù)看作是只讀的對象。這一點在API中通過在SetInput()方法的變量中使用C++的const關(guān)鍵字得到了加強。作為一個通用的規(guī)則,ITK還是包含了一個const-correct的外部API,盡管從內(nèi)部來看,這種const-correctness被某些管線操作重載。

9.2.3.2 管線類層次

圖9.7:UML時序圖

當應(yīng)用程序調(diào)用管線中最后一個濾波器的Update()方法時,整個流程即被觸發(fā);在這個具體的例子當中,這個濾波器就是ImageFileWriter。Update()調(diào)用指向上游方向以初始化第一階段。也就是說,從管線中的最后一個濾波器起,朝向管線中的第一個濾波器。

第一個環(huán)節(jié)的目的是為了查詢這樣的問題,“你能為我生成多少數(shù)據(jù)?”這個問題轉(zhuǎn)化為代碼就是UpdateOutputInformation()。這個方法中,各個濾波器根據(jù)其輸入中的可用數(shù)據(jù)量來計算可作為輸出的圖像數(shù)據(jù)量??紤]到必須在該濾波器回應(yīng)輸出數(shù)據(jù)量之前獲知輸入數(shù)據(jù)量,這個問題就得傳導(dǎo)至上游的濾波器,一直傳至某個能夠回應(yīng)該問題的源濾波器。在這個示例中,源濾波器就是ImageFileReader。它能夠通過從其所讀入的圖像文件收集信息,得出其輸出的數(shù)據(jù)大小。一旦管線中的第一個濾波器對問題做出了回應(yīng),該濾波器下游的一系列濾波器就能夠依次計算其各自的輸出數(shù)據(jù)量,并一直運行至管線中的最末一個濾波器。

第二個環(huán)節(jié)的處理方向也是向上游方向的,用于告知各濾波器應(yīng)該輸出的數(shù)據(jù)量,此數(shù)據(jù)量是管線運行過程中所需要的。Requested Region是支持ITK的流處理能力的基本概念。它使“告知濾波器不要生成整個完整圖像、而只是關(guān)注圖像的某個子區(qū)域(即:Requested Region)”成為可能。這在手頭的圖像大于系統(tǒng)內(nèi)存的時候是非常有用的。調(diào)用請求從最后一個濾波器傳導(dǎo)至第一個,在途中的每個濾波器,requested region的尺寸都會被修正,這些修正要考慮到該濾波器輸入中可能需要的任何附加的邊界,這樣該濾波器才能生成給定區(qū)域尺寸的輸出。在我們的這個示例中,中位數(shù)濾波器一般會向其輸入中加入2-像素的邊界。也就是說,如果writer向中位數(shù)濾波器請求一個500×500尺寸的區(qū)域,那么中位數(shù)濾波器就會相應(yīng)地向reader請求一個502×502尺寸的區(qū)域,因為中位數(shù)濾波器在缺省情況下計算一個輸出像素,需要一個3×3像素的鄰域。這個環(huán)節(jié)被寫入PropagateRequestedRegion()方法。

第三個環(huán)節(jié)要觸發(fā)Requested Region內(nèi)的數(shù)據(jù)的計算。該環(huán)節(jié)的處理方向也是向上游,它被定義為UpdateOutputData()方法。由于各個濾波器在其計算出輸出結(jié)果之前都需要輸入數(shù)據(jù),本環(huán)節(jié)的調(diào)用請求先向其上游的濾波器傳遞,然后再向上游傳導(dǎo)。然后返回到實際進行數(shù)據(jù)計算的當前濾波器。

第四個環(huán)節(jié)(最后一個環(huán)節(jié))的處理方向是向下游的,它由每個實際執(zhí)行運算的濾波器組成。該環(huán)節(jié)被寫為GenerateData()。下游方向并不是一個濾波器向其下游發(fā)送調(diào)用請求的結(jié)果,而是UpdateOutputData()的調(diào)用以從管線中的第一個濾波器到最后一個的順序執(zhí)行。也就是說,所發(fā)生的下游方向的順序,要歸因于調(diào)用的時機,而不要歸因于什么濾波器在驅(qū)動這一調(diào)用。這個說明是很重要的,因為ITK的管線從本質(zhì)上講是Pull Pipeline,其中的數(shù)據(jù)是管線的末端所請求的,而且這種邏輯也是由管線的末端來控制的。

9.2.4 工廠

ITK的基礎(chǔ)設(shè)計需求之一是提供多平臺支持。這一需求出現(xiàn)于追求使該工具箱的影響最大化,通過使工具箱能夠為社區(qū)所廣泛使用,而無需考慮其各自的平臺。ITK采用工廠設(shè)計模式來應(yīng)對這樣的挑戰(zhàn):支持多種不同硬件和軟件平臺、而不犧牲一個解決方案在不同平臺上的實用性。

ITK中的工廠模式使用類的名稱作為向構(gòu)造函數(shù)注冊的鍵值。工廠的注冊在運行時進行,這一過程可以在ITK應(yīng)用程序啟動時,通過簡單地將動態(tài)鏈接庫放入指定路徑來完成。后一種特性提供了一種以干凈、透明的方式實現(xiàn)插件架構(gòu)的基本機制。其影響是減少可擴展圖像分析應(yīng)用程序的開發(fā)難度,同時滿足了提供持續(xù)成長的圖像分析能力的需要。

9.2.5 IO工廠

工廠機制對于IO操作尤為重要。

9.2.5.1 以外觀模式擁抱多樣性

圖像分析社群開發(fā)了非常多的文件格式來儲存圖像數(shù)據(jù)。這些文件格式中的大多數(shù)都是為了滿足特定的需要而設(shè)計和實現(xiàn)的,因此為支持特定類型的圖像而進行了微調(diào)。結(jié)果,新的文件格式定期涌現(xiàn)并推廣到這個社群。注意到這一形勢,ITK開發(fā)團隊設(shè)計了一個IO架構(gòu),適于減輕擴展性工作,向這樣的架構(gòu)中定期添加越來越多的文件格式是簡單的。

,第I卷,Naval Center for Cost Analysis, Air Force Cost Analysis Agency, 2008。)維護估計要占到一個軟件開發(fā)人員實際工作的大約80%,而當忙于維護的時候,開發(fā)人員的大部分時間都被用于閱讀他人的代碼,試圖看懂這些代碼的意圖(見Clean Code, A Handbook of Agile Software Craftsmanship,Robert C. Martin,Prentice Hall,2009)。統(tǒng)一的風(fēng)格確實想減少開發(fā)人員將自己沉浸于一個新近的開源文件、并在對該文件做出任何修改之前理解其中的代碼的工作中所花費的時間。出于同樣的原因,統(tǒng)一的風(fēng)格降低了開發(fā)人員嘗試修復(fù)舊有的bug時、由于對代碼的誤解并隨之做出的引入新的bug的修改的概率(The Art of Readable Code,Dustin Boswell,Trevor Foucher, O'Reilly,2012)。

使這些工具有效的關(guān)鍵在于確保它們:

  • 能夠為每一個開發(fā)人員所使用,因此我們傾向于開源工具。

  • 能夠運行于一個正規(guī)的基礎(chǔ)上。在ITK中,這些工具已被整合到由CDash管理的每日構(gòu)建和Continuous Dashboard構(gòu)建中去。

  • 盡可能緊密地運行于代碼所寫的地方,這樣變動就能被立即修復(fù),開發(fā)人員就能快速查到哪種做法破壞了風(fēng)格規(guī)則。

9.3.4 重構(gòu)

ITK始于2000年,并持續(xù)發(fā)展至2010年。2011年,幸虧融入了聯(lián)邦資助基金,開發(fā)團隊才有了真正的專門的機會進行重構(gòu)的努力。該基金由國家醫(yī)學(xué)圖書館提供,作為美國恢復(fù)和再投資法案(ARRA,American Recovery and Reinvestment Act)所發(fā)倡議的一部分。這不是一個小小的承諾。想象一下你一直致力于一個軟件超過十年時間,然后你獲得了一個把它清理干凈的機會;你該改動些什么呢?

這個做廣泛重構(gòu)的機會十分難得。在之前的十年里,我們依賴于每天的努力來進行小規(guī)模的、局部的重構(gòu),清理那些我們走進的特殊的角落。這個持續(xù)的清理和提高過程利用了開源社群的大規(guī)模協(xié)作的優(yōu)勢,該過程由CDash驅(qū)動的測試基礎(chǔ)設(shè)施確保安全,此基礎(chǔ)設(shè)施通常進行工具包中84%的代碼的測試。注意,與此相反,軟件工業(yè)的平均測試覆蓋率估計只有50%。

在重構(gòu)的努力過程里被改動的許多事物當中,與架構(gòu)最為相關(guān)的有:

  • 工具包中引入了模塊化

  • 整型被標準化

  • typedef被修復(fù),從而能夠在所有平臺上進行大于4GB的圖像數(shù)據(jù)的處理

  • 軟件過程被修正:

    • 從CVS遷移到Git

    • 利用Gerrit引入代碼審查

    • 根據(jù)CDash@home的要求引入測試

    • 用于下載單元測試所需數(shù)據(jù)的改進方法
  • 廢棄對過時的編譯器的支持

  • 對許多IO圖像文件格式的改進支持,包括:

    • DICOM

    • JPEG2000

    • TIFF(BigTIFF)

    • HDF5
  • 引入支持GPU計算的框架

  • 引入視頻處理的支持

    • 加入OpenCV橋

    • 加入VXL橋

基于遞增修正的維護——諸如為濾波器添加特性、提高一個給定算法的性能等任務(wù)——對于特定的C++類的局部改進很奏效。然而,基礎(chǔ)設(shè)施的修改需要大規(guī)模的重構(gòu),這會影響整個工具包中大量的類,像是上面所講到的那些。舉個例子,這些為支持大于4GB圖像的處理所需的變動有可能是迄今為止給ITK所打的最大的補丁之一。它要求對數(shù)以百計的類進行修改,并且無法在不經(jīng)受巨大的痛苦的情況下完成。模塊化是這個任務(wù)中的另一個實例,它并沒有增量地完成。這確實影響了整個工具包的組織,它的測試基礎(chǔ)設(shè)施是如何工作的、測試數(shù)據(jù)是如何被管理的、工具包是如何被打包并發(fā)行的、以及新的代碼貢獻將如何被封裝以添加的未來的工具包中。

9.3.5 可再生性

ITK在其早期所接受的教訓(xùn)之一,就是發(fā)表在這個領(lǐng)域的許多論文的實現(xiàn)并不像我們所了解的那么容易。計算領(lǐng)域傾向于過度褒獎算法,而輕視作為“只是實現(xiàn)細節(jié)”的這一編寫軟件的實際工作。

那種輕視的態(tài)度對這個領(lǐng)域具有相當?shù)钠茐男?,因為它貶低了通過編寫代碼和恰當?shù)氖褂盟@得的第一手經(jīng)驗的重要性。后果是大多數(shù)發(fā)表的論文就是不能重現(xiàn),而且當研究人員和學(xué)生想使用這些技術(shù)的時候,他們都以花費了大量時間在這一(重現(xiàn))過程中、并且引入了對原作的變動而結(jié)束。在實踐中,要驗證一個實現(xiàn)是否與一篇文章中所描述的內(nèi)容是否契合,確實是相當困難的。

ITK出于良善的目的,破壞了那種環(huán)境,并且在這樣一個領(lǐng)域恢復(fù)了一種DIY文化,這個領(lǐng)域已經(jīng)變得習(xí)慣于理論推理、并且已經(jīng)樹立起輕視實驗工作的風(fēng)氣。由ITK帶來的新文化是一種實踐的、實用主義的文化,這種文化中,軟件的性能的判定是基于其自身的實踐結(jié)果的,而不是基于其自身看起來所具有的復(fù)雜性,這種復(fù)雜性被許多科學(xué)出版物推崇備至。事實證明,在實踐中,最有效的處理方法恰恰是那些看起來太簡單而不能以科學(xué)論文的形式被接受的方法。

可重現(xiàn)的文化是測試驅(qū)動型開發(fā)哲學(xué)的一種延續(xù),并且有條不紊地做出更好的軟件;更高的清晰度,可讀性,魯棒性,以及專注的方向。

為了填補缺乏可重現(xiàn)出版物的空白,ITK社群創(chuàng)建了Insight Journal。它是可以公開訪問的、完全在線的出版物,它要求投稿都要包含代碼,數(shù)據(jù),參數(shù),和測試,使可重現(xiàn)性的驗證成為可能。文章在提交后的24小時內(nèi)發(fā)表上線。然后社群中的任何成員就能夠?qū)@些文章進行同行評審。讀者能夠獲得隨文章一起的所有材料:源代碼,數(shù)據(jù),參數(shù),和測試腳本。這個期刊一直提供一個多產(chǎn)的空間,用于共享新的代碼貢獻,這些代碼貢獻將會在這里走上進入代碼主倉庫的道路。期刊最近收到了它的第500篇投遞文章,還將繼續(xù)作為向ITK添加新代碼的正式門戶。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號