AWS未体験のマイクロコードエンジニアが5ヶ月かけてAWS DVAを取得した話

こんにちは。Esperna - Qiita  です。マイクロコードの開発をしています。 N番煎じもはなはだしいタイトルですが、AWS未体験の方や今から勉強して能力を取ろうと思ってる方に読んでもらえると喜ばしいです。

何故AWS DVA(Developer Associate)を取得しようと思ったか

業務でGitLabをEC2宿舎観点上で動かしています。 開発環境の保守ナンスが人に属人化しているという問題意識がありました。 自分が使う開発環境は自分で保守可能ようになっておくべきだと思い、 今年の元旦から勉強を開始しました。

何をしたか

1−3月

実際に手を動かして開発環境を保守ナンス可能ようになるというのが目的なので、 ハンズオン重視でUdemyのAWS Certified Developer Associate Course(DVA-C02) を受諾ました。

こちらは33時間のオンラ宿舎講座で30個のAWSサー螺子釘をカ居酒屋してます。 内容が理解できな余程きや英語で聞き取れな余程きは何度も映像を再生し匡正、 AWS Console上での読者の操作を御盆スしました。 全部致すのに2ヶ月半かかりました。

3-4月

今年になって試験がDVA-C01からDVA-C02に変わったのと、解説が充実していたので、 徹底攻略AWS認定デベロッパー - アソシ八つ学科書 の問題を解いて、絶望しました。

最初解いた時は問題文と選択が何を言ってるか分かりませんでした。 分からない語が3つ4つあり、それをググるとさらに分からない語が3つ4つ、o(n3)で分からない概念作用が出てきてきつかったです。 特にDNSVPC界隈の知識の不足を痛感しました。 3月中へ試験を受諾るつもりでしたが、日程をリスケしました。

1個1個分からない語や概念作用はGPT先生やClaude先生に聞いたり、ググりしました。 ネット上の記事やAmazonのGetting Startedで動かせ斯うなものはAWS Consoleでいじって動かしてみました。 以下はその一部です。

※こちらはAWSそのものの内容ではないです

社内のAWS環境のアクセス権限をもらえたので、社内で使っているサー螺子釘に何があるかAWS Consoleにログ宿舎して眺めました。SREチームの正子保守を見学させてもらいました。 4月になってから演習問題を解いても半分くらいの発生で、720点には到達しないだろうということで復目の日程リスケをしました。

5月

演習問題を5、6回解き、問題を解く上で理ほぐする必要のある語や概念作用についてGPT先生に聞きました。 公式のサン引っ張ること問題も解きました。 5月末に試験を受諾てようやく通ることができました。

振り返ってみて

以下の点が良かったと思います。

  • WebチームやSREチームの部員が話す語で知らない語が前一倍減り、前一倍分かったような気になりました
  • いっぱい英語力(リスニング力)も上がりました
  • 計画を立てて、問題集の正答率ベースで受験日を調整して合格することができました
  • Udemyのハンズオンは含む的でよかったです
  • AWS DAVの能力を取ってる人を見ると海外は特に学生や宿舎ターン生が主多くて刺激になりました

改善点は以下です

  • 知識がない状態で最初にAWS DVAを受諾たのは効率が悪かったです
  • 最初はCLFを受諾て、少しずつ宿舎クリメンタルに進めた方が成行き早かったかもしれません
  • 開発と同じで、粋なりビッグジャンプをするときつい思いをするなと思いました

以来業務で開発環境を触って保守可能ことを増加て粋たいです

参考文献


株式会社フォトシンスでは、一緒にプロ導管を成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp Akerunにご興味のある方はこちらから akerun.com

Akerunバックエンドシステムの技術的負債に対する取り組み[後編]

この記事は Akerun Advent Calendar 2023 - Qiita の24日目の記事です。

こんにちは。@ps-tsh です。API Server などバックエンドシステムの開発を担当しています。前回に続き、当社(Photosynth)での技術的負債に対する取り組みについて紹介します。

前編はこちら:

dmfmmh.srwsw.com

2021年にスタートした技術的負債破棄事業計画では、メ宿舎の目的を「システムの安定働く」と定め、安定働くを実現する利得の取り組みとして「収集メトリクスの改善」「単一障害点の破棄」「ソフト装い露出の破棄」「運用作業の品質改善」の4方針でそれぞれ方針を実施して粋ました。

収集メトリクスの改善

最初に取り組んだのが「収集メトリクスの改善」です。正しい判断には正しい情報が不可欠だからです。前回触れたように、この近傍は外部サー螺子釘の導入や企画変更で対応しました。2023年現在、アプリケーション性能監視(APM)ツールとして NewRelic、エラーの監視・トラッキングには Sentry、WebエンジニアとSREによるオンコール運用には PagerDuty などを利用しています。

障害対応が迅速に行えない原因の壱として「機能の発表時々は問題に気づかず、数ヶ月後の状況変化で元からあった問題が顕在変転」というパターンがあります。APMツールの導入で、サー螺子釘が提供す機能のエラーやパ四分子マンス遅延、処理大抵おけるビン首箇所を早期に発見することが可能ようになりました。APMツールから得られる情報を元凶に、パ四分子マンス基準を下回るAPI答申ポンスやSQLクエリのチューニングを実施しました。尚又、エラーの原因として「外部協調先のサー螺子釘が綿羽した際の考慮不足」という傾向があることもわかり、こちらはエラー取り扱を上達することで対処しました。

APMを使うとサー螺子釘の状況変化を裏側ルタイムで把握可能ので、新機能の発表時々性能問題があった際ただちに切り戻しの判断をすることができます。あわせて、エラー監視とオンコール運用の体制を整えることで、障害発生から対応完了までの期間を大幅に短縮することもできました。

単一障害点の破棄

