はじめに
はじめまして。ヤプリにiOSエンジニアとして2月1日から29日までの1ヶ月間インターンをさせていただいた学部3年の雲下です。
1ヶ月あったものの、2月は祝日も多く、実質稼働は2週間ほどでしたが、その中で得られたことや体験したことを赤裸々にお伝えできればと思います。
なぜヤプリにインターンをしたのか
まず私がヤプリを知ったのは、モバイルエンジニアとして開発を行っていた際に、「いい感じのノーコードツールってないかな」と思い調べた時でした。最初のインパクトとしてはホームページにある通り、私自身が普段利用しているアプリの多くがYappliでつくられていることでした。
そこから、就活が始まり、モバイルアプリエンジニアとして企業選びをする中で、「大規模なプラットフォームであるYappliの中ってどうなっているんだろう」と思い、新卒選考の一環としてインターンに参加することとなりました。
インターン期間中に取り組んだこと
以下の4つについてそれぞれどんなことに取り組んだのかお伝えできればと思います。
アプリ研修
アニメーションUIに関わる動作の改善対応
ゼロトゥワンリンクの開発
成果物の発表
アプリ研修
実際にCMS(管理画面)を用いてアプリを作ります。個人的にはどんな感じでアプリができていくのか知りたかったため、とてもいい経験ができました。
管理画面の使用感としては、「設定が簡潔でわかりやすい」に尽きます。多くの機能がある中で、どの機能も設定する際の画面レイアウトだったり、ボタン等のアクションがわかりやすく、エンジニア関係なくどんな方でもアプリ制作ができるようになっており、とても感動しました。
また、Block UI機能についてはFigmaといったデザインツールのような細かい設定ができたり、レイアウト等のテンプレートが用意されており、作れるアプリの幅が広いなと思いました。
アニメーションUIに関わる動作の改善対応
取り組みのフロー
a. 実際の動きとプログラム、ドキュメントからエラーの内容を把握する
b. プログラムを修正をする
c. 修正内容の動きを確認する
d. a~cを繰り返す
e. 修正が終了したらチームの人にレビューをしてもらう
f. レビューが完了したらQA依頼を出す
今回は以上の流れで改善対応を行いました。レビューを出す前に自分自身では考えきれない部分もあるので、レビューとは関係なくメンターの人にこの修正で大丈夫なのかを積極的に聞くようにしました。
得られたこと・学んだこと
実際のチケットに取り組むと、レビューをするエンジニアのことや、QAのことを考えてさまざまな挙動を予想して対策・改善する必要がありました。したがって、エンジニア視点とユーザー視点の2つを常にもちながら課題が解決できているのかを考えるため、とてもいい経験になりました。
また、メンターの人が修正の内容について「本当にそれで大丈夫?」「このやり方だとどうなる?」とさまざまな視点からアドバイスや疑問を投げかけてくださるので、先入観や固定観念に囚われずに課題解決を考えることができました。
加えて、プルリクエストの作成やQA依頼の作成の際にどのように伝えたら、読む側はわかりやすいのか、確認を行いやすくなるのかを具体例とともに提案してくださるため、文章を作る上で大切なことをたくさん学ぶことができました。
※ここからはiOSエンジニアとして、対応したチケットについて少し具体的に触れていくので、読みたい方は読んでみてください。次の内容はこちらです
問題点
Yappliの機能の一部にLottieを用いてアニメーションを表示し、アクションをカウントする機能があり、そのカウントがうまく動作しないという問題
改修の概要
LottieのAnimationViewのplayメソッドの中でカウントするメソッドを呼び出していたが、そのカウントメソッドをplayメソッドから切り離して、アニメーションが始まる前にカウントするように修正
改修の詳細
元のプログラムの抜粋
struct LikeModel { ・・・ mutating func updateCount(isOn: Bool) { self.isOn = isOn if isOn { count += 1 } else { count -= 1 } } ・・・ } class LikeViewModel { ・・・ func updateCount(isOn: Bool) { datasource.updateCount(isOn: isOn) self.title = getTitle(count: datasource.count, baseTitle: datasource.title) Task { do { _ = try await repostitory.executeLikeAction(action: .init(to: isOn)) sendAnalytics(isOn: isOn) } catch { print("\(#function): LikeActionError:", error) } } } ・・・ } class LikeView: UIView { private var isOn: Bool { viewModel?.isOn ?? false } ・・・ @objc private func setOn(_ sender: UITapGestureRecognizer) { setOn(to: !isOn) } ・・・ private func setOn(to isOn: Bool) { let fromAnimationView: AnimationView = isOn ? onAnimationView! : offAnimationView! let toAnimationView: AnimationView = isOn ? offAnimationView! : onAnimationView! guard let viewModel else { return } toAnimationView.isHidden = true fromAnimationView.isHidden = false fromAnimationView.play { _ in viewModel.updateCount(isOn: isOn) toAnimationView.isHidden = false fromAnimationView.isHidden = true fromAnimationView.stop() } } ・・・ }
1. カウントメソッドをplayメソッドから切り離した理由
playメソッド内のクロージャーでカウントメソッドを呼び出す設計に問題がありました。
具体的には、playメソッドとカウントメソッドが依存関係なく呼び出しが行われるべきでしたが、playメソッドが終了するまでカウントメソッドは呼ばれず、AnimationViewを呼び出す際に作動するトグルが連続の呼び出しによりplayメソッド内のカウントの追加・削除の方には正しく反映されない実装になっていました。
解決策として、カウントメソッドをplayメソッドのクロージャー内から切り出して、連続の呼び出しに対してもカウントメソッド内で正しくトグルが反映されるようにしました。
修正箇所
+ viewModel.updateCount(isOn: isOn) fromAnimationView.play { _ in - viewModel.updateCount(isOn: isOn) toAnimationView.isHidden = false fromAnimationView.isHidden = true fromAnimationView.stop() }
2. アニメーションの開始前にカウントを行う理由
1つ目の理由に関連しており、実行されたplayメソッドの終了を全て待っていると処理が終わり切らないため、1つのplayメソッド実行中に次のplayメソッドが呼び出された場合は、前のplayメソッドの実行を途中で止めるようにしました。
これによってトグルも正しく反映され、呼び出しに合わせてカウントの自然な追加・削除ができるようになりました。
修正箇所
class LikeView: UIView { ・・・ + private var isAnimationPlaying: Bool = false + private var currentAnimationView: AnimationView? ・・・ private func setOn(to isOn: Bool) { + if isAnimationPlaying { + currentAnimationView?.stop() + currentAnimationView = nil + isAnimationPlaying = false + } ・・・ + fromAnimationView.play { [weak self] isFinished in + guard let self else { return } + if isFinished { + toAnimationView.isHidden = false + fromAnimationView.isHidden = true + currentAnimationView = nil + isAnimationPlaying = false + fromAnimationView.stop() + } } } ・・・ }
ゼロトゥワンリンク
概要
「ヤプリでは『失敗を恐れずに新しい挑戦を続けるよう』という価値観(ゼロトゥワン) を大事にしており、エンジニアも新しい機能開発にチャレンジする意識を持つようにしています。」
そういった新機能や改善施策を盛り込んだアプリを気軽に社内配布できるようにするための仕組みとして、本番アプリには影響が出ない、小さなPlayground的なアプリ内導線(ゼロトゥワンリンク)を今回実装してみました。
ゼロトゥワンの詳細については以下の記事を読んでみてください。
やったこと
CMSにおいて、オリジナルのリンクを設定することで、新しい機能やUIを実装したページへ飛ぶことができる
iOS17以降で利用できるAPIやTipKitなどの新機能の実装
影響の大きい部分をモジュールに切り出し、プラットフォーム基盤のYappliにおいても柔軟に組み込むことができる
実装にあたって
私自身、Swift・SwiftUIを触るのは久しぶりではありましたが、楽しく開発できたというのがいちばんの感想です。ゼロトゥワンリンクの実装やデモページの実装は調べたり、他のページの実装を参考にしながら実装したため、スムーズに行えていたと思います。
一方でプラットフォームを提供するYappliだからこそより重要であるモジュールへの切り出しは少し苦戦しました。普段触れない技術の部分だったので、新鮮ではありつつ、やはり実装するのは難しったです。それでも、メンターの方と相談したりアドバイスをいただいたりしながらの開発をして、予定していた通りの実装をすることができました。
モブプロやレビュー会を通して、ヤプリのエンジニアの層の厚さをとても実感しました。高い技術力はもちろんのこと、設計の意図や仕組みを言語化して伝える能力がすごいなと感じました。
成果物の発表
部署ごとにどのようなことをやったのか、成果が出たのかを発表する場(win-session)でインターンの成果物としてゼロトゥワンリンクについて発表をさせていただきました。iOSエンジニア以外の方が多くいたので緊張したものの、自身の発表の前ではユニークなコミカルな発表をしている方もいたので、緊張はほぐれ落ち着いて伝えたいことは伝えることができたのではないかなと思います。
また、多くのフィードバックをいただくことができました。他の部署でどのようなことに取り組んでいるのかを共有する場所がしっかりと設けられており、コメントも盛り上がっていたので、発表の環境はとてもいいと感じました。発表中はSlackにてたくさんのコメントが飛び交っていました。
インターン期間中の社員の方との関わり
参加したもの
パレーボール部の活動
LT会
1 on 1 バトンランチ
開発以外にも社員さんと関わる機会はたくさん用意されており、インターンとして入って実際の会社の様子を一社員かのように体験できるのはとてもいい取り組みだなと思いました。バレー部やLT会は自分から飛び込んで行きましたが、とてもウェルカムな雰囲気でのびのびと楽しむことができました。
1 on 1 バトンランチは人事の方をはじめとして、1 on 1した方が次の人を紹介する形式のもので、会社のことや就活のことや、業務のことなど話題は幅広く、また様々な部署の方とお話しすることができたのでとてもいい機会でした。
このように色々な方と多く触れ合う機会が用意されている環境は個人的にはとてもよく、また、社員の方も部署を横断して関わりを持てているのはいいなと思いました。リモートワークの方が多い中でも広いコミュニケーションネットワークが形成されているのはすごいなと思いました。
おわりに
感想が中心の長い文を最後まで読んでくださりありがとうございます。短い期間のインターンでしたが、ヤプリの魅力をたくさん感じることができたなと思っています。
iOSエンジニアとしては高い技術力に圧倒されながらも、成長できるいい環境であり、様々なことを吸収できたインターンだったかなと思います。
ヤプリってどんな会社なんだろうと疑問を持っていたり、興味を持っている方は、ぜひインターンをしてみてください!