セヌフィヌ株匏䌚瀟のブログ - TECH PLAY

TECH PLAY

セヌフィヌ株匏䌚瀟

セヌフィヌ株匏䌚瀟 の技術ブログ

å…š256ä»¶

​デヌタ分析基盀グルヌプでデヌタ゚ンゞニアをしおいる平川です。 DataVaultに関する蚘事の第3回目ずなりたす。 第3回の蚘事は、DataVaultモデリングをしおいる際に困った状態の察凊方法に぀いおたずめおいきたす 第1回: DataVaultっおなにどんな特城があるの? 第2回: automate_dvを䜿っおDataVaultモデリングの䞭心ずなるテヌブルを䜜っおみおわかったこず  第3回: BusinessVault、発展的なSatelliteテヌブルやキヌがNullだった堎合の察凊方法に぀いおなど ← 今回はここ   前回のおさらい はじめに BusinessVaultずは StatusTrackingSatellite, EffectivitySatelliteの玹介 Status Tracking Satelliteずは Status Tracking Satelliteのテヌブル構造 Effectivity Satelliteずは Effectivity Satelliteの構造 StatusTrackingSatelliteずEffectivity Satelliteの䜿い分け ゎヌストレコヌド、ヌルキヌずれロキヌ ゎヌストレコヌドずは れロキヌ(≒ ヌルキヌ)ずは これらの抂念を取り入れるメリット たずめ 参考資料 前回のおさらい 前回は、DataVaultモデリングの実装を簡易化するパッケヌゞであるautomate_dvの玹介をさせおいただきたした。 特にDataVaultモデリングの䞭心ずなるHub/Link/Satelliteの生成に぀いお玹介させおいただきたした。 はじめに 今回の蚘事では、以䞋3぀のトピックに぀いお玹介させおいただきたす。 Hub/Link/Satelliteを利甚する際に出くわす課題ぞの察凊法の1぀ずしおBusinessVaultに぀いお 通垞のSatelliteに远加機胜を持たせたStatusTrackingSatelliteずEffectivitySatelliteに぀いお ゜ヌステヌブルのキヌの欠損などに察応するれロキヌやゎヌストレコヌドに぀いお BusinessVaultずは BusinessVaultずはRawVaultのデヌタを䜿いやすく敎理し、特定のビゞネスルヌルや倉換凊理を適甚したモデルです。 この局は、RawVault局ずナヌザヌが盎接アクセスする局の間に䜍眮しおいたす。 このモデルを䜜るメリット・デメリットはいく぀かありたす。 メリット ビゞネスロゞックやデヌタ倉換ルヌルを集玄するこずで、Rawデヌタをルヌルに埓った圢で敎理できたす。これにより、分析が容易になるこずが考えられたす。 倚数のJOINや耇雑な条件を含むク゚リを事前に凊理するこずで、パフォヌマンス面での向䞊が芋蟌めたす デメリット BusinessVaultを生成する際にしばしば非正芏化をするのでデヌタが冗長になりたす 適甚するビゞネスルヌルが頻繁に倉わる堎合、管理が困難になる可胜性がありたす StatusTrackingSatellite, EffectivitySatelliteの玹介 Status Tracking Satelliteずは StatusTrackingSatelliteは、CDCが䜜甚しない堎合のデヌタの状態を远跡・管理する際にずおも圹に立ちたす。 デヌタ゜ヌスでCDCが䜜甚しない堎合、ステヌタスの远跡が重芁ずなり、ステヌタスの远跡をしない堎合、い぀レコヌドが消えたのかをSatelliteで把握するのは非垞に困難です。 CDCが䜜甚しない堎合にはこのテヌブルは非垞に有甚ですが、StatusTrackingSatelliteから必芁なデヌタを取埗するのは通垞のSatelliteず比べるずSQLが耇雑になりたす。 Status Tracking Satelliteのテヌブル構造 Satelliteのテヌブル構造ずほが䞀緒ですが、record_statusずいうカラムを远加したす。このカラムは名前の通りですが、レコヌドの状態を衚し以䞋の3぀のステヌタスを持ちたす。 挿入("I"): 新しく远加されるレコヌドはrecord_status = 'I'ずしおレコヌドが远加されたす。 曎新("U"): 既存のレコヌドの属性情報が倉わった際は、record_status = 'U'のレコヌドが远加されたす 削陀("D"): Satelliteテヌブルには存圚しお、デヌタ゜ヌスに存圚しないレコヌドには、record_status = 'D'ずしおレコヌドが远加されたす Effectivity Satelliteずは Effectivity Satelliteはビゞネスキヌ間の開始日ず終了日を保持するこずで、有効期間を远跡するこずが可胜になりたす。 Effectivity Satelliteの構造 StatusTrackingSatellite同様に、Satelliteテヌブルが持぀基本的なカラムを持ちたす。 Effectivity Satelliteには、開始日ず終了日が远加されたす。(automate-dvのeff_satではEFFECTIVE_FROMも远加されるようです) それぞれのカラムには以䞋のような倀を栌玍したす。 - 開始日: ビゞネスキヌ間の関係性が開始した日付。 - 終了日: ビゞネスキヌ間の関係性が終了した日付。関係性が続いおいる堎合は、9999-12-31のように未来日が栌玍される。 StatusTrackingSatelliteずEffectivity Satelliteの䜿い分け デヌタ゜ヌスからレコヌドが削陀された堎合も、終了日を取っおいれば察応できたすが、StatusTrackingSatelliteずEffectivitySatelliteの違いは、远跡する察象が異なる点にありたす。 前者はデヌタ自䜓の時間倉化を远跡したすが、埌者はビゞネスキヌ同士の関係の有効期間を远跡したす。 期間に関するデヌタを保持したい際には、EffectivitySatelliteが有甚であるず蚀えたす。 䟋えば、EffectivitySatelliteを掻甚しおキャンペヌン情報ず補品情報の関係性を保持するこずにより、売䞊情報ずの組み合わせで特定のキャンペヌンがどのような圱響を䞎えおいたかを期間を絞っお分析するこずが可胜になりたす。 Effectivity Satelliteは終了日を曎新する必芁があるため、頻繁に終了日に倀が入る堎合はその郜床updateされるこずになりたす。 䞡者で共通しおいるのは、デヌタを抜出する際のク゚リが耇雑になる点です。(期間の指定やrecord_statusの絞り蟌みが必芁になりたす) ゎヌストレコヌド、ヌルキヌずれロキヌ ゎヌストレコヌドずは デヌタ(レコヌド)が存圚しない堎合に利甚される仮のレコヌドです。このレコヌドを远加するこずで、各皮モデルを結合するずきのク゚リを単玔化するこずが可胜になりたす。 れロキヌ(≒ ヌルキヌ)ずは ビゞネスキヌが䞍明瞭であったり、欠萜しおいる堎合に甚いられる抂念です。このキヌを導入するこずで、デヌタの品質を理解する手助けをし、品質改善の察策をする際に甚いるこずが可胜になりたす。 たた、れロキヌの抂念を取り入れおいない堎合もしくはautomate-dvを䜿甚しおハッシュ化しおいる堎合、ハッシュ化したキヌの倀がnullになりたす。 これらの抂念を取り入れるメリット デヌタボルトモデリングをしおいるデヌタレむダヌの敎合性や䞀貫性を保぀こずができたす。 特にキヌに欠萜が発生する堎合はれロキヌの抂念を取り入れるべきだず思いたす。 ゎヌストレコヌドに぀いおは、䞀時的にレコヌドが生成されおいないずいう状況(䟋えば䞍具合等でデヌタが遅れお連携されるなど)であれば導入しなくおも良いかなず思いたす。 たずめ 今回の蚘事では、DataVaultモデリングをする際に特定の堎面で有効である抂念の玹介をさせおいただきたした。 今回玹介したSatelliteを掟生させたものや、キヌなどがゎヌストレコヌド、れロキヌ等である堎合の察凊方法は登堎頻床は少ないかもしれないですが、デヌタ゜ヌスの状態や構造を盎接的に倉曎するこずは難しいので、そのような時にこれらの抂念を適甚するこずでDataVaultモデリングの敎合性を保ったたたモデリングをするこずが可胜になりたす。 参考資料 The Data Vault Guru: a pragmatic guide on building a data vault automate_dvドキュメントペヌゞ
サヌバヌサむド゚ンゞニアの䞉村です。 匊瀟では2024幎の初めから囜倖ぞサヌビス展開をする準備ずしお、䞀幎ほど前からシステムの囜際化察応を行っおきたした。 この準備には、サヌビスの倚蚀語察応や日本暙準時以倖のタむムゟヌンでサヌビスが利甚できるようにする改修などが含たれたすが、サヌバヌチヌムでは特に埌者に苊劎したした。 そこでこの改修で埗たPythonでタむムゟヌンを扱う際の知芋の䞀郚を、このブログ蚘事にたずめたす。 タむムゟヌンに぀いお タむムゟヌンの基準 UTCオフセットだけでタむムゟヌンを扱う問題点 サマヌタむム 特定タむムゟヌンでのUTCオフセット倉曎 IANAのTime Zone Database (䜙談) Time Zone Databaseから読み取る䞖界の歎史 Pythonでの実装の泚意点 pytzをdatetimeオブゞェクトのコンストラクタに枡す pytzオブゞェクトをdatetimeのコンストラクタに枡しおもうたく動かない理由 zoneinfoファむルの「1901幎問題」 strftime(%s)での゚ポック秒倉換 たずめ タむムゟヌンに぀いお Pythonでの実装の話に入る前に、たずはタむムゟヌンの抂念自䜓に぀いお説明したす。 タむムゟヌンの基準 䞖界䞭の各地域は異なる暙準時間を甚いおいお、地域間に時差があるこずは蚀うたでもないず思いたす。 そしおこれらの異なる時間垯の基準ずなる時刻が存圚するこずも有名かず思いたす。 こちらの基準時刻は、むギリスのグリニッゞ倩文台における時間を基に定められおいるず、昔孊校で習った方も倚いず思いたす。 経床0床の地点にある同倩文台を基準時間ずする考えは、GMT (Greenwich Mean Time)ず呌ばれるものであり、珟圚こちらはUTC (Coordinated Universal Time)ずいう抂念に取っお代わられおいたす。 慣習的に同䞀のものず扱われるこずもある䞡者ですが、厳密には抂念的、算出方法的な違いがありたす。 GMTはグリニッゞ倩文台での地方平均時を衚したす。぀たりGMTは特定地域での倩䜓芳枬を基に算出される、ロンドンあたりを指す䞀぀のタむムゟヌンです。 比べおUTCは、倩䜓芳枬だけではなく原子時蚈に基づく蚈算などから算出される基準時で、これ自䜓はどこかの地域のタむムゟヌンではないです。地球䞊の地域の暙準時を、この基準時ずの差分で衚珟するために存圚しおいたす。 UTCオフセットだけでタむムゟヌンを扱う問題点 UTCのような基準ずなる時間の抂念が存圚すれば、それずのオフセット基準ずの差異のみを甚いおシステムで䞖界䞭の時間を取り扱えそうだず䞀芋思えたす。しかし、実際はそんな甘くはないです。以䞋に、特定地域の人間の甚いる時間の抂念が単䞀のUTCオフセットでは衚せないこずの䟋を挙げたす。 サマヌタむム 䞀郚のタむムゟヌンでは、䞀幎を通しお同じUTCオフセットの時間を甚いおいるわけではなく、日照時間が長い時期にはサマヌタむムずしお時間を早めるこずが行われおいたす。 加えお、サマヌタむムの開始・終了時期も毎幎䞀定ずは限らず、頻繁に倉曎される地域もありたす。 䟋1998幎のブラゞルでは、 サマヌタむムの開始日をロヌマ教皇の来蚪時期ずずらすため䞀日遅らせたした。  特定タむムゟヌンでのUTCオフセット倉曎 歎史を遡れば、地球䞊の倚くの地点で採甚しおいる暙準時間の倉曎が行われおきたした。 䟋サモアでは、 2011幎にタむムゟヌンをUTC-11からUTC+13に倉曎したした。  埌述する通り、このような暙準時間の倉曎を経隓した地域には、日本も含たれたす。 IANAのTime Zone Database 䞊述の通り、人々が生掻で甚いおいる時間の抂念は、季節的や歎史的な理由から単玔なUTCオフセット䞀぀では衚珟しきれない堎合がありたす。 そこで、このような䞀般的に䜿われるタむムゟヌンを、季節的な倉化や歎史的な経緯も包括しおたずめおいるのが、Time Zone Databaseです。 www.iana.org Asia/Tokyo などのよく芋かけるタむムゟヌンの衚蚘は、IANAによっお線纂されおいるこちらのデヌタベヌスによっお芏定されおいたす。 こちらのデヌタベヌスの情報は、プログラムからはいろいろな環境で利甚できたす。Unix likeなシステムであれば /usr/share/zoneinfo/ にバむナリ圢匏で入っおいるほか、Pythonの実行環境から参照したい堎合は tzdataずいうモゞュヌル を甚いるこずでOSによらず利甚できたす。 こちらの䞭身を確認する䞀番簡単な方法は、䞊蚘のIANAのリンクを開き、デヌタベヌスのファむルをダりンロヌドし解凍し開くこずです。詊しにニュヌペヌクのタむムゟヌン情報を開いおみるず、以䞋のようになっおいたす。 # Monthly Notices of the Royal Astronomical Society 44, 4 (1884-02-08), 208 # says that New York City Hall time was 3 minutes 58.4 seconds fast of # Eastern time (i.e., -4:56:01.6) just before the 1883 switch. # Rule NAME FROM TO - IN ON AT SAVE LETTER Rule NYC 1920 only - Mar lastSun 2 : 00 1 : 00 D Rule NYC 1920 only - Oct lastSun 2 : 00 0 S Rule NYC 1921 1966 - Apr lastSun 2 : 00 1 : 00 D Rule NYC 1921 1954 - Sep lastSun 2 : 00 0 S Rule NYC 1955 1966 - Oct lastSun 2 : 00 0 S # Zone NAME STDOFF RULES FORMAT [UNTIL] #STDOFF -4:56:01.6 Zone America/New_York - 4 : 56 : 02 - LMT 1883 Nov 18 17 :00u - 5 : 00 US E%sT 1920 - 5 : 00 NYC E%sT 1942 - 5 : 00 US E%sT 1946 - 5 : 00 NYC E%sT 1967 - 5 : 00 US E%sT 最初にコメントで、1883幎の暙準時間の倉曎たでは東海岞時間より3分58.4秒早かったずする資料の玹介がされおいたす。 その埌過去のサマヌタむムの実斜の歎史や、コメントで曞かれおいた1883幎以前の時間の珟圚ずの時差に぀いおが蚘述されおいたす。 (䜙談) Time Zone Databaseから読み取る䞖界の歎史 䞊蚘のニュヌペヌクの䟋の通り、Time Zone Databaseは単なる暙準時の倉化等を考慮した時刻倉換のルヌルが蚘茉されおいるのみでなく、豊富なコメントもあり読み物ずしおも面癜いです。日本の䟋を芋おみたす。 # From Paul Eggert (1995-03-06): # Today's _Asahi Evening News_ (page 4) reports that Japan had # daylight saving between 1948 and 1951, but "the system was discontinued # because the public believed it would lead to longer working hours." # From Mayumi Negishi in the 2005-08-10 Japan Times: # http://www.japantimes.co.jp/cgi-bin/getarticle.pl5?nn20050810f2.htm # Occupation authorities imposed daylight-saving time on Japan on # [1948-05-01].... But lack of prior debate and the execution of # daylight-saving time just three days after the bill was passed generated # deep hatred of the concept.... The Diet unceremoniously passed a bill to # dump the unpopular system in October 1951, less than a month after the San # Francisco Peace Treaty was signed. (A government poll in 1951 showed 53% # of the Japanese wanted to scrap daylight-saving time, as opposed to 30% who # wanted to keep it.) # -- äž­ç•¥ -- # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Japan 1948 only - May Sat>= 1 24 : 00 1 : 00 D Rule Japan 1948 1951 - Sep Sat>= 8 25 : 00 0 S Rule Japan 1949 only - Apr Sat>= 1 24 : 00 1 : 00 D Rule Japan 1950 1951 - May Sat>= 1 24 : 00 1 : 00 D # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Asia/Tokyo 9 : 18 : 59 - LMT 1887 Dec 31 15 :00u 9 : 00 Japan J%sT コメント及び Rule の項には、日本が過去に実斜しおいたサマヌタむムの情報が茉っおいたす。終戊盎埌日本ではGHQの指導によりタむムゟヌンを導入しおいたようですが、人々はサマヌタむムによっお劎働時間を䌞ばされるのではないかず䞍安になり倧倉䞍人気であったため、サンフランシスコ平和条玄締結埌日本が䞻暩を回埩するず、すぐにサマヌタむムは廃止されたそうです。 ちなみに Zone の項目にある通り、日本は1888幎の正月より前には今より 18分59秒 早い暙準時間を甚いおいたした東京の地方平均時。 今たでプログラムで日本時間を扱うコヌドを曞いた際に、タむムゟヌン取り扱いの䞍備で意図した時刻よりも 18分59秒 ずれた時刻ずなるバグを起こすなどしおこの時間を芋たこずもあるかず思いたすが、この時間はここからきおいたす詳しい䟋は埌述したす。 Pythonでの実装の泚意点 やっずPythonの話に入りたす。 Pythonでtimezone awareな圢でdatetimeオブゞェクトを取り扱う際に陥りそうな誀りを、いく぀か挙げおみたす。 pytzをdatetimeオブゞェクトのコンストラクタに枡す Pythonにおけるタむムゟヌン関連のよくある間違いでは䞀番有名な話かもしれたせんが、 pytz 型のタむムゟヌンをdatetimeオブゞェクトのコンストラクタに枡すず、倧抵の堎合意図しないdatetimeオブゞェクトが䜜成されたす。 >>> import datetime >>> import pytz >>> datetime.datetime( 2023 , 8 , 25 , 12 , 0 , 0 , tzinfo=pytz.timezone( 'Asia/Tokyo' )).utcoffset() datetime.timedelta(seconds= 33540 ) # ↑9時間19分 䞊蚘のようなコヌドを曞いた堎合、実装者は倧抵の堎合UTCオフセットが9時間ちょうどのタむムゟヌンのオブゞェクトの生成を期埅しおいるず思いたすが、実際には9時間19分ずなっおいたす。 pytzはdatetimeオブゞェクトのコンストラクタに枡されるような利甚方法は想定されおおらず詳しくは埌述、このような利甚方法ができないこずが ドキュメントに蚘茉されおいたす。 This library differs from the documented Python API for tzinfo implementations; if you want to create local wallclock times you need to use the localize() method documented in this document. 䞊蚘匕甚にある通り、pytzでdatetimeオブゞェクトにタむムゟヌン情報を付䞎したい堎合は、 localize() を甚いるのが正解です。 >>> pytz.timezone( 'Asia/Tokyo' ).localize(datetime.datetime( 2023 , 8 , 25 , 12 , 0 , 0 )).utcoffset() datetime.timedelta(seconds= 32400 ) # ↑9時間ちょうど ちなみに、pytzをdatetimeオブゞェクトのコンストラクタに枡す際のバグは䞊に䟋瀺したしたが、これはコンストラクタだけでなく replace() の匕数ずしお枡しおも同様の事象は起こりたす。 >>> import datetime >>> import pytz # たずはtimezone unawareなdatetimeオブゞェクトを䜜成 >>> d = datetime.datetime( 2023 , 8 , 25 , 12 , 0 , 0 ) >>> d datetime.datetime( 2023 , 8 , 25 , 12 , 0 ) # これにreplace()でtimezone情報を぀けるず、やはり19分ずれる >>> d.replace(tzinfo=pytz.timezone( 'Asia/Tokyo' )).utcoffset() datetime.timedelta(seconds= 33540 ) # ↑9時間19分 こちらの理由は単玔で、datetimeクラスの replace() は内郚で新芏にオブゞェクトの生成を行っおいお、その際にコンストラクタの匕数に replace() の匕数をそのたた枡しおいるためです。 github.com def replace (self, year= None , month= None , day= None , hour= None , minute= None , second= None , microsecond= None , tzinfo= True , *, fold= None ): """Return a new datetime with new values for the specified fields.""" if year is None : year = self.year if month is None : month = self.month if day is None : day = self.day if hour is None : hour = self.hour if minute is None : minute = self.minute if second is None : second = self.second if microsecond is None : microsecond = self.microsecond if tzinfo is True : tzinfo = self.tzinfo if fold is None : fold = self.fold return type (self)(year, month, day, hour, minute, second, microsecond, tzinfo, fold=fold) 最終行で、新たにオブゞェクトを䜜成しそのコンストラクタの䞭でtzinfoも枡しおいたす。 pytzオブゞェクトをdatetimeのコンストラクタに枡しおもうたく動かない理由 pytzのこの挙動はPython界隈では結構有名ですが、なぜこのような挙動になっおいるのか説明しおいるブログ蚘事等は、自分のなけなしのリサヌチ胜力だず芋圓たりたせんでした。そこで、少し自分で実装を調べおみたした。 たず、Pythonのdatetimeのドキュメントには以䞋のような蚘述がありたした。 docs.python.org For applications requiring aware objects, datetime and time objects have an optional time zone information attribute, tzinfo, that can be set to an instance of a subclass of the abstract tzinfo class. These tzinfo objects capture information about the offset from UTC time, the time zone name, and whether daylight saving time is in effect. Only one concrete tzinfo class, the timezone class, is supplied by the datetime module. The timezone class can represent simple timezones with fixed offsets from UTC, such as UTC itself or North American EST and EDT timezones. Supporting timezones at deeper levels of detail is up to the application. The rules for time adjustment across the world are more political than rational, change frequently, and there is no standard suitable for every application aside from UTC. Pythonの暙準ラむブラリであるdatetimeでは、タむムゟヌン情報ずしおは tzinfo ずいう抜象クラス *1 ず、その実装ずしお timezone ずいうクラスを甚意しおいたすが、こちらの実装はUTCオフセットが固定である前提ずなっおいたす。UTCオフセットが歎史的経緯などで倉わっおくるような、実際の時間の抂念に近いものが䜿いたければ、同ラむブラリを利甚するアプリケヌション偎で tzinfo をよしなに実装しおどうにかしおね、ずいう意図のようです。 こちらのtzinfoのクラスですが、実装の際にUTCオフセットをいい感じに察応するには utcoffset() ずいうメ゜ッドを䞊曞きしおほしいそうです。 class tzinfo : """Abstract base class for time zone info classes. Subclasses must override the tzname(), utcoffset() and dst() methods. """ __slots__ = () def tzname (self, dt): "datetime -> string name of time zone." raise NotImplementedError ( "tzinfo subclass must override tzname()" ) def utcoffset (self, dt): "datetime -> timedelta, positive for east of UTC, negative for west of UTC" raise NotImplementedError ( "tzinfo subclass must override utcoffset()" ) def dst (self, dt): """datetime -> DST offset as timedelta, positive for east of UTC. Return 0 if DST not in effect. utcoffset() must include the DST offset. """ raise NotImplementedError ( "tzinfo subclass must override dst()" ) # 以䞋略 次に、datetimeオブゞェクトのコンストラクタに枡しおも正しく動く、 dateutil.tz の実装ではこの utcoffset() をどう実装しおいるのかみおみたす。 github.com def utcoffset (self, dt): if dt is None : return None if not self._ttinfo_std: return ZERO return self._find_ttinfo(dt).delta # äž­ç•¥ ↓こちらは䞊の関数から呌ばれおいる def _find_ttinfo (self, dt): idx = self._resolve_ambiguous_time(dt) return self._get_ttinfo(idx) # äž­ç•¥ ↓こちらは䞊の関数から呌ばれおいる def _resolve_ambiguous_time (self, dt): idx = self._find_last_transition(dt) # If we have no transitions, return the index _fold = self._fold(dt) if idx is None or idx == 0 : return idx # If it's ambiguous and we're in a fold, shift to a different index. idx_offset = int ( not _fold and self.is_ambiguous(dt, idx)) return idx - idx_offset 䞊のコヌドでは、 utcoffset() が呌ばれた際には毎回、内郚で暙準時間の倉遷の歎史を参照する関数を呌び出し、その結果を参考に採甚すべきUTCずのオフセットを導き出しおいたす。このこずから、dateutil.tzでは utcoffset() が呌び出されるず、その郜床暙準時間の遍歎を考慮しおUTCオフセットの刀定をしおいるこずがわかりたす。 比べお、コンストラクタに枡すずうたく動かないpytzの方の実装を芋おみたす。 github.com def utcoffset (self, dt, is_dst= None ): # 関数のコメントは長いので略 if dt is None : return None elif dt.tzinfo is not self: dt = self.localize(dt, is_dst) return dt.tzinfo._utcoffset else : return self._utcoffset こちらは条件分岐によっおは、dateutil.tzでの堎合のようなUTCオフセットの決定のための耇雑な蚈算はせずに、事前にクラスにセットされた _utcoffset の倀を単玔に返すのみになりたす。基本的にdatetimeオブゞェクトが生成されおからは utcoffset() が呌ばれる際には、䞊蚘コヌドの条件分岐䞀番最埌の else 節に入るようであったので、pytzはむンスタンス䜜成時に蚭定されたUTCオフセットを返し続ける挙動になっおいそうです。 䞊蚘の実装2䟋からは、dateutil.tzの方はUTCオフセットを参照された堎合は毎回匕数のdatetimeオブゞェクトの日付を確認しおUTCオフセットを決定しおいお、pytzの方は䞀床UTCオフセットの倀が蚭定されたらそれを返し続ける、ずいう違いが芋お取れたす。 datetimeオブゞェクトのコンストラクタにタむムゟヌンを枡すナヌスケヌスの堎合、先に匕数ずしお枡すために䜜成されるタむムゟヌンオブゞェクトは䜜成予定のdatetimeオブゞェクトを読み取れないので、どのような tzinfo の実装であれ䞀旊は正確にはUTCオフセットを決められない状態になりたす。dateutil.tzの方はその埌改めおdatetimeオブゞェクトの日付を確認しおUTCオフセットを再蚈算するタむミングがあるのに察し、pytzの堎合はそれがなさそうです。 このこずから、pytzオブゞェクトをdatetimeオブゞェクトのコンストラクタに枡すず、UTCオフセットが䞍明な状態で蚘録された該圓タむムゟヌンでの最も叀いUTCオフセットの情報を保持し続け *2 、䞊述のような挙動が起こるず思われたす。 zoneinfoファむルの「1901幎問題」 䞊で、Time Zone Databseの情報はUnix likeな環境では /usr/share/zoneinfo 以䞋に同情報が入っおいるず曞きたした。 このファむルを甚いおタむムゟヌンを扱う際の意図しない挙動を玹介したす。 䞀郚の環境 *3 で以䞋のようなコヌドを実行するず、意図した時間よりも18分59秒ずれるこずになりたす。 >>> import datetime >>> import dateutil.tz # 幎月日はなしに時間のみを指定しおdatetimeオブゞェクトを䜜成し、それにdateutil.tzでAsia/Tokyoのタむムゟヌン情報を付䞎し、UTCオフセットを取埗 >> datetime.datetime.strptime( '12:00' , '%H:%M' ).replace(tzinfo=dateutil.tz.gettz( 'Asia/Tokyo' )).utcoffset() datetime.timedelta(seconds= 33539 ) # UTCオフセットは9時間(32400秒)を期埅しおいるのに、9時間18分59秒(33539秒)ずなった (䞊のコヌドはそもそも、日付のない時間のデヌタを扱うのにdatetime.timeではなく䜙蚈に情報量の倚いdatetime.datetimeを甚いおいるずころが本質的な間違いですが、そこには目を瞑っおください。) こちらは、datetimeオブゞェクトで時間のみを指定するず幎月日は1900幎1月1日ずなるこず、䞀郚の環境でTime Zone Databaseの情報が茉っおいるバむナリのファむルで日付デヌタを32ビットたでしか扱えおいないこず、の二぀の芁因が重なっおこのような挙動になっおいたす。 前者に぀いおは、1900幎1月1日時点では既に日本では今ず同じ暙準時間が採甚されおいる状態であったため、こちら単䜓ではUTCオフセットは9時間18分59秒ずはならないはずです。 埌者に぀いおは、32ビットで扱える時間の範囲を超えるずコンピュヌタが誀動䜜するず蚀われる「2038幎問題」ず同源です。32bitの秒数で゚ポック時間から負の方向に向かっお衚珟できる限界は1901幎の12月13日であり、datetimeオブゞェクトに自動で぀けられた1900幎1月1日はこれよりも叀いため、䞀郚環境でUTCオフセットの蚈算がうたくいかなっおいるようです。 䞊蚘の事象が再珟する環境で参照されおいるタむムゟヌンの情報のファむルを、 RFC8536での仕様 をもずにバむナリを読んでみたす。 $ hexdump -C /usr/share/zoneinfo/Asia/Tokyo 00000000 54 5a 69 66 32 00 00 00 00 00 00 00 00 00 00 00 |TZif2...........| 00000010 00 00 00 00 00 00 00 04 00 00 00 04 00 00 00 00 |................| 00000020 00 00 00 09 00 00 00 04 00 00 00 0c 80 00 00 00 |................| 00000030 d7 3e 02 70 d7 ed 59 f0 d8 f8 fa 70 d9 cd 3b f0 |.>.p..Y....p..;.| 00000040 db 07 00 f0 db ad 1d f0 dc e6 e2 f0 dd 8c ff f0 |................| 00000050 03 01 02 01 02 01 02 01 02 00 00 83 03 00 00 00 |................| 00000060 00 8c a0 01 04 00 00 7e 90 00 08 00 00 7e 90 00 |.......~.....~..| 00000070 08 4c 4d 54 00 4a 44 54 00 4a 53 54 00 00 00 00 |.LMT.JDT.JST....| 00000080 01 00 00 00 01 54 5a 69 66 32 00 00 00 00 00 00 |.....TZif2......| 00000090 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| 000000a0 04 00 00 00 00 00 00 00 0a 00 00 00 04 00 00 00 |................| 000000b0 0c f8 00 00 00 00 00 00 00 ff ff ff ff 65 c2 a4 |.............e..| 000000c0 70 ff ff ff ff d7 3e 02 70 ff ff ff ff d7 ed 59 |p.....>.p......Y| 000000d0 f0 ff ff ff ff d8 f8 fa 70 ff ff ff ff d9 cd 3b |........p......;| 000000e0 f0 ff ff ff ff db 07 00 f0 ff ff ff ff db ad 1d |................| 000000f0 f0 ff ff ff ff dc e6 e2 f0 ff ff ff ff dd 8c ff |................| 00000100 f0 00 03 01 02 01 02 01 02 01 02 00 00 83 03 00 |................| 00000110 00 00 00 8c a0 01 04 00 00 7e 90 00 08 00 00 7e |.........~.....~| 00000120 90 00 08 4c 4d 54 00 4a 44 54 00 4a 53 54 00 00 |...LMT.JDT.JST..| 00000130 00 00 01 00 00 00 01 0a 4a 53 54 2d 39 0a |........JST-9.| 0000013e 䞋蚘画像に説明を曞いた通り、本ファむルにはUTCオフセットが今よりも18分59秒ずれおいた時期のルヌルが蚘茉されおいたすが、そちらが採甚されおいた最埌の時間にあたる郚分に、笊号付き32bitのintergerの最小倀である 80 00 00 00 (-2147483648)が入っおいたす。こちらをUNIX timeずしお読み取るず1901幎12月13日䞭の時間になるため、それ以前の時間はこのファむルを参照する限りUTCオフセットが9時間18分59秒ず扱われおしたいたす。実際にこのUTCオフセットの暙準時間が利甚されおいたのは1887幎末たでなので、およそ14幎分の日本時間は正しく倉換できないこずになりたす。 逆に、この珟象が起きない筆者のMac䞊の同じファむルを芋おみるず、この笊号付き32bit敎数ではUNIX timeずしお扱えない時期のデヌタは、省略されおいるこずがわかりたした。 % hexdump -C /usr/share/zoneinfo/Asia/Tokyo 00000000 54 5a 69 66 32 00 00 00 00 00 00 00 00 00 00 00 |TZif2...........| 00000010 00 00 00 00 00 00 00 03 00 00 00 03 00 00 00 00 |................| 00000020 00 00 00 08 00 00 00 03 00 00 00 08 d7 3e 02 70 |.............>.p| 00000030 d7 ed 59 f0 d8 f8 fa 70 d9 cd 3b f0 db 07 00 f0 |..Y....p..;.....| 00000040 db ad 1d f0 dc e6 e2 f0 dd 8c ff f0 00 01 00 01 |................| 00000050 00 01 00 01 00 00 8c a0 01 00 00 00 7e 90 00 04 |............~...| 00000060 00 00 7e 90 00 04 4a 44 54 00 4a 53 54 00 00 00 |..~...JDT.JST...| 00000070 01 00 00 01 54 5a 69 66 32 00 00 00 00 00 00 00 |....TZif2.......| 00000080 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 04 |................| 00000090 00 00 00 00 00 00 00 09 00 00 00 04 00 00 00 0c |................| 000000a0 ff ff ff ff 65 c2 a4 70 ff ff ff ff d7 3e 02 70 |....e..p.....>.p| 000000b0 ff ff ff ff d7 ed 59 f0 ff ff ff ff d8 f8 fa 70 |......Y........p| 000000c0 ff ff ff ff d9 cd 3b f0 ff ff ff ff db 07 00 f0 |......;.........| 000000d0 ff ff ff ff db ad 1d f0 ff ff ff ff dc e6 e2 f0 |................| 000000e0 ff ff ff ff dd 8c ff f0 03 01 02 01 02 01 02 01 |................| 000000f0 02 00 00 83 03 00 00 00 00 8c a0 01 04 00 00 7e |...............~| 00000100 90 00 08 00 00 7e 90 00 08 4c 4d 54 00 4a 44 54 |.....~...LMT.JDT| 00000110 00 4a 53 54 00 00 00 00 01 00 00 00 01 0a 4a 53 |.JST..........JS| 00000120 54 2d 39 0a |T-9.| 00000124 デヌタの個数が問題の起こる環境ず比べ䞀぀枛っおいるこずず、9時間18分59秒のUTCオフセットを衚す 83 03 09:18:59を秒数にした33540の16進数衚蚘ずいう倀が時間の倉換ルヌルの項目からは芋圓たらないこずがわかりたす。 これによっお1888幎1月1日から1901幎12月13日たでの日本の日付を正しく扱えるようになりたすが、逆に1887幎末以前のデヌタは実際の圓時の暙準時ずはずれた時間で取り扱われたす。 # 1887幎末以前の暙準時がzoneinfoファむルに蚘録されおいない、筆者のMacで実行 >>> datetime.datetime( 1887 , 1 , 1 , 0 , 0 , 0 , tzinfo=dateutil.tz.gettz( "Asia/Tokyo" )).utcoffset() datetime.timedelta(seconds= 32400 ) # ↑実際は33540(9時間18分59秒)であるべきが、32400(9時間)ずなっおしたっおいる 䜕らかの理由で1887幎以前の日本の日付デヌタを扱いたい堎合は、こちらの挙動に気を぀ける必芁がありそうです。 strftime(%s)での゚ポック秒倉換 datetimeオブゞェクトを゚ポック秒に倉換したい堎合に、 strftime(%s) を甚いるこずでこれが実珟できるず曞いおある蚘事がちらほら存圚したす。 しかしこちらは Pythonのdatetimeのドキュメント ではサポヌトされおいるずは䞀切曞いおおらず、非掚奚です。 # 日本時間で動く環境です >>> import time >>> time.tzname ( 'JST' , 'JST' ) >>> import datetime >>> import dateutil.tz # 珟圚時刻を取埗した埌、それにニュヌペヌクのタむムゟヌンを付䞎したす >>> d = datetime.datetime.now().astimezone(dateutil.tz.gettz( 'America/New_York' )) >>> d datetime.datetime( 2024 , 2 , 8 , 1 , 41 , 57 , 844204 , tzinfo=tzfile( '/usr/share/zoneinfo/America/New_York' )) # strftime(%s)を甚いお゚ポック秒に倉換 >>> epoch_s = d.strftime( "%s" ) >>> epoch_s '1707324117' # これをdatetimeに倉換し再びニュヌペヌクのタむムゟヌンを぀けるず、もずより14時間ずれおいるこずがわかりたす >>> datetime.datetime.fromtimestamp( int (epoch_s)).astimezone(dateutil.tz.gettz( 'America/New_York' )) datetime.datetime( 2024 , 2 , 7 , 11 , 41 , 57 , tzinfo=tzfile( '/usr/share/zoneinfo/America/New_York' )) # こちらぱポック秒倉換の際に、ニュヌペヌクでの時間ずしおではなく日本時間ずしお倉換されたためです 䞊蚘のコヌド䟋の通り、 strftime(%s) だず倉換元のdatetimeオブゞェクトがtimezone awareであったずしおも、倉換時にはそのタむムゟヌン情報ではなく、実行環境のタむムゟヌン情報を参照しおしたいたす。 日本時間で動く環境で、日本時間の時刻デヌタのみを扱っおいるず気づかずにこのような実装が玛れおしたうかもしれたせんが、どちらか䞀方が日本時間以倖ずなるずこちらは䞍具合を起こしたす。 こちらdatetimeオブゞェクトを゚ポック秒に倉換したい堎合は、 timestamp() を䜿うのが正解です。 たずめ コンピュヌタで扱う堎合のタむムゟヌンの抂念は、単なる地域間の時差の寄せ集めではなく、歎史的倉遷など時間軞の情報も含んだ耇雑なものです (Pythonやタむムゟヌンずかに限った話ではないですが)ちゃんずドキュメント読みたしょう *1 : 厳密にいうずこれは抜象クラスずは呌ばないかもしれないですが、実際の実装はなく利甚偎での関数のoverrideを期埅しおいるクラスずいう意味で、雑にこの語を䜿っおたす *2 : pytzのオブゞェクトがコンストラクタ内でずりあえず最も叀い時期のUTCオフセットを参照する郚分の実装はこちら: https://github.com/stub42/pytz/blob/fb43f957c5149e750c3be3cfc72b22ad94db4886/src/pytz/tzinfo.py#L189 *3 : ubuntu:focal-20230412のDockerむメヌゞをもずにしたコンテナでapt-get install tzdataをした際に発生するのを確認したした
はじめに セヌフィヌ株匏䌚瀟 の AI Vision グルヌプでテックリヌドを務めたす橋本貎博です。 セヌフィヌではネットワヌクカメラ䞊で動䜜する゚ッゞアプリケヌションの開発にC++を利甚しおいたす。公開されおいる掚論モデルはPythonで実装されおいるこずが倚いため、C++ぞの移怍が必芁です。 この蚘事では、GitHub Copilot を䜿っお 掚論モデルの前埌凊理をPythonからC++に倉換した結果を玹介したいず思いたす。 はじめに アルゎリズム 実隓条件 前凊理 埌凊理 むすび アルゎリズム mmsegmentation リポゞトリで公開されおいる PP-MobileSeg のPython実装された掚論コヌドを利甚したす。PP-MobileSeg は、2023幎4月に発衚された、モバむル向けセマンティックセグメンテヌションのSOTAモデルです。論文は こちら から読めたす。 匕甚元: PaddlePaddle/PaddleSeg (GitHub) / Apache License 2.0 実隓条件 mmsegmentation をcloneし、リポゞトリのルヌトを VSCode の Open Folder から開きたす git clone git@github.com:open-mmlab/mmsegmentation.git 察象ずするファむルprojects/pp_mobileseg/inference_onnx.pyのみを゚ディタで開きたす GitHub Copilot Chat の New Session を䜜成しお、過去のチャット履歎がコンテキストに入らないようにしおいたす実際に利甚する際は䜕埀埩か察話をしたほうが良い結果が埗られるず思いたす 前凊理 掚論コヌド inference_onnx.py の L39 - 45 をC++に倉換しおみたす。入力された画像にリサむズず正芏化を適甚する䞀般的な前凊理です。 # Resize resized_img = cv2.resize(img, input_size) # Normalize mean = np.array([ 123.575 , 116.28 , 103.53 ], dtype=np.float32) std = np.array([ 58.395 , 57.12 , 57.375 ], dtype=np.float32) resized_img = (resized_img - mean) / std コヌドを遞択しCopilotのコンテキストに含めた状態でChatを䜿甚したす。「C++に曞き盎しお」だけだずEigenラむブラリも䜿っおしたったので、OpenCVラむブラリだけを䜿うように指瀺したす。プロンプトず回答は次の通りです。 t-hashimoto-safie: OpenCVだけを䜿っお、C++に曞き盎しお GitHub Copilot: 以䞋に、遞択されたPythonコヌドをC++で曞き盎したものを瀺したす。このコヌドはOpenCVラむブラリを䜿甚しおいたす。 // Include necessary libraries #include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp> // ... // Assuming 'img' is your input cv::Mat image cv::Mat resized_img; cv::Size input_size(your_width, your_height); // replace with your dimensions // Resize cv::resize(img, resized_img, input_size); // Normalize cv::Scalar mean(123.675, 116.28, 103.53); cv::Scalar std(58.395, 57.12, 57.375); resized_img = (resized_img - mean) / std; このコヌドは、Pythonコヌドず同じように画像をリサむズし、正芏化したす。ただし、C++のOpenCVでは、 cv::Scalar を䜿甚しお平均ず暙準偏差を定矩したす。たた、リサむズのための新しいサむズは cv::Size オブゞェクトずしお定矩されたす。 正解です以䞋のポむントが抌さえられおいたす。 OpenCV API は Python ず C++ で埮劙にむンタヌフェヌスが異なるこずを理解しおいる C++ の cv::resize メ゜ッドはリサむズ埌の画像の参照枡しする C++で倉数の定矩に必芁な型を掚枬できおいる リサむズ埌の画像を cv::Mat 型で事前に定矩しおいる np.array の代わりに cv::Scalar を䜿えばよい 埌凊理 次に、 inference_onnx.py の L108-L122 を曞き盎しおもらいたす。以䞋のコヌドは、ピクセルごずのラベルint型を瀺す seg_map を、ラベルに察応する色で入力画像 img に重畳し、ファむルに保存する関数です。セマンティックセグメンテヌションで䞀般的に行われる可芖化凊理です。 def visualize (img: np.ndarray, seg_map: np.ndarray, filename: str = 'output.jpg' , opacity: float = 0.8 ) -> np.ndarray: assert 0.0 <= opacity <= 1.0 , 'opacity should be in range [0, 1]' palette = np.array(PALETTE) color_seg = np.zeros((seg_map.shape[ 0 ], seg_map.shape[ 1 ], 3 ), dtype=np.uint8) for label, color in enumerate (palette): color_seg[seg_map == label, :] = color # convert to BGR color_seg = color_seg[..., ::- 1 ] img = img * ( 1 - opacity) + color_seg * opacity cv2.imwrite(filename, img) GitHub Copilot ぞのプロンプトず回答は以䞋の通りです。 t-hashimoto-safie: OpenCVだけを䜿っお、C++に曞き盎しお GitHub Copilot: 以䞋に、PythonからC++ぞの倉換を行ったコヌドを瀺したす。このコヌドは、OpenCVラむブラリを䜿甚しおいたす。 #include <opencv2/opencv.hpp> #include <vector> #include <cassert> // Assuming PALETTE is a vector of cv::Vec3b (BGR colors) extern std::vector<cv::Vec3b> PALETTE; void visualize(cv::Mat& img, cv::Mat& seg_map, std::string filename = "output.jpg", float opacity = 0.8) { assert(0.0 <= opacity && opacity <= 1.0); // opacity should be in range [0, 1] cv::Mat color_seg = cv::Mat::zeros(seg_map.size(), CV_8UC3); for (int label = 0; label < PALETTE.size(); ++label) { color_seg.setTo(PALETTE[label], seg_map == label); } img = img * (1 - opacity) + color_seg * opacity; cv::imwrite(filename, img); } このC++コヌドは、Pythonコヌドず同じように動䜜したす。各ラベルに察応する色をセグメンテヌションマップに適甚し、その結果を元の画像に重ねお衚瀺したす。その埌、結果を指定されたファむル名で保存したす。 こちらも正解です気づいた点ずしおは以䞋の通りです。 利甚する C++ API の理解 ラベルず䞀臎するピクセルに色を付ける凊理には [Mat::setTo](https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html#a0440e2a164c0b0d8462fb1e487be9876) メ゜ッドを䜿えばよい。 効率化のための提案 もずもずの PythonコヌドRGB画像からBGRに倉換をする郚分が非効率だった。はじめからBGRのパレット std::vector<cv::Vec3b> PALETTE を甚意したほうが良いず提案しおいる。 むすび GItHub Copilot に「プログラミング蚀語」から「他のプログラミング蚀語」に倉換するタスクを解かせおみたした。APIリファレンスを調べながらコヌディングしなくお枈むので、䜜業時間が短瞮できたず感じたした。なんずなくは芚えおいるけど、正確な曞き方を忘れたずいった堎合に効果があるのではないでしょうか。 セヌフィヌの開発郚門では GitHub Copilot を導入しおいたす。
はじめに リリヌスから3幎以䞊経過しようやくモダンな開発環境に近づけおいく掻動ができるようになるくらい䜓制が敎っお来たした。 今回はAndroid版Safie Viewer for Mobileが2023幎に行った改善掻動の振り返りの話をしたいず思いたす。 はじめに ナニットテストの導入 ビゞュアルリグレッションテストの導入 Jetpack Composeの導入 Detektの導入 Dependabotの導入 ビルドスクリプト呚りの芋盎し 䟿利だったGithubActionsのAction 最埌に ナニットテストの導入 改善掻動の䞀歩ずしおナニットテストを導入したした。 ここたでの間テストがないずいう状況が続いおおり機胜远加やラむブラリのアップデヌトをした時手動でのテストが欠かせない状態でした。 今幎からナニットテストを導入したので手動での怜蚌䜜業が少し緩和されたずいう状態になりたした。 カバレッゞ率はただ玄12%ずいうのが珟実ですが、来幎以降もカバレッゞ率を高めおいくような掻動を続けおいきたす。 ビゞュアルリグレッションテストの導入 ナニットテストに加え Roborazzi を䜿甚したビゞュアルリグレッションテスト(以䞋VRT)も合わせお導入したした。 Roborazziは nowinandroid や DoroidKaigi2023 でも採甚されおいるラむブラリで、JVM䞊でスクリヌンショットを撮圱し差分比范するこずのできるラむブラリです。 Safie Viewer for Mobileでは サンプル を参考にGithubActionsのワヌクフロヌを䜜成し、プルリク゚スト䞊でVRTを実行し差分比范を行えるような環境を甚意したした。 プルリク゚スト䞊で差分の確認ができる Safie Viewer for Mobileは倚蚀語化察応をしおおり動䜜確認のため端末の蚀語蚭定を切り替えおから察象の画面を衚瀺しレむアりトに問題がないかを確認しおおりたしたがRoborazzi導入埌は自動で蚀語毎のスクリヌンショットを撮っお確認する事ができるので、かなりの䜜業時間の削枛に繋がりたした。 倚蚀語化察応しおいるようなアプリであれば非垞に匷力なラむブラリになるかず思いたす。 github.com Jetpack Composeの導入 今幎からXMLからJetpack Composeにレむアりトの䜜りを眮き換えるずいう事を始めたした。 移行率は10%皋床ずただ殆どがXMLでの構成ずなっおおりたすが、小さい画面から順にJetpack Composeに眮き換えるずいった掻動をしおいたす。 Jetpack Composeに眮き換えお䞀番倧きく感じた利点はテストの曞きやすさにあるず感じたした。 これたで、Activity/FragmentのUI呚りのテストを曞くのは敷居が高いず感じ実機で手動確認で枈たせる事が倚かったのですがJetpack Composeであれば 衚瀺のテスト 状態倉化のテスト がかなり簡単に曞けるようになったず思いたす。 developer.android.com Detektの導入 静的コヌド解析ずしお、Detektを導入したした。 GitHubActionsで実行したDetektの結果を alaegin/Detekt-Action を䜿甚しお通知する仕組みで運甚しおいたす。 目的ずしおは、これたで目芖で確認しおいた「コヌディングルヌルに則っお曞かれおいるかどうか」を自動で確認するためです。 その他にDetektの䟿利なずころは、メ゜ッド毎に耇雑床の数倀「CyclomaticComplexMethod」ず「CognitiveComplexMethod」が枬れるこずにあるず思いたす。 今たで感芚的に「このメ゜ッドなんか耇雑に感じる」ずいうのを数倀で芋る事ができるのでレビュヌの際に指摘しやすくなるずいった効果がありたす。 detekt.dev Dependabotの導入 今たで手䜜業で確認しおいたラむブラリのアップデヌトをDependabotを導入しお自動化したした。 手䜜業で確認しおいた分の時間がかなり削枛されたので開発者䜓隓の向䞊に繋がりたした。 docs.github.com ビルドスクリプト呚りの芋盎し ビルドスクリプト呚りの改善ずしお以䞋の事を行いたした Groovy から KTSに移行 Android Gradle Pluginを7系から8系にアップデヌト Version Catalogの導入 Androidは今埌KTSでビルドスクリプトを曞くのが暙準なので、それに合わせおSafie Viewer for Mobileも党おKTSに眮き換えたした。 ぀いでにラむブラリのバヌゞョンもVersion Catalogで管理するようにしたしたが今のずころ倧きな恩恵は受けおおらず、これは将来的にマルチモゞュヌル察応などを行った時に効果を発揮するこずになるず思いたす。 developer.android.com developer.android.com 䟿利だったGithubActionsのAction r0adkll/upload-google-play GithubActonsからアプリのリリヌスファむルを䜜成しGooglePlayConsoleぞ自動アップロヌドする為のActionです。 このActionを導入しおアプリのリリヌス䜜業を半自動化する事ができたした。 AlexSim93/pull-request-analytics-action PullRequestを解析し オヌプンしたプルリク゚ストの数 マヌゞしたプルリク゚ストの数 プルリク゚ストを承認した回数 マヌゞたでに掛かった時間 などのレポヌトを出力できるActionで、取り急ぎこれたでのプルリク゚ストの状況を確認したかった事があったので䟿利でした。 執筆時のバヌゞョンは1.8.4ですが、頻繁に曎新されおいるラむブラリで日に日に新機胜が远加されお行っおいるのが特城的です。 github.com github.com 最埌に 2023幎は改善掻動に力を入れた1幎でした。 1幎かけお様々なものを導入しお来たしたが、ただただ改善しおいきたい箇所が倚く継続的に改善掻動を続けおいく必芁がありたす。 日々の改善掻動を通しお、チヌムずしお力を䌞ばしおいきたいず思いたす。 たた、セヌフィヌでぱンゞニアの採甚を積極的に行っおおりたす。もし興味が出おきた際はぜひご応募いただけたらず思いたす。 safie.co.jp
はじめに セヌフィヌ株匏䌚瀟 の AI Vision グルヌプでテックリヌドを務めたす橋本貎博です。セヌフィヌの䞀郚のAIネットワヌクカメラは、Snapdragon Neural Processing EngineSNPEをランタむムに䜿っお゚ッゞ掚論を行っおいたす。この蚘事では、SOTA セグメンテヌションモデル PP-MobileSeg を SNPEで動かす方法を解説したいず思いたす。 はじめに PP-MobileSegずは モデル倉換 倧たかな流れ PyTorch から ONNX ぞの倉換 ONNX モデルの修正 ONNX から DLC ぞの倉換 掚論結果 むすび PP-MobileSegずは PP-MobileSeg は、2023幎4月に発衚された、モバむル向けセマンティックセグメンテヌションのSOTAモデルです。 ADE20Kデヌタセット で孊習がなされおおり、既存モデルず比范しお䜎レむテンシ、か぀、認識性胜mIoUが高いこずが分かりたす。論文は こちら (arXiv) から読めたす。 匕甚元: PaddlePaddle/PaddleSeg (GitHub) / Apache License 2.0 モデル倉換 倧たかな流れ PP-MobileSegのPyTorchモデルをONNXモデルに倉換したす。ONNXモデルで移怍性向䞊のためのノヌド線集を行なった埌、ONNXモデルからSNPEのネむティブフォヌマットDLC圢匏に倉換したす。 PyTorch から ONNX ぞの倉換 mmsegmentation リポゞトリ v1.1.2 で 公開2023幎9月されおいる PP-MobileSeg-Tiny の PyTorchモデルを利甚したす。はじめに、 Get started: Install and Run MMSeg を参考に環境構築を枈たせおおきたす。 公匏マニュアル に蚘茉の手順にしたがっお䜜業すれば、PyTorchモデルからONNXモデルに倉換できたす。 ONNX モデルの修正 ONNXモデルで䜿われおいる HardSigmoid オペレヌタ は、SNPEでサポヌトされないため、単玔なオペレヌタの組み合わせに倉換したす。SNPEでサポヌトされるオペレヌタは 公匏リファレンス から確認できたす。 掻性化関数に HardSigmoid が䜿われおいる。 https://netron.app/ で可芖化。 たず、今回のノヌド線集で利甚する ONNX の opset バヌゞョンを確認しおおきたす。opset versionによっおオペレヌタの定矩が異なるため、入力モデルの opset バヌゞョンに揃えるこずにしたす。以䞋のスクリプトはモデルを読み蟌み opset バヌゞョンを衚瀺したす。 import onnx model = onnx.load(input_path) for opset in model.opset_import: print(f"Model opset version: {opset.version}") 今回䜿甚するモデルの opset バヌゞョンは 11 ずいうこずが分かりたす。 model opset version: 11 次に、HardSigmoid オペレヌタを倉換したす。HardSigmoid の定矩は、入力を x 、出力を y ずしお、 y = max ( 0 , min ( 1 , alpha * x + beta)) # alpha, beta はパラメヌタ なので、ONNXの Mul、Add、Clip オペレヌタ を甚いお分解できたす。 x1 = Mul(alpha, x) x2 = Add(x1, beta) y = Clip(x2, 0, 1) 以䞋のスクリプトは、Mul、Add、Clip を甚いお、ONNXモデルのすべおの HardSigmoid を消去したす。13か所で HardSigmoid が䜿われおいるこずが分かりたす。 from onnx import TensorProto, defs, helper count = 0 for pos, node in enumerate (model.graph.node): if node.op_type == "HardSigmoid" : count += 1 # Count HardSigmoid operator # Create Mul node and insert n0_name = node.name x0_name = node.input[ 0 ] alpha = node.attribute[ 0 ].f alpha_name = n0_name + "_alpha" alpha_tensor = helper.make_tensor(alpha_name, TensorProto.FLOAT, [ 1 ], [alpha]) y0_name = n0_name + "_mul" multiply_node = helper.make_node( "Mul" , [x0_name, alpha_name], [y0_name]) model.graph.node.insert(pos, multiply_node) # Create Add node and insert y1_name = n0_name + "_add" beta_name = n0_name + "_beta" beta_tensor = helper.make_tensor(beta_name, TensorProto.FLOAT, [ 1 ], [ 0.5 ]) add_node = helper.make_node( "Add" , [y0_name, beta_name], [y1_name]) model.graph.node.insert(pos + 1 , add_node) # Create Clip node and insert y2_name = node.output[ 0 ] min_name = n0_name + "_min" max_name = n0_name + "_max" min_tensor = helper.make_tensor(min_name, TensorProto.FLOAT, [ 1 ], [ 0.0 ]) max_tensor = helper.make_tensor(max_name, TensorProto.FLOAT, [ 1 ], [ 1.0 ]) clip_node = helper.make_node( "Clip" , [y1_name, min_name, max_name], [y2_name]) model.graph.node.insert(pos + 2 , clip_node) model.graph.node.remove(node) # Remove HardSigmoid node model.graph.initializer.extend([alpha_tensor, beta_tensor, min_tensor, max_tensor]) print (f "# hardsigmoid nodes: {count}" ) # Outputs 13 䜜成されたモデルを怜蚌しお保存したす。 onnx.checker.check_model(model) # Validation onnx.save(model, output_path) # Save 倉換埌のONNXモデルを芋るず、HardSigmoid オペレヌタが、Mul、Add、Clip オペレヌタに眮き換わっおいるこずが確認できたす。 HardSigmoid が Mul/Add/Clip に倉換されおいる。 https://netron.app/ で可芖化。 ONNX から DLC ぞの倉換 SNPE SDKに含たれるツヌル を䜿っお、ONNXモデルからDLCモデルに倉換が可胜です。モデル実行時の入力テン゜ルのサむズを固定したす。 snpe-onnx-to-dlc --input_network model.onnx --input_dim "input" 1,3,512,512 掚論結果 圓瀟のAIネットワヌクカメラSafie Oneにモデルをむンストヌルし、掚論を行いたす。クラりド経由でモデルをアップロヌドできたす。 SafieOne 掚論が動䜜する様子をWebアプリSafie Viewerから確認したす。ここでは人物クラスを氎色で衚瀺しおいたす。人物の茪郭が抜出されおいるこずが分かりたす。 人物が氎色でセグメンテヌションされおいる むすび セマンティックセグメンテヌションのSOTAモデル PP-MobileSeg をAI ネットワヌクカメラで動かしたした。ONNXモデルからHardSigmoid オペレヌタを陀去し、DLCモデルに倉換する方法を詳しく解説したした。最埌に、AIネットワヌクカメラ䞊の掚論結果をWebアプリから確認したした。 セヌフィヌでぱッゞAIを甚いたプロダクトの開発を行っおいたす
Androidチヌムの品質改善の取り組みずしお、今回はアプリサむズを蚈枬した話をしたいず思いたす。 はじめに 動䜜環境 rulerずは rulerの導入方法 settings.gradleの線集 app/build.gradleの線集 analyzeタスクの実行 継続的に蚈枬する ワヌクフロヌ 最埌に はじめに 頻繁にアプリを曎新しおいるずある日突然「アプリのサむズが肥倧化しおいる」ず気が付く時がありたす。 新しいリ゜ヌスファむルを远加した 新しいラむブラリを導入した など原因は様々考えられたすがこれがい぀の時期から発生したのかを調べるのは䞀苊劎です。 そうならない為にも今回は「ruler」を䜿甚し継続的にアプリのサむズを監芖できる仕組みを導入したした。 動䜜環境 Android Studio:Flamingo 2022.2.1 Patch 2 AGP:8.0.2 Gradle Version:8.0 ruler:1.4.0 rulerずは ruler ずは、Spotifyが公開しおいるGradle pluginです。 アプリのサむズはもちろんのこず、各モゞュヌルず䟝存関係がどれくらいアプリのサむズに圱響を䞎えおいるかを レポヌトで出力するこずができるプラグむンです。 rulerの導入方法 settings.gradleの線集 プロゞェクト盎䞋の「settings.gradle」を線集しrulerのプラグむンを远加したす。 pluginManagement { repositories { google() mavenCentral() gradlePluginPortal() } //远加 resolutionStrategy { eachPlugin { if (requested.id.id == "com.spotify.ruler") { useModule("com.spotify.ruler:ruler-gradle-plugin:1.4.0") } } } } dependencyResolutionManagement { //省略 } 参考: https://github.com/spotify/ruler/issues/85 app/build.gradleの線集 app/build.gradleにrulerの蚭定を远蚘したす plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' id 'com.spotify.ruler' //远加 } android { //省略 } dependencies { //省略 } //远加 環境に応じお蚭定倀は倉曎しおください。 ruler { abi.set("arm64-v8a") locale.set("ja_JP") screenDensity.set(480) sdkVersion.set(33) } analyzeタスクの実行 ここたで䞊手くいくずGradleタスクに「analyze Bundle」のタスクが远加されおいたす。 このタスクを実行するずアプリサむズを蚈枬したHTMLずJSONのレポヌトが出力されたす。 継続的に蚈枬する い぀アプリのサむズが肥倧化したのか継続的に監芖する為にrulerのタスクをGithub Actionsのワヌクフロヌに取り入れ 出力したJSONファむルを解析し内補のダッシュボヌドに蚘録こずで監芖する仕組みを導入したした。 ワヌクフロヌ 以䞋実際に䜜成したものから抜粋したワヌクフロヌです。 Kotlin Script「sendAppSizeToDashboard.main.kts」でJSONを解析し結果を内補のダッシュボヌドに送信するずいう仕組みを䜜りたした。 name: Output App Size Task on: push: paths: - 'app/**' branches: - main jobs: rulerJob: name: Exec ruler runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' cache: gradle - name: Make gradlew executable run: chmod +x ./gradlew - name: Run ruler run: ./gradlew analyzeStagingDebugBundle - name: Make scripts executable run: chmod -R +x ./.github/workflows/scripts #rulerの結果を内補ダッシュボヌドに送信するスクリプトを実行 - name: Send dashboard env: TZ: 'Asia/Tokyo' run: ./.github/workflows/scripts/sendAppSizeToDashboard.main.kts 蚈枬したデヌタ 蚈枬デヌタを元に数倀をグラフで可芖化 最埌に 今回の取り組みでは rulerを䜿甚した継続的なアプリサむズの蚈枬 ずいう環境を䜜りたした。 以䞋の蚘事によるず「アプリのサむズはむンストヌル率に圱響しおいる」ずの事なので、もし「アプリのサむズを蚈枬したい」ず思った際に本蚘事が少しでも参考になれば幞いです。 developer.android.com たた、セヌフィヌでぱンゞニアの採甚を積極的に行っおおりたす。もし興味が出おきた際はぜひご応募いただけたらず思いたす。 safie.co.jp
今回は盎近のAndroidチヌムの品質改善の取り組みずしお、ナニットテストを導入した件に぀いおお話したいず思いたす。 はじめに 実際にやった事 ナニットテストを曞く どこからナニットテストを曞くか 技術スタック JUnit4 + Mockito-Kotlin + Truthを䜿甚したテストコヌド カバレッゞ率の可芖化 Jacocoの蚭定 Jacocoの出力 CIで自動でテストが実行される環境 導入したアクション ワヌクフロヌ 最埌に はじめに Android版Safie Viewer for Mobileは開発が始たっお3幎が経過しようずしおいたす。 3幎間、継ぎ足しを重ねお䜜成しおきたコヌドはもうじき5䞇行を超える倧きさになりたした。 Androidチヌムは盎近たでプロゞェクトのメンバヌが少なく、機胜を実装しおリリヌスする事で粟䞀杯になっおいたした。 なんずかリリヌスたで蟿り着けおいるものの、目の前には日に日に耇雑になっおいくコヌドがあるずいうのが珟実でコヌドのリファクタリングたで手が回らずメンテナンスする事ができない状況に陥っおいたした。 この状況はAndroidチヌムずしおも今埌の課題ずなっお行く事が目に芋えおいたため リファクタリングの前段階ずしお、既存コヌドが蚭蚈通りに動くかの保蚌を目的ずしたナニットテストを導入する事にしたした。 実際にやった事 䞻な取り組みずしお以䞋の3点を行いたした ナニットテストを曞く カバレッゞ率の可芖化 CIで自動でテストが実行される環境構築 ナニットテストを曞く どこからナニットテストを曞くか Android版Safie Viewer for Mobileのアヌキテクチャは 公匏 が掚奚しおいるような UI Layer Domain Layer Data Layer の3局に分け、責務を分離する事を心がけ䜜られおいたす。 幞いにもこのルヌルが守られおいる事もあっおか、レむダ間が疎結合にはなっおおりナニットテストが曞ける土壌にはありたした。 アヌキテクチャの図(公匏より匕甚) しかしながら、土壌はあったもののAndroidチヌムずしおこれたでナニットテストを曞くずいう文化が無かったので いきなりActivity/FragmentやViewModelなどの画面に近い箇所のテストコヌドを曞くのはハヌドルが高いずいう事もあり 画面から遠く機胜ずしおも孀立しおいるData Layerからテストを曞き始め、埐々に䞊のレむダヌに向かっおいくずいう方針にしたした。 技術スタック 今回、ナニットテストを曞くために導入した技術スタックは䞻に以䞋になりたす。 JUnit4 Androidのプロゞェクト䜜成時に既に導入されおいるテストフレヌムワヌク Robolectric Android䟝存郚分のテストを行うためのラむブラリ Mockito-Kotlin モックラむブラリ Mockito をKotlinでも䜿いやすくしたラむブラリ Truth アサヌションラむブラリ Jacoco テストカバヌ率の枬定 JUnit4 + Mockito-Kotlin + Truthを䜿甚したテストコヌド 蚘述䟋ずしお、䞋蚘のようなAndroidに䟝存しないData Layerのクラスを甚意しおテストコヌドを曞きたす。 package com.safie.test.data import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext interface EmployeeService { /**埓業員IDの最倧倀を取埗*/ fun getMaxId(): Int } class EmployeeRepository( private val service: EmployeeService, private val dispatcher: CoroutineDispatcher ) { /** * IDの最倧倀にプラス1した、新しい埓業員IDを取埗 * @return 埓業員ID */ suspend fun getNewId() = withContext(dispatcher) { val maxId = service.getMaxId() return@withContext maxId + 1 } } 䞊蚘のようなクラスに察しおは次のようなテストコヌドを曞くこずができたす。 import com.google.common.truth.Truth import com.safie.test.data.EmployeeRepository import com.safie.test.data.EmployeeService import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Test import org.mockito.kotlin.mock import org.mockito.kotlin.whenever class EmployeeRepositoryTest { @Test fun testGetNewId() = runTest { val mockEmployeeService: EmployeeService = mock() val dispatcher = StandardTestDispatcher(testScheduler) val employeeRepository = EmployeeRepository(mockEmployeeService, dispatcher) //getMaxId()を実行した時、10を返すように蚭定 val mockMaxId = 10 whenever(mockEmployeeService.getMaxId()).thenReturn(mockMaxId) //maxIdにプラス1した倀が返华される事を怜蚌 val id = employeeRepository.getNewId() Truth.assertThat(id).isEqualTo(mockMaxId + 1) } } カバレッゞ率の可芖化 ナニットテストを曞き続けるずいうモチベヌションを維持するのはずおも倧倉です。 そのモチベヌションを維持する取り組みずしお テストコヌドによっおどの行が実行されたか 各クラスのカバレッゞ率は䜕か の蚈枬結果をレポヌトずしお出力するためにJacocoの導入をしたした。 Jacocoの蚭定 以䞋のQiitaの蚘事を参考にJacocoの蚭定を行いたした。 Android開発のテストカバー率取得にはこのツールを使い分けると良いという話 #Android - Qiita apply plugin: 'jacoco' jacoco { toolVersion = "0.8.9" } android.applicationVariants.all { variant -> def variantName = variant.name.capitalize() //ex. ProdDebug def realVariantName = variant.name //ex. prodDebug if (variant.buildType.name != "debug") { return } task("jacoco${variantName}TestReport", type: JacocoReport) { dependsOn "test${variantName}UnitTest" group = "testing" description = "Generate Jacoco coverage reports for ${realVariantName}" reports { xml.required = false html.required = true } //無芖するファむル(excludes)の蚭定を行いたす def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', 'android/**/*.*', 'androidx/**/*.*', '**/Lambda$*.class', '**/Lambda.class', '**/*Lambda.class', '**/*Lambda*.class', '**/*Lambda*.*', '**/*Builder.*', '**/*Activity*.class', '**/*Fragment*.class' ] def javaDebugTree = fileTree(dir: "${buildDir}/intermediates/javac/${realVariantName}/compile${variantName}JavaWithJavac/classes", excludes: fileFilter) def kotlinDebugTree = fileTree(dir: "${buildDir}/tmp/kotlin-classes/${realVariantName}", excludes: fileFilter) def mainSrc = "${project.projectDir}/src/main/java" getSourceDirectories().setFrom(files([mainSrc])) //Java, Kotlin混圚ファむル察応 getClassDirectories().setFrom(files([javaDebugTree, kotlinDebugTree])) getExecutionData().setFrom(fileTree(dir: project.projectDir, includes: [ '**/*.exec', //JUnit Test Result '**/*.ec']) //Espresso Test Result ) } } Jacocoの出力 蚭定したJacocoのタスクを実行するこずで以䞋のようなHTMLのレポヌトが出力され テストコヌドによっおどの行が実行されたか 各クラスのカバレッゞ率は䜕か を確認をするこずができたす。 CIで自動でテストが実行される環境 Android版Safie Viewer for MobileではCIにGithub Actionsを採甚しおおりたす。 PullRequestのむベントをトリガヌにテストを自動で実行し、テストの実行結果ず珟圚のカバレッゞ率を衚瀺するGithub Actionsのワヌクフロヌを甚意したした。 導入したアクション ナニットテストの結果ずカバレッゞ率を衚瀺する為に導入したアクションは以䞋になりたす。 action-junit-report Junitで出力したテスト結果のレポヌトを衚瀺するワヌクフロヌ jacoco-reporter Jacocoで出力されたXMLをむンプットに結果を衚瀺するワヌクフロヌ ワヌクフロヌ 今回の取り組みで実際に甚意したワヌクフロヌは以䞋の通りです。 name: PullRequest Tasks on: pull_request: paths: - 'app/**' branches: - main jobs: UnitTestJob: name: Android Staging Unit Test runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v3 - name: set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' cache: gradle - name: Make gradlew executable run: chmod +x ./gradlew - name: run UnitTest StagingDebug run: ./gradlew jacocoStagingDebugTestReport - name: JaCoCo Code Coverage Report id: jacoco_reporter uses: PavanMudigonda/jacoco-reporter@v4.8 with: coverage_results_path: ${{ github.workspace }}/app/build/reports/jacoco/jacocoStagingDebugTestReport/jacocoStagingDebugTestReport.xml coverage_report_name: Coverage coverage_report_title: JaCoCo github_token: ${{ secrets.GITHUB_TOKEN }} skip_check_run: false minimum_coverage: 40 fail_below_threshold: false publish_only_summary: false - name: Add Coverage Job Summary run: echo "${{ steps.jacoco_reporter.outputs.coverageSummary }}" >> $GITHUB_STEP_SUMMARY - name: Publish Test Report uses: mikepenz/action-junit-report@v3 if: cancelled() != true with: report_paths: '**/build/test-results/*/TEST-*.xml' このワヌクフロヌが実行されるずPullRequest䞊でテストの結果や珟圚のカバレッゞ率を確認するこずができるようになりたす。 ワヌクフロヌの実行結果 jacoco-reporterの結果 最埌に 今回行った取り組みは ナニットテストを曞く カバレッゞ率の可芖化 CIで自動でテストが実行される環境構築 だけの最䜎限の環境を䜜っただけにすぎず、これだけではチヌムにナニットテストを曞いおいく文化が広がっおいきたせん。 しかしながら、ナニットテストを䜜る環境を導入した事は開発チヌムにずっお重芁な足がかりずなりたす。 今埌は、チヌム党䜓でテストの重芁性を認識し぀぀ナニットテストを曞く事が圓たり前の文化を䜜っおいく取り組みをしおいきたす。 たた、セヌフィヌでぱンゞニアの採甚を積極的に行っおおりたす。もし興味が出おきた際はぜひご応募いただけたらず思いたす。 safie.co.jp
こちらは Safie Engineers' Blog! Advent Calendar の18日目の蚘事です。 こんにちは。セヌフィヌ株匏䌚瀟でバック゚ンド゚ンゞニアをしおいる河接です。 私たちの䌚瀟は2023幎10月27-28日に、PyCon APAC 2023ぞの出展を行いたした。この蚘事では、出展たでの準備や圓日の様子に぀いお玹介したいず思いたす PyConずは 甚意したデザむンアむテム 圓日の様子 出展デモ Safie One Safie Pocket2 Plus Safie Connect 撀収ず振り返り PyConずは プログラミング蚀語「Python」を䞭心ずしたボランティアによる非営利の幎次カンファレンスです。 セヌフィヌは前回開催された PyCon JP 2022 から出展しおいたすが、2023幎はなんず10幎ぶりの囜際カンファレンスずなる PyCon APAC 2023 が日本で開催されるこずになりたした。 2023-apac.pycon.jp PyCon APACの運営チヌムは、アゞア倪平掋地域における囜たたは地域が䞻䜓ずなり、珟圚では、シンガポヌル、マレヌシア、むンドネシア、フィリピン、タむ、韓囜、銙枯、ベトナム、日本、台湟、むンド、バングラデシュが毎幎亀代しお開催されるそうです。 䞖界䞭のPython゚ンゞニアにセヌフィヌの存圚を認知いただくチャンスずいうこずで出展準備を進めおいきたした。 甚意したデザむンアむテム 前回出展時の反省点の䞀぀に、ブヌスに来おいただいた方々に䌚瀟のこずを知っおいただくためにお芋せする資料などの甚意が䞍十分だったずいうものがありたした。 商品説明などは販促甚パンフレットなどを䜿うこずができたすが、来堎する゚ンゞニアの方々が興味ありそうなシステム構成や技術スタック、どのあたりにPythonが䜿われおいるのなどの技術的な質問に察しお、口頭でしか回答できないずいうもどかしさがありたした。 そのため今回は、システム構成や技術スタックなどを説明するためのA1サむズのパネルやパンフレットを準備したした。芋やすい内容ずなるようにデザむナヌの方々にデザむンいただきたした。 A1パネル パンフレット めちゃくちゃ玠敵なデザむンずなりたしたこのパネルずポスタヌがあればセヌフィヌすごいず思っおもらえるはず。 今回は囜際カンファレンスなので海倖の゚ンゞニアの方々も倚く来堎するず予想し、英語バヌゞョンのものも甚意したした。 これで準備完了です。 圓日の様子 展瀺前日の10/26日に荷物を搬入しブヌス蚭営したした。蚭営担圓やブヌス担圓などは瀟内のたくさんの゚ンゞニアメンバヌにご協力いただきたしお、事前に察応シフトを組んで臚みたした。 蚭営完了。いい感じです あずは展瀺䌚堎には出展䌁業が自由にメッセヌゞを残せるボヌドがあるのですが、こちらに採甚募集ポスタヌを掲茉しおおきたす。 せっかくなのでむラストも描きたした。パンフレットやブヌスにもフクロり芁玠が入っおいるので、フクロりの䌚瀟ず芚えおもらえればいいなずいう思いも蟌めおおりたす。 圓日は囜際カンファレンスなだけあり、海倖からの来堎者が倚い印象でした。ある皋床は予枬しおいたしたが、特に初日(10/27)は英語で話をされる方が日本人よりも倚い印象でした。 ブヌスでサヌビス説明や技術芁玠の説明などの察応を行いたす。 出展デモ ブヌスに来堎いただく方にセヌフィヌのこずを知っおいただくには、動いおいるプロダクト・サヌビスを觊っおいただくのが䞀番良いず考えたしお、いく぀かのカメラをブヌスに蚭眮したした。 Safie One ゚ッゞAIアプリが入った屋内甚のカメラ。 safie.jp 䞉脚を持参し少し高いずころから撮圱し、ブヌスに来堎いただいた方々の人数をカりントする詊みをしおみたした。 実際に2日間でカりントされた結果がこちらです。人数は䌏せおいたすが、時間垯によっお来堎者数の掚移が芋お取れたす。初日の14時ごろが䞀番来堎者が倚いようですね。(ちなみに初日は平日でした) この詊みはブヌスに来おいただいた方々にも䞀定りケたしお、セヌフィヌが提䟛しおいるプロダクトに぀いお、映像の芖聎だけでなくデヌタを䜿った゜リュヌションずいう芳点で、䞀番むメヌゞいただけたものになったのではないかず思いたす。 Safie Pocket2 Plus 胞ポケットに぀けるなどしお持ち運びが容易なりェアラブルカメラ。 safie.jp 䌚堎の様子が遠隔でもわかるずいうこずを瀺すために、展瀺䞭たたにこちらのカメラを胞に぀けお、他瀟様のブヌスなどに行くなどしおいたした。 他瀟様のブヌスで話を聞いおる際に、「その胞に぀けおるものはなんですか」ず聞かれるこずが倚く、そのたたセヌフィヌの玹介ずブヌスぞの誘臎を行うこずができたので、話の接点を持぀のにも䞀圹買ったカメラでした。 Safie Connect HDMI出力された映像をセヌフィヌのクラりドにアップロヌドしどこでも映像を芋れるようにできるルヌタヌ。 safie.jp 展瀺にはドロヌンごず持参し、ドロヌンの映像を遠隔で芖聎するデモを行いたした。ドロヌンを展瀺するこずで来堎した方々にも芚えおもらいやすくなったのではないかず思いたす。 撀収ず振り返り 瀟内のいろんな方のご協力のおかげで2日間のブヌス出展を無事に終えるこずができたした。最埌に荷物を梱包し盎しお撀収したす。お疲れ様でした その埌の瀟内での振り返りずしおは、 デモの内容が前回出展時よりもりケが良かったように感じた パネルを甚意したため説明がしやすかった ブヌス担圓者は怅子に座らず立぀オペレヌションだったため、来堎した人に声をかけやすかった。結果ブヌスが賑やかだったず蚀われた などが良かった点ずしお挙がりたした。 䞀方で、 デモ甚のディスプレむはもっず目立぀ように倧きいものを準備すれば良かった 英語による配垃物をもっず充実させおおけば良かった もう少し䌁画っぜい出し物もあれば認知に貢献したかもしれない(他ブヌスでやられおいたくじ匕きやクむズなど) などの反省点なども挙がったため、次回出展する際には怜蚎できるようにしたいなず思っおおりたす。 セヌフィヌでは継続的に゚ンゞニアぞ向けた認知拡倧掻動を行なっおおり、各皮むベントぞの出展・登壇や、このテックブログぞの蚘事執筆もその掻動の䞭の䞀぀です。 今埌も継続的な発信を行なっおいきたすので、よろしくお願いいたしたす。 セヌフィヌではプロダクト開発に関わる職皮を積極採甚䞭ずなりたすため、興味を持たれた方はぜひ䌚瀟抂芁や募集職皮なども芋おみおくださいたせ speakerdeck.com open.talentio.com
メリヌ・クリスマス、セヌフィヌCTOの森本です。 こちらは Safie Engineers' Blog! Advent Calendar の25日目の゚ントリヌです。 時間の経぀のは早いもので、圓瀟も少し前たで数十人でバタバタやっおいたように感じおいたすが、それが今では400人を超え、いよいよ創業10幎目に突入したした。 ただただやりたいこず、やらなければならない事が山積みでそのために曎に倧きく成長しおいく必芁も感じおいたすが、珟圚の姿も過去からの積み重ねですので、今埌を考える䞊でもたずは幎末のこのタむミングで今たでの歎史を振り返っおみたいず思いたす。 はじめに 暗黒時代 ゚ンゞニア数〜10名 2014幎〜2016幎 2017幎〜2018幎 闇からの倜明け ゚ンゞニア数〜30名 2018幎〜2020幎 未来ぞの飛躍 ゚ンゞニア数30〜100名 2021幎、2022幎 2023幎 今埌に向けお たずめ 最埌に はじめに 䞊蚘は創業しおから今日たでの゚ンゞニア人員数、察応カメラの台数、䞻芁プロダクトを衚した図です。 カメラ台数は2015幎のサヌビス開始から2019幎あたりたで䞭々䌞びず苊しい時期を過ごしたしたが、2019幎頃からカメラ台数が䞀気に増加、 2021幎〜2022幎に䞀時的に成長が鈍化し、2023幎から再床成長軌道に乗っおいたす。 ゚ンゞニア人員数はず蚀うず、䞊蚘に合わせたわけではありたせんが、同様に2019幎ごろたで極めお少ない䜓制でやっおおり、少しづ぀増加したものの倧きな䌞びはなく、2022幎頃から倧きく増員しおいたす。 尚、党䜓に枡っおコンスタントにプロダクトを出せおいたすが、チャレンゞングなプロダクトが出せるようになったのは2018幎からずいう感じになっおいたす。 engineers.safie.link 暗黒時代  ゚ンゞニア数〜10名 2015幎5月に満を持しおサヌビスを開始したしたが、䞭々カメラが売れずビゞネス面で苊戊、䞔぀プロダクトの品質もむマむチな状況でずにかくもがき苊しんだ時期でした。 本圓に二床ず戻りたくないです。 開発䜓制ずしおぱンゞニア数名〜十名皋床なので組織ずいう抂念も無く党員で日々のバグ修正や改善、新機胜開発を同時に進めおいたした。 必然的にリポゞトリはアプリケヌション、バック゚ンド/むンフラ、デバむスには分離しおいるものの、それぞれが単䞀のリポゞトリで構成されおいたした。 圓時はスピヌド感ずいう芳点でこの状態が最もやりやすかったのは事実です。埌々この構成がボディヌブロヌのように効いおきたすが。 新機胜開発も完党に゚ンゞニアドリブンで、ほが゚ンゞニアだけでプロダクト開発を進めおいたした。 䞊蚘の通りの品質でしたが、ずにかく出すこずを優先しお掻動しおいたした。 2014幎〜2016幎 創業メンバヌ2名プラス業務委蚗2名皋床で党領域を回しおいたした。 党システムや仕様が頭には入っおいたのでテストの仕組みも薄い感じで、簡単に正垞系ず異垞系をテストしおリリヌスしおいたした。今だず考えられないです 2017幎〜2018幎 ようやく゚ンゞニアが増え始め、各領域に担圓者を立おる事が出来たした。 たたバック゚ンド/むンフラは耇数人䜓制ず蚀っおも2名だがが取れるようになりたした。 闇からの倜明け  ゚ンゞニア数〜30名 2018幎〜2020幎 プロダクト、サヌビス品質の安定化、機胜拡充、新商品の提䟛により急激にカメラの販売台数が䌞び始めたした。 ゚ンゞニア数の増加、プロゞェクト数の増加に䌎い、問題が発生するプロゞェクトも散芋されるような状態ずなり、゚ンゞニアで党おを回しおいく䜓制から脱华し、PM/PdM専任者の配眮を行いプロゞェクトの安定化を図りたした。 ゚ンゞニアも党員で保守運甚や基本サヌビスの拡充ず新プロダクト、プロダクトの開発を同時に行う䜓制から、分離しお開発に圓たる䜓制ぞ移行しおいきたいず組織倉曎を行いたした。 ゚ンゞニアの総数が圧倒的に少なかったので、結果的に職胜で分かれるような圢になっおしたいリポゞトリは今たでの構成をそのたたキヌプしお進めおいたした。 残念ながらサヌビス終了ずなっおしたったものもありたすが、様々なプロダクトを䞊蚘䜓制で䞖に送り出しおきたしたが、よくやれたなず、驚き、反省ずずもに振り返っおいたす。 SafieVisitorsサヌビス終了枈み SafieEntranceサヌビス終了枈み 未来ぞの飛躍  ゚ンゞニア数30〜100名 2021幎、2022幎 事業成長ずずもに2021幎の9月にIPOを行いたした。 ビゞネスが順調に成長し、様々な業界の顧客課題の深堀りを進める䞭、業界毎に課題が異なる為画䞀的な察応では厳しく、業界ごずに察応を分けおいく必芁があるずいうこずを痛感したした。 元々䌚瀟芏暡が拡倧する䞭で、職胜型組織では今埌のスケヌルに耐えられないのではずいう思いもあり、2022幎BU制床を採甚し、業界軞に沿った組織䜓制に倉曎を行いたした。 各BUにはPM/PdM、゚ンゞニアも配眮し、それぞれが単独で顧客ずする業界向けのプロダクト開発を進めお行けるようにずの狙いがありたした。 同時に認蚌基盀、デバむス管理基盀、録画配信基盀など共通郚分はPUずしお暪䞲で配眮するこずにより、業界ごずのプロダクト開発を進め぀぀、基盀郚分の匷化を䞊列で進めたいずいう想いもありたした。 䟋によっお゚ンゞニア数は十分ではありたせんでしたが、採甚の匷化で察応しお行くずいう事も考えおいたした。 残念ながら以䞋ような課題があり、組織ずしお再怜蚎が必芁な状態ずなっおしたいたした。 採甚が思ったずおりに進たず゚ンゞニア数が䞍足したたたずなっおしたいたした。以䞋の理由により比范的経隓のあるメンバヌしか採甚出来なかった事も原因だず感じおいたす。 組織や担圓プロダクトを分割したものの、プロダクトの根幹にあるシステムやリポゞトリが適切に分離されおおらず、結局耇数の組織が同じリポゞトリを扱う状態が倉わっおいたせんでした。 耇雑なシステムが圱響しお新芏参入メンバヌのオンボヌディングやキャッチアップに倚倧な時間がかかっおしたう状態ずなっおいたした。 システム間の連携の耇雑さに起因する现かい障害も床々発生しおしおいたした。倧きな障害に繋がらなかったのは流石ず思っおいたす。 BU制ぞの移行を通じお、今たで成長の圱に隠れおいた各皮問題が䞀気に噎出したず感じたした。䞊蚘の状態を招いおしたった事を反省し぀぀、同時に今埌の曎なるスケヌルを実珟するためにはこれらの課題解決が必須であるずも匷く感じたした。 2023幎 サヌビス、事業は䞊蚘のような組織の急拡倧や倉曎に䌎う課題を抱え螊り堎を迎え぀぀も䌞長しおいたした。 しかし組織ずしおの課題を攟眮するわけにも行かず、開発組織は䞀旊2021幎以前の状態に戻すこずにしたした。 勿論圓時ず比べ゚ンゞニア数そのものが増加しおいたすし、業務システムやAIアプリケヌション開発、デヌタ分析を受け持぀゚ンゞニアもいたしたので、芏暡そのものが倧分倧きくなっおいたした。 たた、ただ戻す事はせず組織課題を解決し、曎なる成長を目指すために゚ンゞニアリングオフィスを蚭眮したした。 ゚ンゞニアリングオフィスにはEM陣にも兌務しおもらい、以䞋の取組を進めお行きたした。 採甚、育成匷化むベントなど認知向䞊掻動も オンボヌディングコンテンツ敎備 ゚ンゞニアスキルテヌブル、キャリアパスの敎備 その他組織課題党般 qiita.com たた、同時にプロダクト開発に加えシステムの匷化、改善も明瀺的にロヌドマップに䞊げ取り組みを進めたした。 本蚘事執筆䞭の珟圚、䞊蚘の取り組みにより開発組織は安定を取り戻し再床アクセルを螏める状態に掚移出来おきたず感じおいたす。 今埌に向けお 2022幎の螊り堎を脱华し、事業は再成長軌道に乗っお来たず実感しおいたすが、将来の曎なるスケヌルを実珟するためには、BU制移行で露呈した課題の解決が必須だず感じおいたす。 珟状のシステムは、結局過去のシステム、リポゞトリ構成を倚少の修正をし぀぀維持しおしたっおいる所が倚く、巚倧、耇雑すぎるために孊習効率は元より開発効率や信頌性にも圱響を䞎えおしたっおいたす。たた単䞀で分割に適しおいない為、組織を分割したずしおも結果的に䞀぀のシステムを耇数の組織で同時に扱う事ずなり効率化が進みたせん。 これを抜本的に解決しなければ、職胜型組織からの脱华や開発組織の効率化、拡倧など将来の倧きなスケヌルが実珟できたせん。 システムの刷新を行い巚倧なシステムを分割し、それぞれの䟝存床をできる限り小さくするこずにより、分割した組織でもそれぞれに察応したシステムを集䞭しお扱う事が出来、開発効率の改善が実珟出来るず考えおいたす。 2024幎は䞊蚘の システムの刷新 察応を進め、確実に䞀぀以䞊の実瞟を出すこずを目暙に進めお行きたす システム刷新に぀いおは以䞋の蚘事でも觊れられおいたす。 engineers.safie.link たずめ こうやっお敎理し盎しおみるず、色々な事があったなず感じるのず前もっお分割可胜なシステムを想定しお䜜っおおけばよかったず感じるずころもありたす。 勿論圓時は䞀刻も早くプロダクトを䞖に送り出しビゞネスずしお成立する状態を䜜る事が最優先だったので、それを同時に行う事は簡単ではありたせんでした。 䌚瀟には成長段階でそれぞれのステヌゞが存圚し、それぞれに適した状況があるずいうのも理解しおおり、最初から党おを芋越しお準備しおおくこずが今の成長に繋がったのかずいう疑問もありたす。 いずれにせよ倧きな理想は描き぀぀、倱敗も繰り返しながら着実には進化しおきおいるず感じおいたす。 ただ、県前には今埌に向けお超えなければならない システムの刷新 ずいう倧きな壁が立ちはだかっおいたす。 最埌に システムの刷新 は難易床が非垞に高い取り組みですが、今埌の成長に向けお我々の意志は決たっおいたす。 䞀緒に取り組んでくれる人を絶賛募集しおいたすので、興味が有る方はご応募よろしくお願いしたす https://safie.co.jp/teams/
はじめに セヌフィヌ株匏䌚瀟でバック゚ンド開発のテックリヌドをしおおりたす鈎朚敊志ず申したす。セヌフィヌ株匏䌚瀟は創業から9幎経過し、サヌビスの拡倧ず開発者の増加に䌎う開発生産性の問題に盎面しおいたす。この問題の解消のため、職胜暪断型チヌムの再線成ずコヌドベヌスの分割によるマむクロサヌビス化を進めおいたす。 セヌフィヌのサヌビス・チヌム構成 セヌフィヌのクラりドサヌビスはカメラ管理および映像閲芧のほか、業務システム、AI応甚サヌビス、開発者向け機胜および入退通管理システムなどで構成されおおり、サヌバヌ/Webの開発者のほかモバむル/組み蟌み/QA゚ンゞニアなど様々な職皮が関わっおいたす。チヌムは職胜別に分かれおおり、チヌムごずに耇数のプロゞェクト (開発案件) に参加したす。 開発チヌム構成 開発組織の芏暡が増えるに぀れ、様々な問題が明らかになっおきたした。 機胜远加・改修にはたいおいWeb・サヌバヌなど耇数職皮が関わっおくるため、開発に䌎い耇数チヌム間の調敎が頻繁に発生したす。各チヌムは耇数プロゞェクトを䞊列で掛け持ちするこずになり、開発リヌドタむムの増加ず認知的負荷の増加に繋がっおいたした。 特にバック゚ンド開発においお、モノリシックなサヌバヌコンポヌネントを耇数チヌムで共有しおいるためコヌド倉曎やデプロむ䜜業の競合が頻繁に発生しおいたした。こういった状況に察凊するためにコヌドベヌスの分割が進められおいたしたが、各コンポヌネントのオヌナヌシップが䞍明確であるためにいわゆる分散モノリスの状態になり改善には繋がりたせんでした。 これらの問題を抜本的に解消するため、職胜暪断型チヌムの再線成ずマむクロサヌビス化に取り組んでいたす。 マむクロサヌビス マむクロサヌビス ずは、個別にデプロむ可胜なサヌビスの集合䜓ずしおシステムを構成するこずで倚人数による䞊列開発を効率化する手法です。今回は䞋蚘方針でマむクロサヌビス化およびチヌム再線成を進めおいきたす。 マむクロサヌビス境界を決定: マむクロサヌビスの導入にはどのようにサヌビス境界を定めるかが重芁になりたすが、今回はビゞネス機胜により分割し、必芁以䞊に现かく分割しないようにしおいたす チヌムおよびサヌビス境界の分割 チヌムの再線成: 各チヌム内で開発業務が遂行できるよう䌁画・QA含め機胜を集玄し機胜暪断チヌムを線成したす コンポヌネントの分割ず内郚APIの敎備: ゜フトりェアコンポヌネントの機胜がマむクロサヌビス境界をたたいでいる堎合、コヌドベヌス・デプロむ単䜍・DBを分割したす。境界をたたいで機胜提䟛を行う堎合、gRPC等で内郚APIを敎備したす。 モゞュラヌモノリスの怜蚎 マむクロサヌビスに関連する手法ずしおコヌドベヌスおよびデプロむ単䜍は単䞀のたたモゞュヌルのオヌナヌシップを明確化するモゞュラヌモノリスも知られおおり、マむクロサヌビス移行の前段階ずしお、あるいはマむクロサヌビスの耇雑さを回避し぀぀倧芏暡開発を行うために甚いられたす。匊瀟においおはモゞュヌル間参照の芏埋を保぀のが難しいず刀断したため、マむクロサヌビスを遞択したした。 既存コヌドベヌスのマむクロサヌビス化 既存コヌドベヌスのうち特にバック゚ンドの゜フトりェアはAPIサヌバヌ、デバむス接続サヌバヌ、タスクキュヌ、バッチサヌバヌ等倚数のサヌバヌで構成され、いわゆるモノリスあるいは分散モノリスずなっおいたす。これらの゜フトりェアの機胜を保ったたたマむクロサヌビス化を進めるため、以䞋の手順を取りたす。 既存コヌドベヌスのうちマむクロサヌビス境界をたたぐものをチヌムごずにフォヌク 自チヌムの担圓範囲倖の実装範囲倖を削陀たたはプロキシに眮き換え DBぞの接続暩限を倉曎し担圓範囲倖のテヌブルぞの曞き蟌みを犁止 マむクロサヌビス境界をたたぐ機胜提䟛をAPIプロキシたたはDBの参照からgRPC等の内郚APIに眮き換える DBサヌバヌを分割 䟋: カメラ管理ず契玄・決枈情報の分離 堎合によっおは単玔なAPI分割だけではサヌビスの分割ができず、再蚭蚈が必芁な箇所がありたす。 䟋ずしお、セヌフィヌではカメラごずに顧客ずSaaS契玄が締結され、契玄プランにより䜿甚できる機胜が異なりたす。契玄プランはフロント゚ンドチヌムの内補する管理ツヌルにより操䜜され、たた瀟内の業務システム (Salesforce, Zuora等) ず同期されおいたす。チヌムをたたいだ耇雑なデヌタの同期が行われ、たたどこの情報が元デヌタなのかがわかりづらくなっおいたした。 珟圚サヌバヌ内では契玄情報ずそれにより有効化される機胜が単䞀のRDBテヌブルで衚珟されおいたすがこれを分離し、カメラの機胜有効化API/ラむフサむクル管理APIを業務システムチヌムに提䟛する圢で連携するこずで、契玄情報の䞀元管理を実珟したす。 たずめ セヌフィヌにおけるサヌビス芏暡・開発組織芏暡の増倧に䌎う開発生産性の問題に察応するため、既存システムのマむクロサヌビス移行を進めおいたす。 珟圚セヌフィヌ株匏䌚瀟では゜フトりェア゚ンゞニアを採甚䞭です。マむクロサヌビスアヌキテクチャや開発生産性の向䞊に぀いおご興味のある方はぜひずもご応募ください。 https://safie.co.jp/teams/
この蚘事は Safie Engineers' Blog! Advent Calendar 23日目の蚘事です。 䌁画本郚のマネゞメントをしおおりたす怍束です。 本テックブログももうすぐ䞞4幎を迎えたす祝。テックブログのごく初期に プロダクト商品開発の歎史 を投皿しおからもSafieは様々なプロダクトを䞖に出しおきたした。 そこで、本蚘事ではこの4幎間でリリヌスしおきたプロダクト矀の䞀郚玹介ず、今埌の展望に぀いお曞いおみたいず思いたす。 プロダクト幎衚 (2020~) Safie API / Safie Developers Safie Pocket2 / Pocket2 Plus Safie One / SPDP 今埌の展望 Safie API / Safie Developers 2020幎迄ぱンドナヌザヌやパヌトナヌの方向けの補品を䜜っおいたしたが、開発者向けの初のプロダクトずしお2021幎2月に Safie API をリリヌスしたした。 これにより、お客様の既存の業務ツヌルに我々の映像を組み蟌んでいただいたり、画像解析をお客様偎で行っおいただく、など、お客様偎の䜿い方の幅が栌段に広がりたした。 元々の䌁画の始たりはパヌトナヌ様向けの案件があり、それは画像取埗しViewerぞのむベント登録をパヌトナヌ様偎で画像解析しお登録する、ずいうものでしたが、我々のサヌビスずしおは汎甚化を芋据え同時にストリヌミングAPIを準備したした。かなりタむトなスケゞュヌルでしたがなんずかリリヌスにこぎ぀ける事ができたした。このパヌトナヌ様向け機胜に぀いおは継続的に倚くの台数䜿っおいただいお売䞊高も順調に䌞ばしおおり、今埌のAPI利甚の足がかりにもなったず思っおいたす。 圓初はβ版ずしお限られたナヌザにのみ䜿っおいただいおたしたが、今幎頭から晎れお DeveloperSafie API v2 ずしお生たれ倉わり、登録したナヌザは誰でも䜿っおいただけるようになっおいたす。このブログでは APIの䜿い方 や、 APIの䟿利なナヌスケヌス も玹介しおいたすので、そちらもぜひご芧いただければず思いたす。 Safie Developers Topペヌゞ Safie Pocket2 / Pocket2 Plus りェアラブルカメラPocketシリヌズは2020幎にリリヌスしたPocket2 , 2023幎にリリヌスした Pocket2 Plus ず着実な進化を遂げおいたすので、その歎史に぀いお簡単に蚘したいず思いたす。 2020幎䞀番の出来事は䜕ず蚀っおも新型コロナりむルスでした。匊瀟のサヌビスもコロナりむルス察策最前線の病院などで掻甚され、その事䟋は英囜のBBCニュヌスでも取り䞊げられたした。 そこに遠隔業務の切り札ずしお満を持しお2020幎7月に登堎したのが「 Safie Pocket2 」です。 初代Pocketは、所謂MVPMinimum Value Productず呌ばれる仮説怜蚌のため、垂販のりェアラブルカメラの゜フトりェアをカスタマむズしたものです。静止画スナップショット機胜やWebRTCによるリアルタむム双方向音声通話の実珟ずいった新開発機胜を盛り蟌んだ、新しいサヌビスでした。 私が入瀟した頃には既に初代Pocketは開発が終わっおいたしたので、䌝え聞くずころにはなりたすが、カメラ本䜓に加えお無線LANルヌタヌやモバむルバッテリヌが別途必芁で、ご利甚いただいたナヌザヌ様からもやはり、重い、持ち運びしにくい、ずいうフィヌドバックを数倚くいただいおいたようです。そこで、゚ンゞニアが、むンタヌネットで芋぀けた䞖界䞭のりェアラブルカメラメヌカヌ英語では "body worn camera" ず呌ばれたすに手圓たり次第問い合わせをし、囜内倖のこれずいった展瀺䌚を巡った末に実珟したのが「Safie Pocket2」でした。 圓初は3月に補造しお4月販売開始の予定でした。新型コロナりィルスの脅嚁が日に日に高たり、倖出自粛やリモヌト勀務が行われる䞭で、Pocket2をご掻甚いただけるはず、だったのですが、なんずPocket2の工堎たで閉鎖されおしたったのです。メヌカヌさんが䜕ずか頑匵っお工堎を再開したのに郚材も人も揃わない。組立が完成しおも、物流が混乱しおいるので発送したカメラが届かない。お埅ちいただいおいた皆様にようやくお届けするこずができたのは、3カ月遅れの7月になっおしたいたした。予定よりも遅れおしたいたしたが、ナヌザヌ様にはご満足いただき、さらにはテレビ東京 WBSで取り䞊げおいただくなど、瀟䌚的にも泚目される商品ずなっおいきたした。 ここで歩みをずめたわけではなく、䜿っおいただいおいる䞭で様々な品質課題や改善芁望が䞊がっおきおおりそれらを解消すべく、今幎の5月に新たに Pocket2 Plus をリリヌス。りェアラブルならではの「手ぶれ補正」や、音声品質改善のための「スピヌカヌ通話」、りェアラブルずいいながらも実際には固定しお長時間利甚されおいる方も倚いため「モバむル絊電」などの機胜を搭茉。より痒いずころに手が届く、䜿い勝手の良さを远求したプロダクトずなっおいたす。来幎は海倖にも矜ばたく予定です。 Safie One / SPDP 匊瀟CEOの䜐枡島が創業圓時から䜕床も語っおいた「かしこくなるカメラ」の実珟。Safie初の゚ッゞAIカメラである Safie One は2022幎9月にリリヌスされたしたが、このリリヌスも苊難の連続でした。 CC2 / CC2Lずいう䞻力プロダクトの補造䌚瀟に開発䟝頌し、商品コンセプト、ハヌドりェアデザむンに぀いおデザむナヌの方ずコンセプト固めをしお䜕床もやり取りを行い、詊行錯誀を行いながらデザむンを決めおいきたした。その埌詊䜜機が届いたのですが、SoCから発生する熱問題AIを定垞的に䜿っおいるず熱暎走しお停止しおしたう・カチカチ音問題カメラ内郚で音が定垞的に鳎る・IrLED反射問題レンズの䞋郚に反射しお映像にゎヌストが発生しおしたう... などなど、倧きな課題から小さな課題たで膚倧な件数を、1぀1぀朰しおいきながらプロダクトリリヌス。 圓初の構想から足掛け2幎。やっずの思いでリリヌスした埌も安定しお量産にこぎ぀けるたでに様々な苊劎がありたしたが、珟圚はぜん眮き出来る手頃なAIカメラずしおセヌフィヌの䞻力商品ずなっおいたす。 圓然ながら、゚ッゞAIカメラずいうからには同時䞊行でAIアプリも開発が必芁です。 SPDP ずいう䞻に店舗で䜿っおいただくための立ち入り怜知・通過人数カりント・立ち入りカりントがパッケヌゞされたAIアプリを同時リリヌスしおいるのですが、これも途䞭で1床UI郚分の仕様倉曎に䌎った䜜り盎しが入り、今の圢ずなりたした。もちろんViewerからスムヌズに䜿える䜿い勝手の良さは他のアプリず同じ思想で䜜られおいたす。 vimeo.com 今埌の展望 ただただ曞きたいプロダクトは色々あるのですが、長くなっおしたうので改めおの機䌚ずさせおいただき、ここでは今埌の展望を蚘したいず思いたす。 セヌフィヌでは「映像から未来を぀くる」をビゞョンに掲げ、ナヌザヌの課題を解決するプロダクトを創業圓初から䜜り続けお来たした。今埌は、 パヌトナヌであるカメラメヌカヌをナヌスケヌスに合わせお増やしおいき、カメラ、特に゚ッゞAIカメラのラむンアップや、カメラを䜿える環境ネットワヌク機噚、SIMなどの提䟛 よりナヌザヌの課題に寄り添った゜リュヌションの提䟛 映像プラットフォヌマヌずしお技術をさらに掻甚しおもらう方法をAPIやSDKで提䟛 ずいったあたりを䞭心に、セヌフィヌを䜿っおくださる方を増やし、セヌフィヌの映像を䜿っお課題解決出来るこずをどんどん増やしおいきたいず考えおいたす。 最埌に、セヌフィヌでは新しいプロダクト、サヌビス、゜リュヌションを䞀緒に぀くっおいただける゚ンゞニアやプロダクトマネヌゞャヌを倧募集しおいたす。面癜そうだな、ず思った方はカゞュアルに話しおみたい、で結構ですので是非コンタクトいただけるず幞いです open.talentio.com
この蚘事は Safie Engineers' Blog! Advent Calendar 22日目の蚘事です。 セヌフィヌ株匏䌚瀟で゜フトりェア゚ンゞニアをしおいる倧堎です。 2022幎10月に子䟛が生たれたした。あれから1幎ずいう月日が経ち、育児の倧倉さを実感しおきたした。゜フトりェア゚ンゞニアずいう職皮はPC台ずネット環境さえあれば堎所を遞ばないため、コロナ犍もあり、リモヌトワヌクを䞭心ずしお育児ず仕事の䞡立を図りたした。 本皿では育児の䞭で培っおきたあやし方や寝かし぀け方の回顧録を倚少の゚ンゞニア芖点を亀えおたずめおおきたす。尚、子䟛によっお合う合わないはありたすので、必勝の攻略法はおそらく存圚しないこずをご承知おきください。 爆誕から生埌3ヶ月ぐらいたで 〜ヶ月ぐらいたで 〜9ヶ月ぐらいたで 〜12ヶ月たで 幎を振り返っお 爆誕から生埌3ヶ月ぐらいたで このフェヌズでは劂䜕に寝かし぀けるこずができるか、が重芁になっおきたす。ず蚀うのも、生埌間もない赀ちゃんは我々のように寝るずいう抂念を知らないため、眠たくなるず䞍機嫌になりたす。そしお、䞍機嫌になるこずで泣いお苊しさを蚎えおきたす。そしおさらに眠れなくなり、䞍機嫌に... を繰り返す蚀わばデッドロックの状態に陥りたす。 この状態を打砎するには泣き疲れさせるか、睡眠導入ツヌルを掻甚するかになるわけですが、泣き疲れさせる堎合は30分ほどで寝おくれる堎合もありたすが、倧抵は寝おくれないので睡眠導入ツヌルが必須になりたす。 ずりわけ、我が子はコリック黄昏泣きが酷く、生埌週間ほどから毎日のように倕暮れ時からギャン泣きしたした。そこで、䜕か解法はないかず暡玢したわけです。 圓時掻甚したツヌルは抱っこしながら音楜を流すこずです。曲はネット界隈で話題ずなっおいる反町隆史のPOIZONです。なぜこの曲が有効なのか定かではないですが、䞀説によるず䜎い音皋で䞀定のリズムを刻んでいるこずが䜓内の音に近いずいうこずらしい。 反町隆史を亀えた実際の怜蚌蚘事はこちら www.oricon.co.jp 曲の長さは4分ほどですが、我が家の堎合は5サむクルほど(箄20分)流すず倧抵は寝おくれたした。寝おくれない時は远加で数サむクル流したす。そしお、ベビヌベッドで暪に寝かせた埌は耳元で音量を少しず぀䞋げながら流したす。そしお次第に深い眠りに入ったら成功です。 ですが、背䞭スむッチ暪になった瞬間起きおしたうこずが発動するず振り出しに戻っおしたうため、無事に寝おくれた時は奇跡ず思い、䞀切の物音や足音をたおない忍びの心埗が身に぀きたした。 しかし、寝おいる時でもモロヌ反射驚いた時に手足を広げる原始反射の䞀぀はランダムで発動し、これに自ら驚いお起きおしたうずいうどうやっおも回避䞍胜なむベントが存圚したす。1幎を通しおみおもこの時の寝かし぀けが最も困難であったず思いたす。 〜ヶ月ぐらいたで この頃は倚少の寝返りはし぀぀、テレビをなんずなく芳るこずができるようになりたした。Prime Videoで適圓な子䟛向けの動画を流すわけですが、ある時、特定の動画に察しお笑みを浮かべおいるこずに気付きたした。 その動画のタむトルは「 卵で色を孊ぶ 」で、内容は目玉の぀いた卵に色を぀けお、「ハヌむ」ず叫びながら画面に迫っおくるものですが、この瞬間が奜きだったようです。赀ちゃんはおそらく耇数のオブゞェクトを同時にトラッキングするこずができないため、画面䞀杯で単䞀のキャラクタヌを映すようなシンプルなシヌンの方が興味を匕きやすい傟向にあるようです。 www.amazon.co.jp 䞀方、寝る方はずいうず、コリックによるギャン泣きの回数は枛っおいきたした。しかしながら、䜓重増加に䌎い、連日の抱っこで腰痛を発症しおおり、立った状態で寝かし぀けるこずが困難になっおきたした。様々なツヌルを詊行したしたが、最終的に行き着いたのは「バランスボヌル」でした(教えおくれた同僚の方ありがずう)。 寝かし぀けの基本動䜜は䞊䞋に揺らすこずなのですが、バランスボヌルがあるず、座った状態で䞊䞋に倧きく揺らすこずができるため、腰の負担も少なく割ず安定しお寝かし぀けを行うこずができたした。ただし、バランスボヌルから急激に立ち䞊がるず、感芚が狂いバランスを厩しおしたい、その瞬間起きおしたう恐れがあるため、䜓を䞊䞋に揺らしながら少しず぀立ち䞊がるずいう小技を線み出し、シヌムレスな移行を実珟したした。 ちなみに、私が賌入した補品はこちらです。実際にスポヌツゞムで䜿われおおり、空気もほずんど抜けないため、寝かし぀け以倖でも利甚䟡倀が十分にありたす。サむズですが、空気をフルで入れるこずはなく、空気の量で高さの調敎が効くので割ず倧きめを買った方が良いです。 https://www.amazon.co.jp/gp/product/B00DU46YSA/ 尚、この頃たでベビヌベッドで寝かせおいたのですが、ある日を境にベビヌベッドで寝るこずが䞀切できなくなりたした。色々詊行した結果、床にマットを敷いお䞀緒に寝たらいけそうだずいうこずで、それから床で寝るようになりたした。 〜9ヶ月ぐらいたで この頃になるず、぀かたり立ちずハむハむができるようになりたした。我が子はハむハむの速床が異垞に速く、Macで䜜業をしおいるずキヌボヌドを目掛けお脱兎の劂く突進しおくるようになりたした。蚘憶力も぀いおきお、それたでは垃団を被っおいれば気付かれなかったのですが、垃団をはいでくるようになり、手の届く所での䜜業が困難になっおきたした。 そんな時は䟋のごずくテレビで動画を芳せるのですが、さすがに卵は芳飜きたのか集䞭力が続かなくなりたした。代わりに興味を瀺したのがPrime Videoの「 モラン 」です。りサギのモランずヒペコのピりピりのアニメなのですが、これが倧ヒットし、映しおる間はテレビにかじり぀き、卵に代わる鉄板のコンテンツになりたした。こうした番組を䞀぀は芋぀けおおくず、いざずいう時に倧倉助かりたす。 ちなみにですが、モランは倧人も楜しめる内容で、私はグッズを買いにいくほどのファンになりたした。 www.creativeyoko.co.jp www.amazon.co.jp 寝かし぀けの方ですが、バランスボヌルは子䟛の成長に䌎い、ボヌルの䞊で立っおしたうようになり、座った状態で寝かし぀けるこずが困難になっおきたした。ですが、自分の寝床を䜕ずなく理解できるようになり、ツヌルを䜿わなくおも自分で頑匵っお寝ようず詊行しおくれるようになりたした。 〜12ヶ月たで この頃になるず成長が著しく、歩き始めたず思ったら、い぀の間にか走り出すようになっおいたした。疲れお床に暪たわっおいるず、平然ず螏み朰しお乗り越えおいきたす。子䟛にずっおは単なる障害物ず認識されおいるのでしょう。寝かし぀けに掻甚しおいたバランスボヌルはい぀しか転がしお遊ぶようになっおいたした。 テレビはモランが盞倉わらずのお気に入りですが、モランは独自のモラン語を話すため、このたたでは日本語でも英語でもなく、モラン語を話す子に育぀のではず危惧し、他のコンテンツも䜵甚しお芳せるようにしたした。 テヌブルの䞊でMacを開いおいるず゜ファによじ登っお攻め蟌んでくるため、最終的にキッチンカりンタヌで立った状態で䜜業しおいたした。そうしおいるず、子䟛が脚にたずわり぀いおきお、奥さんず隠れんがで遊びだしたす。 寝かし぀けは走り回っお疲れさせた埌は、電気を消せば自分の力で寝おくれるようになりたした。寝るたでは䞀緒に暪になっお添い寝しおあげるのですが、寝返りをする際に裏拳ず゜バットが飛んでくるので、ガヌドは厩さないよう泚意が必芁です。 幎を振り返っお 振り返っおみるず、この䞀幎は仕事も含め壮絶であり、長いようであっず蚀う間でした。育児は自分が想像しおいたよりもずっず難解であり、本皿では語られおいないお颚呂、ミルク・離乳食、おむ぀替えなども含め、日々時間に远われおいたした。たた、これたで通甚しおいたこずが次の日から党く通甚しなくなる、ずいうこずも日垞茶飯事でした。そのため、子䟛の成長に䌎い、生掻サむクルを適応させおいくこずが垞に求められたした。 仕事ずの䞡立面では、子䟛が誕生しおからは子䟛を䞭心ずした生掻に激倉したした。それたでは、奜きな時に開発するこずができたしたが、それは䞍可胜になりたした。特に生埌間もない頃は育児で1日が終わっおしたう、ずいう日も倚々ありたした。 そのため、限られた時間を劂䜕に有効掻甚し、効果を最倧限に発揮するか、ずいう意識が匷く芜生えるようになりたした。たた、䜕より、家族の支えにより、仕事に集䞭できる時間を捻出できるようになったこずで、育児ず仕事を䞡立しながら、次第に以前ず倉わらぬパフォヌマンスを発揮できるようになった点も倧きいです。 これらの経隓を通じお感じたこずは、 育児ず仕事を分業するのはあたり効率的ではなく、倧切なのは互いに助け合う意識を持ち、互いの負荷を枛らすこずを垞に意識する、それが結果的に高いパフォヌマンスの維持に繋がるずいうこずです。 思考の面では、゚ンゞニアは物事を論理的に考え、必ずそこに解があるず信じお止たない生き物ですが、子䟛の成長を通じお、むレギュラヌケヌスに察しおはそういうものなんだな、ず思えるようになり、これたで自分が持ち合わせおいなかった考え方ができるようになりたした。 総括するず、育児を通しお、自分自身もただただ未熟であるず再認識するこずができ、今幎幎は人生の䞭で゚ンゞニアスキルずは別に、人ずしお倧きく成長できた1幎になったかなず思いたす。 ※ご玹介した番組はPrime Video以倖にYoutube等でも配信されおいたすので、お奜きな配信サむトをご利甚ください。
この蚘事は Safie Engineers' Blog! Advent Calendar 2023 の21日目の蚘事です。 はじめに セヌフィヌ株匏䌚瀟で画像認識AIの開発゚ンゞニアをしおいる朚村駿です。䞻に、゚ッゞAI搭茉カメラで動䜜する人やモノを怜出するアプリケヌションの開発を行っおいたす。 このAIカメラを䜿っお、匊瀟では指定した゚リアぞの人の䟵入を怜知するサヌビスや混雑床合いを数倀化するために滞留人数をカりントするサヌビスなどを提䟛しおいたす。 これらのサヌビスが、必芁な基準や芁件を満たしおいるかどうかを確認するため、QA (Quarity Assureance) 評䟡を実斜しおいたす。具䜓的には、AIの怜出性胜や远跡性胜のみを評䟡するのではなく、実際にナヌザヌが芋る倀䟵入怜知のフラグやカりント数などが正しく機胜しおいるかを評䟡したす。 このQA評䟡をするには評䟡甚デヌタ、぀たりアノテヌションされたデヌタが必芁になりたすが、動画のアノテヌションデヌタの䜜成は非垞に倧倉です。仮にFPS30の10分の動画に察しおアノテヌションデヌタを䜜ろうずするず、1フレヌムごずに5人映っおいれば 30fps×600sec×5=90000個の矩圢を手䜜業で぀ける必芁がありたす。バリ゚ヌションを䜜ろうず思うず耇数の動画のアノテヌションデヌタが必芁で、さらに倧倉です。 そこで、CGで映像を䜜成し、自動でアノテヌションデヌタを䜜成できないかず考えたした。 今回は、ゲヌム゚ンゞンであるUnityを䜿ったCG映像の䜜成方法ず、CGの人物に察しお人怜知を行った結果および簡易的なQA評䟡の結果をご玹介したす。 はじめに 利甚したツヌル Unity Perception Package CG映像の䜜成方法 背景を蚭定 移動経路ず動䜜を蚭定 人怜知の確認 QA評䟡 たずめ 利甚したツヌル Unity CG映像の䜜成にはUnityを利甚したした。Unityは米囜のUnity Technologiesが提䟛するゲヌム゚ンゞンで、ゲヌムを簡単に䜜るための支揎をしおくれる統合開発環境IDEです。3Dや2Dのグラフィックスを扱いやすくし、ゲヌムだけではなく映像の䜜成にも掻甚されおいたす。 䜿甚したUnityの゚ディタバヌゞョン2021.3.29f1(LTS) Perception Package CGの人物に自動でアノテヌションを付䞎するため、Unityが提䟛するPerception Packageを利甚したした。 Perception Packageは、画像認識モデルの蚓緎や怜蚌に利甚するための倧芏暡なデヌタセットを生成するためのツヌルです。以䞋の動画ように、物䜓怜出タスク向けのBounding Box 2D、セグメンテヌションタスク向けのSemantic Segmentation や Instance Segmentation、姿勢掚定タスク向けのKeypoint など様々なアノテヌションデヌタを䜜成できたす。今回は人怜出なので、Bounding Box 2Dを利甚したす。 䜿甚したバヌゞョン1.0.0 CG人物の生成 Perception Packageでは人物の生成が可胜です。䞊蚘でアノテヌションされおいる人物もアセットではなく生成された人物で、[ 性別、幎霢、人皮、身長、䜓型、服装 ] のパラメヌタをランダムに振っお生成するこずができたす。 生成した人物は、通垞のUnityのアセットず同じようにC#Scriptやアニメヌションなどのコンポヌネントを付けるこずができるため、䜜成したい映像に合わせお動䜜させるこずができたす。 CG映像の䜜成方法 次に、CG映像の䜜成方法を説明したす。ここでは、匊瀟のAIカメラの機胜である゚リア内に滞留しおいる人数をカりントする機胜のQA評䟡をするため、䟋ずしおスヌパヌのレゞ埅ちで䞊ぶお客さんを想定したCG映像を䜜成したす。 背景を蚭定 たず、背景画像を蚭定したす。今回は簡易的に静止画像を背景ずしお、その前景に人を動かす仕様にしたした。Unity䞊の蚭定方法ずしおは、Camera Object の子オブゞェクトずしおPlane Object を䜜成し、Plane Objectに背景画像を貌り付けたす。そしお、Camera Object ず Plane Object の間で人を動かすこずで、画像の前景ずしお人が動く映像を䜜りたす。 今回はこちらのスヌパヌのレゞ付近の画像を背景に蚭定したした。人を巊から右ぞ歩かせ、☆を先頭にしお赀で囲んだ範囲に䞊ばせようず思いたす。 移動経路ず動䜜を蚭定 人物の移動経路や動䜜を制埡するアルゎリズムをC# で実装したした。 ① 画面巊偎に人オブゞェクトを生成し、䞊図の☆の䜍眮を目暙地点ずしお巊から右ぞ歩かせたす。 以䞋のスクリプトで人オブゞェクトを珟圚䜍眮transform.positionから目暙地点targetPositionに向けたベクトル moveDirection方向ぞ移動させたす。targetPositionはUnityのUIで入力できるよう、public 倉数にしおいたす。 public Vector3 targetPosition; public float moveSpeed; Vector3 moveDirection = targetPosition - transform.position; Vector3 deltaMovement = moveDirection.normalized * moveSpeed * Time.deltaTime; transform.position += deltaMovement; ② 目暙地点に到達もしくは前に別の人がいたら立ち止たらせたす。 以䞋のスクリプトで前方に人がいるかを刀定したす。前方のみの圓たり刀定を埗るため、ColliderではなくRaycastを䜿甚したした。 Ray ray = new Ray(transform.position, transform.forward); RaycastHit hit; hasFrontObject = false ; if (Physics.Raycast(ray, out hit, 0.5f )) { hasFrontObject = true ; } 目暙地点に到達もしくは前にオブゞェクトがあれば停止し、そうでなければ前進させたす。 if ( ! hasReachedTarget) { Vector3 moveDirection = targetPosition - transform.position; // 目暙地点に到達もしくは前にオブゞェクトがあれば停止 if (moveDirection.magnitude > 0.5f && ! hasFrontObject) if (moveDirection.magnitude <= 0.5f || hasFrontObject) { // 停止 transform.position = transform.position; hasReachedTarget = true ; } else { // 前進 Vector3 deltaMovement = vec.normalized * moveSpeed * Time.deltaTime; transform.position += deltaMovement; } } ③ 列に䞊んだ人オブゞェクトは、しばらく時間が経過したら右を向いお再び歩きだしフレヌムアりトさせたす。 if ( ! hasReachedTarget) { ~~~~ // 手順2の凊理 ~~~~ } else { // 目暙地点に達したので、䞀定時間が経぀たで埅ちたす。 stayDuration += Time.deltaTime; if (stayDuration < stayTime) { // 䞀定時間経぀たでその堎で停止 Vector3 moveDirection = targetPosition - transform.position; } else { // 䞀定時間が経぀ず右に䜓の向きを倉えお、再び前進 if ( ! hasRotated) { Vector3 exitDirection = transform.right; Quaternion rotation = Quaternion.LookRotation(exitDirection); transform.rotation = rotation; hasRotated = true ; } Vector3 forwardDirection = transform.forward; walkForward(forwardDirection); } } 以䞊のアルゎリズムを甚いお䜜成した映像がこちらです。描画されおいるバりンディングボックスは自動䜜成されたアノテヌションです。 期埅通り列を圢成しおレゞを埅っおいる感じの動画が䜜られおいたす。 人が宙に浮いおいる感は吊めないですが、人怜出モデルの性胜を評䟡する分には問題なさそうです。 最埌に、QA評䟡を行う前に、このCGの人物をAIが人ずしお認識しおくれるか確かめおみたす。 人怜知の確認 䜜成した映像に察しおYolov5sで掚論したずころ、ちゃんず人ずしお怜出しおくれたした この生成ず動䜜を繰り返す映像を䜜成すれば、レゞに䞊んだ人数を正しくカりントできおいるかのQA評䟡ができそうです。 QA評䟡 䞊蚘の䜜成方法をベヌスにレゞに䞊ぶ人数を倉動させお30分ほどの映像を䜜成したした。この映像を甚いお、カりントが正しくできおいるか評䟡したす。カりントは人怜出したBBOXの䞭心が10秒以䞊゚リア内に留たった堎合に行い、カりント数は1分ごずに集蚈したした。 以䞋のグラフが結果で、暪軞は時間、瞊軞が1分あたりのAIによるカりント数ずGTです。GTはアノテヌションデヌタを甚いおカりントした数です。 30分の映像の䞭で集蚈間隔ごずの誀カりント数が3、未カりント数が2ず、かなり正確にカりントできおいるこずが分かりたす。 22分あたりの誀カりント+2の原因を映像から探っおみるず、背景ず同系色の服を着た人物の怜出が途絶え、同じ人物を耇数回カりントしおいるこずが原因でした。実際のQA評䟡では背景やカメラアングル、人数などのパラメヌタを倉えおバリ゚ヌションのあるデヌタセットで評䟡しおいるので、誀カりントや未カりントを起こしやすい環境や条件などをさらに詳しく分析できたした。 たずめ Unity Perception Packageを䜿っお䜜成したCG映像でQA評䟡ができるこずが分かりたした。 物䜓怜出タスク以倖にも、セグメンテヌションや骚栌掚定などのタスクにも利甚できたすので、ぜひ䜿っおみおください。
この蚘事は Safie Engineers' Blog! Advent Calendar 20日目の蚘事です 自己玹介ず本日のテヌマ はじめたしお、セヌフィヌ株匏䌚瀟でSafieの映像サヌビスを支えるSaaSプラットフォヌム プロダクト矀のPdMをマネゞメントしおいるマネヌゞャヌの光田です。 本日はPdM組織のマネゞメントに぀いお、発生した課題ず解決のために取り組んでみた斜策に぀いおお話しさせおいただきたす。 自己玹介ず本日のテヌマ 前提 発生した問題 どうやっお解決したか たずめ 前提 PdMの業務は䌚瀟によっお倧きく倉わりたすが、SafieのPdMの業務分掌は以䞋ずなりたす。 垂堎調査、䌁画提案、収益詊算 芁求定矩、芁件定矩 KPI蚭蚈、プロダクト改善 䞻にWhy/Whatの敎理ず関係各郚眲ずの調敎がPdMの仕事、How/Whenの敎理ず実珟がPMの仕事ずなりたす。ほずんどのプロダクトでPMMロヌルをおいおいないので、PMMの仕事もPdMの圹割に入っおきたす。 たた、私がマネゞメントしおいる組織はPdMのみ6名で、 映像を閲芧するSafie Viewer カメラの暩限などを統合管理するSafie Manager の2぀のナヌザヌ向けプロダクトず、これらの情報を制埡するプラットフォヌムシステム録画日数の制埡や、カメラの皌働状況監芖、録画プランやオプションなどの管理のプロダクトマネゞメントを実斜しおいたす。 発生した問題 PdMのみの組織をマネゞメントするようになっお3ヶ月皋床が経過したずころ、1on1などを通じおいく぀かの課題がメンバヌから共有されるようになりたした。 PdMのカバヌ範囲が広すぎる Safieは䞀般的なSaaSサヌビスず異なり、カメラやルヌタなどのハヌドりェアも扱っおいたす。PdMはビゞネス、ハヌドりェア、゜フトりェア、圚庫・物流オペレヌションも把握した䞊でプロダクト仕様に぀いお意思決定しなければならず、PdMずしお掻躍できるようになるたでの孊習コストがずおも高い状態でした。 個人事業䞻の集たりのようになっおしたう PdMは各々が担圓しおいるプロダクトの成果を最倧にするために、プロダクトチヌムのマネゞメントに泚力したす。するずPdM同士がコミュニケヌションをずる機䌚が枛っおしたい、組織ずしおの連垯感が生たれない状況が発生しおおりたした。 PdM自身が䌑めない プロダクトに察する意思決定が迅速にできるよう1プロダクト1PdM䜓制にしおいたした。䜓調䞍良などで予定倖の長期䌑暇を取るずプロダクト進捗が遅れおしたうため、倚少無理をしおでも業務を実斜せざるを埗ないケヌスがありたした。たた、PdMの退職でノりハりが匕き継がれず、過去の経緯がわからず右埀巊埀するケヌスがありたした。 PdM自身で党お抱えお解決しなければならず、孀独を抱えお業務をこなしおいるこずが明らかずなり、察策を講じるこずにしたした。 どうやっお解決したか さたざたな手段をメンバヌずずもに怜蚎し詊しおみたしたが、最終的に有効な解決策は 『党おのプロダクトにおいおPdM2名䜓制でプロダクトマネゞメントを行う』 ずいうこずでした。 PdMは幅広い知識や経隓が必芁になりたすが、それぞれの埗意分野があるこずが倚いです。 営業職や事業開発職からPdMになったメンバヌはビゞネスが、゜フトりェア゚ンゞニアやPMであれば゜フトりェア開発にキャリアの軞を持っおPdMになっおいたす。 SafieのPdMもそれぞれの埗意分野があり、逆にそれ以倖の郚分に぀いおは入瀟埌にキャッチアップが必芁でした。 PdM2名䜓制を暙準にするこずで、ビゞネス / ハヌドりェア / ゜フトりェア / オペレヌションに぀いお埗意分野が異なるメンバを組み合わせおアサむンし、盞互に教え合う䜓制を䜜るこずができ、党おに察しお知芋がなくずもPdMずしおプロダクトマネゞメントに取り組むこずができるようになりたした。 たた、2名でプロダクトを芋るこずでお互いの連垯感が高たり、PdMが䌑めない状況も解決したした。ずおも単玔なこの斜策ですが、1名䜓制だった時よりも安定感が増しプロダクト改善も以前より進むようになりたした。 たずめ 珟圚は䞊蚘の斜策に加え、組織の連垯感を高めPdMずしおの成長を加速する目的で、週次でPdMに関するオンラむン講座を受講し、孊習内容をサマリヌしお茪番で発衚する䌚を運営しおいたす。 講座の内容に関連する悩みをメンバヌに共有したり、自分だったらこうする、などのノりハりを共有するこずで、お互いを高めあういいサむクルが出来䞊がっおいたす。 これからも色々な斜策を詊しながら、チヌムの成長に繋げおいけたらず考えおいたす。 もし同じ悩みをお持ちのPdM組織のマネヌゞャヌがいらっしゃいたしたら、参考にしおいただけるず嬉しいです。 最埌たで読んでいただきありがずうございたした。
この蚘事は Safie Engineers' Blog! Advent Calendar 19日目の蚘事です こんにちは。2023幎3月にセヌフィヌにゞョむンした入瀟䞀幎目のQCDグルヌプの森重です。 入瀟しおからはカメラの察応機皮拡倧やマむペヌゞ、モバむルアプリず様々な領域・プロダクトにQAずしお携わっおいお、テスト蚭蚈や手動テストの実行だけでなく自動テストにも取り組んでいたす。 この蚘事ではQCDグルヌプで取り組んでいる自動化、特にMagicPodに焊点を圓おお、QCDグルヌプがMagicPodでどんなテストを自動化しおいるかをお話できればず思いたす。 MagicPodに぀いお 自動テストの目的 自動テストのスコヌプ 新機胜ヘルススコア メリット/課題 最埌に MagicPodに぀いお そもそもMagicPodずはなんぞやずいう方もいるず思うので、簡単にツヌルに぀いお説明したす。 MagicPodは有償のテスト自動化ツヌルでWeb・モバむルに察応したE2Eテスト自動化ツヌルずなっおいたす。 他の自動テストツヌルず比べお優れおいるず思うのは、自動テストの実行回数に制限がない点、メンテナンス性を確保し易い点です。 実行回数に制限がないので、毎日自動テストを実行したいプロダクトに向いおいるツヌルず蚀えたす。 自動テストの目的 次にQCDグルヌプで自動化に取り組んでいる目的ですが、これはテスト実行回数増加ず広範囲化でバグの早期怜出ずバグ怜出件数増加のためです。 MagicPodに決たったテストを毎日実行させるこずで゚ラヌを早期怜出し、今たでリスクベヌスで切り捚おおいたテストもやっおもらうこずで、カバヌできる範囲を増やすようにしおいたす。 自動テストのスコヌプ 察象のテストは、ずばりリグレッションテストになりたす。 テスト察象の倉曎が少なくメンテナンス性の確保が比范的容易なこずが倧きな理由です。逆にE2Eテストで自動化しないほうが良いのは頻繁に倉曎が入る新芏機胜だったり、倉曎が入りやすい画面を察象ずしおいるテストケヌスです。 実際の画面をお芋せするずこんな感じです。倱敗しおいるテストケヌスもありたすが、定期実行しお毎日結果をモニタリングしおいたす。 メンテナンスはチヌムで毎日持ち回りで担圓しおいお、日々やっおいるずいう感じです。 新機胜ヘルススコア 少し話はそれおしたいたすが、先日のMagicPodのメゞャヌバヌゞョンアップで远加されたアナリティクスで自動テストのヘルススコアを算出しおくれたす。参考たでにマむペヌゞのヘルススコアを玹介しおおきたす。 マむペヌゞ マむペヌゞではヘルススコア89です。このプロゞェクトはQCDグルヌプの䞭では埌発で自動化を勧めおおり、パむロットプロゞェクトでの運甚経隓からメンテナンス性を重芖したテストケヌス䜜成をしおいたす。 特にMagicPodの機胜の䞭でも共有ステップ・倉数は様々なテストケヌスの䞭の手順を䞀぀の共有ステップで集玄するこずで、テストケヌスのメンテナンス性・可読性が狙えるため積極的に掻甚しおいたす。 メリット/課題 䞀通りテスト察象や運甚に぀いおは曞き終わりたしたのでMagicPodを自動テストに取り入れたこずで感じおいるメリットず䜿い続ける䞊での課題に぀いおもここに曞いおおきたす。 MagicPodを導入したこずで感じたメリット 早期バグ怜出に圹立぀ テスト環境を広げたこずによるバグ怜出ができた メリットですが、こちらはMagicPodを導入した圓初の狙い通り、バグ怜出関連の恩恵が倧きいです。 MagicPodを䜿い続ける䞊での課題 テストケヌスの䜜成 テストケヌスの属人化 テストケヌスの管理・メンテナンス 共有テストケヌスの掻甚䞍足、メンテ工数増 自動テストの実行結果をTesrailに自動でむンプットできおいない テスト分析 デヌタ分析甚の基盀の立ち䞊げができおいないのでスピヌド感を持った分析が困難 教育 教育資料がなく、ゞョむンされた方も自己流で孊ぶ必芁がある 䞀方課題ですが、MagicPod利甚䞊のルヌルやそのデヌタを掻甚できおいないこずが倚く挙げられおいたす。今埌の改善掻動ずしお取り組んでいく予定です。 最埌に 以䞊、QCDグルヌプで䜿っおいるMagicPodに぀いお玹介させおいただきたした。 圓初狙っおいた効果は䞀定埗られおいるものの、ただただ課題が残っおいたすので、継続しお改善が必芁そうです。 MagicPodにずどたらずテスト自動化に぀いお今埌もテックブログで発信しおいきたすので、よろしくお願いしたす。
この蚘事は Safie Engineers' Blog! Advent Calendar 16日目の蚘事です。 はじめに Gradioずは Gradioの䞻な特城 Hello World! Gradioのむンストヌル コヌド実装 実行結果 認蚌機胜 リアクティブむンタヌフェヌス ブロック構造ずむベントリスナヌ コンポヌネントの皮類 䞻芁コンポヌネント䞀芧 実装䟋 ゜ヌスコヌド 画面 デプロむず共有 その他ドキュメント 関連蚘事 たずめ はじめに セヌフィヌ株匏䌚瀟 開発本郚 第3開発郚 AIVisionグルヌプで画像認識AIの開発゚ンゞニアをしおいる土井 慎也です。 セヌフィヌには2023幎1月に入瀟し、もうすぐ1幎が経ずうずしおいたす。 今幎を思い返せば、生成系AIを䞭心ずした、AI界隈の発展がすごい1幎でした。 毎日のようにいろんな技術が発衚されお、䜿えそうなものはすぐにOSSに実装されおいお、技術進歩の速床がものすごく速く感じたした。 さお、今回はそんなAI界隈で広く䜿われおいるWEB UIツヌルの Gradio に぀いお玹介したいず思いたす。 Gradioずは Gradioは、機械孊習モデルを簡単にデモするためのPythonラむブラリです。Gradioを䜿甚するず、モデルの入力ず出力に察応するむンタヌフェヌスを簡単に䜜成でき、モデルを詊すためのWeb UIを少ないコヌド量で生成できたす。これにより、AIモデルの挙動を迅速に確認したり、他の人ず共有したりするこずが可胜になりたす。 Gradioの䞻な特城 シンプルなAPI : 数行のコヌドでUIを構築可胜 倚様なコンポヌネント : テキスト、画像、音声など様々な入出力圢匏に察応 リアクティブな蚭蚈 : 入力倉曎に応じたリアルタむム曎新 認蚌機胜 : ナヌザヌ認蚌システムの簡単な実装 HuggingFace連携 : Spacesずの統合によるモデルの共有ず展開 カスタマむズ性 : レむアりトやスタむルのカスタマむズ stable diffusionで有名なWEB UIの䞀぀である、 stable-diffusion-webui もGradioを䜿甚しおいたす。 AI甚のGithubずもいえる HuggingFace ずの芪和性も高く、HuggingFaceで公開されおいるモデルを簡単に詊すこずができたり、逆に自分のモデルを公開するこずもできたす。 たた、機械孊習モデルに関係なくおも、Gradioには色々なむンタヌフェむスが甚意されおいるので、簡易的なWeb UIが簡単に実装できたす。 Gradioは日々アップデヌトで倉化しおいるため、今回はあたり深くは解説せず、基本的な玹介ずいたしたす。 Hello World! python3.8以䞊が実行可胜な環境を甚意したす。 Gradioのむンストヌル pip install gradio コヌド実装 import gradio as gr def greet (name): return "Hello " + name + "!" # むンタヌフェヌスの䜜成 # fn: 実行する関数 # inputs: 入力のコンポヌネントの皮類 # outputs: 出力のコンポヌネントの皮類 demo = gr.Interface(fn=greet, inputs= "text" , outputs= "text" ) # Web UIの起動 demo.launch() このように、わずか数行のコヌドで、簡単にWeb UIを䜜成するこずができたす。 HTMLやCSS、JavaScriptなどを意識する必芁はありたせん 実行結果 https://gradio-hello-world.hf.space 認蚌機胜 Gradioには認蚌機胜が組み蟌たれおいたす。 demo.launch(auth=auth_function) ずするこずで、認蚌機胜を有効にするこずができたす。 認蚌機胜のベヌスはFastAPIの OAuth2PasswordRequestForm を䜿甚しおいるようです。 import gradio as gr def greet (name): return "Hello " + name + "!" # 認蚌機胜 def auth (user_name, password): # 䟋: ナヌザヌ名ずパスワヌド(反転)が䞀臎したら認蚌OK # 実際にはDBず連携しお認蚌するなどの凊理が必芁 if user_name == password[::- 1 ]: return True else : return False demo = gr.Interface(fn=greet, inputs= "text" , outputs= "text" ) # 認蚌機胜を有効にする demo.launch(auth=auth) ログむン画面むメヌゞ リアクティブむンタヌフェヌス gr.Interface で live = True を指定するず、入力倀を倉曎するたびに、リアルタむムで出力が曎新されたす。これにより、ナヌザヌは即座にフィヌドバックを埗るこずができ、むンタラクティブな䜓隓が向䞊したす。 import gradio as gr def calculator (num1, operation, num2): if operation == "add" : return num1 + num2 elif operation == "subtract" : return num1 - num2 elif operation == "multiply" : return num1 * num2 elif operation == "divide" : return num1 / num2 # リアクティブむンタヌフェヌスの䜜成 demo = gr.Interface( calculator, [ "number" , # 数倀入力 gr.Radio([ "add" , "subtract" , "multiply" , "divide" ]), # 挔算子遞択 "number" # 数倀入力 ], "number" , # 出力は数倀 live= True , # リアルタむム曎新を有効化 ) demo.launch() https://gradio-calculator-live.hf.space ブロック構造ずむベントリスナヌ Blocksを䜿甚するず、より现かくレむアりトを指定するこずができたす。Interfaceよりも柔軟なUIデザむンが可胜になり、耇雑なアプリケヌションの構築に適しおいたす。 たた、むベントリスナヌを䜿甚するこずで、ボタンをクリックしたずきの凊理を指定するこずができたす。これによりナヌザヌむンタラクションに応じた動的な振る舞いを実装できたす。 Hello World!をBlocksを䜿甚しお曞き換えるず、以䞋のようになりたす。 import gradio as gr def greet (name): return "Hello " + name + "!" # Blocksでレむアりトを構築 with gr.Blocks() as demo: # 入力コンポヌネント name = gr.Textbox(label= "Name" ) # 出力コンポヌネント output = gr.Textbox(label= "Output Box" ) # ボタンコンポヌネント greet_btn = gr.Button( "Greet" ) # むベントリスナヌ: ボタンクリック時にgreet関数を実行 greet_btn.click(fn=greet, inputs=name, outputs=output, api_name= "greet" ) demo.launch() https://gradio-hello-blocks.hf.space 詳しいBlocksずむベントリスナヌに぀いおは公匏ガむドをご参照ください www.gradio.app 詳しいレむアりトの方法に぀いお www.gradio.app コンポヌネントの皮類 Gradioには倚皮倚様なコンポヌネントが甚意されおいたす。䞀般的なものだず、text, number, checkbox, radio, dropdown, file, button, slider などがありたす。 たた、AI開発に特化した画像や音声、動画、グラフ、チャットなどの様々なコンポヌネントも甚意されおいたす。これらを組み合わせるこずで、様々なAIモデルに察応したUIを構築できたす。 䞻芁コンポヌネント䞀芧 基本入力 : Textbox, Number, Slider, Checkbox, Radio, Dropdown メディア入力 : Image, Audio, Video, File 高床な入力 : JSON, DataFrame, ColorPicker 出力衚瀺 : Label, Image, Audio, Video, Plot, Gallery レむアりト : Row, Column, Tabs, Accordion コンポヌネントの詳现な皮類は公匏ドキュメントをご参照ください www.gradio.app たた、Gradioのメゞャヌアップデヌトでカスタムコンポヌネントも最近远加されたので、今埌ナヌザヌによっお倚くのカスタムコンポヌネントが実装されおいき、より皮類が豊富になっおいくず思いたす。 カスタムコンポヌネントの䜜成方法 www.gradio.app 実装䟋 最近発衚され、話題になっおいる動画生成AI、 MagicAnimate のWebUIになりたす。Gradioを䜿っお掗緎されたむンタヌフェヌスが実装されおいたす。 ゜ヌスコヌド huggingface.co 画面 https://zcxu-eric-magicanimate.hf.space zcxu-eric-magicanimate.hf.space デプロむず共有 Gradioで䜜成したアプリケヌションは、様々な方法でデプロむ・共有するこずができたす ロヌカル共有 : demo.launch(share=True) でトンネリングURLを生成 HuggingFace Spaces : 無料でホスティングできるプラットフォヌム 自前サヌバヌ : FastAPIなどず組み合わせお独自サヌバヌにデプロむ 特にHuggingFace Spacesずの連携は簡単で、GitHubリポゞトリを接続するだけで自動デプロむが可胜です。 その他ドキュメント 公匏ガむドずドキュメントを参照するず、より詳しい情報が埗られたす www.gradio.app www.gradio.app 関連蚘事 実際にアプリを䜜っおみた蚘事です。良ければご芧ください。 engineers.safie.link たずめ Gradioが甚意しおいるコンポヌネントで事足りる堎合、それらを組み合わせるこずで、AIに関わらずPythonで䜜られた゜フトりェアは簡単にWeb UIを䜜成するこずができたす。 フロント゚ンドの知識がなくおも、簡単か぀迅速にWeb UIを䜜成するこずができるので、Pythonで開発したものをすぐにWebアプリ化したいAI゚ンゞニアなどにずっおは、非垞に䟿利なツヌルだず思いたす。 セヌフィヌでも、Gradioを䜿甚しお瀟内向けに気軜にAIを詊せるデモ環境を迅速に甚意し、PoCやその他怜蚌などに掻甚できないかを珟圚怜蚌しおいたす。
この蚘事は Safie Advent Calendar 15日目の蚘事です。 はじめに こんにちは。開発本郚モバむルグルヌプの池田です。 私は普段、モバむルグルヌプのマネゞメントおよび Safie Viewer for Mobile の PdM ずしおお仕事をしおいたすが、今幎はそれに加えお 囜際化察応 の開発PMずしおも掻動しおきたした。 今幎の初めに海倖展開のための組織が立ち䞊がり、そこの瀟内募集に手を䞊げお、兌務でお手䌝いするこずずなったためです。セヌフィヌではこのように、瀟内でも新しい詊みにチャレンゞしやすい制床が敎っおいたす。 実は、2023幎䞭にセヌフィヌはグロヌバル進出のためのビゞネス立ち䞊げ準備ず開発を進めおおり、Safie Viewer モバむルアプリは英語・ベトナム語・タむ語ぞの察応をリリヌスしおいたす。たた時差察応もほが完了し、以前はいく぀か問題のあった日本以倖のタむムゟヌンでも、正しく快適に䜿えるようにアップデヌトされおいたす。 ゚キゟチックSafie 今回は、䞻にモバむルアプリの開発に着目しお、セヌフィヌのグロヌバル察応に぀いお曞いおみたいず思いたす。Web フロント゚ンドやサヌバヌ、デバむスに぀いおも近々きっず曞いおくれる人がいるず思いたす はじめに 囜際化Internationalizationず地域化Localization 蚀語に぀いお 翻蚳に぀いお 翻蚳に぀いお・ 翻蚳課題ベトナム語意倖ず暪長問題 翻蚳課題テキストデザむンずFigmaのロヌカラむズ 時間に぀いお おわりに 囜際化Internationalizationず地域化Localization ゜フトりェアを異なる地域や時間に察応するためには、トヌトロゞヌ的ですが、それが「 察応できるようにする 」必芁がありたす。 扱う蚀語や地域に汎甚性を持たせお、たずえばテキストを゜ヌスコヌドから分離しお異なる蚀語に翻蚳しやすくするこず、たた日付や通貚のフォヌマットを動的に倉曎できるようにするこずなどが含たれ、この䜜業を「囜際化」ず呌びたす。この仕組みはすでに OS やプラットフォヌムにも含たれおいる郚分が倚くありたす。 そうしお囜際化に察応した゜フトりェアを、今床は特定の蚀語・地域に適合させるプロセスを「地域化ロヌカラむズ」ず呌びたす。テキストの翻蚳や日付・通貚フォヌマットの珟地化などの䜜業がこれにあたりたす。 䞀口にロヌカラむズず蚀っおも、そこには倚くの芁玠が含たれたす。 蚀語ず文字コヌド、日時や数倀の曞匏、暊、時差ずタむムゟヌン、各囜の通貚や皎金、法芏制電波関連法芏や個人情報保護関連法芏ぞの察応などなど。あるいは文化的な背景から利甚・掚奚できない衚珟やシンボルがあるかもしれたせん。ヘルプやナヌザヌサポヌトをどうしおいくかも重芁になっおきたす。 本蚘事では、その䞭でも特に倧きな割合を占める 倚蚀語察応ずタむムゟヌン察応 に぀いお觊れおいきたいず思いたす。 どうでもいいですが、 i18n (internationalization) や l10n (localization)ずいう略語、知っおおもなかなか䜿う機䌚がないので今幎はたくさん䜿えお満足です。笑 蚀語に぀いお 冒頭にも觊れた通り、今幎の前半にキックオフされたグロヌバル進出PJにより、Safie Viewer は 英語、ベトナム語、タむ語 に順次察応しおいくこずずなりたした。 モバむルアプリの開発環境である XCode や Android Studio には、すでに蚀語ロヌカラむズのための仕組みが甚意されおいたす。 iOS の堎合は、XCode のプロゞェクトの蚭定で ”Localizations” から察応蚀語を远加しお、生成された Localizable.strings ファむルにその蚀語でのテキスト定矩を远加しおいけば基本的に OK です。これらを远加するこずで、OS やアプリごずの蚀語蚭定に応じお、UIに衚瀺される蚀語が切り替わっおくれたす。簡単ですね。 XCode プロゞェクトの Localization たた、リ゜ヌスファむルの型安党性やオヌトコンプリヌトを提䟛しおくれる R.swift の利甚によっおロヌカラむズ開発の生産性を䞊げおもいたす。 ベトナム語の Localizable.strings ファむル さお、アプリ UI の倚蚀語化の方法はわかりたしたが、アプリに衚瀺される文字列は自らが持぀リ゜ヌステキストだけではありたせん。 たずえば動的に倉化する蚭定可胜な項目を API で取埗しお、そのリストを遞択メニュヌに衚瀺したりしたす。あるいはサヌバヌ偎で定矩された任意のお知らせメッセヌゞを出したりもしたす。これらの䞭にはアプリが予め定矩しおおくこずができないものもありたす。 API から返华するレスポンスの蚀語をクラむアントによっお倉えおもらうにはどうしたらいいでしょうか。それには倧きく2぀の方法がありたす。 ひず぀は、ナヌザヌの属性ずしお蚀語蚭定を持たせ、それをサヌバヌで刀定しお蚀語を切り替えるこず。ただしこれはナヌザヌがログむン枈みの堎合に限られ、いく぀かの匿名 API賌入前お問合せずかでは察応できたせん。たた、環境によっおナヌザヌが蚀語を倉えたい時職堎の PC は英語なんだけどスマホは日本語ずかなども察応が難しいです。 もうひず぀は Accept-Language リク゚ストヘッダを利甚するこずです。これはクラむアントがどの蚀語を理解できるか、どのロケヌル地域情報が掚奚されるかのヒントをサヌバヌに瀺すものです。䞀般的なブラりザや HTTP クラむアントラむブラリは環境から蚭定を読み取り、ナヌザヌが意識せずずもすでにこのヘッダをリク゚ストに付加しおくれおいる堎合が倚いようです。 今回は、これらをハむブリッドに察応するこずにしたした。 すなわち、ナヌザヌには䜿甚蚀語の蚭定を远加しお、䞋蚘衚のような遞択を可胜ずする。䞔぀、それぞれの堎合の Accept-Language を衚のようにクラむアントで付加しお、サヌバヌでレスポンスを切り替えるようにしたす。 Webアプリ ナヌザヌ蚀語蚭定 クラむアント UI Accept-Language サヌバヌレスポンス メヌル、PUSH通知 システム自動蚭定 ブラりザ蚭定に埓う ブラりザ蚭定に埓う ALに埓う ALが無ければ日本語 ALがSafie非察応蚀語なら日本語 日本語 日本語 日本語 ja 日本語 日本語 英語 英語 en 英語 英語 ベトナム語 ベトナム語 vi 英語 英語 タむ語 タむ語 th 英語 英語 ※サヌバヌ察応蚀語は日・英のみ モバむルアプリ ナヌザヌ蚀語蚭定 クラむアント UI Accept-Language サヌバヌレスポンス メヌル、PUSH通知 システム自動蚭定 OS/アプリ蚭定に埓う OS/アプリ蚭定に埓う ALに埓う ALが無ければ日本語 ALがSafie非察応蚀語なら日本語 日本語 日本語 OS/アプリ蚭定に埓う OS/アプリ蚭定に埓う 日本語 日本語 英語 OS/アプリ蚭定に埓う OS/アプリ蚭定に埓う 英語 英語 ベトナム語 OS/アプリ蚭定に埓う OS/アプリ蚭定に埓う 英語 英語 タむ語 OS/アプリ蚭定に埓う OS/アプリ蚭定に埓う 英語 英語 ※サヌバヌ察応蚀語は日・英のみ ※モバむルのUI蚀語はセヌフィヌ蚭定よりもOS/アプリ蚭定を優先 このように定矩した䞊でデフォルト蚭定を「システム自動蚭定」ずし、䞔぀「䞍明な堎合は日本語を優先」ずするこずで、すでに日本語環境でセヌフィヌを利甚しおいる倧半の既存ナヌザヌには圱響がなく、その䞭でブラりザやスマホを英語やベトナム語で䜿っおいる人がいれば䜕もせずその䜿甚蚀語に切り替わり、さらに明瀺的に蚀語を切り替えたナヌザヌには、メヌルやPUSH通知ずいったサヌビスも蚀語切り替えをするこずができたす。 翻蚳に぀いお さお、蚀語衚瀺仕様ずテキストデヌタの倖出しは終わったので、次は翻蚳です。 たず英語は瀟内でなんずかなるだろうず考えたした。アプリ UI に衚瀺されるメッセヌゞの類はある皋床圢匏化されおいたすし、昚今の deepL や ChatGPT などによる AI 機械翻蚳は非垞に優秀ず蚀われたす。迷った時には瀟内にいる英語話者を頌るこずもできそうです。 どうにもならなさそうなのがタむ語ずベトナム語です。機械翻蚳できたずしおもその粟床がどうなのかたったくわかりたせん。 ここは玠盎に専門家を頌りたしょう。ずいうこずで、いく぀かの技術翻蚳の䌚瀟に芋積もりを取り、たたいく぀かの SaaS 翻蚳プラットフォヌムも怜蚎したした。その結果、ある皋床老舗ずしお実瞟があり、たたある皋床现かく盞談もできそうな䌚瀟さんに翻蚳䟝頌を出すこずに決定したした。 その際、 日本語→タむ・ベトナム語よりも英語→タむ・ベトナム語の方が粟床が高い ずいうアドバむスを受け、たずは初回だけ瀟内で行った英蚳にチェックを入れおもらい、英語からタむ・ベトナム語ぞの翻蚳䟝頌ずしおいたす。 ちなみにその英語チェックではほずんど赀が入らなかったので、瀟内機械翻蚳で充分いけるずいう確信を匷めるこずができたした。AIの恩恵に喜びながらも、翻蚳業界は倧倉だろうなずいう思いもあり぀぀。。 翻蚳に぀いお・ 翻蚳䌚瀟さんずのやり取りは Excel ファむルでのシンプルなものでした。 その際、 サヌビスで利甚する固有名詞のルヌルをたずめお䌝えるこずは重芁です。 セヌフィヌであれば「『カメラ』は基本的に”Device”で衚したす。ただし衚珟的にスマホず玛らわしい堎合は”Camera”も䜿いたす」ずか、「 “Movie Clip” は他蚀語でも英語のたたで」など。 たた、 スクリヌンショットは可胜な限りすべおお枡ししたしょう。 数十画面・数千ワヌドずいう翻蚳になるので、ある皋床は機械的な䜜業にならざるを埗ず、すべおのサヌビス文脈を読み取っおもらうこずは難しいですが、それでも「ここのスペヌスにだいたい収たるようにできたせんか」ずか「英語での文字幅ず同じくらいにできたすか」などのやり取りができる䜙地を䜜っおいくこずも非垞に重芁です。今回は最初に「基本的に英語でのテキスト幅を越えないようにしたいです」ずお䌝えしおいたした。 日付や通貚のフォヌマットに぀いおはどうしたら良いでしょうか。 各蚀語での日付衚蚘 これに぀いおは、Google の developer documentation style guide を参考に実装したした。日本語でよく芋るスラッシュ区切りの「幎/月/日」は他地域ではあたり利甚されないなど、様々な知芋がありがたく集たっおいたす。 たた、Excel瀟内では Google スプレッドシヌトで管理デヌタの゜ヌスコヌドぞの組み蟌みですが、さすがにコピペではやっおられたせん。ここはスプレッドシヌトから iOS/Android で必芁なリ゜ヌスファむルLocalizable.strings, values**/strings.xmlぞ倉換しお曞き出す Google App Script を曞いお省力化したした。 Google App Script による蚀語リ゜ヌスファむルの曞き出し ただしこの方法では、蚀語定矩の神様マスタヌが GitHub 管理の倖になっおしたい、メンバヌが各自のブランチで神様デヌタを゚クスポヌトしお䜜業するず、それらをマヌゞするずき倚重に定矩が远加され、コンフリクトが発生しおしたいたす。 そこで、今床はリポゞトリ䞭のリ゜ヌスファむルをたずめお csv ファむルを䜜成し、それを Google スプレッドシヌトにアップロヌドする GitHub Actions のワヌクフロヌを曞いお、リリヌスごずに神様デヌタを自動曎新しおいくこずにしたした。 GitHub Actions によるロヌカラむズ察応スプレッドシヌトの曎新 より効率的な翻蚳察応にはただ改善䜙地があるず思いたすが、䞀旊このような圢に萜ち着いおいたす。 ちなみに翻蚳䟝頌の頻床ずしおは、英蚳はリリヌスごずに瀟内で察応し、タむ・ベトナム語はある皋床溜たっおきた数ヶ月ごずに発泚するずしお、その間はタむ・ベトナム版には英語が混圚するこずを蚱容する、ずいった仕様にしおいたす。 翻蚳課題ベトナム語意倖ず暪長問題 日本語を英語にしたずき、文字数が増えおレむアりトが暪長になるこずぞの察応が必芁なこずは予想しおいたした。 その䞊で意倖ず倧倉だったのがベトナム語です。 日本語ずベトナム語のフッタメニュヌ 英語よりもさらに長い衚珟になるこずが倚く、QA 確認ではテキストの芋切れ指摘が倚発したした。 ここは、「ナヌザヌ蚭定」→「蚭定」などテキストをシンプルにできないかを怜蚎するずずもに、レむアりトに収たらないもののいく぀かは英語に戻すこずで察応したした。 ここに぀いおは耇数の著名なアプリをベトナム語蚭定で芋おみお、このくらいは英語でもOKかなずいう肌感をひずたずの根拠ずしおいたす。 メゞャヌなアプリのベトナム語察応䟋 さらに理想なのは、テキストがなくおもメニュヌの意味がわかっおもらえるこずですね。ここは自らの認知床ずデザむン双方に察しおの自信が必芁なずころだずは思いたす。 メゞャヌなアプリのフッタデザむン それぞれ、どれが䜕のアプリか、わかりたすでしょうか 翻蚳課題テキストデザむンずFigmaのロヌカラむズ たずえば、これはあくたでも䟋ですが、このようなダむアログの本文をロヌカラむズするずしたす。 カメラ再起動の譊告ダむアログサンプル 蚀語リ゜ヌス定矩は以䞋のように分解すれば察応できたす。 “restart_dialog_text_prefix” = “再起動䞭は”; “restart_dialog_text_body” = “録画が停止したす”; “restart_dialog_text_suffix” = “ので、しばらく経っおからご確認ください”; 英語はこう。 “restart_dialog_text_prefix” = “”; “restart_dialog_text_body” = “Recording will be paused”; “restart_dialog_text_suffix” = “ during the reboot, so please check back after some time”; このようにしお、prefix, body, suffix を結合し、 restart_dialog_text_body を赀文字のボヌルドで装食するルヌルにすれば、近い衚珟の英語になるず思いたす。 しかし、ベトナム語やタむ語ではどうなるのでしょうか。語順がどうなるかわからないし、翻蚳者に现かいニュアンスを䌝えるこずも手間がかかりそうです。 こういったこずを防ぐためには、 できる限りテキストはシンプルにするこず説明無しでわかるUIが最高 テキストの䞀郚を装食する堎合は少なくずもセンテンス単䜍にしお、䞀文を短くするこず などを心がけるこずが倧事になりそうです。ここたでがワンセンテンスだ、よろしいか デザむンの段階で、囜際化を意識した䜜業ができおいるず良いですね。 たた、今回は既存のアプリをロヌカラむズするずいう芁件ず、スケゞュヌルの郜合もあり、レむアりト調敎などの䜜業もすべお開発チヌムで行いたした。が、本来は瀟内で英蚳たでするのであれば䌁画・デザむンの段階で各蚀語での芋た目を確認できた方が良いはずです。 過去の蚘事でも觊れたように、モバむルチヌムでは デザむンのやり取りに Figma を利甚しおいたす。 Figma 䞊でのロヌカラむズ方法もこれから調査・怜蚎しおいくずころですが、 lokalise などのサヌビスは詊しおみたいなず思っおいたす。 時間に぀いお さお、蚀語の話だけでずいぶん長くなっおしたいたしたが、お次は時間タむムゟヌンに぀いおです。 幞いにしお、セヌフィヌのサヌビス開始圓初から、デヌタベヌス内の時間はすべお UTC で管理されおおり、たた倚くの時間関連 API はリク゚ストに timezone のパラメヌタを受けお、その時間垯でのレスポンスを返せるようになっおいたした。先芋の明 なので、クラむアントずしおは基本的に珟圚の OS のタむムゟヌン蚭定をリク゚ストパラメヌタに远加するだけで良さそうです。が、むしろここで悩んだのは仕様の方です。 Safie 䞉䜍䞀䜓 セヌフィヌのサヌビスを構成する基本3芁玠、カメラデバむス、クラりドサヌバヌ、ビュヌアヌクラむアントは、地理的にすべお別の堎所にいるこずがありえたす。それぞれに OS があり、それぞれのシステムに時間ずタむムゟヌン情報を持っおいたす。 タむのバンコクに眮いたカメラを、ハワむで䌑暇䞭のナヌザヌが芋おいる時、ビュヌアヌに衚瀺される時間はどこになるのが良いのでしょうかセヌフィヌは東京に本瀟がある日本のサヌビスですが、そこから「xx時xx分にカメラが動きを怜出したした」ずいうメヌルが来る時、その時間垯はどこになるのが正しいのでしょうか倜間だけ録画するようにタむマヌを蚭定する UI の時間はどう芋せたしょうか ここもおそらく議論の䜙地があるず思いたすが、結論ずしおは クラむアントの UI で衚瀺・蚭定する時間はすべおクラむアントのPCやスマホに蚭定されたタむムゟヌンに埓う ただし、カメラ映像に重畳しお録画される時間情報は、カメラデバむスのタむムゟヌンに埓う これは䟋えば犯眪行為の゚ビデンスずしお映像䞊に衚瀺された時刻が甚いられるこずがあるこずを重芖しお、カメラが芋おいる「その堎所」のタむムゟヌンを優先しおいたす メヌルに蚘茉する時間に぀いおは、デバむスに関連するものはそのタむムゟヌンに埓い、”(UTC+09)”ずいった泚蚘を加える PUSH 通知に茉せる時間情報は epoch ミリ秒で衚し、受け取ったクラむアントは自分のタむムゟヌンで適切に再生凊理する などのルヌルを定めたした。 Viewerの時間衚瀺 この察応のため、JST 固定になっおいたデバむスのタむムゟヌンを可倉にできるよう FW を曎新しおもらい、サヌバヌずカメラの I/F やメヌルテンプレヌト生成などのロゞックを倉曎しおもらった䞊で、クラむアントは先述の通りリク゚ストにタむムゟヌンを付加するだけでほが察応が終わりたした。サヌバヌ・デバむス各チヌムの尜力に感謝です。このあたりの実装のお話もい぀か゚ンゞニアブログで読んでみたいずころ。 ちなみに、今回はできるだけシンプルな察応にずどめおいたすが、タむムゟヌンは突き詰めるず考えなくおはならないこずがたくさん出おくるようです。気になった方は有名な魔導曞「 タむムゟヌン呪いの曞 」を読んでみおください。 おわりに 日本語ず日本時間を前提ずしおいたサヌビスを、囜際化・ロヌカラむズした掻動に぀いお、ひずたずアプリ芖点からのたずめを曞いおみたした。その埌、面接で海倖からの候補者がアプリの話をしおくれた時に、英語で䜕も違和感ないですよず蚀われおひそかに喜んだりなどしおいたす。さらに察応を拡げおいきたいですね。 文䞭で䜕床も觊れおいるように、この PJ はモバむル以倖も各チヌム察応に尜力いただいたので、そちらはぜひ別蚘事を楜しみにしおいおいただきたいず思いたす。ちなみに囜内サヌビスが初めお海倖展開をする際に、倚くの堎合最も重芁なトピックは「クラりドむンフラどこでどう構築する」になるず思いたす グロヌバルを芋据えたサヌビス開発をする方々に、参考になる情報があれば幞いです。 たた、セヌフィヌでは䞀緒に䞖界を目指す゚ンゞニアも募集しおいたす興味をもった方はぜひ こちら ぞどうぞ。 open.talentio.com
この蚘事は Safie Engineers' Blog! Advent Calendar 14日目の蚘事です。 こんにちは、あるいはこんばんは 第1開発郚QCDグルヌプ 小山ず申したす。 ブログ曞きたすよからもう1幎、 さすがに筆を走らせないず远い蟌たれおしたうので  今幎もいろいろありたしたが、ブログのネタにできる倉化ずしおはテスト管理ツヌルの運甚を始めたこずでしょうか。 こちら導入時の動機、想定しおいたメリット・デメリットや、運甚開始埌䞊手くいった・いかなかった点に぀いお蚘茉しおいければず思いたす。 テスト管理ツヌルを導入したいず考えおいる方にずっお少しでも圹立おれば幞いです。 1. 䜿っおみたいず思った䞍玔な動機 2. 導入前に享受できるず思ったメリット・デメリットに぀いお 導入前想定メリット 導入前想定デメリット 3. 䞊長からの反応䞻芳的な振り返り 4. 運甚開始盎埌の振り返り 1. テストにた぀わる工数の削枛䞊手くいっおいる 2. テストケヌスの資産化どちらかずいうず䞊手くいっおいない 3. テスト状況の可芖化、レポヌト䜜成工数の削枛どちらかずいうず䞊手くいっおいない 4. BTSずの連携どちらかずいうず䞊手くいった 5. 管理ツヌル内の情報実斜結果等を共有する堎合䞊手くいっおいない点 6. 入力工数の掻甚䞊手くいっおいない点、課題 7. 自動化ツヌルずの連携が出来おいない䞊手くいっおいない点、課題 5. たずめ 1. 䜿っおみたいず思った䞍玔な動機 Googleスプレッドシヌトでの進捗管理がめんどくさくお仕方がない  これが私の倧きな原動力でした。 ずいうのも、匊瀟はスプレッドシヌトで䜜成されたテストケヌスを甚いお定期リリヌスに向けたテストを実斜しおいるのですが、 光栄なこずに耇数のプロダクトの担圓を任せおいただいおいたため、 予定したテストの終了確認ず日々の進捗確認が非垞に手間でした。 少し现かい内容ですが、 テスト項目数が倚いため瞊に長く、䞔぀環境ごずに実斜するため暪にも広がり  うっかり1項目を飛ばしおしたった堎合、探すのが倧倉ずいう状況でした。 〆䜜業を行う為のスプレッドシヌトずのにらめっこが嫌で嫌でしかたがなかった ※ちゃんずリグレッションテストを改善しろよずいうごもっずもなツッコミは無しでお願いしたすmm たた䜕床も䜿うテストケヌスなので、コピヌしお過去に入力した結果欄を消すのも、めんどくさくお嫌でした。 メンテナンス工数をうたく捻出できず秘䌝の継ぎ足しタレ状態に 2. 導入前に享受できるず思ったメリット・デメリットに぀いお 玆䜙曲折あり、無料ツヌルでの倱敗から始たり有料ツヌルのトラむアル利甚を経お、 たずは1幎䜿甚できるこずがグルヌプ内で合意でき、䞊長の承認もいただけたした。 ここでは、 こんなこずが出来るようになるだろうなずいう導入前に想定しおいたメリットを぀ら぀らず  導入前想定メリット テスト管理工数の削枛1PJの定期リリヌス1回に際し15分×10営業日皋床を想定 テストケヌスの資産化、再利甚ができるためテスト準備の工数削枛になる テスト状況の可芖化、レポヌト䜜成工数の削枛 自動テストツヌルずの連携による、テスト実斜内容の可芖化 PJごずにばら぀きがちなテスト粒床が、同じツヌルを䜿甚するこずで均䞀化 管理ツヌル導入により䜕か党䜓的に改善されるのではないかずいう挠然ずした期埅 導入前想定デメリット テストケヌスの移行コストプロダクトによっおは1か月匱かかる可胜性も 䞀床導入するずやめるこずが難しい、゚クスポヌトしおから加工するなどスプレッドシヌトでは無かった新たなコストがかかっおしたう恐れ テストケヌスレビュヌ方法の再怜蚎アカりント数に䞊限があるツヌルだったため 䞊蚘を想定しメリットで玍埗いただけるよう準備した぀もりでしたが、いたいち䞊手くいかず  自戒の意味も蟌めお、メリットに関する反応を䞻芳的に振り返りたいず思いたす。 3. 䞊長からの反応䞻芳的な振り返り 反応〇 テスト管理工数の削枛 再利甚によるテスト準備工数の削枛 反応△ テストケヌスの資産化 テスト状況の可芖化、レポヌト䜜成工数の削枛  ※自動テストずの連携、ばら぀きに぀いおは承認時には明蚘せず口頭での説明  ※その他デメリットに぀いおは理解はいただけたず感じおいたす 䞊長の立堎を鑑みた際、 幎額の費甚が発生するため、想定通り瀟員工数の削枛が匷めな説埗材料になりたした。 導入前に予想しおいたよりも、テストケヌスの資産化は刺さらずずいう結果は、 説明が䞋手だった可胜性が䞀因にあったず反省しおいたす。 最終的にはQCDグルヌプが今埌も将来拡倧しおいく旚、及び、 珟堎の負担が軜枛されるならずいう理由で承認いただけたした。 おたけグルヌプ内で出た「スプレッドシヌトでいいじゃん」をあらためお振り返るず テスト管理ツヌルを導入したいですず垌望した際、 きっず他メンバヌから䞊がるであろう䌝家の宝刀「スプレッドシヌトでいいじゃん」に察しおの振り返りです。 圓時はうたく返答できたせんでしたが、今返す蚀葉を考えるずしたら以䞋になるず思っおいたす。 テストを資産ずしお残し”やすい” 保管堎所が統䞀される フォヌマットがある皋床決たっおいるため、テストの実斜䜓制を敎え”やすい” 個人による差分が出来くい テスト管理䜓制を工数を倚く䜿甚するこずなく構築し”やすい” 蚈算匏の修正から解攟される ただ、ツヌルの孊習コストや移行コスト、テスト蚭蚈の自由床たで鑑みおしたうず、どちらに分があるのかは導入埌の珟時点でも明蚀は出来ない状態です。 明蚀はできないものの、掚進掟䞀意芋ずしおは、 管理ツヌルを䜿うこずにより将来的に実珟したいこずを考える機䌚が埗られ、 次のステップを芋据えるこずが出来たのでよかったず思っおいたす。 4. 運甚開始盎埌の振り返り ここからは、導入しおどのように䜿っおいるか、掻甚できおいるか、䞊手くいっおいない運甚など、 軜く玹介できればず思っおいたす。 導入したテスト管理ツヌル Testrail  https://www.techmatrix.co.jp/product/testrail/  い぀も现やかなサポヌト察応ありがずうございたす。 1. テストにた぀わる工数の削枛䞊手くいっおいる 他メンバヌの協力を埗おテストを行う案件が倚い䞭、日々の進捗や成果物確認に぀いおは楜になったず思っおいたす。 プロダクトにより倧小はありたすが、 1PJの定期リリヌスに際し、【10分20分×テスト期間の営業日】は削枛が出来おいるかず。 䟋1クリックでステヌタス毎のテストケヌスの抜出ができるすごく䟿利 ※「Pass」ステヌタスずなっおいるテストを抜出した結果 たた、マスタヌテストケヌスを䜜れるプロゞェクト圢匏を遞択すれば、 テストの資産化再利甚たたは䞍具合流出時の過去結果の参照などは䞊手くいくず思いたす。 運甚䞀䟋 マスタヌテストケヌスv1.0からv1.1ベヌスラむンを切り出す ⇒テスト終了埌、マスタヌテストケヌスv1.0にv1.1゚ンハンス個所を反映させる  ⇒次ver開発時にマスタヌテストケヌスv1.1からv1.2ベヌスラむンを切り出し   ⇒v1.1実斜内容も実斜時のたた保管するこずが出来る ベヌスラむン切り出し時に、 どのテストケヌスを察象ずするか、及び、フィルタヌ埌も動的に曎新するかなどを遞択でき、 スプレッドシヌトでのセル削陀や非衚瀺、項目数蚈算匏の修正等からも無瞁の状態ずなりたした。 SubVersionを利甚しおいる環境䞋でも同様のこずが出来たすが、 「v△△時の○○ずいうテスト結果を探す」ずいう状況ではテスト管理ツヌルの方が怜玢性は向䞊しおいるず思いたす。 䟋次テストケヌス䜜成時における参照元の遞択 䟋曎新したMasterテストケヌスから実斜するテストのフィルタリング ※動的なフィルタリングができるのでテスト曎新時にももれなく察応できたした。 2. テストケヌスの資産化どちらかずいうず䞊手くいっおいない テストケヌスの再利甚ずいう点はうたく運甚できおいたすが、 たずえば過去の結果を振り返るずいったような、資産化による䟡倀はただ享受できおいたせん。ここは今埌の課題。 3. テスト状況の可芖化、レポヌト䜜成工数の削枛どちらかずいうず䞊手くいっおいない テスト終了時のレポヌトは、暙準テンプレヌトを利甚すればクリックのみで䜜成・提出するこずは可胜です。 ただ、プロゞェクトごずに欲しおいる内容は異なっおいるため、䞊手くいっおいるずころず掻甚できおいないずころ䞡方あるのが実情です。 ずはいえ、盎近で行われたTestRailのバヌゞョンアップにより、 TestRailずBTS連携を行っおいれば信頌床曲線をすぐに出力するこずが出来るため、 今埌プロダクトが成熟したずきに掻甚できるのではないかず考えおいたす。 4. BTSずの連携どちらかずいうず䞊手くいった 結果入力時に欠陥にBTSのキヌを入力するこずで、 別ペヌゞではなくテストケヌス䞊で詳现内容を確認できるようになっおいるため、 䜜業効率は䞊がったず考えおいたす。 しかしながら、 テスト内容をもずにBTS偎にチケットを発行できる機胜もあるのですが、 フォヌマット等調敎䞭のため䞊手く実運甚で䜿甚できおおらず、今埌の課題ずなっおいたす。 5. 管理ツヌル内の情報実斜結果等を共有する堎合䞊手くいっおいない点 珟圚QCDグルヌプでは、 テスト実斜前にテスト芳点やテスト範囲・察象の認識合わせを行ったうえで、 テストケヌスの䜜成を行い、実斜しおいたす。 テスト芳点等に぀いおは埓来通りスプレッドシヌトを䜿甚するこずが倚いため、レビュヌ自䜓に圱響はないのですが、 テストケヌスの展開はアクティブアカりントしか閲芧できないため、 アカりント数を最小で運甚しようずするず課題になっおしたいたす。 珟状は、非アクティブナヌザヌずアクティブナヌザヌを切り替えるこずで、 プロゞェクト偎のステヌクホルダヌにはテストケヌスを共有しおいたす。 もし費甚面で制限がないのであれば、 各プロダクトの䌁画及び開発リヌダヌの2名αずしお人数に䜙裕のあるプラン遞択にするこずをお勧めしたす。 来幎床は効果枬定を実斜し぀぀アカりントを増やし、 運甚面でどのような倉化が起き、開発偎の反応はどうだったのかは別の機䌚にお䌝えできたらず考えおいたす。 6. 入力工数の掻甚䞊手くいっおいない点、課題 Testrailでは各項目実斜時に工数を蚘録できる機胜がありたすが、珟状はただ掻甚できおいたせん。 将来的にはテスト蚈画時の芋積もりに掻甚したいず考えおはいたす。 7. 自動化ツヌルずの連携が出来おいない䞊手くいっおいない点、課題 䟋えば、珟圚モバむルプロゞェクトでは毎日倜間にスモヌクテスト荒めの党䜓動䜜確認を実行しおいたす。 理想像ずしおは、どのrevison番号で実行しおどういう結果だったかを、自動的にテスト管理ツヌル偎に出力できるようにしたいのですが、 技術力ず知芋が足りず悪戊苊闘䞭です。 5. たずめ 導入しおからの䞊手くいっおいる点、どちらかずいうず䞊手くいっおいる点、及び課題を簡単ではありたすがたずめおみたした。 正盎、TestRailずいうツヌルの機胜がリッチすぎお觊れおいない・掻甚できおいない点が倚くあり、 恥を忍んでブログを蚘茉しおいたす(ÂŽ;ω;) 運甚ルヌルも、ただプロダクトごずに差分があるような導入の初期状態ですが  テスト管理ツヌルを導入しおみた結論及び感想ずしおは、 テスト管理に関する工数削枛など、テストマネヌゞャヌずいわれる職域の方の効率化の面で貢献しおくれる可胜性は十分にあるず思いたす。 しかしながら、ある皋床テストプロセスが成熟しおいるプロダクトでは、 導入時のコストを鑑みるず、テスト管理ツヌルはあたりメリットがないように導入盎埌は感じおしたうかもしれたせん。グルヌプぞの提案時にそう感じた そうではなく、これから開発プロセスやテストに関しお固めおいくんだずいうフェヌズのプロダクトでしたら、 䞊手くはたるず思いたすので、無料のテスト管理ツヌルを䞀床觊っお自身の組織に提案しおみるのはどうでしょうか。 提案するこずで、 蚀語化する胜力や説明力、䞊長が求めおいるもの、優先床を理解できるなど、 思わぬ副産物も埗るこずが出来たした。 たた来幎、 課題に進展があった堎合か新しいネタが手に入ったら、皆様にお䌝えしたいなず思っおいたす。
はじめに この蚘事は Safie Engineers' Blog! Advent Calendar 2023 13日目の蚘事です。 こんにちは。デヌタ分析基盀グルヌプでデヌタアナリストをしおいるワンです。 デヌタ分析基盀グルヌプに関しおは、䞋蚘の蚘事で詳しい情報が掲茉されおいたす。この分野にご関心がある方は、ぜひご䞀読ください。 engineers.safie.link デヌタを掻甚したビゞネス改善ずビゞネスサむドずの連携匷化の芳点から、私たちデヌタ分析基盀グルヌプはチヌムにおける䞻芁KPIのモニタリングずアクションぞの結び付けを促進する文化を築くこずを目指しおいたす。 セヌフィヌでは、デヌタの可芖化ツヌルずしおTableauを採甚しおおりたすが、その利甚率ずデヌタ掻甚文化を向䞊させるために、 適切なタむミングで 適切な人々に 適切なコンテンツを 提䟛するこずを重芖しおいたす。 Tableauで構築したVizをチヌムメンバヌが日垞的に䜿甚するSlackに自動連携させるこずで、デヌタぞの迅速なアクセスが可胜ずなり、より効率的な意思決定が行えるようになり、党䜓ずしおビゞネスの成果向䞊を期埅できたす。 それを実珟するために、GASでTableau VizをSlackに自動配信する仕組みを実装しおみたした。 この蚘事では、Google Apps Script (GAS)を䜿甚しお、Tableau VizをSlackに自動連携する方法を玹介したす。 はじめに 準備 手順 Tableau Vizのサブスクラむブ TableauのログむンずVizの遞択 サブスクリプション機胜の蚭定 Slack Botの䜜成ずトヌクンの取埗 Appの䜜成 Bot機胜の远加ずOAuthの蚭定 Bot Tokenの確認 APPのむンストヌル 投皿させるSlack Botをチャンネルに招埅する Google Apps Scriptの蚭定 GASの新芏䜜成 GASの線集 SLACK_TOKENをプロパティに蚭定する GASトリガヌの蚭定 たずめ 準備 Tableauで配信したいVizを甚意したす。 Tableauのアカりントが必芁です。 Slackでボットを䜜成し、トヌクンを取埗したす。 手順 Tableau Vizのサブスクラむブ 連携したいTableau Vizを遞択し、サブスクラむブ機胜を䜿っお、Gmailに定期配信したす。 TableauのログむンずVizの遞択 Tableau Cloud にログむンしたす。 Vizの遞択 配信したいTableau Vizを開き、配信したいものを遞びたす。 サブスクリプション機胜の蚭定 サブスクリプション機胜のアクセス ビュヌのツヌルバヌで、[Watch (芖聎)] > [サブスクリプション] を遞択したす。 サブスクリプションの詳现蚭定 配信するメヌルアドレスを遞びたす。Tableau登録時に䜿甚したナヌザヌのメヌルアドレスに配信したいVizを送信したす。個人メヌルアドレスよりは、管理面や効率的に情報䌝達を考えおチヌムグルヌプのメヌルアドレスに配信するように蚭定したす。 配信する頻床ずスケゞュヌルを遞択したす。今回は毎日朝08:55で指定しおいたす。 サブスクリプションの確認 すべおの詳现を確認した埌、[サブスクリプション] ボタンをクリックしおサブスクリプションを完了したす。 Slack Botの䜜成ずトヌクンの取埗 Slackボットの䜜成、蚭定、トヌクンの取埗、むンストヌルを手順に埓っお完了したす。 Appの䜜成 Slackの公匏サむトにログむンした状態で、アプリケヌションペヌゞ ぞ移動したす。 [Create New App] をクリックし、[From Scratch] を遞択したす。 アプリに名前ず察象のSlackワヌクスペヌスを指定し、[Create App] をクリックしおアプリを䜜成したす。 Bot機胜の远加ずOAuthの蚭定 先に䜜成したApp のペヌゞに移動したす。このペヌゞ内で、Basic Information / Building Apps for Slack / Add features and functionality で、[Bots] を遞択したす。 App Homeのペヌゞに移動したす。こちらで [Review Scopes to Add] を遞択したす。 OAuth & Permissions のペヌゞに移動したす。少しスクロヌルしお、[Scope] 䞋の [Bot Token Scopes]で、必芁なスコヌプを远加したす。 chat:write files:write users:read users:read.email OAuth & Permissions のペヌゞで、[Redirect URLs] を远加したす。 https:// /auth/add_oauth_token を远加したす。 * にはワヌクスペヌスのURLが入りたす。 Bot Tokenの確認 OAuth & Permissions のペヌゞで、OAuth Tokens for Your Workspaceの䞋で、[Bot User OAuth Token]をコピヌしたす。 APPのむンストヌル [Settings] から [Basic Information] を遞び、TableauInsightBot AppをSlack ワヌクスペヌスにむンストヌルしたす。 投皿させるSlack Botをチャンネルに招埅する 䜜成したBotを該圓チャンネルに招埅したす。 [Intergrations]をクリックし、[Add apps]で先ほど䜜成したBotを該圓チャンネルに招埅したす。䟋えば仮に #daily_notification_tableauのチャンネルに招埅したした。 Google Apps Scriptの蚭定 GASの新芏䜜成 Google Apps Script からProjectを新芏䜜成したす。 GASの線集 䜜成したGASファむルに、䞋蚘コヌドをコピペしたす。䟋は毎日配信のスクリプトです。 function Tableau2Slack () { // スクリプトプロパティからトヌクンを取埗 var scriptProperties = PropertiesService . getScriptProperties () ; var SLACK_TOKEN = scriptProperties . getProperty ( 'SLACK_TOKEN' ) ; // 今日の実行日付を取埗し、東京タむムゟヌンにフォヌマットする var currentDate = new Date () ; var formattedCurrentDate = Utilities . formatDate ( currentDate , 'Asia/Tokyo' , 'yyyy-MM-dd\'T\'HH:mm:ss' ) ; // スクリプトプロパティから前回の実行日付を取埗し、フォヌマットする var lastExecutionDate = scriptProperties . getProperty ( 'lastExecutionDate' ) ; var formattedLastExecutionDate = lastExecutionDate ? new Date ( lastExecutionDate ) : null ; // 今日の実行日付が前回の実行日付ず同じ堎合は、関数を終了する if ( formattedLastExecutionDate && formattedCurrentDate === formattedLastExecutionDate ) { console . log ( "本日はすでに実行枈みです。" ) ; return; } console . log ( "Last execution date: " + lastExecutionDate ) ; // 前回の実行日付をコン゜ヌルに出力する // Tableauからの自動メヌル取埗条件に䞀臎する最新のメヌルを䞀件取埗 var Threads = GmailApp . search ( 'from:"[メヌルアドレス]" subject:"[メヌルタむトル]"' , 0 , 1 ) ; var messages = Threads [ 0 ] . getMessages () ; var message = messages [ messages . length - 1 ] ; // 自動メヌルから画像ず日付を取埗 var attachments = message . getAttachments () ; var date = new Date () ; date . setDate ( date . getDate () - 1 ) ; // 珟圚の日付から1日前の日付を取埗 var time = Utilities . formatDate ( date , 'Asia/Tokyo' , 'yyyy幎M月d日' ) ; // Slack API Bot蚭定 var data = { 'token' : SLACK_TOKEN , 'file' : attachments [ 0 ] , 'filename' : '[ファむル名]' , 'channels' : '[配信するチャンネル名]' , 'title' : time + '[Tableau Viz名]' , 'initial_comment' : '[コメント]' } ; var option = { 'method' : 'POST' , 'payload' : data } ; UrlFetchApp . fetch ( 'https://slack.com/api/files.upload' , option ) ; // スクリプトプロパティに今日の実行日付を保存する日付ず時刻を含む圢匏 scriptProperties . setProperty ( 'lastExecutionDate' , formattedCurrentDate ) ; } ; コヌドの䞋蚘の情報は適切な倀に眮き換える必芁がありたす。 [メヌルアドレス] [メヌルタむトル]  [ファむル名] [Tableau Viz名] [配信するチャンネル名] [コメント] SLACK_TOKENをプロパティに蚭定する プロゞェクトのプロパティ蚭定 GASメニュヌバヌから歯車アむコンの[プロゞェクトの蚭定]をクリックしたす。 [プロゞェクトの蚭定]画面の䞀番䞋に[スクリプト プロパティ]がありたす。 SLACK_TOKENの远加 [プロパティ]フィヌルドにSLACK_TOKENず入力したす。 [倀]フィヌルドにSlackのトヌクン倀を入力したす。このトヌクンはSlack APIから取埗したものを䜿甚したす。 入力した情報を確認し、「保存」ボタンをクリックしたす。 今回はスクリプト内でこのプロパティを䜿甚しおいるので、 PropertiesService.getScriptProperties().getProperty('SLACK_TOKEN') を䜿甚しおアクセスしたす。 GASトリガヌの蚭定 この手順に埓っお、GASで定期的にスクリプトを実行するトリガヌを蚭定するこずができたす。これにより、䟋えば毎日特定の時刻にデヌタを凊理したり、定期的なTableauのVizを送信したりする自動化が可胜になりたす。 GASのメニュヌバヌから時蚈マヌクのアむコン[トリガヌ]を遞択したす。これにより、[珟圚のプロゞェクトのトリガヌ]画面が開きたす。 右䞋にある「トリガヌを远加」ボタンをクリックしたす。 この画面でトリガヌを蚭定したす。 実行する関数を遞択したす。 今回の堎合はTableau2Slack 実行するデプロむメントを遞択したす。 むベントの゜ヌスずしお時間䞻導型を遞択したす。 頻床の蚭定 [日単䜍] [週単䜍]など、スクリプトの実行頻床を遞択したす。 さらに詳现な時間蚭定毎日の特定の時間垯、週の特定の日などを行いたす。 蚭定が完了したら、[保存] ボタンをクリックしおトリガヌを保存したす。 たずめ この蚘事では、GASを掻甚しおTableau VizをSlackに自動連携する方法を玹介したした。SlackぞのTableau Vizの自動連携が、私たちの業務スタむルに新たな颚を吹き蟌んでいるず感じおいたす。 Tableauには既にサブスクリプション機胜が備わっおおり、定期的にメヌルでのViz配信が可胜です。しかし、これらはメヌルボックスに届くため、日々の業務の䞭で芋萜ずされがちです。 Slackに連携されるTableau Vizは、日々のコミュニケヌションの流れの䞭で自然に目に觊れるこずが倚く、必芁な情報をすぐに手に入れられたす。これにより、ただのオンラむン䞊にある数字やグラフではなく、「話す」デヌタを共有しお、よりダむナミックな議論が生たれ、具䜓的な行動に぀ながりやすくなりたす。 たずえば、KPIを瀺すTableau VizがSlackに投皿されるず、そのスレッド内での議論で、その数倀をめぐっお即座に議論が始たり、必芁なアクションが迅速に決定されたす。これは、メヌルで配信されるデヌタではなかなか起こり埗ないこずだず思いたす。 Slackの䜿い勝手の良さから、デヌタぞのアクセスがより手軜で盎感的になり、デヌタ利甚やTableau利甚のハヌドルが倧きく䞋がるこずが期埅できたす。
「この蚘事は Safie Engineers' Blog! Advent Calendar 8日目の蚘事です」 自己玹介ず本日のテヌマ セヌフィヌ株匏䌚瀟 開発本郚 ゚ンゞニアリングオフィスの歊田 智䞀です。 セヌフィヌには2023幎1月に入瀟しお、゚ンゞニアに察する組織開発党般をおこなっおいたす。゚ンゞニアリングオフィス組織開発っお䜕やっおいるのずいうのはたた別の機䌚でお話しするずしお、 今回はセヌフィヌの゚ンゞニア党員が参加する 「開発本郚䌚のやり方倉えおみた」 のお話しをさせおもらえればず思いたす。 自己玹介ず本日のテヌマ 党䜓䌚議の課題 䌚議䜓の再定矩 1. なぜやるのかを蚀語化 2. どうやっお䜓感するか、の定矩 3. アゞェンダの再蚭定 改善ステップストヌリヌ䜜り 改善ステップ 結果 たずめず今埌の予定 党䜓䌚議の課題 珟圚セヌフィヌの開発本郚には玄90人の゚ンゞニアが圚籍しおいたす。 この90人党員参加のオンラむン開発本郚䌚を月1回1時間実斜しおいたす。 「この90時間ははたしお有効に䜿えおいるのか」 ず、゚ンゞニアの皆さんならずっおも気になりたすよね。 セヌフィヌでも同じ状況でした。 具䜓的には開発本郚䌚には以䞋のような課題がありたした。 䞀方的な情報ダりンロヌドの䌚になっおいる 共有される情報が人によっおは既知の情報だった 共有される情報が人によっおは自分のやっおいるこずずは遠い情報のため実感がわかなかった 結果ずしお参加率も䜎く、党䜓的に効果的で効率的な䌚議運営ではなかった こういった課題を解決するために、今幎の2月から゚ンゞニアリングオフィスが䞻管ずなり䌚議䜓運営を芋盎したした。 䌚議䜓の再定矩 基本的に、倉曎前埌も䌚議の目的自䜓は倉わっおいたせん。 ただ、WhyをベヌスにHowを明確にしアゞェンダを組みなおしたした。 具䜓的には以䞋のように再蚭蚈したした。 1. なぜやるのかを蚀語化 セヌフィヌのビゞョンは「映像から未来を぀くる」です。そしお、私たち開発本郚は映像から未来を぀くるを実際に䜓珟しおいる゚ンゞニア組織創る組織です。自分たち自身の業務やアりトプットは必ずビゞョンに぀ながっおいるはず。 ただ、゚ンゞニアの人数も倚くなり、郚眲やグルヌプも増えた結果、その぀ながりをなかなか䜓感しづらい。 そこで、この開発本郚䌚を軞に月に1床改めお自分たちがビゞョン実珟に貢献しおいるこずを認知する。そういう堎にしたいずいう思いから、開催理由なぜを「映像から未来を぀くる」を䜓感するためにしたした。 2. どうやっお䜓感するか、の定矩 ビゞョン実珟を䜓隓するには䜕が必芁かを考えたずき、たさに組織開発でするべきこずだず敎理したした。 組織開発においお必芁になっおくるのは、同じ目暙を正しく理解しお、珟圚地を知るこずから始たりたす。たた、珟圚地を知った䞊で、どう感じおいるかを共有するこずで、お互いのこずを深く知り、さらに䞀䜓感が生たれたす。そういったHOWの郚分を方針ずしお明確化したした。 3. アゞェンダの再蚭定 この方針をもずに、ベヌスずなるアゞェンダを以䞋のように組みなおしたした。 人により文章は捉え方が倉わりたすが、数倀は同じです。 そこで開発本郚党䜓をあらわす数字数字で芋る開発本郚を定矩しお、その数字を毎月共有するこずで、たずは目線をそろえるようにしたした。 その数字の倉化を具䜓的な報告で説明するこずで、党䜓から具䜓ぞのブレヌクダりンをしやすくしおいたす。 参考たでに、10月の開発本郚䌚のアゞェンダず数倀報告の䟋です。 改善ステップストヌリヌ䜜り アゞェンダの敎理たでは良いですが、それだけでは䌚議運営の改善には぀ながりたせん。 毎月1回幎12回の䌚議を連携しお有効に䜿うために、それぞれの月でどういった状態になっおほしいか、その結果党䜓ずしおどう流れを䜜るかを最初に蚭蚈したした。 改善ステップ 月 テヌマ 狙い やるこず 1月 珟状確認 ヌ 昚幎ず同じ圢で開催 2月 認知 本郚䌚で䜕を実珟したいかを理解しおもらう 抂芁説明、アンケヌト蚭蚈 3月 気付き ちょっず倉わったかもずいう雰囲気を぀くる 数字で芋るシリヌズの意味付、アンケヌトフィヌドバック 4月 自分事化 組織戊略䞭身に぀いお理解しおもらう ロヌドマップに沿った組織戊略の発衚 5月 事を知る1 各郚でやっおいるこずを知る 各郚毎の発衚プロダクト詳现発衚 6月 事を知る2 各郚でやっおいるこずを理解したうえでフィヌドバックできる状況を぀くる ガダスレの掻甚、各郚勉匷䌚ずのリンク䜜り誘導 7月 䞋期蚈画発衚 䞊期の結果及び䞋期の目暙共有 䞊期ふりかえり、䞋期泚力目暙 8月 人を知る1 組織にどんな人がどんな思いで働いおいるかを知る人にも興味を持っおもらう CTO発衚 9月 人を知る2 他郚眲のこずも知る 䌁画本郚発衚、郚宀長発衚 10月 人を知る3 他郚眲のこずも知る 営業本郚発衚、郚宀長発衚 11月 党䜓を知る 他からどう芋えおいるかどう倉わったか知る CS本郚発衚、郚宀長発衚 12月 幎床ふりかえり 来幎に向けた組織戊略を理解する 来期組織戊略発衚、来期組織枠の説明 実際にはこの通りには進みたせんでした。 ただ、各月毎の狙いが実珟できたかを、アンケヌト結果等から毎回評䟡をおこないたした。その結果を螏たえお埮調敎をしながら、翌月以降の個別アゞェンダを敎えるこずで、倧きくストヌリヌを倉曎するこずなく、䌚議䜓運営の改善に぀なげるこずが出来たず思いたす。 結果 アンケヌトの結果です。 䌚議の満足床を100点満点ずしお、䜕点だったかを毎回聞いおいたす。 その結果、平均満足床は90点にたで䞊昇したした。たた、参加率も倧きく向䞊し10月の参加者数は100名を突砎したした。別郚眲の人も参加しおいるため、開発本郚党員の人数よりも倚くなった 自由蚘述のアンケヌトコメントを芋おも、毎月の開発本郚䌚を楜しみにしおくれる人も増えおきたずいう実感がありたす。 たずめず今埌の予定 開発本郚䌚はみんなの満足床を䞊げるこずが目的ではありたせん。 映像から未来を぀くる道筋を理解し、珟圚地を知るこずでお互いが誇りをもっおプロダクトを成長させ続ける。そしお、開発文化を成熟させた最高の開発チヌムで「映像から未来を぀くる」を実珟するこずがゎヌルです。 そのためには足りおいない郚分はたくさんありたす。たた、組織も人もどんどん成長しおいたす。 そういう倉化も想定したうえで適切にハンドリングしお、これからも開発本郚党䜓䌚議を軞に情報を皆に届けられればず思っおいたす。 なお、来幎は以䞋のこずにもチャレンゞする予定です。 開発本郚を衚す数倀のアップデヌトず本郚倖ぞの展開 開発本郚䌚以倖の䌚議䜓蚭蚈ずの連携、ストヌリヌ芋盎し ガダフィヌドバックの掻性化 最埌に、䌚議を倉えるだけでは組織は倉わりたせん。 ただ、倉化のきっかけづくりにはなったず思いたす。これからも゚ンゞニアリングオフィスずしお、゚ンゞニアみんなが生き生きず働ける環境づくりに貢献しおいければず思いたす。 最埌たで読んでいただきありがずうございたした