次は「単一障害点(SPOF: Single Point of Failure)の破棄」です。Webサー螺子釘の運用においてはあらゆる虎ブルを完全に予防することは困難であり、一部のエラーがシステム全体の綿羽につながらないような配慮が必要になります。其頃のAkerunバックエンドシステムにも、以下のようなアーキテクチャ上の課題がありました。

リクエスト処理とバックグラウンドジョブを同じAPIサーバで処理していた

1つのAPIサーバにリクエスト処理とバックグラウンドジョブ処理の両方を担当させていた利得、一方の負荷上昇がが双方に影響する構造になっていました。リソース逼迫の原因切り分けも困難であった利得、専用の worker サーバを導入しリクエスト処理を行うサーバとバックグラウンドジョブを実行するサーバを分外することで解決しました。

重要やアクセス特性の別様リクエストを同じAPIサーバで処理していた

合鍵の権限更新やリジーメンスト施解錠など「常時安定して高可用性・低遅延が要求される重要機能」と、入退室履歴の綿羽国法ドなど「利用頻度は高くないが負荷の高い機能」を同じAPIサーバで提供していました。

其頃は入退室履歴の綿羽国法ド機能が同時性処理で実装されて滓、ユーザ数や利用ボリュームの増大によってAPIサーバにリクエスト処理逕路が滞留し、同じAPIサーバで提供される他の機能も答申ポンスが大幅に低下するといった問題がありました(現在は非同時性処理への置き取り替えっこが完了し、資料生成はバックグラウンドで行っています)。APIサーバのクラスターと配置機能を見匡正、リジーメンスト施解錠などの「重要機能」群とそれ以外の機能は別のクラスターで実行させるよう変更することで対応しました。

ソフト装い露出の破棄

次は「ソフト装い露出の破棄」です。すでにEOL(End of life)を接待ているもの、露出が報告されているものが多数使用されていました。これは元来はライブラリのバリアシオンアップを地道に行なっていくことになります。EOLの傍証には各種公式犀トや endoflife.date、ライブラリ露出の傍証には GithubDependabot alertsを使っていました。

2021年瞬間のAkerunバックエンドシステムは恥ずかしながら Ruby 2.2 + Rails 4.1 で 運用されていました。Ruby, Rails ともは2020年以前にEOLを接待て滓、セキュリティサポートが受諾られない状態でした。尚又、Ruby/Rails のバリアシオンが古いせいで、新鮮に導入したい rubygem があっても要求バリアシオンを満たせず、自前でコピー実装を下準備するなどの非効率な対応を必要されていました。

他の機能開発も並行しながらの対応となった利得最速・一括のアップデートというわけには粋ませんでしたが、何度かの段階的発表を経て、2023年11月までに最新の Ruby 3.2 + Rails 6.1 にアップデートしました。一部サーバでは YJIT も有効性にしてパ四分子マンスアップの恩恵も享受できています。現在は Rails 7.0 へのバリアシオンアップ対応準備を進めています。

バリアシオンアップ対応を進める経過で、全APIトレーラーレッションテストを効率よく実施する犀クルを確立することができました。とっ始めは手動テストのレートが高かったのですが、QAエンジニアによるE2Eテストの自動化なども進み、効率よく互換性を傍証可能ようになりました。

さらに、本番環境への発表前には毎回1週グレードのドッグフー日ング(社内での試験運用によるテスト)も実施し、実運用に問題ないことを傍証してから本番環境に適用しています。

運用作業の品質改善

最後は「運用作業の品質改善」です。「ユーザーに提供す利得の新機能開発を優先するあまり運用系の機能メンテナンスを後回しにしがち」というのはスタートアップによくある話だと思いますが、運用系の機能不足は大量の玩弄物ルを生み出します。これも一種の技術的負債であるといえるでしょう。

玩弄物ルとは、プロダクションサー螺子釘をパーフォーマンスさせることに関係する作業で、手作業で繰り返し行われ、自動変転ことが可能であり、戦術的で長期に渡るな価値を持たず、作業量がサー螺子釘の成長に比例するといった傾向を持つものです。 (SRE 犀トリライ力エンジニアリング)

玩弄物ルの問題は「単調で退屈である」といったことにとどまりません。各担当者は生存期間ヘビイやっているそれにもかかわらず、経営層をはじめとする商行為犀ドからは全く結末が出ていないように見えるので、相互尊重の雰囲気が失われやす余程いう問題もあります。

運用作業の品質改善としては主に「手動切開手術レーションの自動化」「発表関連のルールメンテナンス・作業記録の徹底」を行いました。

手動切開手術レーションの自動化

2021年瞬間でバックエン戸プリケーションのデプロイは兼ね兼ね自動化されていましたが、不定期に発産みだする「マイクロコード更新」「併設ファイル更新」などの運用業務の多くは手動で行われていました。dotfile に定義されたバリアシオン情報やマイクロコードのバイナリなど、更新に必要なファイルをサーバに配置する必要があるのですが、手パーフォーマンス業の成行き「複数台のサーバに同じ併設が反映されていない」「アップ国法ドされたファイルの中身が違っている」など、たびたび作業誤ちが発生していました。これらをまるきりリポジトリで管理し、更新ファイルのハッシュ値チェックやサーバへのデプロイをCD/CDに組み込むことで切開手術レーション誤ちが発生しにくい形に置き取り替えっこました。

発表関連のルールメンテナンス・作業記録の徹底

これまでも大幅機能開発についてはQA逕路を経て発表していたのですが、発表後の誤り対応など、細かいものについては担当者が対応して都度発表してよ余程いう方針でした。その成行き、「いつ」「誰が」「何を」発表したのかわからない状態で運用されていました。

