持續(xù)交付之如何選型代碼分支策略

      網(wǎng)友投稿 943 2022-05-30

      前言

      現(xiàn)狀

      采用的分支策略

      目前團(tuán)隊(duì)特點(diǎn)

      目前落地方案

      目前存在的問題

      前言

      現(xiàn)狀

      采用的分支策略

      目前團(tuán)隊(duì)特點(diǎn)

      目前落地方案

      目前存在的問題

      方案選型

      常見分支策略

      主干開發(fā),分支發(fā)布

      分支開發(fā),主干發(fā)布

      主干開發(fā),主干發(fā)布

      優(yōu)缺點(diǎn)對比

      選出最適合的策略

      四、“兩個(gè)披薩”團(tuán)隊(duì)的代碼管理實(shí)際案例

      持續(xù)交付之如何選型代碼分支策略

      背景

      周一下午

      周二

      周三

      周四

      周五

      小結(jié)

      常見問題說明

      單個(gè)特性分支怎么合入到發(fā)布分支?

      多個(gè)特性分支會(huì)給集成帶來哪些問題?

      Auto Merge 功能及特點(diǎn)

      前言

      高效的持續(xù)交付體系,必定需要一個(gè)合適的代碼分支策略。采用不同的代碼分支策略,意味著實(shí)施不同的代碼集成與發(fā)布流程,這會(huì)影響整個(gè)研發(fā)團(tuán)隊(duì)每日的協(xié)作方式,因此研發(fā)團(tuán)隊(duì)通常需要很認(rèn)真地選擇自己的策略。

      現(xiàn)狀

      采用的分支策略

      目前我們采用的 Git Flow 模型,其在 2011 年左右被大家當(dāng)作了推薦的分支模型。

      主要包括:

      主分支:master,穩(wěn)定版本代碼分支,對外可以隨時(shí)編譯發(fā)布的分支,不允許直接 Push 代碼,只能請求合并(pull request),且只接受 hotfix、release 分支的代碼合并。gitlab 上做權(quán)限限制(開發(fā)組長)。

      熱修復(fù)分支:hotfix,針對現(xiàn)場緊急問題、bug 修復(fù)的代碼分支,修復(fù)完后合并到主分支、開發(fā)分支。

      發(fā)版分支:release,版本發(fā)布分支,用于迭代版本發(fā)布。迭代完成后,合并 dev 代碼到 release,在 release分支上編譯發(fā)布版本,以及修改 bug(定時(shí)同步 bug 修改到 dev 分支)。測試完成后此版本可以作為發(fā)版使用,然后把穩(wěn)定的代碼 push 到 master 分支,并打上版本標(biāo)簽。

      開發(fā)分支:dev,開發(fā)版本分支,針對迭代任務(wù)開發(fā)的分支,日常開發(fā)原則上都在此分支上面,迭代完成后合并到 release 分支。

      特性開發(fā)分支:feature-***,開發(fā)人員可以針對模塊自己創(chuàng)建本地分支,開發(fā)完成后合并到 dev 開發(fā)分支,然后刪除本地分支,涉及多人協(xié)同開發(fā)的可以 push 到服務(wù)端。

      目前團(tuán)隊(duì)特點(diǎn)

      尚不具備主干開發(fā)能力(開發(fā)團(tuán)隊(duì)系統(tǒng)設(shè)計(jì)和開發(fā)能力非常強(qiáng))

      有預(yù)定的發(fā)布周期

      需要嚴(yán)格執(zhí)行發(fā)布周期(雙周迭代)

      目前落地方案

      在代碼分支管理的層面上,團(tuán)隊(duì)源代碼分為五個(gè)主要分支:

      Master:主分支,穩(wěn)定版本

      Hotfixes:補(bǔ)丁分支,穩(wěn)定/預(yù)覽版本或現(xiàn)場問題的應(yīng)急處理

      Release:預(yù)覽分支,Bata版/測試與bug修復(fù)

      Develop:開發(fā)分支,常規(guī)功能的新增與調(diào)整

      Feature:特性分支,同時(shí)可以有多個(gè)特性分支,代碼合并后結(jié)束;

      分支合并時(shí)間:

      主分支:每個(gè)季度一個(gè)正式版本,于每個(gè)季度末合并發(fā)版;由預(yù)覽分支、補(bǔ)丁分支合并;不允許直接 Push 代碼,只能合并;

      補(bǔ)丁(熱修復(fù))分支:隨現(xiàn)場使用情況而定,可以打臨時(shí)版本或補(bǔ)丁;由主分支替換而來,修復(fù)完后合并到主分支、開發(fā)分支;

      預(yù)覽分支:版本發(fā)布分支,用于迭代版本發(fā)布。每日測試打版驗(yàn)證,由開發(fā)分支合并而來;測試完成后此版本可以作為發(fā)版使用,然后把穩(wěn)定的代碼 push 到 master 分支,并打上版本標(biāo)簽。

      開發(fā)分支:不對外發(fā)布,可以由其他分支合并而來;針對迭代任務(wù)開發(fā)的分支,日常開發(fā)原則上都在此分支上面,迭代完成后合并到 release 分支;

      特性分支:不直接打版,可以由開發(fā)分支合并而來;新功能穩(wěn)定后合并到開發(fā)分支;

      目前存在的問題

      分支關(guān)系復(fù)雜:GitFlow 包含的分支過多,以及許多繁瑣的合并規(guī)則。重流程,使用起來并不是很容易,發(fā)布分支拉出后,直到合回主干,若有特性修改或 Hotfix 需要維護(hù)多處 CherryPick(選擇部分變更集合并到其他分支) 合并;

      集成時(shí)間滯后:特性分支在功能完成前,“不敢”隨意合并回 Dev 分支,造成代碼集成時(shí)間嚴(yán)重滯后;

      代碼集中沖突:每次功能完成后進(jìn)行“大集成”,十分容易出現(xiàn)大范圍代碼沖突;

      特性易合難分: 特性一旦集成到 Dev 分支便難以再次分離, 單個(gè)特性問題可能導(dǎo)致整體發(fā)布延期。

      無法自動(dòng)化:各特性分支進(jìn)入到穩(wěn)定階段,必然需要 merge 在一起,然后一起被編譯、打包和測試。怎么讓這個(gè)過程更加自動(dòng)化呢?

      方案選型

      常見分支策略

      圖片來源:https://paulhammant.com/2013/12/04/what_is_your_branching_model/

      在這種分支策略下,開發(fā)團(tuán)隊(duì)共享一條主干分支,所有的代碼都直接提交到主干分支上,主干分支就相當(dāng)于是一個(gè)代碼的全量合集。在軟件版本發(fā)布之前,會(huì)基于主干拉出一條以發(fā)布為目的的短分支。

      圖片來源:https://paulhammant.com/2013/12/04/what_is_your_branching_model/

      當(dāng)開發(fā)接到一個(gè)任務(wù)后,會(huì)基于主干拉出一條特性開發(fā)分支,在特性分支上完成功能開發(fā)驗(yàn)證之后,通過 Merge request 或者 Pull request 的方式發(fā)起合并請求,在評審?fù)ㄟ^后合入主干,并在主干完成功能的回歸測試。開源社區(qū)流行的 GitHub 模式其實(shí)就是屬于這種。

      根據(jù)特性和團(tuán)隊(duì)的實(shí)際情況,還可以進(jìn)一步細(xì)分為兩種情況:

      每條特性分支以特性編號或需求編號命名,在這條分支上,只完成一個(gè)功能的開發(fā);

      以開發(fā)模塊為單位,拉出一條長線的特性分支,并在這條分支上進(jìn)行開發(fā)協(xié)作。

      兩者的區(qū)別就在于特性分支存活的周期,拉出時(shí)間越長,跟主干分支的差異就越大,分支合并回去的沖突也就越大。所以,對于長線模式來說,要么是模塊拆分得比較清晰,不會(huì)有其他人動(dòng)這塊功能,要么就是保持同主干的頻繁同步。隨著需求拆分粒度的變小,短分支的方式其實(shí)更合適。

      圖片來源:https://paulhammant.com/2013/12/04/what_is_your_branching_model/

      團(tuán)隊(duì)只有一條分支,開發(fā)人員的代碼改動(dòng)都直接集成到這條主干分支上,同時(shí),軟件的發(fā)布也基于這條主干分支進(jìn)行。對于持續(xù)交付而言,最理想的情況就是,每一次提交都能經(jīng)歷一系列的自動(dòng)化環(huán)境并部署到生產(chǎn)環(huán)境上面,而這種模式距離這個(gè)目標(biāo)就更近了一點(diǎn)。可想而知,如果想要做到主干分支在任何時(shí)間都處于可發(fā)布狀態(tài),那么,這就對每一次提交的代碼質(zhì)量要求非常高。在一些追求工程卓越的公司里,你要提交一行代碼,就必須經(jīng)歷“九九八十一難”,因?yàn)橛幸幌盗械淖詣?dòng)化驗(yàn)收手段,還有極為嚴(yán)格的代碼評審機(jī)制來保證你的提交不會(huì)把主干分支搞掛掉。

      優(yōu)缺點(diǎn)對比

      選出最適合的策略

      很難說有一種通用的分支策略可以滿足我們所有場景的需求。但是,有些分支策略的原則更加適合于快速迭代發(fā)布的場景,也就更加適合 DevOps 的發(fā)展趨勢。所以,這里我個(gè)人比較推薦的是分支開發(fā),主干發(fā)布的模式,也就是團(tuán)隊(duì)共享一條開發(fā)主干,特性開發(fā)基于主干拉出特性分支,快速開發(fā)驗(yàn)收后合并發(fā)布,同時(shí),在特性分支和發(fā)布分支分別建立不同的質(zhì)量門禁和自動(dòng)化驗(yàn)收能力。

      這樣做的好處在于:

      保留“特性分支”的工作方式,便于團(tuán)隊(duì)協(xié)作;

      簡化 Gitflow 的復(fù)雜分支策略,上手容易;

      靈活的特性分支組合集成,集成后亦可快速剝離;

      實(shí)現(xiàn)“準(zhǔn)持續(xù)集成”

      略低于單主干,遠(yuǎn)高于 Gitflow 的集成頻率 ;

      選擇性的特性持續(xù)集成(方便靈活,但其實(shí)并非優(yōu)點(diǎn))

      不過,在執(zhí)行的過程中,需要遵守以下原則:

      團(tuán)隊(duì)共享一條主干分支;

      強(qiáng)力的特性拆分的能力;

      特性的粒度和分支存活的周期是關(guān)鍵要素。根據(jù)經(jīng)驗(yàn)來看,分支存活的周期一般不要超過2周;

      特性分支的命名需規(guī)范;

      保證一個(gè)特性的關(guān)聯(lián)改動(dòng)需要提交到一條分支上,而不是到處都是,盡量做到原子性提交。

      分支發(fā)布的策略圖如下所示:

      代碼管理后臺:GitLab

      主分支:master,開發(fā)主分支,對外可以隨時(shí)編譯發(fā)布的分支,不允許直接Push代碼,只能請求合并(pull request)。gitlab上做保護(hù)性限制。

      熱修復(fù)分支:hotfix/版本號命名,針對現(xiàn)場緊急問題、bug修復(fù)的代碼分支,修復(fù)完后刪除。

      發(fā)布分支:release/版本號命名,版本發(fā)布分支,用于迭代版本發(fā)布。迭代完成后,合并代碼到master,在release分支上編譯發(fā)布版本,以及修改bug。測試完成后此版本可以作為發(fā)版使用,然后把穩(wěn)定的代碼合并到 master 分支,并打上版本標(biāo)簽。支持針對不同項(xiàng)目的特性發(fā)布。

      特性分支:feature/特性命名,開發(fā)版本分支,針對迭代任務(wù)開發(fā)的分支,日常開發(fā)原則上都在此分支上面。

      本地分支:local/特性命名,開發(fā)人員可以針對模塊自己創(chuàng)建本地分支,開發(fā)完成后合并到 feature 特性分支,然后刪除本地分支。

      四、“兩個(gè)披薩”團(tuán)隊(duì)的代碼管理實(shí)際案例

      在亞馬遜內(nèi)部有所謂的“兩個(gè)披薩”團(tuán)隊(duì),指的是團(tuán)隊(duì)的人數(shù)不能多到兩個(gè)披薩餅還不夠吃的地步。也就是說,團(tuán)隊(duì)要小到讓每個(gè)成員都能做出顯著貢獻(xiàn),并且相互依賴,有共同目標(biāo),以及統(tǒng)一的成功標(biāo)準(zhǔn),這樣團(tuán)隊(duì)的工作效率才會(huì)高。

      現(xiàn)在有很多互聯(lián)網(wǎng)公司喜歡采用“兩個(gè)匹薩”團(tuán)隊(duì)的模式,你可能很好奇,這些團(tuán)隊(duì)通常是如何實(shí)施代碼管理的?

      當(dāng)前國內(nèi)互聯(lián)網(wǎng)公司通常采用特性分支開發(fā)的模式,我在上面的文章中,為你詳細(xì)介紹了這種模式,下面我就以這種模式為例,為你解開困惑。以迭代周期為一周的項(xiàng)目為例,我將按照從周一到周五的時(shí)間順序,通過整個(gè)團(tuán)隊(duì)在每天的工作內(nèi)容,跟你分享項(xiàng)目任務(wù)分配,分支創(chuàng)建、集成與分支合并、上線,包括分支刪除的關(guān)系。你可以從中了解研發(fā)團(tuán)隊(duì)日常代碼管理的真實(shí)情況,體會(huì)團(tuán)隊(duì)為了提高研發(fā)效率,在代碼管理上做出的創(chuàng)新與改進(jìn)。

      背景

      周一上午 11:30,“復(fù)仇者” 團(tuán)隊(duì)的周會(huì)結(jié)束,會(huì)議室里陸續(xù)走出了 6 名工程師:

      “鋼鐵俠”:現(xiàn)任“復(fù)仇者”項(xiàng)目經(jīng)理及產(chǎn)品負(fù)責(zé)人;

      “美國隊(duì)長”:負(fù)責(zé)“復(fù)仇者”項(xiàng)目的技術(shù)架構(gòu),兼開發(fā)工作;

      “綠巨人”:全棧開發(fā);

      “雷神”:全棧開發(fā);

      “蜘蛛俠”:負(fù)責(zé)幾個(gè)成熟模塊的維護(hù);

      “黑寡婦”:資深測試工程師,負(fù)責(zé)系統(tǒng)集成與測試。

      其他同事泡咖啡喝茶的時(shí)候,“鋼鐵俠”在公司的 YouTrack 上已經(jīng)把 issue 分配給了團(tuán)隊(duì)成員,預(yù)示著忙碌又充實(shí)的一周要開始了。

      周一下午

      “美國隊(duì)長”“綠巨人”“雷神”“蜘蛛俠”這 4 名開發(fā)人員早已熟悉團(tuán)隊(duì)的工作流程,午休之后,他們紛紛打開 YouTrack 界面,在待辦事項(xiàng)上找到自己的 issue,查看無誤后,直接根據(jù) issue 建好了新的特性分支。

      每個(gè)新分支代表了一個(gè)具體的任務(wù),待四人建好新分支后,“鋼鐵俠”不由得微微一笑,心想:哈哈,任務(wù)都被大伙兒認(rèn)領(lǐng)了,看樣子,他們下午就要開工啦。這 4 名開發(fā)人員新建的 4 個(gè)分支,如圖 1 所示。

      這時(shí),資深測試工程師“黑寡婦”也沒閑著,開始查看起本周計(jì)劃完成的 issue,整理出功能點(diǎn)、性能要求和粗粒度的接口列表,基本明確了測試范圍。隨后,她在公司 Jenkins 平臺上為本周迭代設(shè)置好了“Auto Merge”(jenkins-gitlab-merge-request-builder-plugin 是高效地解決分支合并的一系列問題的插件),如圖 2 所示。

      有了 Auto Merge,任何一個(gè)分支的 PR 會(huì)自動(dòng)觸發(fā)合并,一旦出現(xiàn)沖突,開發(fā)人員就會(huì)立刻收到釘釘通知。周一下班前,4 位開發(fā)人員分別把各自的代碼 PR 到了 release 分支。大家開開心心回家了。

      周二

      “美國隊(duì)長”起了個(gè)大早,9 點(diǎn)半就到公司了,昨天他已經(jīng)實(shí)現(xiàn)了核心功能,今天要完善這些功能并升級 API。他忙了個(gè)把小時(shí),本地開發(fā)自測完成,并把本地 feature/captain 分支 push 到了 GitLab 服務(wù)器。

      一分鐘不到,“美國隊(duì)長”的郵箱收到了 Jenkins 發(fā)來的通知,告訴他剛提交的某兩個(gè)文件和 feature/hulk 分支發(fā)生了沖突。

      “美國隊(duì)長”知道肯定是黑寡婦創(chuàng)建的 Auto Merge 幫助自己快速發(fā)現(xiàn)了沖突,他直接用 GitLab 的 compare 功能對比了 feature/captain 和 feature/hulk 這兩個(gè) PR,找到了沖突所在的行。

      通過分析,“美國隊(duì)長”判斷出 feature/hulk 的變更是合適的,這個(gè)沖突應(yīng)該由他解決掉。

      “美國隊(duì)長”選擇在本地對自己的分支執(zhí)行 git rebase -i ,把引入沖突的 commit 進(jìn)行了變更,自測通過后,再次把 feature/captain 分支 PR 到了 release 。為了確保沖突的問題已經(jīng)被解決,他打開了 Gitlab ,發(fā)現(xiàn)狀態(tài)是“已合并”(Merged) ,這才端起杯子泡咖啡去了。

      團(tuán)隊(duì)已經(jīng)約好了協(xié)作節(jié)奏:每周四下班前完成一個(gè)迭代的上線。通常周二下午開發(fā)人員要把每個(gè) issue 的基本功能開發(fā)好,“黑寡婦”周二下午會(huì)給 release 配置好持續(xù)交付的環(huán)境,一旦某個(gè)分支 PR 后,自動(dòng)完成分支合并,然后自動(dòng)編譯、打包,并部署到測試環(huán)境。在測試環(huán)境上,除了跑自動(dòng)化測試外,“黑寡婦”也會(huì)手工做一些集成測試和性能測試。

      周二下午,“美國隊(duì)長”開始 review 大家的代碼, Auto Merge 把本周開發(fā)的 4 個(gè)分支,在 GitLab 上分別創(chuàng)建了 merge request,目標(biāo)分支都是 release。“美國隊(duì)長”覺得 GitLab 的 review 功能很完善,交互也很便捷。這時(shí),其他 3 名開發(fā)人員,忙著寫代碼和自測。“黑寡婦”除了搭建測試環(huán)境外,還補(bǔ)充了自動(dòng)化測試的用例。

      周三

      經(jīng)過周一和周二的努力,本周的基本功能均已實(shí)現(xiàn),“黑寡婦”開始對系統(tǒng)實(shí)施集成測試,并做一些壓力測試。上午測試時(shí),“黑寡婦”發(fā)現(xiàn)在某些場景下系統(tǒng)存在較大的延遲,這個(gè)問題在上周的版本中并不存在。她判斷是本周新引入的功能導(dǎo)致了這個(gè)問題,但一下子又很難確定是怎么引起的。

      于是,“黑寡婦”決定回滾 Merge 的代碼,把嫌疑最大的分支剔除掉后再打包測試。通過這樣的方式,最后查出是 feature/thor 這個(gè)分支引入的問題,她把測試情況詳盡地告訴了“雷神”。

      大半個(gè)下午雷神都在查問題,到下午四點(diǎn)鐘時(shí),問題終于被“雷神”修復(fù)了,他把 feature/thor 分支做了 push,然后向“黑寡婦”求助,請她合入自己的分支后再幫忙做測試。

      “黑寡婦”把“雷神”的分支重新 Merge 入 release,并把編譯包重新部署到了測試環(huán)境。經(jīng)過測試驗(yàn)證:延時(shí)大的問題真的不見了。

      下班前,“黑寡婦”召集項(xiàng)目組開了個(gè)簡短的質(zhì)量會(huì)議,大家商量后認(rèn)為本周計(jì)劃內(nèi)的四個(gè)開發(fā)任務(wù)集成后沒有大的質(zhì)量問題,周四可以一起上線。

      會(huì)后,“黑寡婦”看了看本周的合并請求,“美國隊(duì)長”對請求意見都是贊成合入 release ,Sonar 檢查也都合格,加上自己測下來質(zhì)量也過關(guān),于是,她果斷地接受了合并申請。在回家前,release 對應(yīng)的最新 commit 已經(jīng)順利地編譯、打包后被發(fā)到用戶驗(yàn)收測試環(huán)境,“黑寡婦”對這個(gè)環(huán)境啟動(dòng)了自動(dòng)化測試服務(wù)。至此,測試加修復(fù) Bug,忙碌了一整天,大家終于可以回家休息了。

      周四

      “黑寡婦”一早上班時(shí),首先查看了自動(dòng)化測試的結(jié)果,顯示 release 分支構(gòu)建出的包符合質(zhì)量要求。于是,她又對沒有設(shè)計(jì)自動(dòng)化測試用例的部分,進(jìn)行了手工測試,發(fā)現(xiàn)幾個(gè)界面上存在文字描述的問題,隨后通知開發(fā)做修復(fù)。

      開發(fā)在本地分支上修復(fù)問題后 push 到 GitLab,再次發(fā)起合并請求,“黑寡婦”逐個(gè)接受了這幾個(gè) Fix 的請求。

      到中午時(shí)分,用于上線的產(chǎn)品包終于生成了。

      等到發(fā)布窗口開啟時(shí),“黑寡婦”通過公司的發(fā)布系統(tǒng)把合格的產(chǎn)品包發(fā)布到了線上。觀察一段時(shí)間,線上運(yùn)行都正常。

      對應(yīng)本次上線,“黑寡婦”把 release 代碼合并入 master 分支及時(shí)給 master 打了 tag,然后把本周成功發(fā)布的消息通知到項(xiàng)目組,并向“鋼鐵俠”做了匯報(bào)。

      “鋼鐵俠”看大伙兒忙碌了這么多天,豪爽地請大家喝果汁,并告訴大家他又有幾個(gè)緊急的用戶需求,囑咐大伙下周繼續(xù)努力。

      周五

      通常在這一天,項(xiàng)目組會(huì)一起清理過期的分支,刪除本周已合并到 master 的分支。而對于下周開發(fā)的新分支,項(xiàng)目組約定統(tǒng)一從 master 上拉取。另外,利用這一天,項(xiàng)目組也會(huì)召開回顧和改進(jìn)會(huì)議,以討論解決目前的一些已有問題的方案,這些討論即包含工作流程問題,也包含代碼和系統(tǒng)等問題。

      小結(jié)

      介紹了由 6 人組成的“兩個(gè)披薩”團(tuán)隊(duì)代碼管理的實(shí)踐,通過周一到周五的具體活動(dòng),你可以看到采用特性分支開發(fā)的團(tuán)隊(duì)是如何創(chuàng)建分支、集成分支和刪除分支的,希望能對我們的日常工作改進(jìn)也有所幫助。

      常見問題說明

      單個(gè)特性分支怎么合入到發(fā)布分支?

      為了保證集成分支的質(zhì)量,在 gitlab 上集成分支通常都被保護(hù)起來(protected),不允許直接 push 到被保護(hù)的分支。不過,我們可以通過發(fā)起 Merge Request 的方式把特性分支合入到發(fā)布分支 。借助 Merge Request,我們可以完成 sonar 靜態(tài)檢查、代碼 review 等質(zhì)量管理的活動(dòng)。

      多個(gè)特性分支會(huì)給集成帶來哪些問題?

      不同分支可能會(huì)修改相同文件,集成時(shí)很可能出現(xiàn)代碼沖突。

      A、B兩個(gè)分支先后合入到集成分支,B合入后導(dǎo)致A分支對應(yīng)的功能發(fā)生故障。

      A 合入到集成分支后可能需要一套測試環(huán)境;B 合入到集成分支后也可能再需要一套測試環(huán)境。多特性分支分別合入集成分支所需的測試環(huán)境也多。

      Auto Merge 功能及特點(diǎn)

      合并沖突自動(dòng)告警

      自由選擇需集成的特性分支

      支持 CI

      基于 Merge Request 擴(kuò)展

      如果自動(dòng)集成時(shí)代碼發(fā)生沖突,則 gitlab 上會(huì)提示沖突,也會(huì)通知給相關(guān)人員。如下圖所示:

      參考資料:

      [1]:《持續(xù)交付36講》

      [2]:《DevOps實(shí)戰(zhàn)筆記》

      Git GitHub 代碼托管 CodeHub

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:(數(shù)據(jù)分析)網(wǎng)課評論分析
      下一篇:《TypeScript圖形渲染實(shí)戰(zhàn):2D架構(gòu)設(shè)計(jì)與實(shí)現(xiàn)》 —3 動(dòng)畫與Application類
      相關(guān)文章
      国产综合亚洲专区在线| 亚洲色在线无码国产精品不卡| 亚洲女子高潮不断爆白浆| 亚洲国产美女在线观看| 亚洲国产综合91精品麻豆| 亚洲精品自产拍在线观看| 亚洲人成无码网站| 亚洲国产无套无码av电影| 亚洲精品无码成人AAA片| 亚洲女初尝黑人巨高清| 亚洲无人区午夜福利码高清完整版| 亚洲午夜久久久影院| 亚洲乱码日产一区三区| 久久被窝电影亚洲爽爽爽| 亚洲Av无码专区国产乱码DVD| 午夜亚洲AV日韩AV无码大全| 亚洲今日精彩视频| 亚洲黄色中文字幕| 亚洲国产成人在线视频| 亚洲人成伊人成综合网久久| 2020久久精品亚洲热综合一本| 亚洲中文字幕一区精品自拍| 亚洲午夜无码久久久久软件| 亚洲av无码一区二区三区人妖| 久久精品国产亚洲AV未满十八| 亚洲av无码成人精品区在线播放| 亚洲国产精品无码久久久久久曰 | 亚洲小说区图片区| 亚洲一本之道高清乱码| 亚洲一区二区无码偷拍| 最新亚洲人成无码网站| 亚洲人成人无码网www国产| 中文字幕亚洲乱码熟女一区二区| 国产成A人亚洲精V品无码| 亚洲一区中文字幕久久| 久久精品国产亚洲av麻豆图片 | 国产亚洲无线码一区二区| 亚洲国产老鸭窝一区二区三区 | 亚洲人成无码www久久久| 亚洲熟妇无码另类久久久| 麻豆亚洲AV永久无码精品久久|