Androidを学びたい人はcodelabsを一通りやるといい
先日こんな記事が話題になっていた。
android-developers.googleblog.com
ノンプログラマ向けのAndroidアプリ開発の学習コンテンツらしい。
早速やってみたら動画とcodelabs形式で起動してクリックイベントを拾って画面を切り替えるアプリが出来上がった。動画で講師陣がやたらテンションが高いのはアメリカらしい。
ものの数時間で終えたので、すでに開発業務にやってる人にとっては物足りないなーと思ったらブログの末尾に3つコースが紹介されていた。
1つめはKotlinの言語についてのcodelabs、2つめはKotlinをつかったAndroid開発の基礎編のcodelabs、最後は応用編といった形だ。
せっかくなので流れでKotlinと基礎編を全部やってみたら案外量が多くて、土日を3回ほど費やしたが自粛で暇だったのでいい学習題材になった。
コンテンツは以下の内容を含んでいて、かなり満足いくものだった。
- Layout
- Navigation
- ActivityとFragment
- Architecture Components
- Room
- Recycle View
- Internet connection(Retrofit)
- Repository
- Design(ThemeとStyle)
進め方は穴埋め形式でガイドに従ってソースを補完していくとアプリが出来上がるという流れ。コピペでもとりあえず動くものが出来上がる。
一通りやるだけでArchitecture Componentsを使ってMVVMなAndroidアプリの作りが理解できた。すごい。
GitHubに演習前と回答のソースもすべて公開されている。
昔Androidを扱った研修コンテンツを作る仕事を少しやってたけど、もうこれでいいじゃんってなった。テスト技法とか通知とかがあるといいかなーって思ったらAdvancedコースの方にある模様。さすがである。
とりあえずAndroidを学びたい人はこれを一通り理解するとよいと思いました。
またこれを終えた人は実際に自分でアプリを作ってみたり、以下の本を読んで理解が深められたらもう晴れてAndroidエンジニアになれるのではなかろうかと錯覚した。紹介リンク付きツイートを貼っておきます。
人気アプリから生きた設計を学べる「Android 設計パターン入門」一般販売開始! https://t.co/7sawUOqAN7
— takamii228 (@takamii228) 2021年4月25日
安心のリリースを実現する、バイブル。「Androidテスト全書」が一般販売開始! https://t.co/jsXF1sFlSk #AndroidTesting
— takamii228 (@takamii228) 2021年4月25日
iOSもこういうのあるといいんだけどなー。探してみよう。
2021/4/25 追記
Google Play Academyでストア配信について学ぶ
Google Play Storeで実際にアプリを配信する場合は以下の学習コンテンツが参考になります。
Google Play Storeのストアポリシーは以下になります。
- 英語版 https://play.google.com/intl/ja/about/developer-content-policy/
- 日本語版https://play.google.com/intl/us/about/developer-content-policy/
定期的な更新情報については、Google Play PolicyBytesというコンテンツがYoutubeに上がっています。
iOS版も書いてみました。
iOSについても書いてみました。
iOSのPush通知でAPNsとの連携を証明書と認証キーでそれぞれやってみた
iOSアプリのPush通知を実現するには、APNs(Apple Push Notification Service)と連携する必要があります。この連携方式について調べてみたので備忘録としてまとめておきます。
APNsとの連携方式
APNsとの連携はPush通知を受け取るアプリケーションとの連携と、アプリケーションにPush通知を送るようにAPNsへ依頼するアプリケーションとの連携 の2種類行う必要があります。
前者のPush通知を受け取る側の設定についてはiOSのアプリケーションのApp IDをApple Developer Console上で発行するときにPush Notificationsを有効にし、APNsの証明書と紐付けることで実現できます。証明書の発行の手順はやや複雑ですが、ググればいろんな記事がヒットします。
一方で後者のPush通知を発行する側の連携方式については、実際はAPNsと直接やりとりするケースはあまりなく、Firebase Cloud MessagingやニフティクラウドなどMBaaS製品を経由することが多いと思います。今回はこちらの連携方式について詳しく見ていきます。
Push通知をAPNsへ依頼するアプリケーションとの連携方式
Push通知をAPNsへ依頼するアプリケーションとの連携方式は、調べてみると現在は認証キー(p8ファイル)での認証方式と証明書(p12ファイル)での認証方式の2種類があるようです。
- 認証キー(p8ファイル)での認証方式
- 証明書(p12ファイル)での認証方式
認証キーでの認証方式の方が新しく、証明書での認証方式は以前からある方式のようです。それぞれのメリット・デメリットを比較すると以下のようになります。
連携方式 | メリット | デメリット |
---|---|---|
認証キー(p8ファイル)での認証 | キーの有効期限がなく更新の運用がいらない | ・Apple Developer Programに対して2つまでしか認証キーが発行できない ・App ID単位で管理ができない ・開発環境・本番環境と区別ができない |
証明書(p12ファイル)での認証 | ・App ID単位で管理ができる ・開発環境・本番環境と区別ができる |
1年単位で更新が必要となる |
メリット・デメリットはそれぞれの裏返しになっています。
認証キーの方が便利そうに見えますが、キーが2つしか発行できないので、同一アカウントで複数のアプリを開発・配信している場合は鍵の原本管理に注意が必要です。とはいえ証明書のケースでも管理は大変なので、管理対象の数が減って更新運用が不要になるのはだいぶ楽ですね。 今後はどうなっていくかについてはAppleのご都合次第ですが、恐らく認証キーの方に流れていくのではないかと予想しています。
Legacy Binary Protocolでの連携は2021年3月以降サポートされない
ちなみにもっと昔にはLegacy Binary Protocolというものもあったようです。こちらは2021年の3月以降はサポートしないとAppleから発表されています。以前のアナウンスの11月からさらに延長されました。
- Legacy Binary Protocolの連携方式
- 2021年3月以降はサポートされないという通知
- 2020年11月以降はサポートされないという通知
少し混乱しますが、ここでサポートが切れるのはLegacy Binary Protocolの連携方式であって、証明書ベースの認証方式自体は2021年3月以降も利用できると考えられます(証明書でもhttp2で通信できるますし)(でも違ったらごめんなさい...)。
各種MBaaSにおけるAPNsとの連携方式
ここで各種MBaaSのツールのAPNsとの認証方式が現在どうなっているか見てみましょう。
Firebase
Firebaseの設定手順を見ると、authentication keyとあるので認証キーでの設定が推奨されているようです。
FCMの設定画面ではAuthentication Keyが推奨と出ていますが、APNs CertificatesのアップロードUIも用意されているので今現在は両方利用できるようです。
ニフティクラウド
ニフティクラウドはp12ファイルのアップロードとあるので証明書での認証方式のようです。
AWS Amplify
AWSのBaaSツールであるAmplifyはp12ファイルのアップロードとあるので証明書での認証方式のようです。
Salesforce
セールスフォースはp12ファイルの利用をやめてp8ファイルへの以降に舵を切ったようです。
証明書での認証と認証キーでの認証は共存できる?
証明書での連携方式を今後どこかのタイミングで認証キーへ移行していくケースを考えてみます。証明書(p12ファイル)と認証キー(p8ファイル)は、いずれもPush通知の発行を依頼するサービスがAPNsへリクエストを投げる時の認証に使うものです。そのため、基本的にはAPNsの受け口が空いている限り共存できるのでは思いましたが、少し不安になったので同一アプリに対してp12ファイルで認証したPushのリクエストとp8ファイルで認証したPushのリクエストがいずれも受信できるか実際に検証してみました。
証明書一式を準備する
検証用のアプリを作るにあたっての一式をApple Developer Program上で準備します。
- 開発用証明書
- AppID(Push Notificationsをオンにする)
- provision profile(検証につかう端末を含む)
- APNs証明書(P12ファイル)
- AuthKey(p8ファイル)
iOSのサンプルプロジェクトを作る
次にPush通知を受け取るサンプルアプリを作ります。今回はPush通知が受け取れればいいので、デフォルトのSingle Page Viewアプリプロジェクトを作り、AppDelegate.swiftに最低限の設定のみを記述します。PushのCapabilitiesをオンにするのを忘れないようにします。
import UIKit import UserNotifications @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Push通知の許可ダイアログを出す UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in guard granted else { return } DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } UNUserNotificationCenter.current().delegate = self return true } ... // Push通知の用のデバイストークンをログに吐き出す func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let token = deviceToken.map { String(format: "%.2hhx", $0) }.joined() print("Device token: \(token)") } // Push通知のペイロードの受信を確認する func application(_ application: UIApplication, didReceiveRemoteNotification payload: [AnyHashable: Any]) { print(payload) } // フォワグラウンドで通知バナーを出す func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.alert, .sound, .badge]) } }
この状態でアプリを実機でビルドし、Push通知の許可ダイアログを許可するとログからデバイストークンが取得できます。このデバイストークンを使ってPush通知のリクエストを組みます。
証明書を使ってAPNsへPush通知のリクエストを投げる
p12ファイルを使ったAPNsへのリクエストはcurlコマンドを使って組むことができます。ググってみたらちょうどcurlコマンドがあったのでこれを参考にして組んでみます。
https://gist.github.com/greencoder/16d1f8d7b0fed5b49cf64312ce2b72cc
#!/bin/sh set -x P12_CERT_FILE_PATH="xxxxx.p12" APP_BUNDLE_INDENTIFER="com.takamiii.push-test" DEVICE_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" API_ENDPOINT="https://api.development.push.apple.com/3/device/" curl -v \ -d '{"aps":{"alert":{"title":"Test","body":"Hello from request with P12 certificates"}}}' \ -H "Content-Type: application/json" \ -H "apns-topic: ${APP_BUNDLE_INDENTIFER}" \ -H "apns-priority: 10" \ --http2 \ --cert-type P12 --cert ${P12_CERT_FILE_PATH} \ ${API_ENDPOINT}${DEVICE_TOKEN}
curlコマンドを実行すると無事200で成功し、Push通知を受信できました。ログからPushが受け取れていることがわかります。
< HTTP/2 200 < apns-id: 66AF09FA-154B-F68F-CAB3-5CBD49104122 < * Connection #0 to host api.development.push.apple.com left intact * Closing connection 0
[AnyHashable("aps"): { alert = { body = "Hello from request with P12 certificates"; title = Test; }; }]
通知バナーも出ています。
認証キーを使ってAPNsへPush通知のリクエストを投げる
p12ファイルの設定はそのままに、p8ファイルの認証キーを使ったPush通知のリクエストを投げてみます。こちらはjwtの文字列を組む必要があって少し複雑なのですが、こちらのqiita記事を参考を参考にリクエストを組んでみます。
#!/bin/bash set -x AUTH_KEY_FILE_PATH="AuthKey_xxxxxx.p8" AUTH_KEY_ID="xxxxxxxx" TEAM_ID="xxxxxxxxx" APP_BUNDLE_INDENTIFER="com.takamiii.push-test" DEVICE_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" API_ENDPOINT="https://api.development.push.apple.com/3/device/" base64() { openssl base64 -e -A | tr -- '+/' '-_' | tr -d = } sign() { printf "$1"| openssl dgst -binary -sha256 -sign "${AUTH_KEY_FILE_PATH}" | base64 } TIME=$(date +%s) HEADER=$(printf '{ "alg": "ES256", "kid": "%s" }' "${AUTH_KEY_ID}" | base64) CLAIMS=$(printf '{ "iss": "%s", "iat": %d }' "${TEAM_ID}" "${TIME}" | base64) JWT="${HEADER}.${CLAIMS}.$(sign ${HEADER}.${CLAIMS})" curl -v \ -d '{"aps":{"alert":{"title":"Test","body":"Hello from request with P8 certificates"}}}' \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${JWT}" \ -H "apns-topic: ${APP_BUNDLE_INDENTIFER}" \ --http2 \ ${API_ENDPOINT}${DEVICE_TOKEN}
こちらも無事200で成功し、Push通知を受信できました。ログからPushが受け取れていることがわかります。
< HTTP/2 200 < apns-id: 09393B36-E1CE-4F9A-5A29-2FC7FF73D424 < * Connection #0 to host api.development.push.apple.com left intact * Closing connection 0
[AnyHashable("aps"): { alert = { body = "Hello from request with P8 certificates"; title = Test; }; }]
通知バナーも出ています。
以上から、p12ファイルとp8ファイルを使ったリクエストは併用できているので、証明書と認証キーの設定は共存できていると考えられます。
なのでもともとニフティクラウドでp12ファイルでPushを送っていたところからp8ファイルを使ったFirebaseでのPushに移行する、なんてことは問題なくできそうということですね。
まとめ
iOSのPush通知についてAPNsとの連携方式ついて調べた結果をまとめてみました。Push通知の実現にはアプリの実装に加えて証明書連携が必要で、その手順は複雑ですが一つ一つ紐解いていけば理解できるものだと思いました。
またAPNsの証明書と認証キーの移行については今のところどちらでも利用できているので、Pushを実際に発行するアプリケーションの連携方式に合わせて利用していけばよいでしょう。認証キーでの連携は今後は増えていくと思われるので、鍵ファイルの管理をきちんとしていく必要があると感じました。
おまけ
Push通知のリクエストのエンドポイントを調査している中でapi.sandbox.push.apple.com
とapi.development.push.apple.com
の2つがあって混乱したので、digで掘ってみました。
$ dig api.sandbox.push.apple.com ; <<>> DiG 9.10.6 <<>> api.sandbox.push.apple.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32012 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;api.sandbox.push.apple.com. IN A ;; ANSWER SECTION: api.sandbox.push.apple.com. 269 IN CNAME api.sandbox.push-apple.com.akadns.net. api.sandbox.push-apple.com.akadns.net. 185 IN A 17.188.138.73 ;; Query time: 14 msec ;; SERVER: 2404:1a8:7f01:b::3#53(2404:1a8:7f01:b::3) ;; WHEN: Mon Jul 13 18:40:18 JST 2020 ;; MSG SIZE rcvd: 122
$ dig api.development.push.apple.com ; <<>> DiG 9.10.6 <<>> api.development.push.apple.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45266 ;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;api.development.push.apple.com. IN A ;; ANSWER SECTION: api.development.push.apple.com. 242 IN CNAME api.sandbox.push-apple.com.akadns.net. api.sandbox.push-apple.com.akadns.net. 554 IN A 17.188.165.218 api.sandbox.push-apple.com.akadns.net. 554 IN A 17.188.166.29 api.sandbox.push-apple.com.akadns.net. 554 IN A 17.188.165.219 api.sandbox.push-apple.com.akadns.net. 554 IN A 17.188.166.27 ;; Query time: 17 msec ;; SERVER: 2404:1a8:7f01:b::3#53(2404:1a8:7f01:b::3) ;; WHEN: Mon Jul 13 18:40:36 JST 2020 ;; MSG SIZE rcvd: 174
どっちも最終的には同じapi.sandbox.push-apple.com.akadns.net
を向いてるようなので、どちらでもよさそうです。
アプリケーションが依存するFWやライブラリからアップデート戦略を考える
最近はFlutterでiOS / Androidアプリ開発をしているのですが、ある程度の頻度でプラットフォームやライブラリのアップデートに追従していかないとあっという間に取り残されてしまう空気を感じています。
ネイティブのOSでいうとちょうど先日Android 11のBetaがリリースされたり、来週WWDCでiOS 14が発表されたりと、年に一回は必ずアップデートがある領域ではあるのですが、Flutterはそれ以上に短いサイクルでアップデートが入っています。
Flutter自体はstableのリリース頻度を見ても3-4ヶ月に一回のペースで更新があるようです。
このようにあるFWを使ってアプリを作ってサービスを継続的に提供していく場合、そのFWのバージョンアップにどうやって追従していくべきかなんとなく考えてみたのでまとめてみます。
追従していくおおまかな流れ
だいたいこんな感じで考えればよいのではないか、というのを以下にまとめてみました。
- アプリケーションが依存するものを洗い出す
- 依存するものの更新ライフサイクルを確認する
- FW/ライブラリのバージョンアップ or リプレースを計画する
今回はFlutterを例に順番に考えてみます。
1.アプリケーションが依存するものを洗い出す
まずアプリケーションが構成しているものを順番に洗い出して、それを要素分解して依存関係を明確にしていきます。
洗い出す観点は以下のとおりです。
- プログラム・設定ファイル
- SDK・ライブラリ
- 実行環境
- 開発環境
Flutterの場合はまず大きく①FlutterのDart部分、②Androidのネイティブ部分、③iOSのネイティブ部分に分けられます。
①FlutterのDart部分
FlutterのDart部分はFlutterのSDKに含まれるPackagesを参照する部分と、Pluginをimportする部分があります。
Flutter Pluginは参照するときはpubspec.yamlに記述するだけですが、中身は入れ子でFlutterプロジェクトになっていてDartソースはもちろんAndrodやiOSのネイティブコードを含んでいるものがあるので注意が必要です。
開発にはAndroid StudioとAndroid StudioのFlutter Pluginを使います(VS CodeやIntelliJのケースもあるでしょう)。
②Androidのネイティブ部分
Androidのネイティブ部分はKotlin / JavaのコードやJAR / AARライブラリ、Android SDKのライブラリやGraldeプラグインからなります。ビルドにはGradleが利用され、build.graldeに設定が記述されます。そもそもAndroidにはJDKが必要ですね。
③iOSのネイティブ部分
iOSのネイティブ部分はSwfit / Objective-Cと、CocoaPodsからimportするライブラリ、XCodeのFrameworkなどからなります。ビルドはXCodeに内包されるSDKで実行されます。
全体像
①ー③を1枚絵にすると以下のようになります。
依存するもののアップデート頻度を確認する
洗い出したコンポーネントをカテゴリ別に分類し、更新頻度や依存するものをまとめておきましょう。
項目名 | カテゴリ | 依存定義場所 | 更新頻度 | 依存するもの |
---|---|---|---|---|
XCode | 開発環境 | 開発マシン上 | メジャーバージョンは年1回 マイナーバージョンは3-4ヶ月に1回 |
Mac OS |
Android Studio | 開発環境 | 開発マシン上 | 3-4ヶ月に1回 | - |
Flutter SDK | 開発FW | 開発マシン上 pubspec.yaml |
3-4ヶ月に1回 | Android Studio XCode CocoaPods |
Android SDK | 開発FW | build.gralde AndroidManifest.xml |
年に1回 | Android Studio Gradle |
iOS SDK | 開発FW | XCodeプロジェクト設定 | 3-4ヶ月に1回 | XCode |
Flutterプラグイン | 外部ライブラリ | pubspec.yaml | ライブラリに依存 | Android SDK iOS SDK Flutter SDK |
Android外部ライブラリ | 外部ライブラリ | build.gradle | ライブラリに依存 | Android SDK Gradle 依存ライブラリ |
iOS外部ライブラリ | 外部ライブラリ | Podfile | ライブラリに依存 | iOS SDK CocoaPods 依存ライブラリ |
Dart Programs | ソースコード | - | SDKに依存 | Flutter SDK 依存ライブラリ |
Kotlin Programs (Java) |
ソースコード | - | SDKに依存 | Android SDK Kotlin Version JDK |
Swift Programs (Objective-C) |
ソースコード | - | SDKに依存 | iOS SDK Swift Version XCode |
Flutterの場合はFlutterプラグインの中で依存関係があったり、更にAndroidやiOSのソースが入っていてSDKを参照してたりするのでより注意が必要です。
FWのバージョンアップ、ライブラリのバージョンアップ or リプレースを計画する
上記の表を並べて見てみると大きなアップデートサイクルとして1年単位のOSメジャーバージョンアップとFWのバージョンアップが4半期に一回程度あるので、少なくともこれらを考慮してバージョンアップを計画しておけばよさそうです。
細かい外部ライブラリのパッチやバグ改修には、もしかしたらFWのアップデートが必要かもしれません。また外部ライブラリのみのパッチであれば月次単位でのアップデートでもよさそうです。
OSのメジャーバージョンアップ対応やフレームワークのバージョンアップは影響が広範囲に及ぶため、マイナーバージョンアップと比べて修正箇所が多くなる可能性があるため作業量を多めに見積もっておきましょう。
いずれにしても、どいういう時にどのバージョンアップを計画しておくのか、事前に決めておくことが大事です。決して据え置きにして蓋をすることはやめましょう。あとになって必ず負債化することになります。
アップデートを安全に行うために
更新のバッチサイズを小さくする
フレームワークのバージョンアップを控えていると、それに合わせてライブラリもバージョンアップしておけばいいや、となりがちです。
しかし、アプリケーションのバージョンアップは広範囲であればあるほど影響範囲が広くなり、変更箇所が多くなって対処に時間がかかります。
なのでバージョンアップの回数分コストが発生するためこまめに複数回やるか、一括で一気にやるかとのトレードオフにはなりますが、影響範囲が狭い範囲でバッチサイズを小さくした細かいバージョンアップを定期的に行っておくほうがリスクを低く抑えられるでしょう。
E2Eテストを用意する
FWをバージョンアップするときに、アプリケーションの振る舞いが変わっていないかをFWのDiffから追うことは結構大変です。
FlutterのRelease Noteを見ると、破壊的な変更は説明があるものの、細かいPRを一つ一つ追っていくのはかなり大変です。
このとき、アプリケーションの外から見た振る舞いをEnd-to-Endテストで記述して自動で実行できるようにしておくと、バージョンアップで壊れている箇所がないかをすぐに確認することができます。また失敗するテストから修正が必要な箇所をすぐに特定できるようにもなります。ただし、重厚に全機能を網羅するテストを用意するのはメンテナンスコストとのトレードオフにもなるため、まずは正常系の画面遷移のパスを網羅する程度のものを準備しておくとよいでしょう。Flutterの場合はFluter drive testでE2Eテストが記述できます。
アップデートに追従しにくいライブラリはリプレースできないか考える
FWの頻繁な更新に対応しようとすると、場合によっては3rdパーティによるメンテナンスが追いつかないケースもあります。そういう場合はFWの更新と天秤にかけた意思決定が必要です。場合によっては違うライブラリに置き換えたり、自前で作成してしまうなどして依存関係を見直すようにしましょう。
プラグインの選定方法に関しては以前記事をまとめたのでこちらも参考にしてみてください。
この段階でいろいろ考えてみてどうしても負債が解消できないとなった場合は、FWを再選定したりアプリケーションを大々的に作り変えることも選択肢の一つになるかもしれません。
アプリケーションの外の依存関係も明らかにしておく
今回はアプリケーション開発・更新にフォーカスしていますが、サービス提供という一つ上の目線で見てみると、その周りにあるものも依存するものとして捉えることができます。単純にヒト・モノ・カネの観点でいうと、関わっているエンジニアや委託している外部ベンダ、マシンや計算リソース、予算管理などが該当します。また社内の運用ルールなども含めて、起こりうる変更に備えておけばよりアジリティ高く変化に対応できるようにできそうです。
まとめ
プラットフォームやフレームワークを選定し外部に公開されているライブラリと組み合わせてアプリケーションを構成するときは、上記のようなアップデートライフサイクルを考慮した開発方針を事前に決めて追加開発の中で計画的に更新していくことで、技術的な負債の発生を未然に抑止し、アプリケーションを継続的に安定稼働させることができるようになるでしょう。初期リリース偏重で、アップデート戦略なしに小手先の末端のソースコードを継ぎ足すだけの機能開発を続けていると、あっという間にコアな部分で負債が発生する未来がやってきてしまいます。
一昔前のSpringやAngularJS、LaravelのLTS版を見てみると数年単位で塩漬けにしていても安泰ではありましたが、今はもうそのような世界はありません。Javaのバージョンアップライフサイクルに代表されるように、ライブラリやFWの寿命が昔に比べて短命になっていると感じます。
このように作って終わり、あとは塩漬けの時代は終わりつつあるので、継続的に依存ライブラリやFWをどう更新してくか、アプリケーション開発の初期段階できちっと考えておきたいものです。