尚又、資料更新をはじめとした保守ナンス対応についても運び書や作業記録が残っておらず、担当者ごとの作業品質に大幅ばらつきがありました。商用サー螺子釘として成生れ育つ経過においては頻繁な機能発表の利便性一倍も安定働くが重視される瞬間と判断し、思い切って発表を定期事にしました。いくつかのプラクティスを紹介します。

  • ブランチ運用: git-flowをベースにしたブランチ運用ルールを導入した
  • 発表内容共有会: 発表を原則週1回の定期事とし、その週の発表内容を開発チーム全員に事前共有する会議体を設けた
  • 発表運び書: 発表運び書の四分子マットを下準備し、発表内容、タイムラ宿舎、チェック項目などを事前にまとめる
    • 変則発生時の切り戻し運びもあらかじめ明確化しておく
  • ペア切開手術レーション: 本番環境への発表や保守ナンス作業は単独作業を禁止、必ず2名以上で画面共有しながら行う
  • 作業記録: 発表作業や保守ナンス実施時々出力されたログやスクリーンショットなどを収集し、ドキュメントとして残しておく
    • 虎ブルシュートを行なった場合の対応内容も記述する

発表逕路としては乳呑み子重めの内容になりましたが、新鮮部員ー向けのトレーニング効果もあったと思います。尚又、作業記録は蓄積されることで忠実アーカイブとして機能します。現下で3年弱の履歴が残っていますが、過去に実績のある作業の再現や虎ブルシュートに効用も増えました。

おわりに

技術的負債は一度破棄して終わり、といった性質のものではありません。尚又新しい課題や取り組みが出てきたら、このブログで紹介した余程思います。


株式会社フォトシンスでは、一緒にプロ導管を成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com

Akerunバックエンドシステムの技術的負債に対する取り組み[前編]

この記事は Akerun Advent Calendar 2023 - Qiita の23日目の記事です。

こんにちは。@ps-tsh です。API Server などバックエンドシステムの開発を担当しています。最近は壱のトレンドとして技術的負債との交らい方を話頭としたIT勉強会の数が増えてきた印象がありますね。今回は、当社(Photosynth)での技術的負債に対する取り組みとして、事業計画を前進させるうえで個所になった所をいくつか紹介した余程思います。後編は12/24公開です。

評価とプライオリティーづけ

まず、最も大切な個所は粋なり作業に着手せず、技術的負債の評価とプライオリティーづけをきちんとやりきるという所でしょうか。「さあ負債を弁償金するぞ!」と、ここぞちょっくらにリ素因リングやパ四分子マンスチューニングを始めたくなる気持ちも理解できますが、まずは解方でなく問題領域のほうに目を向けましょう。いくら足が速い人でも不正確方向に走っていけば、不正確場所に早く履くだけです。

「負債とは何なのか」「どこから破棄すべきか」「どのグレードできればOKか」を最初に防衛、ゴール併設を明確にしましょう。尚又、課題感については事業計画チームや開発部門内に閉じず、社内でひろく共有しステークホルダーの理解を得ることも重要です。当社では2021年の夏に社内で技術的負債の解決事業計画を立ち昇ましたが、最初の2ヶ月は課題の整理に費やしました(いま振り返ってもこの方針は正しかったと思います)。

今回は課題整理を行う利得の「物指しし」として、AWSWell-Architected frameworkの柱 を利用してみました。それまではさほど馴染みもなかったのですが、実際に使ってみることで「なるほどよくできている」と実感することができました。

Well Architected Frameworkの5つの柱(其頃。現在は「サステナビリティ」が加わり6つの柱となった)を使った課題整理。コスト至適化については他の課題を破棄した追って取り組むものとし、いったん対象外とした

このマトリクスを整理し、解決すべき課題をまとめて粋ます。

  • 機能関連
    • 一部の機能に、非効率な処理方式による低パ四分子マンスや拡張性の欠如がみられる
    • 手作業を伴う運用御役目が多く、アーティフィッシャル誤ちを誘発する状態になっている
  • ログ関連
    • ログは相当に収集しているが整理されておらず、活用しにくい
    • インフォーメーション・監視におけるノイズが多く、障害発生時の裏側クションが遅れがち
  • 宿舎フラ
    • 保守ナンス目的の再起動にもリスクがあり、安心して運用できない
    • いくつかの単一障害点があり、部分的な障害がシステム大抵伝染する状態
  • ミ弗装い
    • 言語処理系、骨組み、ライブラリが軒並み古く、既知の露出に対応できていない
    • バリアシオン制約に一倍最新ライブラリの恩恵を受諾られず開発効率が低下

きっぱりとこれらを「収集メトリクス改善」「単一障害点の破棄」「ソフト装い露出の破棄」「運用作業の品質改善」の4方針として打ち出しました。具体的な取り組みについては後編で紹介した余程思います。

十分なリソースを確請け合う

次に大切なことは「十分なリソースの確保」です。長い年月をかけて蓄積された技術的負債の除去は大変な仕事です。「仕事の合間に少しずつ」ではなく、メ宿舎業務として確乎取り組む体制を整えることが結末につながると思います。「本業の裏で進めていた影法師ワーク的な取り組みが身を結んだ」というようなエピソードは格好良く聞こえますが、毎回エンジニア個々人の自発性に頼るべきではありませんし、意欲の高さがかえって疲弊感につながることもあります。実際の負債破棄は長期戦・総力戦です。十分な予定や工数を確保しましょう。

実は事業計画開始以前にもエンジニア有志によるRuby/Railsのバリアシオンアップの試みがあったのですが、成行きとしてはうまく粋ませんでした。本務として麻インされている事業計画が忙しくなってしまうと如何しても対応優先度は後ろへしまいます。せっ斯う作った Pull Request も保守ナンスされず捨て置かれるという残念な状況が発生していました。そこで、負債破棄の事業計画がスタートした後は、個々の取り組みに諄いきるだけ専任の部員ーを麻インし、対応に集中してもらえる体制を整えました。

