摘要:今天我來(lái)和大家分享一下以及自動(dòng)化生成工具的開(kāi)發(fā)經(jīng)驗(yàn)。代碼生成工具接著講講代碼生成工具,對(duì)于來(lái)講,有官方的代碼生成器,還有其他的同類(lèi)開(kāi)源項(xiàng)目比如。現(xiàn)有的代碼生成器沒(méi)有可以開(kāi)箱即用的,都需要去進(jìn)行不少的修改。
前言
在開(kāi)發(fā)工作中,經(jīng)常會(huì)遇到新產(chǎn)品、服務(wù)上線(xiàn)后,需要將其 API 編寫(xiě)不同語(yǔ)言的 SDK。但不同語(yǔ)言 SDK 中都有很大一部分內(nèi)容是用來(lái)進(jìn)行 API 的描述,而且這部分代碼量是最大的,手寫(xiě)起來(lái)也枯燥易錯(cuò)。所以我們需要一種?Data-Driven 的開(kāi)發(fā)方式,通過(guò)工具(Snips)來(lái)自動(dòng)化的生成準(zhǔn)確、優(yōu)雅的代碼,讓開(kāi)發(fā)者減少重復(fù)無(wú)意義的工作,將更多精力放在產(chǎn)品以及業(yè)務(wù)上。
本文共 4420 字,閱讀大概需要 18 分鐘。
今天的內(nèi)容包括:?
? QingStor SDK 簡(jiǎn)介 ? QingStor SDK 開(kāi)發(fā)流程的改變 ? API Specification ? SDK 生成工具 Snips ? 場(chǎng)景化測(cè)試 ? 使用 Snips 開(kāi)發(fā) QingStor Go SDK?正文
大家好,我是青云 QingCloud 系統(tǒng)工程師 Aspire 。今天我來(lái)和大家分享一下 QingStor SDK 以及自動(dòng)化 SDK 生成工具 Snips 的開(kāi)發(fā)經(jīng)驗(yàn)。
今天交流的內(nèi)容包括:
QingStor SDK 簡(jiǎn)介
QingStor SDK 的開(kāi)發(fā)流程
API Specification
SDK 生成工具 Snips
場(chǎng)景化測(cè)試
使用 Snips 開(kāi)發(fā) QingStor Go SDK
1. QingStor SDK 簡(jiǎn)介QingStor? 對(duì)象存儲(chǔ)為用戶(hù)提供可無(wú)限擴(kuò)展的通用數(shù)據(jù)存儲(chǔ)服務(wù),在 QingCloud Console (青云控制臺(tái))中可以直接創(chuàng)建、使用和管理對(duì)象存儲(chǔ) Bucket ,可以方便的上傳下載文件。我們也提供了命令行工具(如 qingcloud-cli, qsctl) 來(lái)在各種場(chǎng)景下進(jìn)行數(shù)據(jù)的存取。但是面對(duì)海量數(shù)據(jù)的操作時(shí),圖形化的界面和命令行工具是不夠的。另外,我們的用戶(hù)也需要在代碼層面使用 SDK 或者直接請(qǐng)求 API 來(lái)接入 QingStor 對(duì)象存儲(chǔ)。自上線(xiàn)以來(lái)我們就開(kāi)放了一套標(biāo)準(zhǔn)、規(guī)范且簡(jiǎn)潔的 RESTful API ,以及一個(gè) Python 的 SDK 。雖說(shuō) Python 的用戶(hù)量非常大,但是顯然只有這一種的 SDK 是無(wú)法滿(mǎn)足用戶(hù)需求的,再加上 QingStor 的 API 是遵循 RESTful 標(biāo)準(zhǔn)的,直接使用 API 來(lái)接入 QingStor 的成本也會(huì)高一些。(不過(guò)好在我們已在今年上半年兼容了 AWS S3 的 API ,所以用戶(hù)也可以使用 S3 的 SDK 來(lái)接入 QingStor 。)
這里將 QingStor API 和 QingCloud IaaS 的 API 做個(gè)簡(jiǎn)單比較:
相比之下用戶(hù)使用 API 來(lái)接入 QingStor 的難度會(huì)高一些,對(duì) SDK 的需求也就更強(qiáng)烈。
目前 QingStor 提供了包括 Go 、 JavaScript 、 Ruby 、 PHP 、 Swift 、 Java 、 Python 在內(nèi) 7 種語(yǔ)言的 SDK ,已經(jīng)可以做到覆蓋主流編程語(yǔ)言,而且有了 Snips 的幫助,開(kāi)發(fā)者也能夠在短時(shí)間內(nèi)開(kāi)發(fā)出另一種語(yǔ)言的 SDK 。
同時(shí),此次我們將 QingCloud IaaS 和 QingStor 的 SDK 進(jìn)行了拆分,例如 qingcloud-sdk-swift (尚未發(fā)布) 和 qingstor-sdk-swift 。這樣做主要是考慮到移動(dòng)端對(duì)空間比較敏感,所引入的第三方庫(kù)越小越好,由于 QingCloud IaaS 目前開(kāi)放的 API 數(shù)量是 QingStor 的三倍,將兩者合并為一個(gè)包會(huì)造成空間的浪費(fèi),對(duì)于一個(gè)僅需要 QingStor 做為存儲(chǔ)的 App 來(lái)講,只引入 QingStor 的 SDK 就足夠了。
QingStor SDK 的中文使用文檔可以參考 https://docs.qingcloud.com/qi... ;另外這些 SDK 也已開(kāi)源在 GitHub ,可以訪問(wèn) https://github.com/yunify 來(lái)獲取,也歡迎大家給我們提 Issue 和 Pull Request 。
2. QingStor SDK 的開(kāi)發(fā)流程首先可以回顧一下我們 Python SDK 的開(kāi)發(fā)方式,就是在 API 發(fā)生改變之后,手動(dòng)增加 SDK 中與之對(duì)應(yīng)部分的代碼,這種做法效率不高,維護(hù)起來(lái)也讓人頭疼。
再加上 QingCloud IaaS 和 QingStor 共有兩百多個(gè)開(kāi)放 API ,并且不斷有新的 API 伴隨產(chǎn)品或功能上線(xiàn),要做到 SDK 的實(shí)時(shí)跟進(jìn)比較困難。而且現(xiàn)在只有一個(gè) Python 的 SDK ,如果再加上其他語(yǔ)言的,每種語(yǔ)言都手動(dòng)維護(hù),會(huì)耗費(fèi)工程師很多不必要的精力。還有一個(gè)問(wèn)題比較麻煩,如果有用戶(hù)對(duì)一些小眾語(yǔ)言的 SDK 有需求,我們也沒(méi)法立即進(jìn)行支持,這點(diǎn)行業(yè)內(nèi)基本都有類(lèi)似的情況。
要解決這些問(wèn)題,就需要換一種思路。我們可以看到,不同語(yǔ)言的 SDK 中都有很大一部分內(nèi)容是用來(lái)進(jìn)行 API 的描述(或者叫定義),而且這部分代碼量是最大的,手寫(xiě)起來(lái)枯燥易錯(cuò)。所以我們采用了一種新的 SDK 的開(kāi)發(fā)流程,使用標(biāo)準(zhǔn)的數(shù)據(jù)來(lái)生成代碼,之后通過(guò)場(chǎng)景化的測(cè)試來(lái)進(jìn)行驗(yàn)證,其中用到了我們自己寫(xiě)的一個(gè)代碼生成工具━━ Snips 。
Snips 使用 API 的標(biāo)準(zhǔn)化描述和代碼模版來(lái)生成各種語(yǔ)言 API 調(diào)用的那部分代碼,除了生成出來(lái)的代碼,還需要手動(dòng)編寫(xiě)的代碼,每種語(yǔ)言都不一樣,不適合統(tǒng)一生成代碼,比如錯(cuò)誤處理,文件讀寫(xiě),網(wǎng)絡(luò)請(qǐng)求等。這樣做比起純手工打造一個(gè) SDK ,需要開(kāi)發(fā)的代碼量會(huì)小很多,開(kāi)發(fā)效率能夠得到很大的提升。
上面是利用 Snips 開(kāi)發(fā)一種新的語(yǔ)言的 SDK 的示意圖。下面具體說(shuō)明一下。
新增一種語(yǔ)言的 SDK :
手寫(xiě)哪些錯(cuò)誤處理、網(wǎng)絡(luò)請(qǐng)求等相關(guān)的的代碼
編寫(xiě)代碼模版
使用 Snips 生成代碼
通過(guò)場(chǎng)景化測(cè)試
發(fā)布
更新 SDK :
更新 API 描述
重新生成代碼
通過(guò)場(chǎng)景化測(cè)試
發(fā)布
這里的 API 的描述我們是通過(guò) Git Submodule 的形式引入到各個(gè) SDK 項(xiàng)目中,這樣如果是 API 的變更,完全不需要手動(dòng)編寫(xiě) SDK 的代碼就可以做到 SDK 的更新。
下面會(huì)逐個(gè)講一下 API 描述規(guī)范 ( API Specification )、 Snips 和 場(chǎng)景化測(cè)試( Scenario Based Testing )這幾個(gè)部分,我們是怎么做的。
3. API Specification要實(shí)現(xiàn)上述的流程,得先有 API 的描述,我們花了很長(zhǎng)時(shí)間來(lái)確定使用怎樣的 API 描述規(guī)范,也走了一些彎路。
起初我們自己制定了一個(gè) API Specification 的 Schema :
這個(gè) Schema 的目標(biāo)是描述 HTTP API
每一個(gè) API Specification 文件呈現(xiàn)一個(gè) Service (如 QingCloud IaaS 或者 QingStor )
Service 中可以有 SubService
同時(shí) Service 和 SubService 中都包含 Metadata 、 Properties 、 Operations 、 Endpoint 等信息
Operation 是具體的 API 請(qǐng)求,其中包含 Request 和 Response 的描述以及其他基本信息
定義了 boolean 、 integer 、 timestamp 、 binary 、 list 、 object 等幾種基本的數(shù)據(jù)類(lèi)型,及自定義的數(shù)據(jù)類(lèi)型 CustomizedType, CustomizedType 可以出現(xiàn)多級(jí)引用
之后使用這套 Schema ,去描述了 QingStor 的 所有 API ,并且寫(xiě)了解析器,快速實(shí)現(xiàn)了從 API 描述生成 Go SDK 的代碼。但是 Review 時(shí)我們發(fā)現(xiàn)這個(gè)自己定義的 Schema 還是太簡(jiǎn)陋,沒(méi)有經(jīng)過(guò)足夠的數(shù)據(jù)進(jìn)行驗(yàn)證,很多情況都沒(méi)有考慮到,還有一些 Corner Case 也難以描述,并且這個(gè) Schema 本身的校驗(yàn)效果也不理想。而且如果使用這套自己定義的 Schema 來(lái)描述 QingStor 和 QingCloud API ,無(wú)論是在內(nèi)部使用還是開(kāi)放出去,都是讓人比較難以接受的,這種自立門(mén)戶(hù)的做法也沒(méi)有太大意義。
然后我們對(duì)比了幾個(gè)目前可以用到的幾個(gè) API Specification 的規(guī)范,最后選擇了 Swagger 。
Swagger 是一個(gè)描述 RESTful API 的規(guī)范, Swagger 具體的 Specification 大家可以訪問(wèn)它的網(wǎng)站來(lái)查看: http://swagger.io 。
今年的一月份 Swagger 更名為 OpenAPI Specification ,由 Linux 基金會(huì)贊助成立了 OpenAPI Initiative 來(lái)繼續(xù) OpenAPI Specification 的開(kāi)發(fā)。在 Google 、 Microsoft 等大廠的支持下, Swagger 儼然已經(jīng)成了業(yè)界標(biāo)準(zhǔn),相關(guān)的生態(tài)和工具也已比較齊全,用它來(lái)作我們 API 的描述規(guī)范再合適不過(guò),所以我們最終選擇了 Swagger 來(lái)重新描述了 QingStor APIs ,并且實(shí)現(xiàn)了用 Swagger 描述規(guī)范來(lái)生成代碼。
使用 Swagger 規(guī)范無(wú)疑是正確的,因?yàn)?Swagger 的工具和生態(tài)相對(duì)比較完善。以 Swagger Editor 為例,它是一個(gè) API Specification 的 Web 編輯器,可以在編輯的同時(shí)提供代碼補(bǔ)全、高亮和實(shí)時(shí)語(yǔ)法驗(yàn)證功能,感興趣的朋友可以在 http://editor.swagger.io 體驗(yàn)一下。
Swagger 雖然發(fā)展的比較快,但并不是對(duì)所有 API 都友好。 QingCloud IaaS 的 API ,請(qǐng)求參數(shù)部分里會(huì)有數(shù)組( Array )和字典( Map )。例如 statics.n.router_static_name 、 statics.n.router_static_value 這種請(qǐng)求參數(shù),用戶(hù)實(shí)際提供的是一個(gè)由 Static 字典組成的數(shù)組,并且這個(gè)請(qǐng)求參數(shù)是位于 Request URL Query , SDK 會(huì)把數(shù)組和字典轉(zhuǎn)換一下格式,構(gòu)造出 statics.0.router_static_name=name&statics.0.router_static_value=value 這種形式的請(qǐng)求串。這樣就會(huì)出現(xiàn)問(wèn)題,在描述請(qǐng)求的時(shí)候需要定義數(shù)組和字典參數(shù),由于 Swagger 的規(guī)范比較嚴(yán)格, Operation Parameter 不允許自定義類(lèi)型出現(xiàn),這時(shí)就只能將請(qǐng)求參數(shù)的描述放在 Request Body 里面來(lái)定義,這樣就需要解析 Specification 的時(shí)候做一些特殊處理。
Swagger 標(biāo)準(zhǔn)也考慮到了 API 數(shù)量很多導(dǎo)致描述文件過(guò)長(zhǎng)的情況,它支持使用 $ref 來(lái)引用其他文件,當(dāng)然這個(gè)引用的功能其實(shí)是 JSON Reference 和 JSON Pointer 規(guī)范提供的,但是這里的 $ref ,只支持同一個(gè)文件內(nèi)的引用,或者是引用某個(gè) URL 鏈接。我們測(cè)試的解析器,包括 Swagger 官方的 swagger-codegen 都不支持文件間的引用,更不用提 Circle Reference 這種常用的情況了。不過(guò)這個(gè)問(wèn)題我們?cè)?Snips 中也解決掉了,可以看到我們的 QingStor API Specs 中的 API 描述是拆分成了很多文件的,具體內(nèi)容等下 Snips 的部分會(huì)提到。
使用 Swagger API Specification 規(guī)范來(lái)描述 API ,其作用不僅僅可以用來(lái)生成代碼,生成文檔,更重要的是它的約束作用,它反過(guò)來(lái)可以規(guī)范 API 的開(kāi)發(fā)和交付,進(jìn)一步保證 QingCloud 的整體服務(wù)質(zhì)量。對(duì)于 SDK 開(kāi)發(fā)來(lái)講則是一種 Data-Driven 的開(kāi)發(fā)方式,這種思路可以讓產(chǎn)出的各個(gè) SDK 在功能上保持很強(qiáng)的一致性,不會(huì)出現(xiàn)某種語(yǔ)言的 SDK 缺失功能,或者是更新滯后,這種思路的優(yōu)勢(shì)也會(huì)隨著更多產(chǎn)品和功能的上線(xiàn)變得越來(lái)越明顯。
API Specification 文件本身也需要驗(yàn)證正確性,而使用 Swagger 標(biāo)準(zhǔn)可以輕而易舉的使用 JSON Schema 來(lái)實(shí)現(xiàn) Specification 數(shù)據(jù)的驗(yàn)證。
QingStor 的 API Specification 也放到了 GitHub ,這里是地址 https://github.com/yunify/qin... 。
4. 代碼生成工具 Snips接著講講代碼生成工具,對(duì)于 Swagger 來(lái)講,有官方的代碼生成器 swagger-codegen ,還有其他的同類(lèi)開(kāi)源項(xiàng)目比如 go-swagger 。
它們雖說(shuō)可以生成代碼,但是生成出來(lái)的代碼可控性和可讀性都不高,并不能滿(mǎn)足我們的需求,定制起來(lái)也比較麻煩。
例如采用 swagger-codegen 得 fork 過(guò)來(lái),改它的 Java 代碼,而且每增加一種語(yǔ)言的 SDK 基本上都要去增加對(duì)應(yīng)的 Java 代碼,這對(duì)于 Java SDK 之外的開(kāi)發(fā)者來(lái)講是非常不友好的。
除此之外還有很多其他細(xì)節(jié)上的問(wèn)題,例如我們 API 的遺留問(wèn)題,上面說(shuō)到的 QingCloud IaaS 的請(qǐng)求參數(shù)不標(biāo)準(zhǔn);例如 swagger-codegen 和 go-swagger 不支持文件引用的解析;生成出來(lái)的代碼大小寫(xiě)控制不嚴(yán)格( acl 被轉(zhuǎn)換成了 Acl ,而不是 ACL )等。
現(xiàn)有的代碼生成器沒(méi)有可以開(kāi)箱即用的,都需要去進(jìn)行不少的修改。但是去實(shí)現(xiàn)一個(gè) Swagger 的解析器又太費(fèi)時(shí)費(fèi)力了,所以我們想到了一種折中的方案,使用開(kāi)源的 Swagger 解析器來(lái)構(gòu)建自己的生成器。
比對(duì)了幾個(gè)開(kāi)源項(xiàng)目之后,我們采用的解析器是 go-openapi/spec ( https://github.com/go-openapi/), 這個(gè)解析器的作者也是 go-swagger 的作者, go-swagger 是在這個(gè)解析器之上構(gòu)建的。遺憾的是 go-openapi 也不支持文件引用,看到未來(lái)有支持文件引用功能的計(jì)劃,不過(guò)不知道什么時(shí)候才會(huì)加上。于是我們簡(jiǎn)單熟悉了一下代碼,之后提交了幾個(gè) PR 把這功能幫他們實(shí)現(xiàn)了,作者也欣然接受 “ With this PR go-swagger is the first library on go that fully supports json schema and ref resolving so very happy with it ?”。
隨后就有了代碼生成工具 Snips ,它是一個(gè)命令行工具,很好地支持著我們的 SDK 開(kāi)發(fā),以 Go 語(yǔ)言 SDK 為例,包括模版在內(nèi),手寫(xiě)的代碼大約 6 千行左右,而生成出來(lái)的代碼已經(jīng)達(dá)到了 2 萬(wàn)多行,開(kāi)發(fā)效率得到了不小的提升。
關(guān)于模版, Snips 會(huì)從指定路徑加載模版文件,模版目錄下需要有一個(gè) manifest 文件,可以是 JSON 或者 YAML 格式,這個(gè)文件指定了一些生成規(guī)則,例如指定該目錄下模版文件的格式,輸出文件名的命名風(fēng)格是 CamelCase 還是 snake_case ;輸出文件的擴(kuò)展名和前后綴,可以參考 example 下的 manifest.yaml 來(lái)查看所有支持的規(guī)則。模版文件格式目前只支持一種,是 Go 語(yǔ)言的 template 。
與代碼生成有關(guān)的簡(jiǎn)單邏輯是放在模版里去實(shí)現(xiàn)的,同時(shí)生成器也提供了一些內(nèi)置函數(shù)可以在模版中使用,如大小寫(xiě)風(fēng)格的轉(zhuǎn)換、字符串替換、數(shù)據(jù)傳遞等,從而做到了生成器與某種語(yǔ)言無(wú)關(guān),新增語(yǔ)言不需要去修改生成器的代碼。上文提到的 acl 轉(zhuǎn)換成 Acl 的問(wèn)題,使用 Snips 提供的函數(shù)就可以正確轉(zhuǎn)換,例如 {{snakeCase "acl"}} 會(huì)轉(zhuǎn)換成 “ ACL ”。
關(guān)于多版本 API , Snips 也有解決方案。
通過(guò) -n (--service-api-version) 參數(shù)來(lái)指定使用的 API 版本,然后將代碼生成到不同的目錄,例如 latest version 的代碼在 service 目錄,特定版本的代碼可以在 service-2016-01-06 中,再根據(jù)語(yǔ)言的不同看是否還需要相應(yīng)的調(diào)整。以 Go 語(yǔ)言為例,用戶(hù)使用的時(shí)候 import 不同的路徑的 service 即可切換不同版本的 API ,如 import "github.com/yunify/qingstor-sdk-go/service-2016-01-06"。
Snips 目前已經(jīng)開(kāi)源, GitHub 地址: https://github.com/yunify/snips 。目前是針對(duì) QingCloud IaaS 和 QingStor API 的代碼生成工具, Snips 的思路和其他的 Swagger 生成器的思路不太一樣,未來(lái)也可能會(huì)做成一個(gè)通用的代碼生成器。
5. 場(chǎng)景化測(cè)試SDK 開(kāi)發(fā)出來(lái)了,除了單元測(cè)試之外,還需要在線(xiàn)上生產(chǎn)環(huán)境進(jìn)行測(cè)試,保證交付的 SDK 可正常工作,我們稱(chēng)之為服務(wù)測(cè)試( Service Test )。
服務(wù)測(cè)試中我們采用 Cucumber ( https://cucumber.io),它是一個(gè) Behaviour-Driven Development (BDD) 工具。 Cucumber 會(huì)讀取通過(guò)自然語(yǔ)言描述的測(cè)試場(chǎng)景和數(shù)據(jù),然后結(jié)合不同的測(cè)試實(shí)現(xiàn)去驗(yàn)證是否通過(guò)。 Cucumber 可以被稱(chēng)作是一種測(cè)試方式,基本上每種語(yǔ)言都有它的實(shí)現(xiàn)。
舉個(gè)例子:
獲取一個(gè) Object , Cucumber 描述是這樣的:
Ruby 中對(duì)應(yīng)的測(cè)試實(shí)現(xiàn)是這樣的:
Cucumber 會(huì)檢查代碼場(chǎng)景執(zhí)行過(guò)程中的數(shù)據(jù)是否滿(mǎn)足預(yù)期,給出一個(gè)完成的測(cè)試結(jié)果
這樣以使用者的角度來(lái)真實(shí)的測(cè)試 SDK ,并且可以讓所有 SDK 的測(cè)試用例保持一致,在保證 SDK 質(zhì)量的同時(shí),也可以做到各種語(yǔ)言 SDK 功能的一致性。
QingStor SDK 的測(cè)試場(chǎng)景也放在了 GitHub : https://github.com/yunify/qin...
6. 使用 Snips 開(kāi)發(fā) QingStor Go SDK上面講了整套的 QingStor 的 SDK 開(kāi)發(fā)流程,下面用 QingStor Go SDK 來(lái)舉例說(shuō)明一下。
qingstor-sdk-go https://github.com/yunify/qin...
首先需要實(shí)現(xiàn) SDK 最基礎(chǔ)的部分,比如網(wǎng)絡(luò)請(qǐng)求和簽名處理、文件讀寫(xiě)、錯(cuò)誤處理等等,然后再使用 Snips 生成 API 相關(guān)的代碼。
假設(shè)基礎(chǔ)部分現(xiàn)在已經(jīng)完成了,并且經(jīng)過(guò)了單元測(cè)試。
接下來(lái)安裝 Snips ,可以使用 go get -u github.com/yunify/snips 安裝,或者直接訪問(wèn) GitHub 下載編譯好的二進(jìn)制文件。
在代碼倉(cāng)庫(kù)目錄下以 git submodule 的形式引入 API Specification 和 Test Scenarios:
./specs/qingstor 引用 QingStor API specifications
./test/features 引用 QingStor 測(cè)試場(chǎng)景
然后便可編寫(xiě)代碼模版,下圖所示為 Go SDK 的模版文件:
具體的模板文件內(nèi)容請(qǐng)見(jiàn):
https://github.com/yunify/qin...
模板編寫(xiě)完成后,即可利用模版和 API Specifications 來(lái)生成代碼。下圖為生成代碼的命令,生成完的代碼有可能會(huì)難看,可以格式化一下代碼,當(dāng)然如果模版控制的嚴(yán)格,生成出來(lái)的代碼足夠漂亮,可以跳過(guò)格式化的步驟。
之后便可使用這些生成好的代碼,實(shí)現(xiàn)測(cè)試場(chǎng)景,具體的代碼請(qǐng)見(jiàn)這里: https://github.com/yunify/qin...
最后運(yùn)行測(cè)試
目前 QingStor 已經(jīng)提供了七種語(yǔ)言的 SDK (其中 Python SDK 的新版也會(huì)使用 Snips 來(lái)重新生成),覆蓋了主流的編程語(yǔ)言,但還有一些編程語(yǔ)言的 SDK 我們沒(méi)有來(lái)得及開(kāi)發(fā),為激勵(lì)更多的開(kāi)發(fā)者參與進(jìn)來(lái)貢獻(xiàn)其它語(yǔ)言的 SDK ,我們特此發(fā)起 QingStor SDK 大賽活動(dòng),報(bào)名地址請(qǐng)見(jiàn): https://jinshuju.net/f/0MB6w6
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/38281.html
摘要:今天我來(lái)和大家分享一下以及自動(dòng)化生成工具的開(kāi)發(fā)經(jīng)驗(yàn)。代碼生成工具接著講講代碼生成工具,對(duì)于來(lái)講,有官方的代碼生成器,還有其他的同類(lèi)開(kāi)源項(xiàng)目比如?,F(xiàn)有的代碼生成器沒(méi)有可以開(kāi)箱即用的,都需要去進(jìn)行不少的修改。 前言 在開(kāi)發(fā)工作中,經(jīng)常會(huì)遇到新產(chǎn)品、服務(wù)上線(xiàn)后,需要將其 API 編寫(xiě)不同語(yǔ)言的 SDK。但不同語(yǔ)言 SDK 中都有很大一部分內(nèi)容是用來(lái)進(jìn)行 API 的描述,而且這部分代碼量是最大...
摘要:今天我來(lái)和大家分享一下以及自動(dòng)化生成工具的開(kāi)發(fā)經(jīng)驗(yàn)。代碼生成工具接著講講代碼生成工具,對(duì)于來(lái)講,有官方的代碼生成器,還有其他的同類(lèi)開(kāi)源項(xiàng)目比如?,F(xiàn)有的代碼生成器沒(méi)有可以開(kāi)箱即用的,都需要去進(jìn)行不少的修改。 前言 在開(kāi)發(fā)工作中,經(jīng)常會(huì)遇到新產(chǎn)品、服務(wù)上線(xiàn)后,需要將其 API 編寫(xiě)不同語(yǔ)言的 SDK。但不同語(yǔ)言 SDK 中都有很大一部分內(nèi)容是用來(lái)進(jìn)行 API 的描述,而且這部分代碼量是最大...
摘要:配置驗(yàn)證,輸入。按鍵,自動(dòng)補(bǔ)全則成功添加相關(guān),將里面目錄下的文件移動(dòng)到目錄下的文件下,就可以使用了,如 安裝plug (https://github.com/junegunn/v... curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent... 編輯~/.vimrc文件(不...
摘要:配置驗(yàn)證,輸入。按鍵,自動(dòng)補(bǔ)全則成功添加相關(guān),將里面目錄下的文件移動(dòng)到目錄下的文件下,就可以使用了,如 安裝plug (https://github.com/junegunn/v... curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent... 編輯~/.vimrc文件(不...
摘要:為了構(gòu)建可伸縮的測(cè)試自動(dòng)化框架,需要記住以下三個(gè)最重要的干凈編碼實(shí)踐。因此,組織期望其或測(cè)試自動(dòng)化架構(gòu)師設(shè)計(jì)和開(kāi)發(fā)健壯,可維護(hù)的智能測(cè)試自動(dòng)化框架。包括適當(dāng)?shù)奈臋n在測(cè)試自動(dòng)化框架開(kāi)發(fā)項(xiàng)目中工作的程序員不太可能獨(dú)自編寫(xiě)代碼。 ...
閱讀 2167·2021-11-24 09:39
閱讀 2781·2021-07-29 13:49
閱讀 2322·2019-08-29 14:15
閱讀 2233·2019-08-29 12:40
閱讀 3312·2019-08-26 13:42
閱讀 632·2019-08-26 12:13
閱讀 2065·2019-08-26 11:41
閱讀 3345·2019-08-23 18:32