潮流特區

最新文章

Spring Boot - Maven Cheat sheet

科技新知
MacauYeah・2024-01-12

基礎 刪除所有結果,全部重新編譯 mvn clean compile 跑起用Spring boot寫的main class,運行Spring boot context。 mvn spring-boot:run # or mvn clean compile spring-boot:run 執行測試用例,預設只會測試test資料夾下以某些命名規則的class(例如class名以Tests或Test結尾的class,其他命名規則筆者未有能力一一驗證) mvn test # or mvn clean compile test 多Profile、多組件、多測試 使用-P指定編譯時的選用pom.xml中的project.profiles.profile參數。也可以用此來傳遞到spring profile,使得編譯後的spring war預設選擇特定profile。 mvn clean compile -PmvnProfile # or mvn clean compile spring-boot:run -PmvnProfile 使用-pl限定mvn指令只對某個子組件生效,但有時候子組件之間也有引用關係,所以需要再額外加上-am參數(--also-make) mvn clean compile spring-boot:run -pl SUBMODULE_NAME -am 使用-Dtest=限定只執行某個class的測試用例,或單個測試函數。(可以無視class名的命名規則) mvn test -Dtest=TEST_CLASS_NAME # or mvn test -Dtest=TEST_CLASS_NAME#TES_METHOD_NAME 若屬於多組件情況下,其他子模組找不到同樣名稱的測試,會測試失敗。需要再加上-Dsurefire.failIfNoSpecifiedTests=false mvn test -pl SUBMODULE_NAME -am -Dtest=TEST_CLASS_NAME -Dsurefire.failIfNoSpecifiedTests=false # or mvn test -pl SUBMODULE_NAME -am -Dtest=TEST_CLASS_NAME#TES_METHOD_NAME -Dsurefire.failIfNoSpecifiedTests=false 打包 在本機電腦中,把java變成jar或者war。通常用於自行發佈的環境中。 mvn package 有時特定Profile沒法成功執行測試用例,或者你認為有些測試問題不影響使用,需要跳過package中的test。 mvn package -Dmaven.test.skip=true # won't compile test folder mvn package -DskipTests=true # compile, but won't run 例外情況 強行把一個第三方jar,種到本機電腦中的.m2/repository # copy from https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html mvn install:install-file -Dfile= -DgroupId= -DartifactId= -Dversio

找一個可以私有化的協作平台

科技新知
MacauYeah・2023-12-19

在現今這個網路為王的年代,大部份文書等編輯工作都可以在Google Drive, One Drive那邊多人協作。唯一的問題是,你是否考慮資料保密問題。 一些開放資料,放在雲端上,故然無問題;個人用資料,就自己為自己負上保密責任。但作為一家公司,把自家客戶的資料放在Google Drive、One Drive上,你又會否覺得足夠保密? 不放在這些協作平台上,改為自購一個NAS File Server,把共享檔案都放進去,這樣又足夠方便嗎?現在File Server最大的問題,是無法提供同時協作編輯的功能,想在同一個檔案,多人同時更新不同的部份,是不可能的。 Etherpad-lite 如果大家只需要一起寫文字稿,可以試用Etherpad-lite https://github.com/ether/etherpad-lite 。 筆者試用過,它提供實時協作,其他人的更改可以即時顯示,也有一些基本的排版功能。缺點是lite版沒有好好處理大量的資料問題,一次過複制貼上大量文稿的話,會出現網路問題。 NOCODB 如果大家需要的是試算表,可以試用NOCODB https://github.com/nocodb/nocodb 。它強大的地方,是可以匯入CSV, Excel,做欄位搜尋。老實講,這些功能,對於一個IT人來說,隨便安裝一個資料庫,例如:MySQL、 MSSQL, 都可以做到匯入結構性資料,並供多人操作資料。但對於普通用戶來講,要學會操作SQL語言,實在有難度。而經過nocodb之後,可以把MySQL等轉化為常見的試算表型式,實在驚喜。而且,它也能提供一些簡單的填表方式(Google Form)

Lambda 表達式之可讀性

