ユニファ開発者ブログ

ユニファ株式会社プロダクトデベロップメント本部メンバーによるブログです。

効率的な問い合わせ対応を目指して:Firebase活用による改善策

効率的な問い合わせ対応を目指して

こんにちは、ユニファでプロダクトマネージャーをしているしんせいです。今日は私がユニファに入社して最初に担当した「ルクミー for FAMILY」というネイティブアプリについて、運用・保守の観点で最初に課題に感じたことについてお話ししたいと思います。

続きを読む

スタートアップのスピード感 価値とリスク

スタートアップのスピード感 価値とリスク

こんにちは。プロダクトマネージャのサトウです。

今回のテーマはスピードです。趣味の釣りでもスピードは重要な要素で、釣果(釣った魚の数)を求めるときには「手返し」がポイントになります。 手返しとは、魚を釣り上げて魚を外し、再度エサやルアーの仕掛けを魚のいるポイントに投入する一連の動作となります。ルアーでは最近は従来の鉛ではなく、より比重の高いタングステンが登場し、狙ったポイントにより早く仕掛けを運ぶことができるようになりました(お財布には厳しい)。

さて、そんなスピードの話ですが、最近ユニファのValueが刷新されまして、新たに「Speed Driven」が追加されました。

続きを読む

フォトチームの開発体験の改善 2024秋

フォトチームの開発体験の改善 2024秋

こんにちは。プロダクトエンジニアリング部の伊東です。

エンジニアにとって開発者体験って大事ですよね! 単にプロダクトに必要な機能開発だけをしていたら開発体験は自然と悪くなってしまいがちです。😭
例えば、技術的負債が溜まって改修コストが高くなったり、関連ライブラリのバージョンアップを怠ってレガシーな環境になっていたり。。

私が所属するフォトチームでは、システムの保守や機能開発などをしながら、積極的に技術的負債の解消や新しい技術の導入も試みています!

本記事では、最近フォトチーム(リード1名、エンジニア4名)で行っている技術的負債の解消や、新しい技術やツールの導入についてご紹介させていただきます!✋️

技術負債の解消

1. RubyとRailsのバージョンアップ

現在、フォトのサーバーサイドのバージョンアップが進行中です。
Rubyは3.1系、Railsは6.1系でしたが、最新バージョン(Rubyは3.3系、Railsは7.2系)を目指してバージョンアップ中です。
最近はRails8に関する発表がされるなど、進化が早いなあと感じる昨今ですが、なるべく常に最新に追従できるような体制にしていきたいです。
Rails7.1では、ActiveRecord::Base.normalizesによるモデルの属性の正規化など便利な機能もあるので利用していきたいです。☕️

2. 古いシステムの移行

フォトのプロダクトは歴史的経緯によって2つのRailsアプリが動いています。
2つに分かれていると、コードの重複など不都合があるので、徐々に1つにまとめるように動いております。
最近、移行するための基盤づくりが完成しました。今後、機能単位で移植していくことができそうです!
不要なコンテキストスイッチを減らして、コードの凝集性を高めて、開発効率をあげていきたいです。☘️

3. デプロイフローの改善

フォトチームは隔週で、モブプロをリモートで実施しています。
その中での成果の1つですが、普段から行っているデプロイの流れを簡略化できました。
デプロイ作業は日々何度も行うことなので、簡略化されるととても気軽になって嬉しいです。
AWSのCodeBuidとCodePipelineでデプロイを行っていますが、gitで所定のタグをつければデプロイができるようになりました。🚀
(今までは、デプロイまで何ステップか必要でした)

4. その他

こちらもモブプロの中で行っているものですが、不要なリモートブランチの削除、不要なAWSのリソース削除なども行っています。
目下、エラー通知の整理などを行っており、なるべく不要な通知を削除し、本当に必要な通知だけにし、すぐに問題に気づけるように頑張っています!

新しい技術・ツールの導入

1. GitHub Copilot

こちらは去年からですが、希望者はVscodeでCopilotをつかえます!
Copilotのコード補完はすごく便利なので、かなりコーディングの効率があがっていると感じます。
AIの分野は進化が早いので、Copilotの進化に期待です。✨️

2. Tailwind CSS

