Java及Node.js對dependency module的不同管理方式

自己有玩過Java又玩過Node.js,兩者對於library dependency是頗不同的做法,這篇文是想講講兩者的分別。

Java

Java,多數是用maven or gradle來做library dependency management。
而我作為一個application developer,常常遇到一個問題:
我需要用到的libraries分別用到不同version的Spring或Jackson的不同version。
maven做法是會幫你resolve成同一個version。
但有時version conflict會出問題。

在Java裡面,不同library大多都是直接把class load到同一個class loader來用,所以不能存在multiple version的class。
很多時一些針對某些library來做的動作,都是直接hack/inject logic到那些class。

換句話說,Java的做法就像是有一個global空間,然後不同的library都放在裡面。
這樣把library都放在global空間好處就是,如果我是身為framework developer,這會較方便我去做middleware library,因為我可以直接掌控不同library。
而壞處就是,global空間如果library都各自有dependency,就很難統一manage,所以當library upgrade時就會較多問題/較痛苦。

Node.js

另一方面,Node.js的dependency management是另一種做法。
node.js裡,每個module之下都可以有自己的dependency及version。
如果你用上module A與module B而它們分別depends on module C的不同version,
那麼module A會在其下depends on它需要的module C的某version,
而module B會在其下depends on它需要的module C的另一個version。
兩個module分別用到自己需要的version,而不會conflict。

Node.js的做法,其實都是一個Global空間。
只是它容許不同module的不同version同時存在,而每個module都只會用到自己需要的version。
這樣的design的好處是,較易適應library的upgrade,upgrade的impact只會impact到adopt新version的module/code,而不是所有用某個module的module/code。

而這亦是為什麼node.js的開發能很快的其中一個原因。
因為module順手沾來就能用,較少機會會有module version conflict的問題。

不過Node.js這樣的design的short side是,假如我是framework developer,我就較難去建構middleware library。
我不是說你不能做middleware(express.js的那種),我是指你很難去針對其他library來作出一套全面掌控的framework library。
當然你不是真的不能,就像express.js那樣。
但express是較為多人adopt的web framework,而它本身也沒有很aggressive地去inject logic到其他library之上。

所以寫Node.js的話,如果你是app developer,你固然能把你到手的library都hack掉來for your usage。
但如果你是作為framework developer,你的心態就可能要調整一下,不要用寫java framework的心態及思維去做這件事。

給想學Programming的新手建議

過去都試過有好幾次有唔係IT既朋友問我學programming有冇咩advise俾到佢地。

其實, 都真係好睇佢地各自purpose係想做乜。
寫mobile app寫網頁寫backend application其實係唔同範疇黎, advise都唔同。
亦有朋友purpose係想寫特定行業既野, 例finance既application, 我唔熟都俾唔到咩advise。

不過, generally, 我通常都會advise, 如果係新手入門, 最好先學下掌握下少少基本concept。
而打好concept底, 我通常都建議係由python入手。

python唔係新野, 有一定歷史, 有一定community。但python亦都易上手。
唔好以為係舊野, 其實好多data analytic library都係python base, data analytic其實係黎緊既trend, 學完都有potential用得返(唔似pascal學完出黎冇人用)。

當然, java我估可能係最多job(好耐冇搵工, 印象中係咁), 由java入手都ok, 但學python會易上手d。

冇特別preference唔建議由frontend stack(javascript)入手, 因為太多野要同時學, 難上手。

mobile app, 我都會建議睇清楚諗清楚。
黎緊係咪仲興mobile app, 定係轉緊其他trend, 要諗諗依d問題。(open question, 各自可以諗諗)

Java農曆公曆轉換

早前需要在Java上用到農曆公曆互相轉換,但在網上找了好些別人寫的library,要不就是只能做到公曆轉農曆,要不就是會計錯了農曆閏月部份。
最後在 中国阴历与阳历的转换实现【java实现】 這一個網頁上找到了一個能計算農曆閏月部份並互相轉換的source code。
但我在使用時測試過,以香港天文台的 公曆與農曆日期對照表對照 後發覺有些日子會轉換錯誤,e.g: 1990-06-23 <-> 閏五月初一。
所以我把那網頁的source code修改了一下修正了問題。
後來亦參考了 1900年至2100年公历、农历互转Js代码 而加入了一些年份數據,令它支援到1900至2099年之間的計算。

註:這程式只能支援換算以下日期:

 

  • 農曆轉公曆: 農曆一九零零(庚子)年一月初一農曆二零九九(己未)年十二月三十日之間。
  • 公曆轉農曆: 公曆1900年1月31日公曆2099年12月31日之間。

 

Code repository:

https://bitbucket.org/Airic/lunarutil

 

更新日誌:

  • 2017-10-13-v1.3.1:
    • 修正2017年農曆閏六月三十日無法轉成公曆8月21日的bug。
  • 2016-04-21-v1.3:
    • Format code,加入Unit test。
  • 2016-02-05-v1.2:
    • 修正2033置閏問題。
    • 加入2050-2099的年份資料以支援該年份計算。
  • 2014-12-29 – v1.1:
    • 用上了 Joda-Time 去修正了一些因為timezone而出現的bug。
    • 加入了兩個新method:
      • Lunar getPrevLunar(int year, int month, int day, boolean isLeap)
        輸入農曆日期,輸出前一天的農曆日期
      • Lunar getNextLunar(int year, int month, int day, boolean isLeap)
        輸入農曆日期,輸出後一天的農曆日期
  • 2014-12-27 – v1.0: 最初版本

(最後更新日期:2017-10-13)

如找到有bug,請email到 airic.yu@gmail.com 告訴我。