ゆめみインターン参加レポート

2/16-2/29の平日、合計9日間にわたる、株式会社ゆめみのiOSインターンシップ参加レポートです。

ゆめみインターン参加レポート

2/16-2/29の平日、合計9日間にわたる、株式会社ゆめみのiOSインターンシップ参加レポートです。

フルリモートだったので、写真がありません!!

今回は、研修セッションへの参加でした。

ゆめみの研修課題

ゆめみが、GitHubで公開しているiOSの研修課題は、現在2つあります。

1つ目は、yumemi-inc/ios-engineer-codecheckです。

GitHub - yumemi-inc/ios-engineer-codecheck: This is a code check task for iOS engineers employment in YUMEMI.
This is a code check task for iOS engineers employment in YUMEMI. - yumemi-inc/ios-engineer-codecheck

これは、今回のインターンに参加する前に課題として提出しました。

GitHubのAPIを使ってリポジトリを検索するアプリのリファクタリング課題です。

Issueが用意されており、2週間でResolveしていきます。

提出後には、合否に関わらず、エンジニアによるコードレビューが行われ、コメントが送られてきます。うれしいですね。

UIフレームワークにUIKitが使用されており、UIKitの経験値が不足している身としては難しい課題でした。

UIKitに普段触れることがあまりないので、いい経験となりました。

2つ目は、yumemi-inc/ios-trainingです。

GitHub - yumemi-inc/ios-training: 株式会社ゆめみ iOS研修
株式会社ゆめみ iOS研修. Contribute to yumemi-inc/ios-training development by creating an account on GitHub.

今回取り組んだのはこちらの課題です。

研修スタート

リポジトリ内のSwift Package "YumemiWeather" のAPIを使って、天気予報を表示するアプリを作成する課題です。

Documentation

技術トピックごとに分かれた15のセッションを順番に、PRを出して、エンジニアのコードレビューを受け、修正し、マージするという形で進めていきます。

この研修課題はUIKitを前提として作られていますが、今回は、SwiftUIを使ってこの課題に取り組むことに。

UI構成

SwiftUIなのでサクッと終わるかと思いきや、いろいろと制約が多く、最初はかなり複雑な構成となりました。

レビューで、.containerRelativeFrameモディファイアが使えるという指摘をいただきました。

containerRelativeFrame(_:count:span:spacing:alignment:) | Apple Developer Documentation
Positions this view within an invisible frame with a size relative to the nearest container.

Viewのframeを相対的に決定できるモディファイアです。

iOS17から使える新機能ということで、新しい発見でした。

これを使う前は、GeometryReaderなどを用いており、かなり複雑になっていました。

親Viewの大きさを意識せず、そのViewのframeを相対的に決められるので、非常に便利でした。

Error

APIの呼び出し時のエラーハンドリングと、そのエラーをどのようにユーザに伝えるかというトピックです。

エラーハンドリングは自分の中で課題だと思っていたので、この機に徹底的に考えることができてよかったです。

難しかった点は、どのようなエラーメッセージを表示するかについてです。

Appleは、アラートのベストプラクティスをHIGに定めています。

Alerts | Apple Developer Documentation
An alert gives people critical information they need right away.

エラーメッセージはいつもlocalizedDescriptionをそのまま使用していたので、今回はすごく考えさせられました。

最終的には、タイトルは、シンプルな文章で固定にしました。説明文は、localizedDescriptionを使用するようにし、YumemiWeatherがthrowするErrorをLocalizedErrorに準拠させて、errorDescriptionを設定しました。

LocalizedError | Apple Developer Documentation
A specialized error that provides localized messages describing the error and why it occurred.

.alertモディファイアで、isPresentedの型がBinding<Bool>である理由もよくわかったので、面白かったです。

alert(_:isPresented:presenting:actions:) | Apple Developer Documentation
Presents an alert using the given data to produce the alert’s content and a text view as a title.