新規で作成している画面で、お試しでTailwind CSSを導入してみました。
こういったCSSのフレームワークは流行り廃りがありますが、知名度の高さや使い勝手的に結構良いかなと思っています。
今後、利用を進めていく中でわかった知見があれば共有したいです!🌿

3. RailsのHotwire

HotwireはTurbo、Stimulus、Strada(現在はHotwire Nativeに名称が変更されていました)の3つの技術から構成されていますが、 今回導入をしてみたのは、TurboとStimulusです。
こちらも、一部画面のドロップダウンメニューなどで利用してみたのみで、まだ経験値が足りていないので、今回これら技術の良さについて語れるほどのことがないのですが、今後利用をすすめていき、既存のフロントエンド技術(ReactやVueなど)などとの違いや良さについて理解していきたいです。✍️

おわりに

最近フォトチームで行っている開発者体験の改善への取り組みを紹介しました!
これらの取り組みを通して、さらに開発効率を上げて、お客様により早く良い物を提供できるようにがんばりたいです。
そして、会社の新しいバリューであるSpeed Drivenを体現していきたいです。

話は変わりますが、Kaigi on Rails 2024 に Gold Sponsorになりました。🥇こういった技術系カンファレンスに貢献できることはとても嬉しく思います。

tech.unifa-e.com 私達フォトチームからも当日ブースに参加予定です!よろしくお願いします。

--

ユニファでは新たな仲間を積極採用中です。

詳細についてはこちらからご確認ください。

unifa-e.com

Product Leaders Week 2024 に Bronze Sponsor として協賛します!

こんにちは。ユニファで開発組織副本部長を務めているやまぐち(@hiro93n)です。主にプロダクトマネージャーとデザイナーの部門を管轄しています。

10月22-24日に開催されるプロダクトマネジメント系カンファレンス Product Leaders Week 2024 にBronze Sponsor として協賛させていただけることになりました!

続きを読む

オンボーディングスケジュールを整備した話

こんにちは、ユニファQA課のえりです。

今年の3月に入社して、あっという間に7か月が過ぎ去っていきました。

今回は私がユニファのQAチームに参画して取り組んだものの1つ、オンボーディングスケジュールの整備ついて書きたいと思います。

続きを読む

QRコード打刻(β) のフィジビリ検証の話

こんにちは。ユニファPdMの武岡です。 ルクミーでは登園降園時の打刻を扱うプロダクトとして、ルクミー登降園を提供しています。 先日、ルクミー登降園の新機能として、QRコードで登園降園時の打刻ができる「QRコード打刻(β)」をリリースしました。

「QRコード打刻(β)」では本開発前にフィジビリ検証を行いました。 このフィジビリ検証で確認できたことは多く、本開発前に実施して非常に効果があったなと思ったので改めて振り返ってみます。

※QRコードは(株)デンソーウェーブの登録商標です。

  • 待望の「QRコード打刻(β)」は期待値も高かった
  • 「ストレスのない打刻」をめざす強い気持ちで検証へ
    • でも、検証項目、多いな
    • いざ打刻テスト
  • フィジビリ検証の効果
    • 効果1:「これは良いものができそうだ!」とフィジビリ開始序盤に社内で確信が持てた
    • 効果2:対応基準が明確になり、本開発時の判断に迷いが少なくなった
    • 効果3:画面外の論点が早めに整理・検討できた。
  • 手探りしながらなんだかんだで楽しんで進められた
  • ユニファでは一緒に働く仲間を募集しております

待望の「QRコード打刻(β)」は期待値も高かった

ルクミー登降園のQRコード打刻(β)は、園・施設様が管理するタブレット端末などのインターネットブラウザ上でWebカメラを起動し、園児毎に発行されたQRコードを保護者様がかざして打刻する仕組みです。

QRコードをかざす打刻画面

タッチ打刻の場合はクラスを選択して、園児を選択して、打刻ボタンを押す、という手順を踏む必要がありますが、QRコード打刻(β)の場合はかざすだけで打刻完了できます。 朝の忙しい時間帯やお迎えの延長利用が気になるタイミングで素早く、簡単に打刻ができるため、 園・施設様から長い間ご要望をいただいておりました。

