TL;DR。
簡單來說,本文探討了大模型驅(qū)動的軟件工程實踐標(biāo)準(zhǔn)化,以及如何將需求和設(shè)計規(guī)范化為 DSL 格式。通過這種方式,可以讓 AI 更自動化、高效地編寫代碼。
隨著大語言模型在軟件開發(fā)中的應(yīng)用越來越廣泛,傳統(tǒng)的軟件工程實踐開始被重新關(guān)注和提及。在諸如于編寫清晰的文檔、進(jìn)行代碼審查和單元測試等領(lǐng)域,我們可以看到 LLM(大語言模型) 能帶來極多在提升。而在其它的一些領(lǐng)域,諸如于輔助接口設(shè)計、輔助架構(gòu)設(shè)計、架構(gòu)治理,我們看到人們有了越來越多的嘗試。
而不論是架構(gòu)設(shè)計,還是接口設(shè)計,最后還依賴于需求的表達(dá)上。而從需求到模型的標(biāo)準(zhǔn)化設(shè)計,正是經(jīng)典軟件工程(如 UML,即統(tǒng)一建模語言)等特別擅長的方式。在過去,我們對于編寫詳細(xì)的需求疲憊不堪,而 LLM 正好能在一定程度上幫助我們。
這是否意味著經(jīng)典軟件工程的復(fù)興?又是否我們需要新一代的軟件工程方式?
引子:回顧過往
你是否試過提供一個詳細(xì)的需求或者 API 接口,以讓 ChatGPT 繪制 PlantUML(支持 UML 實現(xiàn)的開源軟件) 圖?
引子 1:手工藝人的編程時代
我剛在學(xué)編程那會,學(xué)校用的二手計算機(jī)還是藍(lán)底白字的 DOS。由于那時計算機(jī)很慢,腦子也不靈光,一個小小的函數(shù),老師也會要求你先在紙和筆上寫寫畫畫,然后再輸入到計算機(jī)里。上大學(xué)的時候,搞的是嵌入式開發(fā),寫個只帶任務(wù)調(diào)度的 OS 都得先理論驗證一波,再扔到芯片上跑跑。今天,設(shè)計個 Web 系統(tǒng)、框架,還都是 PoC 驗證起步,寫個功能都是一個測試起手。
印象中,不同層次、不同領(lǐng)域的實現(xiàn)方式里,我很少能做到設(shè)計與實現(xiàn)是完全一致的,所以我對于經(jīng)典的軟件工程方法一直都是不看好。
在 Web 應(yīng)用開發(fā)上,我們一直在追求一種快速驗證的方式,諸如于:
創(chuàng)建應(yīng)用模板,及其 hello, world。
第一個單元測試的成功運(yùn)行。
第一次 CI/CD 的成功驗證。
第一個功能的本地桌面檢查。
第一個功能的端到端交付。
產(chǎn)品的 MVP 上線。
在追求穩(wěn)定的基礎(chǔ)設(shè)施,諸如于運(yùn)行在資源受限設(shè)備的嵌入領(lǐng)域里,由于用戶同樣在期待類似互聯(lián)網(wǎng)的交付方式,所以也受到一系列的沖擊。像過去我們認(rèn)為的汽車軟件,也搞起了 OTA 升級方式,以出現(xiàn)、也避免你在路上因操作系統(tǒng)升級導(dǎo)致拋錨。
引子 2:軟件工程方法:思考 LLM + 經(jīng)典軟件工程設(shè)計
當(dāng)工作以后,我開始習(xí)慣于標(biāo)準(zhǔn)的敏捷軟件開發(fā)流程,它意味著在開發(fā)項目里,我需要(由 ChatGPT 生成):
確定需求:與利益相關(guān)者合作,識別和記錄需求。這通常通過用戶故事、用例和需求規(guī)范等方式實現(xiàn)。
計劃和設(shè)計:確定項目的范圍、時間和資源,并創(chuàng)建一個項目計劃。在這個階段,團(tuán)隊還需要設(shè)計系統(tǒng)的架構(gòu)和技術(shù)方案。
執(zhí)行迭代開發(fā):敏捷方法采用迭代開發(fā)方式,每個迭代通常持續(xù) 1-4 周。團(tuán)隊根據(jù)需求和設(shè)計創(chuàng)建可工作的軟件,并在每個迭代結(jié)束時進(jìn)行演示和回顧。
持續(xù)測試和集成:在迭代和開發(fā)過程中,團(tuán)隊需要持續(xù)測試軟件,并進(jìn)行持續(xù)集成。這有助于確保軟件的質(zhì)量和穩(wěn)定性,并減少缺陷和技術(shù)債務(wù)。
交付和部署:在每個迭代結(jié)束時,團(tuán)隊交付可工作的軟件,并進(jìn)行部署。這樣,利益相關(guān)者可以盡早地了解軟件的功能和特性,并提供反饋。
評估和持續(xù)改進(jìn):團(tuán)隊需要定期評估過程和結(jié)果,以便持續(xù)改進(jìn)。這包括回顧迭代、評估團(tuán)隊績效和采取行動來解決問題。
在敏捷軟件開發(fā)里,我們會強(qiáng)調(diào):工作的軟件 高于 詳盡的文檔。而現(xiàn)在我們多了一個新的團(tuán)隊成員:LLM,這個新的團(tuán)隊成員它需要文檔、詳盡的文檔、更種詳細(xì)的文檔。(PS:當(dāng)然了文檔的方式是多種多樣的,比如代碼信息也是文檔的一部分。)
引子 3:LLM as Copilot
隨后,我們嘗試在軟件開發(fā)領(lǐng)域引入 LLM 之后。在進(jìn)行了一系列的內(nèi)部頭腦風(fēng)暴之后,我們認(rèn)為它會在不同的成熟階段,扮演不同的角色:
階段 一:LLM as Copilot。不改變軟件工程的專業(yè)分工,但增強(qiáng)每個專業(yè)技術(shù),基于AI的研發(fā)工具平臺輔助工程師完成任務(wù),影響個體工作。
階段 二:LLM as Co-Integrator??缪邪l(fā)職責(zé)及角色的協(xié)同增效,基于AI的研發(fā)工具平臺解決不同的角色溝通提效,影響角色互動。
階段 三:LLM as Co-Facilitator。影響軟件研發(fā)流程的角色分工,基于AI的研發(fā)工具平臺輔助決策。輔助計劃、預(yù)測和協(xié)調(diào)工作,影響組織決策。
回到經(jīng)典軟件工程開發(fā)上,我們?yōu)槭裁床辉敢馊ギ?UML 圖呢?一來,它只適合提供參考;二來,學(xué)習(xí)成本不低。簡單來說,就是性價比太低。
而恰好 LLM 能在一定程度上解決這兩個問題,LLM 可以作為一個 Copilot 解決“我懶得做”及“我重復(fù)做”的事兒,諸如于你可以讓它生成 UML,雖然不是那么靠譜,但是改一改也就能用。
而在有了 “改一改就能用” 的這一基礎(chǔ),那么剩下的事情就變得非常簡單了。
動態(tài)構(gòu)建上下文:LLM + 軟件工程的核心
在探索了 LLM + 軟件工程的一系列實踐與應(yīng)用開發(fā)之后,我們著手構(gòu)建 ArchGuard Co-mate 用于指導(dǎo)軟件架構(gòu)設(shè)計與軟件架構(gòu)治理。
位于其背后的瓶頸是:如何動態(tài)的構(gòu)建軟件開發(fā)所需要的上下文?
隱性知識:為什么 ChatGPT 無法生成滿意的 API?
多數(shù)人或許都嘗試過讓 ChatGPT 生成 RESTful API,修改過一個又一個的 prompt,諸如于:
您是一個軟件架構(gòu)師,請生成 博客 entity 的所有 API。使用表格返回,格式:方法、路徑、請求參數(shù)、返回參數(shù)、狀態(tài)碼。
然后,ChatGPT 就開始生成 API 了,這時候你發(fā)現(xiàn)了,它生成的 API 可能并不符合內(nèi)部的 API 規(guī)范。于是,我們嘗試和它對話去生成更準(zhǔn)確的 API,然而,這時可能并不如你直接修改來得快。又或者,我們可以提供一個精煉的 API 規(guī)范給它,諸如于我們在 Co-mate 中所設(shè)計的:
您是一個軟件架構(gòu)師,請生成 博客 entity 的所有 API。要求:
1. 使用表格返回,格式:方法、路徑、請求參數(shù)、返回參數(shù)、狀態(tài)碼。
2. 你需要參考 API 規(guī)范生成。
API 規(guī)范如下:
###
rest_api {
uri_construction {
pattern("/api\\/[a-zA-Z0-9]+\\/v[0-9]+\\/[a-zA-Z0-9\\/\\-]+")
example("/api/petstore/v1/pets/dogs")
}
http_action("GET", "POST", "PUT", "DELETE")
status_code(200, 201, 202, 204, 400, 401, 403, 404, 500, 502, 503, 504)
security(
"""
Token Based Authentication (Recommended) Ideally, microservices should be stateless so the service instances can be scaled out easily and the client requests can be routed to multiple independent service providers. A token based authentication mechanism should be used instead of session based authentication
""".trimIndent()
)
}
###
然后,隨著我們提供越來越多的上下文之后,ChatGPT 終于可以像你一樣工作了。盡管,這時結(jié)合 ChatGPT 生成 API 的時間已經(jīng)遠(yuǎn)超過我們動手去設(shè)計 API 的時間 —— 因為我們一直需要提供上下文所需要的時間,我們一直在將知識進(jìn)行顯性化。
LLM 就像 “新來的畢業(yè)生”:畢業(yè)生需要什么上下文?
在這時,你就會發(fā)現(xiàn):“哦,LLM 就像我們團(tuán)隊新來的畢業(yè)生”。你需要教給他一系列的知識:
系統(tǒng)的功能:核心系統(tǒng)是做什么的?它有哪些主要的功能模塊?這些模塊如何為用戶提供價值?
系統(tǒng)的優(yōu)勢:相比于其他同類系統(tǒng),核心系統(tǒng)有哪些獨特的優(yōu)勢和特點?它的性能如何?它是否提供了更好的用戶體驗?
系統(tǒng)的應(yīng)用場景:核心系統(tǒng)適用于哪些應(yīng)用場景?它可以為哪些行業(yè)或領(lǐng)域提供幫助?
系統(tǒng)的技術(shù)架構(gòu):核心系統(tǒng)的技術(shù)架構(gòu)是怎樣的?它使用了哪些技術(shù)和工具?它的可擴(kuò)展性和靈活性如何?
系統(tǒng)的用戶群體:核心系統(tǒng)的主要用戶群體是誰?他們的需求和行為模式是怎樣的?
順便給了畢業(yè)生一堆文檔,讓他花兩天的時間閱讀。隨后,你開始讓他去實現(xiàn)某個功能,以讓他去練手。最后,你發(fā)現(xiàn) 10 個畢業(yè)生里有 9 個寫不出符合要求的代碼。還有一個寫得出來的是因為,他在這個團(tuán)隊實習(xí)過。
思考一下,我們在實現(xiàn)一個 API 的功能時,分別需要:
設(shè)計 API 時,需要遵循 API 規(guī)范設(shè)計的規(guī)范。
編寫測試時,需要按照最佳的測試實踐規(guī)范。
實現(xiàn) API 代碼時,需要遵循代碼規(guī)范的規(guī)范。
編寫提交信息時,需要遵循條件的 API 規(guī)范。
……
沒錯,每一小步我們都需要一個精確的 spec 才能寫出符合要求的代碼。而在多數(shù)的團(tuán)隊里,這些都是隱性的知識,又或者是由過時的文檔所維護(hù)。(PS:所以,事實上,就算工作幾年的團(tuán)隊成員,也不一定能寫出符合規(guī)范的代碼)
所以,我們更倡導(dǎo)采用結(jié)對編程的方式來分享知識,以讓團(tuán)隊新人更快上手。
LLM 驅(qū)動的軟件工程實踐標(biāo)準(zhǔn)化
現(xiàn)在,在繞了一大圈之后,讓我們回到文章的主題。我們把 LLM 看成是一個團(tuán)隊的新人,它需要知道團(tuán)隊的上下文,才能輔助我們更高效的完成工具。
在構(gòu)建架構(gòu)治理平臺 ArchGuard 時,我們圍繞三態(tài)架構(gòu)(設(shè)計態(tài)、開發(fā)態(tài)、運(yùn)行態(tài))的思想所實現(xiàn)。對于軟件來說,它也是頗為相似的,我們會基于初期的需求來設(shè)計架構(gòu),也就是設(shè)計態(tài)架構(gòu)。而在實現(xiàn)時,是基于細(xì)化的、響應(yīng)市場變化的架構(gòu),也就是開發(fā)態(tài)架構(gòu)。如果想具備快速的市場響應(yīng)力,我們往往會平衡花在兩部分上的時間,所以往往兩者不會完全一致。
實現(xiàn)架構(gòu)之下:實現(xiàn)過程標(biāo)準(zhǔn)化
相信大部分人沒用過 GitHub Copilot 寫代碼,但是大部分人都用過 ChatGPT 寫代碼。我想大家都會得到一個結(jié)論:當(dāng)我們給定足夠精確的上下文時,AI 能與出非常準(zhǔn)確的代碼,盡管還存在一定的隨機(jī)性。(PS:當(dāng)然,第二個結(jié)論還是先前提到的那個:如果我給了足夠精準(zhǔn)的上下文,那我早寫完了。)
所以,為了讓 AI 更自動化的寫代碼,我們就需要探索實現(xiàn)過程標(biāo)準(zhǔn)化,諸如于:
從需求管理系統(tǒng)獲取需求,并進(jìn)行需求分析。
結(jié)合源碼與需求系統(tǒng),選擇最適合變更的入口(如 Java 中的 Controller)
將需求與 Controller 交給 AI 分析,以實現(xiàn)代碼的代碼。
根據(jù) Controller 逐步自動完成其它部分代碼(實現(xiàn)中…)
……
在當(dāng)前的軟件開發(fā)流程之下,我們只能讓 LLM 模擬現(xiàn)在的流程工作。這也就是我們創(chuàng)建了 AutoDev 的初衷,用 ChatGPT 分解需求,將分析需求流程編寫到工具中,以讓 ChatGPT 去分析單個的需求,基于此來自動寫代碼。
而在這時,我們會發(fā)現(xiàn)另外一個問題:ChatGPT 缺乏一種全局觀。它只拿到了單個的需求,表現(xiàn)得就是一個新人一樣。它還需要更多的設(shè)計、規(guī)范相關(guān)的信息。
設(shè)計架構(gòu)之下:規(guī)范 DSL 化
作為一個 AI + 軟件工程的實踐者,我并不相信文檔能幫助 LLM 解決這個問題。因為文檔總是落后的,缺少人維護(hù)的,而且無法自動化。
所以,我們在 Co-mate 中探索的是規(guī)范 DSL 化,即在原先 ArchGuard 規(guī)范代碼化的基礎(chǔ)上進(jìn)行了二次封裝。即可以讓 LLM 按 DSL 來生成設(shè)計,還可以通過 DSL 來檢查生成的設(shè)計是否符合規(guī)范。
諸如于在 Co-mate 的 Foundation Spec 里,我們可以用如下的方式來檢查命名:
naming {
class_level {
style("CamelCase")
pattern(".*") { name shouldNotBe contains("$") }
}
function_level {
style("CamelCase")
pattern(".*") { name shouldNotBe contains("$") }
}
}
而在生成代碼里,也可以以此作為 LLM 的上下文提供。由于它是一個 DSL,而不是一個文檔,所以可以動態(tài)地拿出作為上下文的一部分。
經(jīng)典軟件工程的新 DSL
在過去,我們的行業(yè)積累了一系列的 DSL,諸如于大量的 ADL(架構(gòu)設(shè)計語言)、UML(統(tǒng)一建模語言)、BDD 語言(如 Cucumber)等等。
Cucumber 是背后的 Gherkin 是一種很有意思的 DSL,特別適合于與 LLM 結(jié)合。它也符合那篇《[語言接口:探索大模型優(yōu)先架構(gòu)的新一代 API 設(shè)計](https://www.phodal.com/blog/language-api-llm-first-api/)》所提及的新一代流式(Streaming) DSL 格式。如下:
Feature: OKR協(xié)作與管理
用戶可以創(chuàng)建和管理OKR,跟蹤目標(biāo)和關(guān)鍵結(jié)果的進(jìn)展。
Scenario: 創(chuàng)建OKR
Given 用戶已登錄到OKR協(xié)作與管理系統(tǒng)
When 用戶進(jìn)入系統(tǒng)主界面
And 用戶選擇創(chuàng)建OKR
And 用戶填寫目標(biāo)和關(guān)鍵結(jié)果的詳細(xì)信息
And 用戶設(shè)置時間周期和權(quán)重
And 用戶點擊保存按鈕
Then 系統(tǒng)應(yīng)成功創(chuàng)建并保存OKR
所以,我們可以通過上述的方式將需求格式化。
但是我們又遇到了一個問題,如何去表述更宏觀的需求呢?
所以,我又從經(jīng)典的工程方法里,找到了 UML。我依舊還是“相信”,很多人已經(jīng)嘗試過讓 LLM 生成 PlantUML,以輔助進(jìn)行架構(gòu)設(shè)計。盡管有一定的概率生成的 UML 不生效,或者不準(zhǔn)確,但是都覺得挺好玩的。
因為,我一直不擅長標(biāo)準(zhǔn)的 UML 寫法,所以我并不看好它。而因為大部分后端開發(fā)人員都寫過 Gradle 配置,所以我覺得類似于 Kotlin DSL 的方式,更方便于理解和修改:
caseflow("MovieTicketBooking", defaultRole = "User") {
// activity's should consider all user activities
activity("AccountManage") {
// task part should include all user tasks under the activity
task("UserRegistration") {
// you should list key steps in the story
story = listOf("Register with email", "Register with phone")
}
task("UserLogin") {
story += "Login to the website"
}
}
activity("MovieSelection") {}
// ...
activity("PaymentCancel") {
task("ConfirmCancel") {
role = "Admin" // if some task is role-specific, you can specify it here
//...
}
}
}
我一直嘗試在平衡用例與用戶故事,并嘗試將它們結(jié)合在一起,以為未來生成代碼時,提供一種動態(tài)的上下文。
所以呢?
為了更好將 LLM 應(yīng)用于軟件開發(fā)過程,那么我們需要:
構(gòu)建軟件開發(fā)過程的標(biāo)準(zhǔn)化,以將其工具化。
將文檔規(guī)范 DSL 化、代碼化,動態(tài)提供,降低 AI 思考成本。
封閉經(jīng)典的軟件工程方式,以新瓶方式提供。文章來源:http://www.zghlxwxcb.cn/news/detail-527903.html
而這一些還需要相當(dāng)長的時間。文章來源地址http://www.zghlxwxcb.cn/news/detail-527903.html
到了這里,關(guān)于經(jīng)典軟件工程復(fù)興?大模型驅(qū)動的軟件工程實踐標(biāo)準(zhǔn)化的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!