JSON

JSONをエンコード・デコードする時に、keyEncodingStrategy/keyDecodingStrategy, dateEndocingStrategy/dateDecodingStrategyのオプションを指定することができます。

keyEncodingStrategy/keyDecodingStrategyを.convertToSnakeCase/.convertFromSnakeCaseにすることで、snake_caseのキーをエンコード・デコードすることができます。

また、dateEncodingStrategy/dateDecodingStrategyを.iso8601にすることで、ISO8601形式の日付を変換することができます。

エンコーダとデコーダの責務をどこに持たせるかということについて悩みました。

最初は、Weather、WeatherRequestなど、エンコード・デコード対象のメソッドに定義していました。

最終的には、エンコーダとデコーダの依存をswift-dependenciesで定義して、APIを呼び出すメソッドがそれらに依存する形にしました。

最近は、Bufに依存してるので、このあたりのことは考えなくてよくなってしまっていましたが、学びが多かったのでよかったです。

Scene

SwiftUIでは、@Environment(\.scenePhase)によって今のアプリの状態を取得することができます。

Scene | Apple Developer Documentation
A part of an app’s user interface with a life cycle managed by the system.

.onChangeモディファイアで、変更を検知して、.backgroundから.inactiveに変化した時に、天気予報をリロードするという課題でした。

Foregroundには、.inactiveと.activeがあります。

アプリが起動している状態 (.active) からホーム画面に戻ると、.active -> .inactive -> .backgroundという遷移をします。

ホーム画面にいる状態 (.background) からアプリに戻ると、.background -> .inactive -> .activeという遷移をします。

レビューで指摘された点は、エラーによってAlertが表示されている状態でこの遷移をしたときに、リロードされていいのか、という点です。

Alertが表示されている時にはリロードしないようにするか、Alertを消してリロードするようにするかをしなければ、不自然な動作になります。

実際に修正した内容は後者ですが、今考えると前者の方がより自然ですね。

Unit Test

ユニットテストは、自分の中で課題だと感じており、勉強する機会を求めていました。

そもそもテストは何のために行うのか、テストケースの作り方、書き方、DIについて学びました。

他にも細かい観点でレビューをしていただき、特に収穫の大きいセッションでした。

DIの方法はいろいろありますが、swift-dependenciesを使いました。

GitHub - pointfreeco/swift-dependencies: A dependency management library inspired by SwiftUI’s “environment.”
A dependency management library inspired by SwiftUI’s “environment.” - pointfreeco/swift-dependencies

今まで、TCAで何となく使っていましたが、今回はテストを書いたこともあり、使いこなしてる感があって楽しかったです。

今後は積極的にテストを書いていこうと思います。

Thread Block

UIは、全てメインスレッドで管理しています。

そのため、メインスレッドが別のプロセスで使われていると、UIが固まったまま動かなくなります。

そのため、時間のかかるプロセスを別のスレッドで行うことで、メインスレッドをブロックすることを防ぐという課題です。

Swift Concurrencyを使いました。

APIを呼び出す前に、Viewで持っているisLoadingというステートをtrueにしておいて、APIの処理が終わったらfalseに戻します。

isLoadingがtrueの間は、ProgressViewを表示します。

ここまでは課題の内容です。

工夫した点としては、isLoadingがtrueの間は、Reloadボタンをdisabledにしておくことです。

ListとNavigationStack

これまでのセッションで行なってきたことを、リストに拡張するイメージの課題なので、難しくはありませんでした。

SwiftUIは楽ですね...

合わせてテストも追加しました。

git rebase

普段あまり使うことのない、git rebase。

今回の研修では、多用しました。

PRのレビュー待ちの状態で、そのブランチから新しいブランチを切って次の課題に取り組み、前のPRがマージされたらmainに今の課題のブランチをリベースするという計画です。