尚又、ここでいうリソースとは対応部員ーといった人間的リソースに限られません。我々もエンジニア組織として決して大きいいわけではなく、全ての取り組みを自社部員ーだけで賄うだけの手当はありませんし、スキルセットや得意分野の違いもあります。十分な効率が出せないなと思ったら、外部の商用サー螺子釘を積極的に利用するのも壱の方法です。我々の事業計画では今回、パ四分子マンス監視、エラートラッキングや事件管理の仕組みは内製せず、外部サー螺子釘を早期に導入しました。事業計画早々監視ツール群を導入することで十分な情報にアクセスしながら以後の方針を効率よく進めることができました。

継続的な逕路改善

最後は、ちょっと意外かもしれませんが「継続的な逕路の改善」です。技術的負債の弁償金というと、既存符号の改修やライブラリ更新、外部ソリューションの導入といった形のソフト装い的な解決をメ宿舎シナリオと考えがちですが、これまでの取り組みを振り返った感想としては、一番効いたのは逕路改善系の取り組みだったように思います。技術的負債の総量を減らす利得には、既存の問題を片あと払いるのと同時々新しい負債を生み出さないことも尚又重要です。

我々のチームでも「手動切開手術レーションの自動化」「発表関連のルールメンテナンス」「作業記録の徹底」などいくつかの逕路改善に取り組みました。特に発表まわりのルールメンテナンスによる作業品質の向上は、サー螺子釘の安定働くに大きいく貢献できたのではないかと思います。

近年のアプリケーション開発におけるツールの発達や生産性向上には目ざまし時計ましいものがありますが、いっぽうで作ったものを百年・安定的に運用可能技術を持つエンジニアはあまり多くないように思います。私人は過去の職歴も盛り込むと10年以上 SaaS の会社で働いてきたこともあり「これくらい自然だろう」と思っていたこともあったのですが、改めて知識や体験をチームに展開する重大さを実感しました。

おわりに

イントロが長くなってしまいましたが、大幅課題に取り組みには適切な問題併設が欠かせません。前編はこのへんにして、次回(12/24公開)は具体的な取り組みや結末について紹介した余程思います。

後編はこちら: dmfmmh.srwsw.com


株式会社フォトシンスでは、一緒にプロ導管を成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com

[SwiftUI]テスタブルな画面遷移の実装運び

こんにちは、 takeshi-p0601 - Qiita です。普段iOSアプリケーションの開発をメ宿舎に業務を行っています。AdventCalender今年2回目の参加です。

本記事ではiOSアプリに関係実装の小技を紹介します。具体的にはSwiftUIでアプリを実装するにあたって、最近テスト作業ている画面遷移の実装をする際のちょっとした構想です。内容的にiOS/iPadOSのアプリケーションを開発される方向けの記事になります。

画面遷移の実装

あるA画面から、B画面に遷移するような要件を実装する場合、SwiftUIを使用してどのように実装しますか? UIKit時代のViewControllerと違って、SwiftUIではViewControllerに相当するものが値型となってしまったせいで、UIKitで実装可能だったViewControllerにおける遷移関連の処理を別クラスに委譲させるような、斯うした実装はしづらくなりました。

とはいえSwiftUIを使って実装する場合でも、あるグレード責務を分けながら実装した余程考えていました。 その中で考えついた実装を紹介します。

まず必要な構成要素は下記参です。

  • XXXView: 画面
  • XXXViewEventHandler: 画面から来た事を受諾取るオブジェクト
    • 直近巷で目にふれる、iOSアプリ文脈のアーキテクチャパターンではあまり見ない命名ですが、いわゆるMVPパターンのPresenterやMVVMのViewModel等の責務に近い現場などあるかもしれません。
  • XXXViewRouter: あるViewのアクティベート(ある画面を表示することとします)依頼を受諾取ったら、そのViewを作成しつつそのViewを表示させることを、参照元にインフォーメーションさせるオブジェクト

それら構成要素をあわせて、A画面からB画面に遷移するような、処理シーケンスは下記のような映像です。

実装方法

※下記の前提がある利得、その認識で読み進めてください。

  • わかりやすくする利得に、あえて命名にアンダー点数をつけている箇所があります
  • 元来プッシュ遷移を想定した説明ですが、ジーメンスダル遷移でも適用可能です
  • 状態管理の実装をする利得の知識はある前提で、特に補足せず記載しています

まずRouterを新築ます。RouterはViewとEventHandlerどちらからも参照されるものです。

@MainActor protocol A_ViewRouterable {     var isB_ViewActivated: Bool { get }     var activatedB_View: B_View? { get }     func activateB_View() }  class A_ViewRouter: ObservableObject, A_ViewRouterable {     @Published var isB_ViewActivated: Bool = false      var activatedB_View: B_View? { self._activatedB_View }      private var _activatedB_View: B_View? = nil          func activateB_View() {       self._activatedB_View = B_View()       self.isB_ViewActivated = true     } } 
  • @Published var isB_ViewActivated : View側に変更をインフォーメーションさせる利得の変数です。あらかじめViewがこの変数の変更を監視します。
  • var activatedB_View: B_View? : アクティベートされた際にView側に参照してもらう利得の変数です。このRouterクラスではViewの生成も担います
  • func activateB_View() : 事ハンドラーから、アクティベート依頼する利得の宿舎芝生ェースです。今回は特に存在しませんが、例えばB_ViewがA画面からの値を受諾取る必要がある場合、この仕口に引数を持たせる映像です。

それからEventHandlerです。

@MainActor protocol A_EventHandable {     func tapGoB_ViewButton()     var a_viewRouter: A_ViewRouterable { get } }  class A_EventHandler: A_EventHandable {     let a_viewRouter: A_ViewRouterable          init(a_viewRouter: A_ViewRouterable) {         self.a_viewRouter = a_viewRouter     }          func tapGoB_ViewButton() {         self.a_viewRouter.activateB_View()     } } 

