どのプログラミング言語にも、バージョンがあります。そして日々バージョンアップされていきます。
開発のとき、どのバージョンを使うのか。意外と悩ましい問題です。
最新のバージョンでいいんじゃない?いや、話はそう単純でもありません。
バージョン選定は、状況によっても、言語によっても、選ぶ考え方が違ってきます。
11種類の言語で、バージョン選びの考え方を学びましょう。
なぜ言語はバージョンアップするのか?
プログラミング言語は、リリース後にもバージョンアップされていきます。
言語によっては、半年とか1ヵ月とかの勢いで、頻繁にバージョンアップされるものもあります。
なぜ、プログラミング言語はバージョンアップするのでしょう?
バージョンアップで変わること
言語がバージョンアップすると、具体的にはこんなことが変わります。
- 新しい構文の導入 使いやすく便利な構文の採用
- 性能の向上 コンパイル速度や実行速度の改善
- 構文の改変や廃止 使いにくい構文の仕様変更や廃止
- 脆弱性の対応 セキュリティ不備などの対応
簡単に言えば、より便利に、より安全に、より簡単に、コーディングできるようになる、のが目的ですね。
最新バージョンにすればいい、とも限らない?
より良いものなら、最新バージョンを使えばいいんじゃない?
そう、これからまっさらな状態で、
「さあプログラミングを始めよう!」ってなら、素直に最新バージョンを使えばいいんです。
問題になるのは、こういうとき。
- 過去に、古いバージョンでプログラム開発している
- そのコードを使って、今回プログラムを改造する
ここで、最新バージョンに置き換えるか、否か?これが悩ましい。
古いコードが動かない!
悩みの根源は、これ。
有名な事例が、Python 2 から Python 3 のバージョンアップです。
Python 2では、
print 'Hello, World!'
で動いていたものが、Python 3ではエラーになります。
Python 3ではこう書かないと動きません。
print('Hello, World!')
Python2ではprintは文として扱われていましたが、Python3では関数になったため、です。
古いコードが動かなくなるような変更を、「破壊的変更」と呼びます。破壊的変更が起こったなら、コードを修正せざるを得ません。
破壊的変更の修正コストをかけてでも、バージョンアップするべきか?悩ましい判断です。
動かない、の2つの意味
さらに、バージョンアップには、根深い問題が潜んでいます。
古いコードが動かない、には、実は2つの意味があります。
- 古いコードが、コンパイルできない/エラーになる
- 古いプログラムが、新しいバージョンで挙動が変わる
1番目はまだいいんです。構文変更によりエラーになるもの。エラーを直せばいい。
2番目が、根深い問題。
構文改変や脆弱性の対応などで、こんなことが起こります。
- これまでと判定結果が変わる!(曖昧だった判定が厳密になったため)
- これまでと計算結果が変わる!(計算処理が正しく修正されたため)
バージョンアップ前は、たまたま動いていたものが、動かなくなったり、結果が変わったりするのです。
この問題、非常に発見しにくい。バージョンアップを躊躇する大きな理由のひとつです。
それでもバージョンアップする理由
それなら、元のバージョンのままでいいんじゃない?
…というと、これまたそうとも限りません。
バージョンアップが必要な場合も、あるのです。ポジティブ/ネガティブ両方の理由があります。
ポジティブな理由
まず、積極的にバージョンアップしよう、という場合。
- 開発の効率化 新しい構文で開発効率UP
- ライブラリの対応 使おうとしているライブラリのバージョン対応
これは、新しいバージョンの恩恵を存分に受けよう、という話なので、いいでしょう。
ネガティブな理由
問題はこっち。バージョンアップをせざるを得ない、という場合。
- プラットフォーム対応 今使っているバージョンが新しいOSで動かない
- サポート終了 今使っているバージョンのサポートが切れる
- 深刻な脆弱性 今使っているバージョンに脆弱性が発見される
特に問題なのが、脆弱性です。
プログラミング言語には、セキュリティ侵害につながる脆弱性が見つかるときがあります。
例えば、2024年4月、このような脆弱性が発見されています。
2024年4月、Windows上で動作する複数のプログラミング言語に、コマンドライン引数の不適切なエスケープによる脆弱性が発見された。Rustの標準ライブラリにも影響があり、Rust 1.77.2のリリースで同脆弱性を解消した。
こういう場合、脆弱性に対応するには、バージョンを上げるしか手がないのです。
さらに、たいていの場合、バージョン毎にサポート期限があります。サポート期限が切れると、例え脆弱性が発見されても修正されません。
こういう場合も、バージョンアップの必要に迫られる場合があります。
バージョンアップ時の「後方互換性」を確認しよう
バージョンアップで問題が生じないこと。これは、どのプログラミング言語でも意識されています。
どのプログラミング言語も「後方互換性」を非常に重視しています。
バージョンアップされようとするとき、必ず公式からこのようなアナウンスがあります。
- バージョンアップに伴う、後方互換性の考え方
- バージョンアップに伴う、破壊的変更の有無
この情報が、バージョンアップを決定するときの、重要な判断材料になってきます。
言語ごとバージョン決定ガイド
ここまで、言語のバージョンアップについて、一般的な話を見てきました。
ただ、それぞれのプログラミング言語で、その思想により、バージョンアップ方針は異なります。
よく使われる11種の言語について、バージョンの遍歴と適用ガイドを示します。
細かい内容になるので、お使いの言語について参照してください。
C++
結局のところ、プラットフォームのコンパイラ次第で、バージョンが決まります。
C++のバージョン戦略
C++は数年ごとにバージョンアップしています。バージョンにはリリース年の数値が付与されます。
バージョン | リリース年 | 内容 |
---|---|---|
C++98 | 1998年 | 初の国際標準化 |
C++11 | 2011年 | ラムダ式、スマートポインタなど |
C++14 | 2014年 | 小改良 |
C++17 | 2017年 | 小改良 |
C++20 | 2020年 | コルーチン、モジュールなど |
特に、C+11とC++20は、大幅な改良が加えられた、エポックメイキング的なバージョンです。
ただ、C++のバージョンは、あくまで書面の規格。実際に対応しているかは、gccなどのコンパイラによります。
そしてC++は、ハードウェアに直接アクセスするような言語。
結局は、動作プラットフォームに対応したコンパイラに依存します。
- 動作プラットフォームのコンパイラ次第。コンパイラが対応する最新バージョンの利用、がベスト
Java
基本的に、LTSバージョンを使う、のが王道です。
Javaのバージョン戦略
Javaは半年ごとにバージョンアップし、連番のバージョン番号が振られます。
特徴的なのは、いくつかのバージョンおきに、
- Long-Term-Support (LTS)リリース指定されるバージョンがある
ということ。LTS指定バージョンは、指定なしバージョンと比べて、長期間のサポートが行われます。
近年でLTS指定されているバージョンは、このようなもの。
バージョン | リリース年 | 内容 |
---|---|---|
Java 8 | 2014年 | ラムダ式、Stream APIなど |
Java 11 | 2018年 | 型推論など |
Java 17 | 2021年 | AppleSilicon対応など |
Java 21 | 2023年 | 仮想スレッド対応など |
Javaは、LTSバージョンを利用するのが王道です。後方互換性が非常に重視されているので、破壊的変更は特に問題にならないでしょう。
- LTS指定された最新バージョンを使おう
C#
どの.NETバージョンに乗っかるか、次第です。
C#のバージョン戦略
C#は1~2年ごとにバージョンアップしています。バージョンごとに連番が振られます。
バージョン | リリース年 | 内容 |
---|---|---|
C# 3.0 | 2007年 | LINQ、ラムダ |
C# 8.0 | 2019年 | .NET Coreターゲット、Null許容参照型など |
C# 12.0 | 2023年 | コレクション式、プライマリコンストラクタなど |
C#は、Microsoftの.NET戦略と深く連携した言語です。どの.NETバージョンに乗っかるかで、自ずとバージョンの選択肢が限られてきます。
またC#は、バージョンアップで、意欲的な構文の追加が頻繁に行われています。構文が先進的である故に、バージョンごとに構文解釈が変わったりするときもあります。ただ基本的に後方互換性を守っているので、トリッキーなコーディングをしていなければ大きな問題はないでしょう。
なおUnityでC#を使うときは、最新バージョンに追随し切れている訳ではないので、Unityがいまサポートしているバージョンに従うことになります。
- 使う .NETのバージョン次第
- 基本的に最新バージョンで問題ない
- Unityで使うなら、Unityのサポート範囲に従う
Python
3.X系の最新版を使いましょう。2.X系は使っちゃダメです。
Pythonのバージョン戦略
Pythonは、1~2年のサイクルでバージョンアップが行われています。
バージョン | リリース年 | 内容 |
---|---|---|
Python 2.7 | 2010年 | 2X系最終バージョン |
Python 3.0 | 2008年 | 3.X系初回リリース |
Python 3.10 | 2021年 | 構造的パターンマッチングなど |
Pythton 3.11 | 2022年 | パフォーマンス向上 |
Python2は、サポートも終了しているため、現実的にこれから開発するときに、2.Xは選択肢にはなり得ません。
ただ、古いLinuxやmacOSでは、Python2がデフォルトでプリインストールされている場合があります。開発する時のPythonバージョンは確認しておきましょう。
基本的に、3.X系の最新バージョンを使っておけば問題ないでしょう。
- 3.X系の最新バージョンを使おう
- 2.X系はもはや使ってはいけない
JavaScript/TypeScript
Viteなどのビルドツールを使っていれば、あまりバージョンは気にする必要ないでしょう。
JavaScript/TypeScriptのバージョン戦略
JavaScriptは、標準規格においては、ECMAScriptが正式名称です。近年ではリリース年代がバージョンに付与されます。
バージョン | リリース年 | 内容 |
---|---|---|
ECMAScript 2015 (ES6) | 2015年 | アロー関数、クラス、モジュール |
ECMAScript 2017 (ES8) | 2017年 | async/awaitなど |
ECMAScript 2020 (ES11) | 2020年 | Optional Chainingなど |
ECMAScript 2022 (ES13) | 2022年 | トップレベルawaitなど |
TypeScriptは、ECMAScriptの仕様改訂に合わせてバージョンアップされています。
バージョン | リリース年 | 内容 |
---|---|---|
TypeScript 1.0 | 2012年 | 初版リリース |
TypeScript 2.0 | 2016年 | null非許容型対応など |
TypeScript 5.0 | 2023年 | デコレータなど |
JavaScript/TypeScriptのバージョンで気にしないといけないのが、ブラウザでのバージョン対応状況。
ひと昔前は、Internet Explore(IE)という存在により、ややこしい話がありました。IEが退場した現在、ほとんどのモダンブラウザはECMAScript仕様に追随しており、ほぼ問題はありません。
さらに、ReactやVue.jsなどのフロントエンド開発をしているなら、Viteなどのビルドツールを使う場合が大半でしょう。
これらのビルドツールがうまくトランスパイル(JavaScript/TypeScript→JavaScript変換)してくれるので、開発者がバージョンを気にするシチュエーションはあまりないと言えるでしょう。
- Viteなどのビルドツールなら、トランスパイルうまくやってくれる
PHP
バージョンは構築環境次第です。ただしサポート切れなら置き換えの検討要。
PHPのバージョン戦略
PHPは、現在サポートしているのは8.X系であり、7.X以前はサポート終了しています。
バージョン | リリース年 | 内容 |
---|---|---|
PHP 7.4 | 2019年 | サポート終了 |
PHP 8.0 | 2020年 | サポート終了 |
PHP 8.1 | 2021年 | 列挙型など |
PHP 8.2 | 2022年 | 読み取り専用クラスなど |
PHP 8.3 | 2023年 | タイプ定義改善など |
PHPは、明示的にバージョンを指定するというよりも、
- ApacheなどのWebサーバー
- XAMPPなどのソフトウェアパッケージ
- WordPressなどのCMS
こういった環境に含まれるので、あまりバージョンを意識する場面はないでしょう。
ただし、7.X系などのサポート切れバージョンを使っているなら、8.Xへの置き換え検討が必要です。
7.Xから8.Xの、完全な後方互換性はありません。なにかしら改修が必要になる可能性があります。
- バージョンは動作環境次第
- サポート終了バージョン使っているなら置き換えを検討
Ruby
3.X系を使いましょう。あとはRuby on Railsのバージョン次第。
Rubyのバージョン戦略
Rubyは2.X系のサポートが終了し、3.X系が毎年バージョンアップされています。
バージョン | リリース年 | 内容 |
---|---|---|
Ruby 2.7 | 2019年 | サポート終了 |
Ruby 3.0 | 2020年 | 3.0初版 |
Ruby 3.1 | 2021年 | JITコンパイラ導入など |
Ruby 3.2 | 2022年 | 標準ライブラリ追加など |
Ruby 3.3 | 2023年 | JIT改善など |
Rubyを使う理由は、ほぼこれでしょう。Ruby on Railsを使うため。
そして、Ruby on Railsは、Rubyの特定バージョン以上が必須となります。例えばRails 8 なら、Ruby 3.2 以上が必須です。
Railsのバージョンを上げるなら、自ずとRuby自体のバージョンも上げる必要がある、というわけです。
- 3.x系の最新バージョンを使おう
- あとはRuby on Railsのバージョン次第
Kotlin
2.Xに乗り換えましょう。あとはAGPのバージョン次第。
Kotlinのバージョン戦略
Kotlinは、先日、メジャーバージョン2 がリリースされました。
バージョン | リリース年 | 内容 |
---|---|---|
Kotlin 1.0 | 2016年 | 初版 |
Kotlin 1.7 | 2022年 | 1.X最終版 |
Kotlin 2.0 | 2024年 | K2コンパイラ、プラットフォーム統合 |
2.0での大きな変更は、K2コンパイラという次世代コンパイラの導入です。コンパイルの高速化やマルチプラットフォーム対応などの特徴があります。どちらかといえば構文の変更などは些少です。
Kotlinといえば、主要の目的はAndroidアプリ開発。そこで必要となるのが、AGP(Android Gradleプラグイン)です。
Andriodの最新APIを使うため、AGPのバージョンアップが必要となったときには、必然とKotlinのバージョンアップも必要となるでしょう。
- Kotlin 2.0 に乗り換えよう
- あとはAGP(Android Gradle Plugin)のバージョン次第
Swift
どのバージョンを使うかはApple製品次第。Swift 6なら「Swift 5 モード」で段階的移行。
Swiftのバージョン戦略
バージョン | リリース年 | 内容 |
---|---|---|
Swift 1.0 | 2014年 | 初版 |
Swift 3.0 | 2016年 | 大幅な言語仕様改善 |
Swift 5.0 | 2019年 | ABI安定性など |
Swift 6.0 | 2024年 | 並行処理安全チェックなど |
Swiftの用途は主に、MacBookやiPhoneなどのApple製品アプリの開発でしょう。
そしてこれらのアプリ開発には、XCodeが必須となります。
なので、Swiftのバージョンは、Apple製品のリニューアルにどこまで追随するか、によってきます。必要に応じてXCodeをバージョンアップし、XCodeのバージョン次第でSwiftバージョンが決まる、ということになるでしょう。
なおSwift 6 では「Swift 5 モード」という、旧バージョンで動かすモードが使えます。まずはこのモードを使って移行する、ということも可能です。
- 結局のところ、Apple製品への対応次第
- Swift 6 は「Swift 5 モード」で段階的移行もできる
Go
基本、最新バージョンを使えばOK。心配ならGODEBUGを使いましょう。
Goのバージョン戦略
Goは、おおよそ半年ごとにバージョンアップが行われています。
バージョン | リリース年 | 内容 |
---|---|---|
Go 1.0 | 2012年 | 初版 |
Go 1.18 | 2022年 | ジェネリクスなど |
Go 1.23 | 2024年 | イテレータなど |
Goでビルドした実行ファイルは、使用ライブラリも含めてネイティブバイナリに変換されます。
従って、ランタイムライブラリなどバージョンに依存する環境構築が不要です。実行時にバージョン不整合が発生しない安心感があります。
またGoは、バージョンアップで後方互換性を維持することを重要視しています。破壊的変更はほぼ無いレベルと言えるでしょう。
さらに、GODEBUGの指定で、旧バージョンでコンパイルすることも可能です。
- 実行環境に、バージョンに依存した環境構築は不要
- 常に最新バージョンを利用すればOK
- GODEBUGで旧バージョンとしてコンパイルすることも可能
Rust
エディションは必要に応じて更新、バージョンは常に最新に。
Rustのバージョン戦略
Rustは、エディション、バージョンの2パターンの進化があることが大きな特徴です。
- エディション 言語仕様による大きな変更
- バージョン コンパイラや標準ライブラリの改善
以下はエディションの遍歴です。バージョンは更に頻繁に更新されています。
エディション | リリース年 | 内容 |
---|---|---|
Rust 2015 Edition | 2015年 | 初版 |
Rust 2018 Edition | 2018年 | async/awaitなど |
Rust 2021 Edition | 2021年 | トレイトオブジェクト構文 |
Rustでは、
- 後方互換性を破るような変更:エディション
- 脆弱性などの対応:バージョン
と使い分けることで、より柔軟なアップグレードができます。
つまり、エディションは必要なときに、バージョンは常に最新に、更新すればよいわけです。
またRustでビルドした実行ファイルは、使用ライブラリも含めてネイティブバイナリに変換されます。
従って、実行環境には、ランタイムライブラリなどバージョンに依存する環境構築が不要です。実行時にバージョン不整合が発生しない安心感があります。
- 実行環境に、バージョンに依存した環境構築は不要
- エディションは必要に応じてアップグレード
- バージョンは常に最新でOK。rustupで最新にしよう
将来のバージョンアップに備えよう
将来には、言語のバージョンアップが必要となる場面が、来るかもしれません。
その時に備えた、普段からの準備は大切です。バージョンアップしやすいコードを書くポイントです。
「非推奨」を対策しよう
構文が改変/廃止されるというとき、大抵はいきなり変わることはなく、このような段階を踏みます。
- バージョンアップで、まず非推奨(deprecate)に指定される
- その後のバージョンアップで、実際に廃止される
もし非推奨の構文を使っている場合、コンパイル時や実行時に、非推奨(deprecate)がメッセージされます。
すぐに使えなくなることはありません。ただし将来は無くなる予定の構文です。
非推奨の構文は、今のうちに代替策を施しておきましょう。
「警告」を対策しよう
バージョンアップで、不適切な構文の使い方が禁止されたりします。
そういう不適切構文は、バージョンアップ前でも、コンパイルや実行時に警告(warning)が発せられることがあります。
コンパイル時/実行時の警告が無くなるよう、すべて対策しておきましょう。バージョンアップ時の問題が軽減されます。
まとめ
プログラミング言語のバージョンアップ。悩ましいです。
「最新でいいじゃん」でも「そのままでもいいじゃん」でも無い、色々な角度からの検討が求められます。
そういった判断を適切に行うため、大事なのはやっぱりこれ。
Web記事からでも、雑誌からでも、人からでも。
いざというとき慌てないよう、情報のアンテナを高く掲げておきましょう。
コメント