近十年來軟體產業蓬勃發展,許多新語言、框架跟工具都不斷被推出,我們應該如何選擇?我以一名 Ruby 愛好者的角度來說明持續選用 Ruby 的理由,來解釋問題沒有想像中困難,也不那麼單純。更多是我們自身的個性、環境影響,當我們了解一個語言跟框架的特性,就很好找到適合自己的工具和技能。
選擇適合你的技能組合Pick up the best skill set for yourself
View Slide
蒼時弦也Software Developerhttps://blog.aotoki.me
歷史背景語言特性生態系技能搭配
資訊量過大我們來看一些有趣的地方
網站與程式語言把網路的進展與程式語言面世的時間對照
C19721983C++ Python19911995Java PHP Ruby JavaScript200
C19721983C++ Python19911995Java PHP Ruby JavaScript2001990 年代,World Wide Web(全球資訊網)被提出
PHP Ruby JavaScript C#20002009Go Node.js Rust20132000 年代,Web 2.0 被提出
PHP Ruby JavaScript C#20002009Go Node.js Rust20132006 年代,Amazon Web Service 推出
Ruby、Python 初期沒有內建 HTTP 伺服器,直到 2010 年前後才被加入到標準函式庫,然而 Go、Node.js 一開始就內建
開發框架的進展除了語言之外,現今主流的框架在何時誕生
Spring20022005Rails Django .NET MVC20072010Angular Laravel2011
Spring20022005Rails Django .NET MVC20072010Angular Laravel2011Web 2.0 後當代主流的網站開發框架才逐漸成形
2005Rails Django .NET MVC20072010Angular Laravel20112013React Vue2014後端成型後的十年,前端框架也開始被提出
從時間的角度來看,不同時期推出的語言、框架剛好對應當時面對的問題
型別一個語言如何看待型別會影響使用
# Rubydefend(value)valueinspectinspect [ ]inspectputs"string""array"
// Golang// ...funcswitch :=case stringcase stringstring(obj any) {v obj.(type) {:fmt. (v)[] :fmt. (v)}}( )([] { })InspectPrintlnPrintlnInspectInspect"string""array"
動態型別語言會自動分辨,在撰寫上通常會比較簡潔
# RubyPerson Struct :name :agePerson name: age: 28Person name: age:. ( , )bob . ( , )john . ( , )= new= new= new"Bob""John" "John"
// Golang// cannot use "John" (untyped string constant) as int value instruct literaltype structstringint:=:={NameAge}bob Person{Name: , Age: }john Person{Name: , Age: }Person"Bob""John" "John"28
動態型別的語言通常會需要額外確認資料是否正確
# Rubydefdonewend&end(services)services.map |service|. { service.start }.each( )runThread:join
// Golang// select { ... }packagetype interfacefunc ...:=for := rangego func{ (ctx context.Context) }(services Service) {ctx context. ()_, svc services {() { svc. (ctx) }}}daemonServiceRunStartBackgroundStart
// Golang// ...packagetype structfunc *{}(s Server) (ctx context.Context) {}httpServerStart
// C#namespaceinterfacevoidclassvoid Serviceforeach IService in{{()}{( [] ) {( services) {service. ()}}}}DaemonIServiceStartMainRun servicesserviceStart
// C#// ...namespaceclass Daemon IService{: . {() {}}}HttpServerStart
同樣是靜態型別,也會有所不同,在使用不同工具的思考方式就會有所差異
不同語言描述事物的方式都不太一樣,我自己比較喜歡 Ruby 保留很多彈性的方式,因為很彈性不同人寫出來的差異就會更大
物件不同語言中對物件的看法都有點不同
# Rubyclass <defnew + +endend= new= new+( , )(other)(x other.x, y other.y)p1 . ( , )p2 . ( , )p1 p2Point Struct.new+:x :yPoint x: 1 y: 1Point x: 2 y: 2puts
# Elixir# ...defmodule dodefstructdef ++end==|>[ , ] (%{ x, y}, %{ x2, y2}), % { x x2,y y2 }p1 % { , }p2 % { , }. p1 . (p2)Pointadd PointPointPointIO inspect Point add:x :yx: y: x: y: do: x:y:x: 1 y: 1x: 2 y: 2
typedef structintint= = + = +returnint= = == = ==return{x;y;} Point;Point (Point , Point ) {Point p { .x p1.x p2.x, .y p1.y p2.y };p;}() {Point p1 { .x , .y };Point p2 { .x , .y };Point p (p1, p2);( , p.x, p.y); ;}addmainaddprintfp1 p21 12 2%d %d0"x = , y = "
Point(1, 1)ObjectAdd(p1, p2)MethodPoint(3, 3)Object物件是一組有意義的資料,類別(Class)則是定義哪些函示能對資料發揮作用,稱為方法(Method)https://hackmd.io/@sysprog/c-oop#物件導向是一種態度
# Ruby# ...moduledefendendclassincludeincludeend(other)AddableaddPointAddablePrintable
# Python# ...classdefclasspass:(self, other):( , ):AddableaddPoint Addable Printable
// Go// 這是對的嗎?type interfacetype struct{(other Addable) Addable}{Addable}AddablePointAdd
Mixin(混合)是部分語言才有的概念,這類語言通常會有 DuckTyping 的概念存在(可以呼叫特定方法即可)
// Go// Yes, But!type interfacetype struct:= &{(other Addable) Addable}{Addable}p Point { Addable: Vec2{ , } }AddablePointAdd1 1
// C// Usage: p.addable->vec2// 更像這個狀況typedef structunion**= = == = *{{Vec2 vec2;Vec3 vec3;} addable;} Point;Vec2 vec2 { .x , .y };Point p { .addable vec2 };1 1
不是將方法混合到物件中,而是作為一部分組合(Composite)到物件裡面
框架輔助開發的利器
Ruby on RailsModelViewController
LaravelModelViewController
Spring FrameworkSpring WebFluxSpring MVC...
Golangnet/httptemplate/htmldatabase/sql
不同語言的框架解決方案並不相同,Golang 通常只使用 Router 為主的框架,Rails 以 MVC 為主體,Spring 有非常完整的解決方案
Spring 有 VMWare 的支持,同時 Java 是許多企業採用的語言,因此提供完整的解決方案能讓工程師專注在商業問題上
不同社群在維護功能的選擇上有不同差異,有的可能以少數意見領袖為主,有些則是非常開放以社群意見為方向
Golang 主要設計給網路服務,在多核心、網路相關的支援完善,重心不完全在 Web 上,框架的發展大多只針對不好處理的 Router
Vue React Angular扣掉喜好這類外在因素,我們會怎麼選擇?
Vue React Angular產品原型、個人專案、功能明確的產品
Vue React Angular跨團隊協作維護、功能複雜的產品
Vue React Angular大型企業使用系統、多租戶服務
單純從框架規範、開發方式來看,越強大完善的框架限制也越多,也就越適合多人協力(規範明確不容易出錯)
解決方案生態系決定選擇
如果我們想處理 AI/ML 的題目,想到什麼語言?
PythonPython 有許多適合處理資料的套件,而且非常完整容易使用
如果想快速製作產品原型,會想到什麼語言?
Ruby PHPRuby on Rails 和 Laravel 兩個框架在在初始化後即可馬上可用,語法彈性更容易驗證想法
如果想做網路服務,會想到什麼語言?
GolangGolang 天生對網路服務的相容性就非常好,因此被大多微服務基礎建設專案選用
如果想做安全、系統底層的應用,會想到什麼語言?
RustRust 對記憶體的使用非常嚴謹,並且大量利用編譯器檢查來改善軟體的品質
如果想做遊戲,會想到什麼語言?
C# C++Unity 讓遊戲開發的門檻極大降低,目前兩大主流引擎分別使用 C# 和 C++
工具選擇如果要學習一個語言,該怎麼選?
從個性來看,喜歡彈性還是有規則跟標準?
Ruby JavaScript雖然不排斥繁複的定義,但是因為自己很多想法想驗證,有彈性的語言更適合
從喜好來看,想做遊戲相關聯的軟體
Ruby C# JavaScript這幾個語言都有遊戲開發相關的解決方案可以用
從環境來看,當下的趨勢與機會是什麼
Ruby JavaScript自己在程式領域進步最快的 2013 年那個時期,Ruby on Rails 是最有潛力的工具與職業
綜合各種條件,大致上就能找到適合的語言
Ruby TypeScript從 PHP 開始學習,到 Ruby & TypeScript 能用十年以上有很多條件
然而,現代人的人生長到足以學習大多數程式語言
Golang Python考量到職涯發展,我在工作中使用截然不同的語言跟環境來「解決問題」
C C#遊戲開發跟研究技術是我的興趣,我也會不時使用他們
Elixir Rust嘗試不同的語言跟思考方式,也是作為工程師有趣的一環
比起語言跟框架,清楚自己「想做什麼」以及「如何做好」更重要
END工商一下網誌的連載內容
2023 Later - Rails 開發實踐2024 Early - Cucumber 的文件測試法2024 Later - Rails 架構設計(規劃中)https://blog.aotoki.me