しかし、最後の課題が終わっても、最初のPRがマージされていない状態だったので、修正するたびに、直近のブランチまで順番にリベースする必要がありました。

その度に生じる、コンフリクト解消作業。

本当に ~~地獄~~ 良い経験でした。

1度ミスするとそのミスが後のPRにも知らないうちに伝播していく...

本当に ~~地獄~~ 良い経験でした。

今まで、CLIとVSCodeで行なっていましたが、GUIツールを使うことで今の状態が見える化できて少しだけスムーズに進みました。

Fork - a fast and friendly git client for Mac and Windows
Fork - a fast and friendly git client for Mac and Windows

Fork: 教えていただいたGUIツール

研修課題を通して

PRのレビュー待ちの時間ができてしまいました。

しかしその分、レビューがされ次第じっくり考えて取り組む時間が確保できたので、有意義なものとなったと思います。

今まで、こういうケースではどんな書き方がいいんだろうとか、こういうケースでAとBのどちらを使うといいんだろうとか、モヤモヤがありました。

そのいくつかレビューの中でのやりとりによって解消されたのでよかったです。

また、iOS17の新機能など、今まで知らなかった書き方を知る機会にもなりました。

これらがコードレビューしてもらう醍醐味であり、自分のプログラミングスキルを高めていくための大切な機会だと思っています。

勉強会

ゆめみは、勉強会が多いことで有名 (?) です。

その密度に社内の勉強会カレンダーをみて驚きました!

毎週定例で行われているものが多く、中でも、熊谷さんのやさしいSwift勉強会は、週3回のペースで行われています。

熊谷さんの やさしい Swift 勉強会
Swift 言語の素養を深めるための、株式会社ゆめみ の社内勉強会です。

一部、YouTubeで公開されています。

1回あたり45分程度と、ちょうどいい長さで、Swift言語のトピックについて取り上げています。

難しい説明がときどきありますが、初心者でも入っていきやすいトピックが多い印象です。

自分としては、わからない説明があっても、それをきっかけに調べることができるので、わからずに聞くだけでもかなり面白いです。

Slack・Notion

ゆめみは、Slackが活発なことでも有名です。

SlackのMaturity Scoreが国内No.1企業だそうです。

https://note.yumemi.co.jp/n/necbcd409b7b2

実際に、非常に活発でした。

timesチャンネル的な役割を果たす、1人ひとつのOJT (On the Job Training, たぶん) チャンネルがあり、そこにいろいろつぶやきます。

そのほかにも、今日が誕生日の人が流れるチャンネルがあったり、

というのも、非同期コミュニケーションが非常に上手だと感じました。

ゆめみはフルリモし放題制度があるほど、フルリモートを前提としています。

フルリモし放題制度 ㊗️ MAX

フルリモートを前提としているからこそ、非同期コミュニケーションが前提となっています。

ペアプロなども積極的に行なっており、自分に合わせたスタイルで取り組むことができそうです。

社内外向け多くの情報はNotionを起点にして発信されています。

ゆめみオープンハンドブックもNotionで公開されています。

ゆめみオープンハンドブック
👨‍👩‍👧‍👧チーム

まとめ

今回は研修だったので、実際の業務の内容や進め方、雰囲気などはわかりませんでしたが、今まで自分の中で謎だったゆめみの中の雰囲気が少しだけわかった気がします。

その要因の1つとして、いくつかの定例MTGに参加したことです。

実際のMTGに参加できる機会はなかなかないので、貴重な機会でした。

チームの皆さんをはじめ、暖かく迎え入れていただいたので、充実したあっという間の9日間でした。

ありがとうございました!

リンク

GitHub - kantacky/yumemi-ios-training
Contribute to kantacky/yumemi-ios-training development by creating an account on GitHub.
GitHub - kantacky/yumemi-ios-training-bug-fix
Contribute to kantacky/yumemi-ios-training-bug-fix development by creating an account on GitHub.