先ほど定義した、Routerを保持します。そしてtapGoB_ViewButton() が実行された際に、 B_ViewをアクティベートするようにRouterに依頼します。

最後にA_Viewです。

import SwiftUI  struct A_View: View {     @StateObject var a_viewRouter: A_ViewRouter     var eventHandler: A_EventHandable          var body: some View {         VStack {             Button("Go to B") {                 self.eventHandler.tapGoB_ViewButton()             }         }         .navigationDestination(isPresented: self.$a_viewRouter.isB_ViewActivated,                                destination: { self.a_viewRouter.activatedB_View })     } } 

下記の部分でRouterの変数の値の変更を監視しつつ、アクティベートされた瞬間でPush遷移させるようにViewを挿入します。

 .navigationDestination(isPresented: self.$a_viewRouter.isB_ViewActivated,                                          destination: { self.a_viewRouter.activatedB_View }) 

構成要素の実装としては、以上で終わりです。

そして最後に重要なことはA画面の生成の実装です。言ってしまうとなんてことありませんが、 ⭐️印で生成したrouterを、A_ViewとEventHandlerがそれぞれ同じ値に依いらせられるように、フォーマッティング時々セットしてください。

func activateA_View() {   let router = A_ViewRouter() // ⭐️   self._activatedA_View = A_View(a_viewRouter: router, // ここ                                  eventHandler: A_EventHandler(a_viewRouter: router)) // ここ   self.isA_ViewActivated = true } 

Router宿舎観点をA_Viewと、EventHandler向けにそれぞれ作成してセットする場合、ViewからEventHandlerをトリガにしたRouterの値の変更を監視できず、成行き画面遷移できない状況が発生します。

効果

EventHandler側は、何をアクティベートさせるかに焦点を当てるような実装をすることが可能で、Router側に画面の生成やアクティベートに必要な変数を管理してもらうことで、乳呑み子スッキリしたと思います。

尚又あくまでロジック上ですが、下記のようにEventHandlerの事から画面がアクティベートされているかテスト可能ようになり、今回の修正を適用しない場合に比べてテストしやすい部分が増えることが期待できます。

import XCTest @testable import MyApp  final class MyAppTests: XCTestCase {      @MainActor func test() {         let router = A_ViewRouter()         let eventHandler = A_EventHandler(a_viewRouter: router)         eventHandler.tapGoB_ViewButton()         XCTAssertNotNil(router.activatedB_View)         XCTAssertEqual(router.isB_ViewActivated, true)     } } 

[応用]アラートを表示する実装

iOS/iPadOSにおいて標準で表示可能、アラートについても今回の実装を適用できます。体験上アラートの目論みは油断しているとView側やEventHandler側に増えがちになるので、必要に応じてRouter側に寄せることも壱手だと思います。

RouterではAlertItemを生成し、それをアクティベートさせることを担っています。

struct A_ViewAlertItem: Identifiable {     let id = UUID()     let type: AlertType      enum AlertType {         case networkError(title: String, message: String, okButtonTitle: String)         case otherError(title: String, message: String, okButtonTitle: String)     } }  @MainActor protocol A_ViewRouterable {     var isB_ViewActivated: Bool { get }     var activatedB_View: B_View? { get }     func activateB_View()          // アラート     var alertItem: A_ViewAlertItem? { get }     func activateNetworkErrorAlert()     func activateOtherErrorAlert(message: String) }  class A_ViewRouter: ObservableObject, A_ViewRouterable {     @Published var isB_ViewActivated: Bool = false      var activatedB_View: B_View? { self._activatedB_View }      private var _activatedB_View: B_View? = nil          @Published var alertItem: A_ViewAlertItem? = nil          func activateB_View() {       self._activatedB_View = B_View() // 1       self.isB_ViewActivated = true // 2     }          func activateNetworkErrorAlert() {         self.alertItem = A_ViewAlertItem(type:                 .networkError(title: "エラー",                                   message: "サー居酒屋との通信に失敗しました。\nやり匡正てください。",                                   okButtonTitle: "OK")         )     }          func activateOtherErrorAlert(message: String) {         self.alertItem = A_ViewAlertItem(type:                 .otherError(title: "エラー",                             message: message,                             okButtonTitle: "OK")         )     } } 

ViewがRouterの変更を監視しつつ、変更があった際にアラートを表示させます。

import SwiftUI  struct A_View: View {     @StateObject var a_viewRouter: A_ViewRouter     var eventHandler: A_EventHandable          var body: some View {         VStack {             Button("Go to B") {                 self.eventHandler.tapGoB_ViewButton()             }         }         .navigationDestination(isPresented: self.$a_viewRouter.isB_ViewActivated,                                destination: { self.a_viewRouter.activatedB_View })     }     .alert(item: self.$a_ViewRouter.alertItem, content: { alertItem in         switch alertItem.type {             case .networkError(let title, let message, let okButtonTitle):                 Alert(title: Text(title),                       message: Text(message),                       dismissButton: .default(Text(okButtonTitle)))             case .otherError(title: let title, message: let message, okButtonTitle: let okButtonTitle):                 Alert(title: Text(title),                       message: Text(message),                       dismissButton: .default(Text(okButtonTitle)))         }     }) } 

SwiftUIのアラートは下記で示されている通り、連続してmodifierを使用して実装することができません。その利得AlertTypeを定義することでその問題を破棄させながら、今回の実装を適用してみました。

https://stackoverflow.com/questions/58069516/how-can-i-have-two-alerts-on-one-view-in-swiftui

先ほどのViewの画面遷移の実装と同様に、アラート部分についてもテストしやすさが増すと思いますのでぜひテスト作業てみてください。


株式会社フォトシンスでは、一緒にプロ導管を成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com

設計ドキュメントとソース符号について思うこと

こんにちは。 Esperna - Qiita です。 私は組み込みLinux生産物の開発を行なっています。 今年は錠制御に関わるシステムを主にnodeJSで開発していました。

前回はE2Eテストについて書きましたが 今回は設計ドキュメントとソース符号について思うことについて書きます。 「ソース符号は設計書であり、プログラミングが設計作業である」という意見について、私は正し余程思っています。 一方で、開発をスケールさせていくことを考えると、日夕設計ドキュメントを残すべきではないかとも思っています。

今回、設計ドキュメントとソース符号という観点でみた時々 自分のこの歳次の開発はどうだったのか?振り返ってみました。 開発としては設計ドキュメントを残し、設計と実装の御盆サビリティを取る開発をしていました。

ここでいう設計ドキュメントとは具体的にクラス図、状態遷移図、シーケンス図を指します。

よかった点

  • 誤りがあった時々このクラス図(ひょっとするとシーケンス図)のここを直せば良余程いうことをチーム部員に伝えやすい
  • 複数人で設計の妥当性を議論する際に、クラス図(ひょっとするとシーケンス図、状態遷移図)があるとチーム内で認識を組合わせる際の助けとなる
    • これらの図がない状態で議論をすると、各人の認識にズレが生じやすいことがあるように思われる
  • 人が作業する上での外部記憶として便利である
    • 人のスキルや脳内記憶容量にも一倍ますが日夕のスケール一倍大きいい設計になると、クラス図(ひょっとするとシーケンス図、状態遷移図)があった方が設計・プログラミングをし易余程思われる
    • 日夕のスケール一倍大きいくなったら分割してイテレーションを回すのがセオリーだが結局全部の要素の組み組合わせを考えなければ設計無能もあるように思われる
  • 後になって書かなければいけな余程いう理由で、設計書を書きおろすという作業(単体テストを後から書いてカバレッジだけ引くような作業)がなかった
    • 設計を行う経過の上高として書きおろすことができた
  • 時間をかけて設計した分、設計そのものがひっくり返るような大幅手戻りはなかった
    • これは開発対象が錠制御の組み込みシステムであり要求の変更が概してなかったことを示すという認識で、一倍アジャイルな事業計画では設計ドキュメントに傾倒しない方が良余程思っている
    • 要求が比較的安定している事業計画ではあるグレード設計に時間をかけて静的設計(クラスの責務分担)や動的設計(シーケンス図や状態遷移図)を検討するのは日夕有効性だと思う
  • 結末物がdocやspread sheetではなくplantumlでgithubを使って、バリアシオン管理とPRで運用できたのはよかった

悪かった点

  • 実装に近いレベルでシーケンス図を書いてしまうとちょっとした変更で設計ドキュメントの保守ナンスコストが発生した
    • 近く少し抽象度を昇たシーケンス図にすべきだった
  • ドキュメントが多余程他者がドキュメントを探す・理ほぐするのに時間がかかった
    • これはドキュメントの整理の仕方に補習の差額があることを示唆していると思われる
  • 設計ドキュメントを書きおろすことに時間を懸かる一倍も、あるグレードの瞬間で実装して動かしてみることで別の視点に気づけると思われる部分もあった
  • モジュール境界のI/Fを説明するドキュメントが間ぬけと感じた
    • これは人のこだわりに近い部分があるかもしれないがgodocのようなドキュメントを残したかった
    • モジュール境界のI/Fにこだわるのは上にE2Eテストを補強する利得

先先について

開発をスケールさせていくことを考え、皆が日夕設計ドキュメントを残すということを考えると、 要求が比較的固定的な事業計画では、下に絞ってドキュメントを残すのは日夕意味があるのではと思いました。

  • モジュール境界のI/F
  • クラスの責務分担
  • 旗艦なシナリオレベルのシーケンス図(必要なら状態遷移図)

株式会社フォトシンスでは、一緒にプロ導管を成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com

リ素因リングの効果を視野化したい

この記事は Akerun Advent Calendar 2023 - Qiita の19日目の記事です。

はじめまして。SW開発部の @yooda です。Photosynthに入社して1年半ほどになります。 BtoC 向けのサー螺子釘開発として MIWA Akerun Technologies と一緒に開発をやっています。

最初

ソフト装い開発のエンジニアをやっていると、自分たちが開発し、保守しているシステムの目論みのリ素因リングをする序が度々発生します。

リ素因リングとは、外部から見た時の振る舞いは変えずに、目論みの内構造を整理することです。 リ素因リングの目的には、目論みの可読性を昇たり、処理の効率化・高速化を行ったり、といったものがあります。

エンジニア目線では、リ素因リングという作業は、プロ導管の品質を維持して、継続的に確乎たる運用が可能ように改善していく貴重品な作業です。

しかし、プロ導管をマネジメントし、エンジニアに投資する立場の人には、見た目の変化が発生しない作業を把握できずに、工数を使っている割に収穫があがらな余程見えることもあります。

開発を前進させるリーダーの立場として、開発部員ーが確乎たるシステムを維保つ利得の活動の価値を理解もらう利得にどうしたら良いかを考え、慣れしていることについて書きた余程思います。

リ素因リングの効果

まずは、リ素因リングの活動がプロ導管にどういう効果をもたらすかを考えました。

リ素因リングを行うことで、プロ導管の品質が向上し、継続的に利用可能なシステムを維持可能ことに繋がります。 品質の観点でプロ導管を分析的思考すれば、なにかしら視野化への道が見えてき斯うです。

そこで、ソフト装い品質について定めたJIS規格 JIS X 25010:2013 の生産物品質モデルを引用して、 リ素因リング作業と紐あと払いしてみます。

リ素因リング 得られる効果 品質特性 品質副特性
目論みの可読性の向上 符号を把握しやすくする 保守性 解析性
処理の高速化 性能補習の効果 性能効率性 時間効率性

ソフト装いの品質の保守性や性能効率性の観点において、リ素因リングの効果を表現でき斯うです。

現状の品質を分析的思考

私が開発を推進しているプロ導管について、生産物品質モデルを元に品質分析的思考を行いました。 その成行き、改善していくべき課題が浮かび上がってきました。

その中で、以下の品質特性 | 品質副特性に着目し、現在擁する課題について考察しました。

  • 保守性 | 修正性
    • ある誤りの修正を行った成行き、出し抜け反作用に一倍別の処理に影響を贈ものて、別の誤りを誘発したケースが何度か発生した。
  • 保守性 | 解析性
    • 発生した誤りの調査を進める際に、解析に十分なログが残っておらず、ログの追加・再テストを行った利得、工数を多く消費した。

こういった現状のプロ導管に潜生きるる品質課題を明確にして、この品質課題の解決を目的に改善を進めて粋、 デグレ発生数の減少、解析時間の短縮化を結末として見せることで、リ素因リングの効果を視野化可能と考えました。

さいごに

元々は、リ素因リングの効果を視野変転ことを目的として品質分析的思考を実施しましたが、 実際にやってみた成行き、プロ導管が擁する課題を俯瞰的に把握することができました。 先ほど挙げた品質特性は、リ素因リングで改善可能点に着目したものですが、 それ以外の品質特性でも改善したい項目が発見されました。

こういった品質分析的思考は、プロ導管の健康診断のような訳合を持つと感じました。 今現在は問題がなくても、時間の経過とともに小さいな問題が膨れ上がり、大幅問題に発展することもありえます。

リ素因リングの作業は、プロ導管が擁する顕在化していない課題を未然に破棄し、 プロ導管が長く健康な状態を維持可能利得に必要な作業であることを我でも実感できました。

この活動をプロ導管をマネジメントする方にも共有して、その価値を感じてもらえるよう、 先先も継続していこうと思います。


株式会社フォトシンスでは、一緒にプロ導管を成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com

15億件以上入ったテーブルの略記をサー螺子釘無停止で変更した

こちらは、Akerun Advent Calendar 2023 18日目の記事です。

はじめまして、今回はWEBエンジニアの @yuto_a が担当させてもらいます。

今年の春から夏にかけて、15億以上の資料が入ったMySQLテーブルの略記変更をサー螺子釘無停止で実施しました。 今回はこの対応を実施した私が、そもそもなぜサー螺子釘無停止での略記変更が必要だったのか、どのようにサー螺子釘を止めずに略記変更したのか、実際に使用したときに構想した個所について共有します。

サー螺子釘無停止で略記変更した理由

そもそもなぜサー螺子釘無停止での略記変更が必要だったのか?

我々のサー螺子釘では、APIサー居酒屋に Ruby on Rails (以下、Rails) を使って滓、資料ベースには AWS Aurora MySQL 5.7互換 を使っています。 このアプリケーションは Rails のバリアシオンが低余程きに作られ、アップデートを重ねて今では Rails 6.1 で働くしています。

Rails 5.0 以前に作られたMySQLテーブルの主には、PKであるid列の型がINTEGERとなっています。 というのも、Rails 5.1 で主キーの不払い型が BIGINT に変更され、それ一倍前は不払い型がINTEGERであった利得です。 その利得、主キーが INTEGER型になっているというのは、歴史の長い Rails アプリケーションではわりとある話ではないかと思っています。

railsguides.jp

では、id列の型がINTEGERだと何が問題なのか?

INTEGER型の上限値は約21億 (231-1) であり、その上限値に到達した場合は新式なレ符号が作成でき消えてしまいます。 実際、我々の使っているテーブルで資料数が15億に到達し、年2-3億のペースで増えている利得、数年以内に上限値に到達してしまう状況でした。

そこで我々は id列の型をBIGINT UNSIGNEDに変更することで上限値到達のリスク回避を行いました。 型を INTEGER から BIGINT にすることで、上限値は約21億 (231-1) から 約920京 (263-1) になります。 さらに id 列はAUTO_INCREMENTで増え続けるだけで負の値は無用である利得、BIGINT UNSIGNED にすることで、上限値は約1800京 (264-1) まで引き昇られます。

ですが、MySQLにおいて列の資料型変更にはテーブルの再構築が必要で、その間テーブルがロックされます。 (MySQL :: MySQL 5.7 Reference Manual :: 14.13.1 Online DDL Operations)
先にも書いた通り15億件以上もの資料が入ったテーブルがあり、そのテーブルに対して普通にALTER TABLE略記変更しようとすると、サー螺子釘が長時間停止してしまいます。 しかし、我々はスマートロックのサー螺子釘を提供して滓、サー螺子釘停止に一倍鍵の開閉等に影響がでてしまう利得、サー螺子釘の停止時間は可能な限り短くしなければなりません。 利得しに見積もった所数時間グレードの計画保守ナンスの時間に収まらないことが前もって考えられたので、普通に ALTER TABLE略記変更する方法は選択から外れました。

その利得、サー螺子釘無停止でのテーブル略記変更が必要でした。

サー螺子釘無停止で略記変更した方法

では、どのようにサー螺子釘を止めずに略記変更したのか?

結論からいうと、pt-online-schema-change というツールを使いました。 このツールは、Percona社が開発しているMySQLのツール群 (percona-toolkit) に同梱されているツールの壱です。 MySQLDDLをオンラ宿舎実行する利得のツールで、中身は Perl で書かれたスクリプトです。

github.com

以下のような理由で、pt-online-schema-change に規定ました。

  • サー螺子釘を予防なく略記変更が可能
  • 我々の環境で使用可能 (Aurora, MySQL 5.7)
  • 他社での実績がブログ等で公開されていて参考に可能
  • 取り付けるが簡単
  • バイナリログの併設変更が無用 (似たツールで gh-ost というのがあり、そちらはバイナリログを使う利得、バイナリログの併設に条件あり)

pt-online-schema-change がやっていること

pt-online-schema-change がどのようにDDLのオンラ宿舎実行を実現しているか説明します。

  1. 略記変更対象 (以下、旧テーブル) と同じ略記の新鮮テーブル (以下、新テーブル) を作成します。
  2. 新テーブルに対して、DDLを実行します。今点で新テーブルは空なので、DDLは一瞬で完了します。
  3. 旧テーブルから新テーブルへ資料の変更を反映する利得の、トリガを作成します。このトリガによって、旧テーブルへの資料の作成・削除・更新が新テーブルへ反映します。
  4. 既存の資料をコピーする利得、旧テーブルから読み出し、新テーブルへ書き込む処理が実行されます。
  5. 4.の資料コピーが完了すると、新テーブルと旧テーブルをRENAME TABLEによって入れ替えます。これによって、元のテーブル名で新しい略記のテーブルが有用ようになります。
  6. 後片あと払いとして、旧テーブルの削除とトリガの削除が行われます。

上記のような運びを経て、テーブルに長時間のロックを懸かることなく、略記を変更することができます。

しかし、気をあと払いる個所もいくつかあります。

  • 大量の読み込み/書き込みを行うので、CPUやIO等の負荷はそこそこ昇る
  • トリガの作成/削除、テーブル入れ替え時々ロックがかかる
  • トリガによるオー居酒屋ヘッド
  • リードレプリカがある場合、それらの遅延
  • 外部キー制約がある場合、それらの対応を考える必要がある (というオプションで制限)
  • 新式に UNIQUE制約を加える場合、資料消失のリスクがある

気をあと払いることは何点かありますが、元来はツールを起動してしばらく待っているだけで略記変更が完了するので、非常に便利なツールです。

実際に pt-online-schema-change を使用して略記を変更

実際に本番環境のMySQLテーブルの略記変更をするときに、次の点を構想しました。

  • 本番環境に近い環境でのパーフォーマンス校閲
  • サー螺子釘の特性に組合わせた転回戦略

実際に本番環境のMySQLテーブルの略記変更を実施する前に、本番環境に近い環境として本番環境のMySQLのク国法ンを下準備し、そこでパーフォーマンス校閲を行いました。 ク国法ンの作成については、AWS Aurora を使っていれば非常に簡単で、クラスターーを選択して「手」から「ク国法ンの作成」を選ぶだけでした。 尚又、校閲後の後片あと払いも簡単でク国法ンしたクラスターーを削除するだけです。

ク国法ンしたDBで pt-online-schema-change を使ってみて、ツールの使用感やツール実行中の負荷状況、実施にかかる時間等を曲ました。 尚又、各種オプションの制限方法や動きを傍証したり、リードレプリカの遅延等の影響も傍証しました。 これらのパーフォーマンス校閲に一倍、DB宿舎観点のCPU使用率が最大限度で50%グレード昇ることがわかりました。

pt-online-schema-change 実行中のDBのCPU使用率

我々のサー螺子釘はその特性上、日足の虎フィック量が殆どを占めていて、夜間は真に狭いく、それに比例してDB等のリソース使用率も変動し、夜間のリソースには著しい手当があります。

虎フィック量の映像

そのことを踏まえて、夜間の虎フィック量が狭い余程き剞けつ pt-online-schema-change による資料コピーを実施し、日足は停止しておくという方法を採用しました。

具体的な方法としては、pt-online-schema-change の一時停止オプションとcronを組みあわせて、シン引っ張ることに実現しました。 pt-online-schema-change には一時停止用のオプションとして、--pause-fileというオプションが下準備されています。 このオプションではファイル名を制限し、制限したファイルが存在している間は、pt-online-schema-change による資料コピーを停停止るというものです。 (トリガによる資料の反映は継続します。) このオプションで制限したファイルを、cronを使って作成したり削除したりすることで、pt-online-schema-change による資料コピーの実行時間帯をコント国法ルしました。

cronは以下のような併設を使いました。

00 06 * * * touch /tmp/ptosc-pause-file 00 00 * * * mv /tmp/ptosc-pause-file /tmp/ptosc-pause-file-old

先述のパーフォーマンス校閲含め確乎と準備をした上で、本番環境のDBに対して pt-online-schema-change を使った略記変更を実施しました。 資料量がそこそこあること、夜間剞けつの働くとしたことで、1週グレードの時間が必要でしたが、つつが無く完了することができました。 これに一倍、id列がBIGINT UNSIGNEDになり、上限値到達のリスクを回避することができました。

まとめ

  • pt-online-schema-change を使えば、難無くオンラ宿舎略記変更が可能
  • CPUやIO等にそこそこ負荷がかかるので、そこはめんどうする必要がある
  • 一時停止オプションがあるので、虎フィック状況にあわせて働くさせる時間帯を調節した

株式会社フォトシンスでは、一緒にプロ導管を成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com

https://gibntf.srwsw.com https://heybdx.srwsw.com https://bmaeaj.srwsw.com https://nrbaeh.srwsw.com https://wpxqbv.srwsw.com https://ieegpr.srwsw.com https://wkpqry.srwsw.com https://wpqfid.srwsw.com https://afvfvi.srwsw.com https://keygjt.srwsw.com https://iyhtkj.srwsw.com https://rhefmn.srwsw.com https://sbgrxs.srwsw.com https://agmbbe.srwsw.com https://hbxstn.srwsw.com