開発においての一番の焦点は「QRコードでストレスなく打刻できるか?」という点でした。 出勤前で時間に追われる朝の登園時、延長料金発生する前に打刻したい夕方の降園時、 「とにかく素早く打刻したい⌛」「子供から目が離せないので、簡単な方法でお願いしたい👨‍👧」という保護者様の高い要求に応えなければなりません。 なんか遅い、、、かざしにくい、、、反応しなくなった、、、という状態は出来る限り避けたいところです。

通常のユニファのサービス開発は、要件整理→概算見積→スコープ決定→着手決済→外部仕様設計→画面デザイン(ワイヤー・デザイン)→開発→QA検証……と進むのですが、今回はスコープ決定の前に先に打刻機能のプロトタイプを作ってフィジビリ検証を行うことにしました。

続きを読む

How to Use Coroutine with Jetpack Compose

kotlin coroutine
Greetings! I'm Farhan, an Android Engineer.

In software development, keeping applications responsive is a key challenge. Asynchronous programming is an important technique that addresses this issue by allowing long-running operations such as network requests, data processing, or heavy computations to occur in the background. This concept is especially vital in mobile development, where a smooth user experience is crucial.

Jetpack Compose, is Google's modern toolkit for building native UIs on Android and simplifies UI development. Today we will learn How to use Asynchronous programming with Jetpack Compose.

What Are Coroutines?

Coroutines are a feature of Kotlin that simplifies asynchronous programming by providing an easier way to handle long-running tasks. They manage their own execution with the help of CoroutineScope and execute on specific threads facilitated by Dispatchers. A suspend function is a type of function in Kotlin that can be paused and resumed at a later time, making it perfect for tasks such as fetching data from the internet or accessing a database.

Why Are Coroutines Needed in Jetpack Compose? In any UI application, maintaining responsiveness is crucial. Blocking the main thread can lead to an unresponsive app and a poor user experience. Coroutines address this issue by allowing expensive operations to be offloaded to background threads, while the main thread remains free to handle user interactions.

How to Use Coroutines in Jetpack Compose

There are several ways to integratete coroutines in Compose, today we'll focus on two key concepts: LaunchedEffect and rememberCoroutineScope. These tools are most used to call coroutines efficiently from Compose screens.

LaunchedEffect

LaunchedEffect is a powerful Composable function that you can use to launch side effects (such as network calls) in your Compose UI. It takes a key and a lambda as parameters. The key is important because it determines when to stop the current task and start a new one if something changes during recomposition.

Here's how you can use LaunchedEffect in a practical scenario:

gist.github.com

LaunchedEffect is particularly useful for making API calls directly from a Compose screen setup or in response to changes in the UI's state that should trigger a new coroutine.

rememberCoroutineScope

While LaunchedEffect is suitable for scenarios where coroutines are directly tied to the composition lifecycle and specific recomposition keys, rememberCoroutineScope offers more flexibility. This function creates a CoroutineScope that is remembered across recompositions and is bound to the lifecycle of the Compose screen where it is used.

This is especially useful for triggering actions like showing a snackbar or updating UI elements in response to user interactions, which may happen multiple times and are not directly tied to the composition of the UI:

gist.github.com

Using rememberCoroutineScope allows for more dynamic interactions within your Compose UI, managing multiple coroutine launches based on user input or other events that don't correspond to the lifecycle of the entire composable.

Choosing the Right Tool

Both LaunchedEffect and rememberCoroutineScope are essential in their own contexts. Use LaunchedEffect for operations that should be tied directly to the composition lifecycle and specific recomposition conditions. On the other hand, use rememberCoroutineScope for more interactive or repeated actions within a Composable that can occur at any time during its lifecycle.

Conclusion

In this article, we've explored how LaunchedEffect and rememberCoroutineScope can be used in Jetpack Compose to manage asynchronous operations effectively. These tools help ensure that your apps remain responsive and handle tasks smoothly. LaunchedEffect is great for tasks linked to the lifecycle of your UI components, such as fetching data when a screen is displayed. rememberCoroutineScope, on the other hand, is ideal for handling user interactions and other dynamic events.For more in-depth knowledge, you can always dive into the official Jetpack Compose documentation. Happy coding!

unifa-e.com