将25k行C#转换为Java的经验教训
由于各種原因,我最近完成了一個(gè)將復(fù)雜的財(cái)務(wù)應(yīng)用程序從C#轉(zhuǎn)換為Java的項(xiàng)目。 港口的原因大部分是非技術(shù)性的,相反,這是有關(guān)企業(yè)的一項(xiàng)戰(zhàn)略舉措。
這是一次有趣的經(jīng)歷,我在此過(guò)程中吸取了一些經(jīng)驗(yàn)教訓(xùn),可以分享這些經(jīng)驗(yàn)。
1.在現(xiàn)有系統(tǒng)上構(gòu)建語(yǔ)言中立的測(cè)試。
我將從最重要的一課開(kāi)始。 移植系統(tǒng)時(shí),由于任何原因它可能是任何端口,因此必須具有確定該端口是否成功的標(biāo)準(zhǔn)。 最好的方法是圍繞原始系統(tǒng)構(gòu)建一整套測(cè)試,這些測(cè)試可以“ 無(wú)需更改就導(dǎo)出”到新系統(tǒng)。 因此,例如,如果要將系統(tǒng)從Java遷移到不支持JUnit的其他語(yǔ)言,則沒(méi)有一套JUnit測(cè)試是不好的。 我不能過(guò)分強(qiáng)調(diào)測(cè)試的更改從字面上可以從舊系統(tǒng)復(fù)制到新系統(tǒng)而無(wú)需干預(yù)的重要性,這是多么重要。
JUnit測(cè)試的另一個(gè)問(wèn)題是它們通常與現(xiàn)有的實(shí)現(xiàn)緊密地聯(lián)系在一起。 由于將要重寫(xiě)實(shí)現(xiàn),因此測(cè)試無(wú)法在實(shí)現(xiàn)之間移植。
我們選擇的并且非常有效的策略是使用Cucumber測(cè)試。 幾乎所有語(yǔ)言都有Cucumber的綁定,IDE(至少是IntelliJ和Visual Studio都)很好地支持了Cucumber,此外,該測(cè)試是人類(lèi)可讀的。 這樣,您可以讓非技術(shù)用戶參與測(cè)試的準(zhǔn)備工作,以準(zhǔn)備端口。 (順便說(shuō)一句,我們?cè)噲D通過(guò)記錄舊系統(tǒng)所做的所有事情并圍繞這些需求構(gòu)建測(cè)試來(lái)讓用戶定義新系統(tǒng)的需求,但這不足為奇,這并不奇怪?;跇?gòu)建測(cè)試用例要好得多而不是嘗試為新系統(tǒng)發(fā)明它們!)。
使用Cucumber確實(shí)是成功的,每當(dāng)系統(tǒng)之間存在差異時(shí),我們都會(huì)創(chuàng)建一個(gè)新的測(cè)試。 到完成時(shí),我們已經(jīng)有了大約1000種方案,我們對(duì)新系統(tǒng)的正確性充滿信心。 它為我們提供了堅(jiān)實(shí)的基礎(chǔ),我們需要繼續(xù)開(kāi)發(fā)新系統(tǒng)中的其他功能和重構(gòu)。
2.嘗試并使盡可能多的翻譯自動(dòng)化。
當(dāng)面對(duì)超過(guò)25k行的C#時(shí),考慮將每行手動(dòng)翻譯成Java是一件非常艱巨的任務(wù)。 幸運(yùn)的是,那里提供了非常有用的工具。 我們使用的產(chǎn)品來(lái)自有形軟件解決方案 。 花了幾百美元,它實(shí)際上節(jié)省了數(shù)百個(gè)工時(shí)。 它無(wú)論如何都不是完美的,但是它將為您提供Java代碼的結(jié)構(gòu)(部分允許C#中的類(lèi)的代碼被拆分成多個(gè)文件),并做出了使您可以使用Java的相當(dāng)不錯(cuò)的嘗試。
在我們的案例中,幾乎沒(méi)有任何生成的代碼可以實(shí)際編譯,但這確實(shí)是一個(gè)很好的起點(diǎn)。 我的類(lèi)比是OCR的早期嘗試。 您可以掃描文檔,但是當(dāng)您在編輯器中打開(kāi)文檔時(shí),您會(huì)發(fā)現(xiàn)許多未正確識(shí)別的單詞帶有紅色下劃線。 這是要遍歷所有紅色底線并弄清楚單詞應(yīng)該是什么的問(wèn)題。 自動(dòng)翻譯產(chǎn)生的代碼大同小異,當(dāng)它被導(dǎo)入IDE時(shí),會(huì)出現(xiàn)許多編譯器錯(cuò)誤。 有時(shí)自動(dòng)化會(huì)留在原始C#中,并說(shuō)無(wú)法自動(dòng)完成翻譯。 值得稱(chēng)贊的是,該工具總是偏于保守,它從未對(duì)所產(chǎn)生的Java犯錯(cuò),這一點(diǎn)很重要。
3.不要著急翻譯
運(yùn)行自動(dòng)翻譯后,您需要返回代碼并手動(dòng)修復(fù)編譯錯(cuò)誤。 如果我有時(shí)間,我將花費(fèi)10倍以上的時(shí)間來(lái)確保對(duì)代碼所做的每個(gè)更改都是絕對(duì)正確的。 由于我不是C#專(zhuān)家,所以有時(shí)我會(huì)假設(shè)C#庫(kù)的工作方式。 這些假設(shè)并不總是正確的,有時(shí)我會(huì)付出沉重的代價(jià)進(jìn)行調(diào)試,在這種情況下,如果我在原始譯文中更加謹(jǐn)慎,就永遠(yuǎn)不會(huì)有問(wèn)題。 花時(shí)間閱讀要翻譯的類(lèi)的C#API絕對(duì)值得。 我發(fā)現(xiàn)在使用Date和DateTime對(duì)象時(shí),這一點(diǎn)特別重要。
花時(shí)間學(xué)習(xí)Visual Studio IDE也是值得的。 并行調(diào)試時(shí),如果您知道如何正確使用IDE,從長(zhǎng)遠(yuǎn)來(lái)看將節(jié)省時(shí)間。
4.使用Java 8
除了使用Java 8的所有顯而易見(jiàn)的原因(這是Java的最新版本,所以為什么不使用它……)之外,Stream API也可以很好地映射到C#Linq。 語(yǔ)法略有不同,例如Java使用'->'和C#使用'=>' ,但是使用Java 8的新功能確實(shí)有助于保持代碼的可比性,這在進(jìn)一步調(diào)試時(shí)都很有幫助。
5.注意意外行為
語(yǔ)言的某些功能是您不應(yīng)該依賴的,但可能會(huì)完全一樣。 讓我舉一個(gè)我花了太多時(shí)間的例子來(lái)說(shuō)明。 C#代碼使用的是Dictionary ,代碼生成器將Dictionary正確翻譯為HashMap 。 兩者都是無(wú)序地圖。 然而,盡管Dictionary是無(wú)序的合同(還有一個(gè)OrderedDictionary )當(dāng)?shù)ㄟ^(guò)Dictionary似乎保留插入順序。 HashMap并非如此,并且由于元素的順序?qū)τ诮Y(jié)果HashMap ,因此我們發(fā)現(xiàn)了難以調(diào)試的差異。 解決方案是用確實(shí)保留順序的LinkedHashMap替換HashMap所有實(shí)例。
6.不要過(guò)早重構(gòu)
從代碼生成器生成的代碼不是很漂亮。 實(shí)際上,這看起來(lái)非常恐怖,幾乎違反了有關(guān)命名約定等的所有規(guī)則。隨著時(shí)間的流逝,它很容易整理。 抵制這種誘惑,直到所有單元測(cè)試都通過(guò)為止。 您以后總是可以整理一下。 重構(gòu)(甚至重命名)可能會(huì)引入錯(cuò)誤,尤其是在定義上您不熟悉的代碼庫(kù)中。 同樣,您可能決定在某個(gè)地方重新運(yùn)行代碼生成器,并且所有整理工作最好都需要合并,最糟糕的是浪費(fèi)時(shí)間。
結(jié)論
即使您不太熟悉C#,將相當(dāng)復(fù)雜的程序從C#轉(zhuǎn)換為Java也并非不可能。 使用正確的工具和技術(shù),并嚴(yán)格進(jìn)行可靠和可重復(fù)的測(cè)試,將對(duì)您的項(xiàng)目成功產(chǎn)生重大影響。
翻譯自: https://www.javacodegeeks.com/2015/05/lessons-learnt-translating-25k-line-of-c-into-java.html
總結(jié)
以上是生活随笔為你收集整理的将25k行C#转换为Java的经验教训的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 喜结连理是什么意思 喜结连理的意思
- 下一篇: WildFly Swarm:使用Java