科技新知
MacauYeah・2023-11-24

Java作為一個真OOP物件導向的程式,在設計和編寫上是很嚴謹,什至是囉嗦的程度。近年很多Programmer因為各種原因,都放棄Java跳船去其他語言。 Javascript是其中一個很多人的選擇,因為Javascript有nodejs的加持,在Web世界下,可以同時走frontend、backend路線。而Javacript亦有一個很明顯的特性,就是大部份的library都以callback的型式出現。另外,Javascript也讓很多人覺得很簡潔,這除了是因為它沒有強型態的規限外,另一個原因也是因為有callback的大量使用。 Function Pointer 其實callback,籠統一點講就是在一個function A傳入另一個function pointer B。而編寫function A的作者,並初期並不知道function pointer B的實際操作會是什麼。A作者只是強調在特別定時候,它就會使用這個function pointer B。而這種把function pointer 傳來傳去的做法,就可以看成是Functional Programming的基礎。 Functional Programming除了把function pointer 當成是一等公民以外,還有很多附加要求,例如: Pure Function: 它只會使用到自己的Local Variable本地變數,這樣它的作用域就鎖死在Function內部,就不會有副作用。 傳統的OOP,Class中不少變數會以Class Attribute型式存在,雖然它們可能是private attribute,但還是獨立於Function外,這樣各Function的操作,都要靠作者好好地記著Class Attribute的狀態。 Nested Functions: 與普通程式語言類似,很多情況下都需要local variable,而Function Programming要足夠好用的話,就需要彈性地在function裏定義local function pointer。 Java Lambda 表達式 其實從Java 8開始,就有提供Lambda表達式,這是一個可以制作匿名function pointer的方法。所以硬要講,Java也可以做Functional Programming。 但必需要盡早強調的是,Java經常性地使用class attribute,它們很多時候都會引申請狀態的概念。即是在它們必需經過特定步驟後,class attribute才會有特定的意義。也就是Lambda表達式想保持Pure Function的特性,它可以使用的時期就有很大限制。 但我們還有必要使用Lambda嗎? 以筆者的經驗來講,它還是有作用的,特別在於它可以改善Class Function的閱讀性。 例如下面一個Java Class。它是一個工廠,提供一個服務可以生產一堆車。那些車而需要經過特定檢測,才能推出。 public class Factory { // ex1 public static List generateListOfCarByForLoop() { List tempCars = new ArrayList(); // many other logic // many other logic // many other logic List passTestCars = new ArrayList(); for (Car car : tempCars) { if (car.getWheels().size() == 4) { // many other check logics // many other check logics // many other check logics passTestCars.add(car); } } return passTestCars; } } 中間的for loop可以用lambda來改寫。 // ex2 public static List generateListOfCarByLamda() { List cars = new ArrayList(); // many other logic // many other logic // many other logic cars = cars.stream().filter((car) -> { if (car.getWheels().size() == 4) { // many other check logics // many other check logics // many other check logics return true; } return false; }).toList(); return cars; } 有人會說,上述ex2只是形式上改變了,沒有特別易讀。就像ex3這樣,把特定邏輯抽成獨立function,才是真正的易讀,對嗎? // ex3 public static List generateListOfCarByForLoopFunction() { List tempCars = new ArrayList(); // many other logic // many other logic // many other logic List passTestCars = filterCarsByWheelsSize(tempCars, 4); return passTestCars; } private static List filterCarsByWheelsSize(List originalList, int targetSize) { List passTestCars = new ArrayList(); for (Car car : originalList) { if (car.getWheels().size() == targetSize) { // many other check logics // many other check logics // many other check logics passTestCars.add(car); } } return passTestCars; } 上述ex3是一個有效的改進。如果大家不計較傳入參數的先後順序及交互影響的話,就已經很足夠。 但如果大家對於多參數的解讀又怎樣? private static List someotherfunction(List cars, List wheels) 大家又會不會突然停住,想想到底是cars影響wheels,還是wheels影響cars? 對於多參數的function來講,相互影響就會越來越多,但使用Lambda的話,可以針對性地表達這是一個Predicate Lambda。 // ex4 public static List generateListOfCarByLamdaComposition() { List cars = new ArrayList(); // many other logic // many other logic // many other logic List wheels = new ArrayList(4); cars = cars.stream().filter( filterCarByWheelSizePredicate(wheels) ).toList(); return cars; } private static Predicate filterCarByWheelSizePredicate(List wheels){ return (car) -> { if (car.getWheels().size() == wheels.size()) { // many other check logics // many other check logics // many other check logics return true; } return false; }; } 就最後的ex4版本,可以很明確的知道是cars被Predicate所作用。 如果大家還有其他使用Lambda的明顯好處,也可以一起來Github分享大家的Code

澳門IT教育 | 到底現在缺什麼?

科技新知
MacauYeah・2023-11-10

筆者最近跟朋友聊天,也剛好在進修,談到一些IT知識的傳播問題。進修課的導師,或更廣泛的教育機構,都很積極地宣傳,人必需經常upgrade自己,接受新知識。而不同的導師,就是用不同的方式,去介紹新知識。而最普偏的知識傳播方式,就是人與人之間有溝通。 溝通,好像好實制好有效,對不對? 對。溝通是很易的,不過掌握知識,是很難的。所以阻礙大部份人持續進修的原因,其實是實踐知識的成本,包括時間、空間、金錢。但最近在接觸一些大公司的官方課程後,至少在software上,都有遠端的實驗環境。 Cisco 在多年前就有提供Packer Tracer,可以模擬一些網路情況。雖然不多,但至少可以實作打command。Oracle、SQL Server,現在除了提供免費的開發版本多,還有提供docker版本,希望把本地初次安裝的問題也解決了。Oracle的官方班,還會提供雲端的預安裝版本,你就可以省下本機資源做其他整合測試。寫程式方面,在早期,為推廣Web Frontend開發方面,已經有JSFiddle,很多朋友要試code,要做POC,都可以直接跑起程式看效果。這些,都是推廣IT知識的良好切入方式。 近年多得VM、Docker、VSCode,即使Web Backend,什至是Binary program,也完全可以提供遠端的實驗環境。良心的Github、GitPod,還有提供一定量免費的VM、Docker服務,你想把整個IDE放上Cloud,真的不再用像筆者以前要自己研究的CodeServer,用它提供的就好。不過遠端的環境還是有限制,例如你需要模擬硬件,或是需要很健全的測試環境,例如frontend backend cookie domain rewirte,又或是需要健全的除錯工具,都還是要等等。 好多事,雖然不能馬上上production,但look and feel,是吸引新朋友加入的重要關口。現今澳門IT的教育發展,就是總是留存在實體課,去指定的教室讀者PT教材,使用指定機器。若導師準備充足,就還好,可以順利實習,邊聽講解邊做實驗。頂多就是上課時間、地點不夠便利。但預者有一些老師不備課,食老本,Lab沒有提前預習,做live demo時才錯誤百,修正錯誤的時間成本很高。若要想更多人持續接受新事物,就必需要提供足夠多的可以實操的Lab,而且要可以自行重複。 對於澳門IT教育機構,希望可以提供更多的網上資源,讓學生可以解放地點和機器的限制。對於現在的IT/Software的從業員,希望大家都可以擁抱Docker/Linux Container,這樣才能最低成本地試用新事物。

Spring官方教學 | Spring Certified Professional 2023

科技新知
MacauYeah・2023-11-07

筆者作為一個網頁程式開發者,使用Spring Boot開發已經有六年。從當初Spring Boot 1.x開始,查看官方Tutorial七零八落,慢慢摸索,到大改版升級2.x,都碰過不少釘。最近Spring Boot亦要升級到3.x,正式進入Java 17時代。筆者亦不斷Update自己,保持程式於一個可支援的狀態。 相對以前,現在入門Spring Boot已經比1.x年代輕鬆很多。主要前些年某些網頁開發的概念,例如REST API,已經深入行業,大家不再糾結要走傳統MVC還是RESTFul API,也使得Spring Boot這樣的Framework,可以有一個受眾比較廣的統一入門教學。 筆者最近也正式參與Spring Academy的官方教學,好好地厘清一些概念。 官方連結 https://spring.academy/paths/spring-certified-professional-2023 在讀過官方的幾個章節後,真的覺得很適合有興趣的人去看一看。主要是因為: 官方以一個經典例子作為切為點,教學REST API,In Memroy Database。它還介紹了一些簡易的HTTP Code Standard、Test Case。真的比其他民間教學更有系統性。 提供一個可以在網頁上就實驗到的Lab實習環境。那是極為重要的一件事,因為九成人,在setup java 及library dependency (maven, gradle)時,都碰釘到直接放棄。有時是因為公司工作環境比較有要求,並不允許你使用一鍵安裝的java套件及它的library dependency;有時則因為網路安全,java把你公司的firewall當作a man in the middle (MITM) attack擋了,也有時是因為你公司的firewall把java擋了。Spring Academy在一個遠端的https網頁提供實驗環境,真的比本機開發要易入門很多。 Spring Academy可要多謝vscode、code-server,及其他VM、Container技術。 在真實環境中,筆者也有自己的code-server,打包java / os cert等等,盡量減少firewall問題。 因為官方教學持續以Spring boot的最新版本作為教材,它更新的速度總比民間要快。只是官方的教學不會全面覆蓋到所有Spring project。如果大家作為Web入門的話,還是有推薦的。 在Spring boot 3.x當中,因為要求Java 版本至少為17以上,那些教材也有使用一些Java 17的新語法(Syntax),實在也令人驚喜。 基本上Java 17現在可以簡化getter / setter / switch statement,這些在開發Web的環境下都是很重複的事。在Java 11或以前,只能經過IDE去生成getter / setter等,但似始都有會一大堆Code佔據你的頁面。 官方教學及Lab環境暫時免費,除非大家很在意的修業證書,不然都可以自由免費看。 官方教學真的值得一看,雖然距離真正開發還差很遠,筆者日後若有條件,會針對官方沒有提及的內容作補充,分享一些在技術面上所需求的最少可運行配置。

Coding | Test Case 值得寫嗎?

科技新知
MacauYeah・2023-11-02

很多做軟件開發的朋友,其實都會聽過Test-driven的開發模式。就像Scrum一樣,名氣很高,但試過的人很少。為何會這樣呢?筆者認為,並非開發者懶,而是編寫Test Case的難度真的高。對比開發程式本身的成本,寫Test Case的時間/學習成本一樣高。 造成這些高成本的原因很多。一來是因為開發者並不像過往一樣,慢慢從零寫程式,一般都應用Framework去預構建一些東西,例如打包Database connection pool,Dependency injection。Framework是好用的,但就令你要模擬Mock up特定資源,變得越來越複雜。所以一般中、小型開發,都鮮有人懂得做Test Case(除了大神獨立開發者外)。筆者對於Spring boot等Framework,都摸索了很久,才能模擬一些特定資源。但Framework一更新,就很多部份都要重寫。所以筆者沒有很強調要做Test Case,因為成本認真大。 最近,在摸清一些test case 基本concept後,筆者又重新開始嘗試編寫test case。以下假設用的是object oriented programming 在開發自己的class,為每個public function,都寫test case。很多IDE, 都有提供相關自動生成test case function signature的功能(就是為你的目標function,起一個只有外框的test function。)vscode雖然不是原生支援java,但只安裝基本的java test package,就可以達到同樣效果。 在不依靠framework的情況下,自己class要『引用』的其他class object,不要經過自己使用new來生成object。全部經set function來傳入你要引用的class object。除非你的class是作為Factory Pattern(工商模式)生產某些object,不然你就不會再有new字眼。 在為自己class編寫test case時,就會可以模擬被『引用』Object的行為。這個object在傳統上可以使用oop中的interface類型來達到模擬又不會影響到原結構的做法。實在不想做interface,java還可以用mackito 這個libraray來硬改Object的行為。 同理,自己class要『引用』一些外部資源,那些設定資源的config,都應該要set function傳入。這樣你在test case中才能起一個臨時的模擬外部資源。 在不使用framework的情況,要全數去自行模擬,當然很痛苦,但至少你可以做一些很簡單的測試。 在使用framework的情況下,還有些教學都是教你mockito繼續模疑。但這會是很痛苦的,因為這樣叫做unit test,單元測試,你要模擬所有東西。在折衷的情況下,應該底層元件做unit test,但上層的元件就做integration test,整合測試。 在做integration test時,就差不多等同使用framework行起部份或必要的資源。而那些必要資源,可能指是的database service, network service。我們可以在test case中設立不同的config,從而把framework指向一些備用資源。 Database好貴,腦細不會付錢set up多一套,自己電腦不夠強,也不能跑起多個開發用Database。好在還有h2 database可以幫你,它是memory可以操作的。只要你的framework支緩就好。在初次使用Framework時,你總會覺得為何Database層要設得這些抽像,其實為的就是讓你可以隨時換Database。不論做測試還是做移植,都會少很多問題。 模擬Network service還是沒有銀彈,要麼就mockito硬改行為,要麼就是提供一套測試用service。筆者曾經為模擬別人的Network Http API,也花了相當時間自己建立dummy server,提供模擬效果。無論dummy的效果有多假,有多局限,例如if id == 1,always return true,也是有一定價值。當你做source code refactoring (重構),又或是做framework升級時,還是讓你可以安心一點。

SCRUM:用一半的時間做兩倍的事

科技新知
MacauYeah・2023-10-13

這個假期,筆者沒有再去寫Code增值。取而代之的是看看書,吸收一下新思維,把頭腦好好更新一下。機緣巧合之下,翻開了早在幾年前就讀過的書《SCRUM:用一半的時間做兩倍的事》。當下心頭一陣心酸,為何SCRUM明明是資訊行業裏面的表表者,但自己在實踐上,就總是無法應用?所以又重新讀了一遍。 先講講SCRUM是什麼,SCRUM是暫件開發上的一種迭代模式,它有另一個名字,也是我們更常聽到的是【Agile-敏捷開發】。它主張的是以最短的時間,造出最少的實際產品,讓客戶真的可以驗證當初的需求是否合理。而不是像瀑布式開發,先做好最前面,再做中間,再做最後面,然後再等客戶總體驗收。非科技業的朋友,可以想像成是ISO 9001機制上Plan Do Check Act。 理論筆者就不講太多了,筆者直接就講講實務上的問題。 首先,你要有一個團隊。沒有團隊你就不能在相互幫忙的情況下得益 但不是坐在同一辦公室的就叫做團隊,大家要真的一起協調,大家的目標和時間上可以協調,會一起幫忙解決他人問題的才叫團隊。所以,大部份情況下,當公司為了方便管理,都希望一個人負責做一個Project,每個同事是自己的project的Team Leader,這就沒有了緊密合作的意義。 你要有做專心做同一Project權限。這樣你才不會因為分心,因為做轉換,而浪費時間。 但基於公司營運,接新單新Project一定會天天都接,即使同事手頭上舊單未完成,都要強行跟同事加入新的工作說明,著手新Project的酬備。主要是因為平均分配各個客戶的期待,每個Project都要定期交點東西出來。公司也認為每個Project不可能一口氣進行下去,總有些時候是要等客戶、供應商回覆,轉換Project才不會讓同事閒著。 你要有心力去解決實際問題,讓你工作越來越順暢。這樣才會越做越快。 但問題總是每日新鮮,特別是你每次都要接觸新事物,解決方案亦不是一天就可以想到,所以會讓人失去衝刺的熱情。 運用了SCRUM/Agile開發後,應該可以走少很多不必要的路。 但其實只有你在基礎能力都很超班,新事物都不用掃雷,你才會有可能覺得少走點。就以軟件開發來說明,若你沒有自動化的CI/CD的伺服器,每次都要花很多時間才完成發佈,你想讓客戶驗收新功能的頻率一定很低。你的同事連SVN/Git都不用,你想取用他人的新功能來測試的難度也很高。你的開發環境沒有分為開發/測試/驗收/上線,開發時改爛了就根本無辦法Rollback。及早驗收這不是代表你做錯事的機會變少,只是提早一點知道,讓錯誤不會繼續延伸下去。因為要重新改造而花掉的成本也是很明顯的。 一切一切在重讀《SCRUM:用一半的時間做兩倍的事》時,筆者也看到一些人生的希望。 若沒有團隊,但只要堅持專心做同一個Project,單人團隊也是一個可以嘗試的方向。當你專心做同一件Project,你會少了轉換成本,也不會感到同時多個Project的爛尾感,更容易累積信心和成就感。 當有問題真的解決不了,不是轉換Project,而是面對問題,要麼Workaround,要麼就解決它,把新增成本交給客戶/老闆做決定。因為Plan Do Check Act的週期性,即使不是開發出完全滿意的產品,至少客戶都有部份功能可以用,也驗收過。公司收帳也應該跟開發期週期掛鈎,驗收過了,就收回開發費用。雙方有意見,不願意繼續開發,就按照剩餘未開發的部份收取解約金。以醫院的收費模式來舉例,一個慢性病,不會一下就可以治好。每次覆診,都會獨立計算診金,病人不願意繼續,可以選擇轉醫院;自己認為足夠了,也可以不再去覆診。 如果客戶/老闆沒有因為堅持最初的合約一字不改,後續因為分歧而產生的負面情感也沒有這麼大。有些問題,可以及早止蝕,對公司與客戶都好。作為員工,在中間做磨心的情況也可以減少,不必為一開錯誤的開頭而繼續走下去。

Steam Deck With Podman

科技新知
MacauYeah・2023-10-06

Steam Deck With Podman 眾所週知,Steam Deck預裝的是一台Linux主機。但它的系統比較特別,為了可以安全更新,所以系統最主要的部份都設定為唯讀(read only)。也就是,傳統你可以直接在Linux上經管理員權限安裝的軟件包,全部都會被擋,即使你把唯讀部份設為可讀寫(read / write),在下次更新時,都會被一次過覆蓋掉。 筆者作為一個負責任的機迷+開發者,怎樣可以白白讓一台Linux機只可以玩遊戲呢? (怎樣跟老婆交代呢?) 所以筆者千辛萬苦,找到一個折衷方案,讓他可以當為開發機使用,那就是Podman。(當然,若果大家有條件有金錢,直接改裝Windows就可以了。) Podman是什麼? Podman跟Docker一樣,都是一些管理和運行Container的主程式。跟Docker不一樣的是,它是Open source,而且是daemonless。 所謂的daemonless,就是不會有一個背景程式去長期管理Container。好處是不會因為背景程式死了,就全部Container一起掛掉,預設也不需要走管理員權限路線。但也因此跟Docker有一些使用上的差異,例如Podman沒有原生的docker-compose結構,即使坊間有python寫的podman-compose去硬對應docker-compose,但某些network是跟結構還是不能直接從Docker轉移過來。 就筆者早期的踩雷經驗而言,用Podman跑起一兩個獨立固定Port的Container來說,都很夠用,也不會遇到奇怪的Bug。所以這次,亦用來作為Steam Deck運行整合式開發的Container。 不平凡的安裝之路 install homebrew Steam OS 3,雖然可以使用更改read / write,再使用pacman來安裝podman。但因為Steam OS更新後,全部要重來,工作量和網路流量都不少,所以筆者改為使用homebrew來安裝podman。homebrew只需要首次安裝時使用管理員權限,之後就會在/home資料夾下留下可執行的程式,所以它不會被Steam OS更新所破壞。 install podman 記得記得重新開機,之後應該就可以成功運行container

Oracle Database in Docker

科技新知
MacauYeah・2023-09-22

雖然筆者之前有提過,Docker並不是萬能,Docker在管理有狀態應用(Stateful Application)的情況下,只能走單機路線。但因為Docker實在很方便,所以連Oracle Database這類強狀態應用也有出Docker版本。當然,它在預設的情況下,只能在單機下操作。 不過即使在單機操作下,還是有一些跟其他Docker Image有差異的地方,需要特別拿出來聊聊。 假設根據官方的教學,跑起了一個oracle19c的Docker Container。再查看當中的Process,你會發現有一個內部PID為1的runOracle.sh 在Docker中這個PID為1的Process是很重要的,它是判斷整個Container有沒有運行的依據。它就是當初在Docker Image中Entrypoint或CMD指定的那個指令生起的Process。Docker daemon要進行停止指令,要停止container時,也是對著PID為1的那個process來處理。 一般的情況下,如果PID為1的那個process可以無腦地停了、重開,那一切都好辦。但在Oracle Database的情況下,就不適合。因為Database始乎都是有交易概念的(Transaction),它的停止並不是殺了process就了事,它還要考慮HDD操作中,有那些可以被考慮為完成,有那些下次要還原(undo)、重做(redo)。如果殺了process就等於Oracle 的Shutdown Abort,有機會下次開機會,就會有交易異常而且無法決定該如何操作。 大家需要先進入Docker container,經sqlplus進行必要的關閉Database指令。但此時,PID為1的那個process,其實還在進行中,在Docker 層面,它就像是Docker Container還在正常運行中,只是Database離線了。又因為sqlplus關閉Database並不是馬上有結果的,所以在整體關閉時可能需要串連command。就像

Git Submodule

科技新知
MacauYeah・2023-09-15

Git Submodule 初次實務上使用submodule來同時管理幾個project的更新。如果有任何理解上的錯誤,請在github中提issue或pull request。 Why Submodule 假設你的團隊中有三個人,A君做A Project,B君做B Project,C君做Main Project。如果可以,A,B各提供已編譯的Binary或Library,給C君直接使用就最好。 但要做到好好管理,A,B都要有自己的發佈系統,即是把Binary上傳到某個分享Repo中,這樣C君就能有條理地通過IDE或Compile工具下載對應的版本。如果是javascript,Repo可能就是npm repo,如果是java,可能就是maven repo。這亦代表A,B君對程式編譯、打包、版本命名等都要很熟悉,不能一輩子都命名為v1.0.0。 如果團隊對這些都不熟悉,C君還有什麼方法呢?其實靠著Submodule的功能,C君也可以硬把A,B的Source code取出,做最後打包。 這跟A、B君自己把source code壓縮然後Email寄給C君是有不同的。因為這樣C君並不清楚A,B的git脈絡:C君需要自己做好A、B的版本記錄。想要只回滾A,B的版本普不容易。但經過git Submodule後,C君可以清楚知道現在正使用的是A、B的那一個commit版本。假如有一天,A、B、C三個都更新了,但發現合起來時就跑不動。C君可以保持A、C的版本不變,單獨提取B的某個版本進行測試。當然,你可以說原本Email也可以這樣管理,但始終你不清楚B的版本記錄,Email的日期並不代表Source Code的進度。(因為有時候,Bug Fix是針對舊版本的做更新,新功能的Email日期反而比Bug Fix要早) 同理,如果大家要連結多個沒有發佈系統的文字資料,也可以利用Submodule。例如筆者正在編輯一本書,當中不同的主題,就是使用Submodule的功能串連起。 Command 馬上看來來Submodule可以怎樣做。 假設你已經知道git 怎樣用,也起了git repo。假設你是C君,進入你的本機repo資料夾內,使用submodule參數。 上面的效果,就是把C君當前repo的狀態,連結到B君submodule當時預設分枝(default branch)的最後一個commit 中。然後C君在自己的repo怎樣更新,它引用到B君的submodule版本都不會變。 直到某一刻,B君說他加了一個穩定的新功能,請C也連帶更新一下。C君也做好自己的準備後,使用submodule參數進行更新。 注意,如果C君有多於一個submodule,上述指令會全部一口氣更新。另外,如果你覺得B君的最新版本不能用,還是可以針對B君取得特定的版本。