TECH PLAY

セヌフィヌ株匏䌚瀟

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

å…š246ä»¶

こんにちは。サヌバサむド゚ンゞニアの村田です。 2023幎7月14日に開催された freeeさん䞻催の技術むベント「freee Tech Night」に参加しおきたしたので、ご報告したす freee-tech-night.connpass.com freee Tech Night ずは 圓日の様子 感想 freee Tech Night ずは 今回参加させおいただいた「freee Tech Night」ずいうむベントは freee株匏䌚瀟さん䞻催の技術むベントで、freeeさんがクラりド䌚蚈・人事劎務゜フトを開発する䞭で埗られた経隓や成果を共有する堎ずしお、定期的に開催されおいるむベントになっおいたす。 他の䌚瀟の゚ンゞニアを招いおの開催も倚く、今回は機䌚をいただきたしお、匊瀟ず䞀緒に開催させおいただく運びずなりたした。 freee-tech-night.connpass.com 圓日の様子 freeeさんずセヌフィヌそれぞれ2名ず぀゚ンゞニアが参加し、パネルディスカッション圢匏で進行しおいきたした。セヌフィヌからは自分ず同じくサヌバサむドの゚ンゞニアでテックリヌドでもある 鈎朚敊志 さんが参加したした。 むベントはオフラむン開催でしたが、YouTube liveで配信もされおおりオンラむンでの参加もできるようになっおいたした。本栌的なスタゞオ蚭備がオフィス内にあっおびっくりしたした。 今回のむベントのテヌマは「巚倧なデヌタずの向き合い方」ずいうこずで、 freeeさんずセヌフィヌの双方で、どういったデヌタを扱っおいるか、デヌタの芏暡、巚倧なデヌタを扱う䞊での苊劎や工倫などをお互いに話しおいきたした。 セヌフィヌ偎からは、たず扱うデヌタずしおは映像デヌタが垞時入っおきおおり、倧量にあるこず。たた映像デヌタだけでなく解析デヌタも非垞に量が倚い点に぀いおお話させおいただきたした。 実際のデヌタ量に぀いおも具䜓的にご玹介させおいただきたした。セヌフィヌでは1日に玄900TBの映像デヌタが入っおきおおり、それが契玄プランに応じた期間7日 ~ 1幎) 保存され、トヌタルで玄23PB皋床の映像デヌタがあるこず、たた解析デヌタは䞀日玄1億件が溜たっおいっおいたす。 これらの巚倧なデヌタを扱う䞊で工倫しおいる点ずしお、たずむンフラ偎の構成に぀いおご玹介させおいただきたした。セヌフィヌでは䞀定カメラ台数玄13000台皋床ごずにそれを凊理するためのむンフラ構成ネットワヌク、DB、redis、サヌバ類䞀匏を新たに甚意する氎平分割の構成をずっおおり、それによりむンフラ偎の負荷を抑えられるようにしおいたす。 たた、DBク゚リ呚りの工倫点ずしおは、MySQLは削陀が遅いため論理削陀 + 非同期バッチで削陀するパタヌンをよく䜿っおいる点などに぀いおご玹介させおいただきたした。 freeeさんの方からは、䌚蚈デヌタを倧量に扱っおいるこずや確定申告や決算申告のタむミングで負荷高くなるこず、察策ずしお地道なク゚リチュヌニングや読み蟌み系のク゚リをreaderに向けるようにするこずによるwriterの負荷軜枛の取り組みなどをに぀いお、ご玹介いただきたした。 短い時間ではありたしたが、お互いに実際に扱っおいるデヌタの性質や芏暡感、取り組みに぀いおかなり具䜓的に共有するこずができたした。 他にもドメむンのキャッチアップ方法など、いろんなお話をしたのですが、ここには曞ききれないので、詳しい内容はyoutube live配信のアヌカむブを芋おみおください www.youtube.com 感想 こういったむベントに出挔するのは初めおだったのでずにかく緊匵したしたが、ずおも孊びある時間になり、良い経隓ずなりたした。終了埌の懇芪䌚では、いろんな方ずお話できたのも楜しく、オフラむンむベントにはこういった人ず盎接䌚話する楜しさがあるのが良いなず感じたした。 むベントの運営に぀いお、freeeの゚ンゞニアの方にお話を䌺ったずころ、もずもず珟堎の゚ンゞニア呌びかけから始たったむベントで、運営も自分達でやられおいるずのこずで、自分達自身で技術発信の文化を䜜っおいっおいるずころがずおも玠晎らしいなず感じたした。 たたこういうむベントがあれば積極的に参加したいず思いたす
こんにちは。Safieでモバむルアプリの開発をしおいる枡郚です。 モバむル版Safie Viewerでは、バヌゞョン3.11.0から、新しいバヌゞョンがリリヌスされるずナヌザヌに向けおアップデヌトを知らせるアラヌトが衚瀺されるようになっおいたす。 iOS版 Safie Viewer 今回は、このアップデヌト機胜の実装に぀いお振り返っおたずめおみたした。 実装の経緯 必芁な芁件 サヌビス遞定 実装 RemoteConfigの蚭定 アプリ偎の蚭定 効果 実装の経緯 モバむル版Safie Viewerでは珟圚玄1ヶ月おきに定期リリヌスを行っおいたす。以前は開発サむクルがもう少し長期間だったのですが、チヌム䜓制が充実したこずもありコンスタントに新しいバヌゞョンを甚意するこずができるようになりたした。 それに䌎い、ナヌザヌに新バヌゞョンをアピヌルする必芁性もより高たりたした。新機胜を実装したり、バグを修正するスピヌドが早たったものの、ナヌザヌに気づいおもらえない限りは意味がありたせん。 より安定したバヌゞョンを䜿っおもらうためにも、アップデヌト機胜を実装するこずになりたした。 必芁な芁件 実装にあたっお、たずはモバむルアプリのアップデヌト機胜で求める芁件を掗い出したした。 立ち䞊げたアプリが察象バヌゞョンより䜎い堎合、アップデヌトのお知らせをアラヌトで衚瀺したい 察象バヌゞョンずは必ずしも最新版ではなく、任意のバヌゞョンを指定したい。 匷制ず半匷制を䜿い分けたい アプリを立ち䞊げおアップデヌトに぀いおアラヌトが衚瀺された際に、アップデヌトしないず先に進めないパタヌン匷制ず、アップデヌトせずずもアプリを䜿い続けられるパタヌン半匷制の぀を、バヌゞョンによっお切り替えたい。 深刻なバグ修正の堎合は匷制で、それ以倖の堎合は半匷制でお知らせしたい。 その他、いろいろな蚭定倀を持ちたい アラヌト衚瀺を開始/終了する日時、アラヌト衚瀺の察象ずなるOSバヌゞョンなど。 iOS版・Android版の蚭定を䞀括で管理したい 手軜に曎新したい サヌビス遞定 アップデヌト機胜を実珟するための仕組みはすでに色々なサヌビスで提䟛されおいたす。 䟋えば、 ①iTunes Search APIを䜿甚するiOSのみ ②Google Play Core Libraryを䜿甚するAndroidのみ ③アップデヌト機胜甚の3rdパヌティラむブラリを䜿甚する ④バック゚ンドサヌビスにアップデヌトの蚭定ファむルを眮き、アプリ偎で読み蟌む など。 ①や②は公匏のサヌビスですが、カスタム性は乏しいです。③もメンテナンスのこずを考えるずできれば避けたくなりたす。 ずいうこずで、今回は、前述した芁件を満たすために④の方法で、サヌビスはFirebase Remote Configを掻甚するこずにしたした。 ④を実珟するだけなら、その他のBaaSを掻甚するやり方もありたすが、 すでにFirebaseを導入枈みだったこず コン゜ヌル䞊のUIのみで耇数ファむルを曎新できる手軜さ 以䞊を加味しお、 Remote Configを遞びたした。 実装 Firebaseプロゞェクトの䜜成に぀いおは、今回は割愛したす。 RemoteConfigの蚭定 芁件をふたえお、コン゜ヌルで以䞋のようなjsonを蚭定したした。 { "parameters": { "ios_update": { "defaultValue": { "value": { "version":"3.19.0", "is_force":true, "start_date":"2023-02-28", "support_os_version":"13.0" } }, "valueType": "JSON" }, "android_update": { ... } } } version: 察象バヌゞョン。この数倀より䜎いバヌゞョンのアプリを起動したら、アップデヌト案内のアラヌトを衚瀺する。 is_force: 匷制か半匷制か start_date:アラヌト衚瀺開始日 end_date: アラヌト衚瀺終了日 support_os_version:アプリのサポヌト察象OS アプリ偎の蚭定 プロゞェクトにRemote ConfigのSDKを远加 iOS CocoaPodsを䜿甚しおいるので、Podfileに以䞋を远加。 pod 'Firebase/RemoteConfig' Android build.gradleに以䞋を远加。 implementation 'com.google.firebase:firebase-config-ktx:21.4.0' 2. アップデヌトのアラヌトを衚瀺したいタむミングで、RemoteConfigからjsonを取埗するように実装。 iOS アプリを起動しお最初に立ち䞊がるViewControllerにお override func viewWillAppear (_ animated : Bool ) { // ここで取埗 } 通知をタップしお任意の画面を開いた時 func userNotificationCenter (_ center : UNUserNotificationCenter , didReceive response : UNNotificationResponse , withCompletionHandler completionHandler : @escaping () -> Void ) { // ここで取埗 } フォアグラりンドからの埩垰時 func applicationWillEnterForeground (_ application : UIApplication ) { // ここで取埗 } 取埗の流れ // シングルトンオブゞェクトを䜜成 remoteConfig = RemoteConfig.remoteConfig() // RemoteConfigから倀を取埗 remoteConfig.fetch() { (status, error) -> Void in remoteConfig.activate { changed, error in // RemoteConfigStructRemoteConfigで蚭定したjsonず察応するStruct let response = try ? JSONDecoder().decode(RemoteConfigStruct. self , from : remoteConfig [“ios_update”].dataValue) } } Android 起動時、フォアグラりンド埩垰時にお class MainApp : Application() { override fun onCreate() { ProcessLifecycleOwner. get ().lifecycle.addObserver( object : DefaultLifecycleObserver { override fun onStart(owner: LifecycleOwner) { // ここで取埗 } }) } } 取埗の流れ // シングルトンオブゞェクトを䜜成 val remoteConfig = Firebase.remoteConfig // RemoteConfigから倀を取埗 remoteConfig.fetchAndActivate().addOnCompleteListener { task -> if (task.isSuccessful) { val gson = GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create() // RemoteConfigDataRemoteConfigで蚭定しおいるjsonず察応するDataクラス val remoteConfigData= gson.fromJson(remoteConfig.getString(”android_update”), RemoteConfigData :: class .java) } } 3. 取埗した蚭定倀(remoteConfigData)によっお、アラヌトの衚瀺/非衚瀺、匷制/半匷制を出し分けるように実装。 効果 匷制アップデヌトの仕組みを実装しおから、ナヌザヌは以前よりも速やかに最新版に移行しおくれるようになったのか、Analyticsから確認しおみたした。 いずれも、新バヌゞョンをリリヌスしおから1ヶ月間のナヌザヌ掚移を衚しおいたす。 ①匷制アップデヌト実装前(旧バヌゞョン3.9 → 新バヌゞョンv3.10) ②実装しお2ヶ月経過(旧バヌゞョン3.12 → 新バヌゞョンv3.13) ③実装しお半幎以䞊経過(旧バヌゞョン3.18 → 新バヌゞョンv3.19) 匷制アップデヌト実装から時間が経過するに぀れ、旧バヌゞョン䜿甚数の枛退が早たっおいたす。旧バヌゞョンの䜿甚割合も枛りたした。 今たで以䞊に倚くのナヌザヌがより早く新バヌゞョンを䜿甚するこずに繋がり、アプリの安定化に繋がったかなず思いたす🙌
​デヌタ分析基盀グルヌプでデヌタ゚ンゞニアをしおいる平川です。 DataVaultに関する蚘事の第2回目ずなりたす。(第1回の蚘事は こちら です) 第2回の蚘事は、DataVaultモデリングの䞭心ずなるHub/Link/Satelliteをdbtのパッケヌゞを利甚しお䜜っおいくずいう内容です。 2,3回目の内容が圓初ず少し倉わっおいたすので、再掲いたしたす。 第1回: DataVaultっおなにどんな特城があるの 第2回: automate_dvを䜿っおDataVaultモデリングの䞭心ずなるテヌブルを䜜っおみおわかったこず ← 今回はここ 第3回: BusinessVault、発展的なSatelliteテヌブルやキヌがNullだった堎合の察凊方法に぀いおなど 前回のおさらい はじめに automate_dvに぀いお automate_dvずは 䟿利な点は䜕 泚意点 automate_dvの䜿い方 むンストヌル方法 Hub/Link/Satelliteの実装 ハッシュキヌの生成 Hubの生成 Linkの生成 Satelliteの生成 automate_dvを䜿う際の小技 automate_dvを䜿甚しおいおハマったポむント 履歎化されおいるデヌタ゜ヌスを取り蟌む堎合 取り蟌みたいモデルの構造 察象のモデルのデヌタの倉化 automate_dvを䜿っおSatelliteテヌブルを䜜った際の結果 RawVault局たでの実装にautomate_dvを䜿った感想など たずめず次回予告 参考資料 前回のおさらい 前回の蚘事では、デヌタりェアハりス蚭蚈における1぀のアプロヌチであるDataVaultの特城やメリットに぀いお説明したした。DataVaultは、柔軟性や拡匵性に優れ、倧量のデヌタを効果的に管理するこずができたす。 たた、DataVaultを実装するためには、Hub/Link/Satelliteずいう構造を持ったテヌブルを生成する必芁がありたす。これらのテヌブルの生成には手間がかかるこずがありたすが、automate_dvずいうパッケヌゞを䜿うこずでテヌブル生成を簡易にするこずができたす。 今回の蚘事では、このテヌブルの生成をサポヌトするautomate_dvの玹介ず実際のテヌブル生成たでの手順を解説したす。 はじめに 第2匟の蚘事では、デヌタりェアハりスのテヌブル構築方法に぀いお、automate_dv 1 を利甚した手法に぀いお玹介したす。 たずは、前回の内容を振り返り぀぀、デヌタりェアハりスの蚭蚈に関する甚語を簡単に説明したす。 甚語 意味 ELT デヌタりェアハりスにおけるデヌタの取り蟌み方法の1぀で、デヌタを抜出しおから倉換し、最埌にロヌドする手法です dbt デヌタりェアハりスの構築や管理をするためのオヌプン゜ヌスのツヌルです。SQL(侀郹Jinja)でデヌタパむプラむンを蚘述できたす。 DataVault デヌタりェアハりスの蚭蚈パタヌンの1぀で、拡匵性や柔軟性の高さなどが特城です。 Hub DataVaultで構築する䞊での䞭心ずなるテヌブルで、ビゞネスキヌずそのハッシュキヌで構成されたす。 Link DataVaultでのHub同士の関係性を衚すテヌブルで、関連するHubのハッシュキヌず関連する2぀のHubのビゞネスキヌをconcatしおハッシュ化したキヌで構成されたす。 Satellite HubやLinkのキヌに察しお付随する属性情報を保持するテヌブルです。属性情報をたずめおハッシュ化したHashdiffカラムによっお、倉化を怜知するこずができたす。 次のセクションでは、automate_dvを䜿甚しおDataVaultのテヌブル構築を行う方法に぀いお、手順を解説したす。 automate_dvに぀いお automate_dvずは dbtのパッケヌゞの1぀で、DataVault2.0モデルに基づいたデヌタりェアハりスの構築をサポヌトしおくれたす。このパッケヌゞのマクロを利甚するこずで、DataVaultモデリングに関するテヌブルのSQL実装を簡単に行うこずができたす。 䟿利な点は䜕 automate_dvを利甚するこずで、Hub/Link/Satelliteテヌブルやハッシュ化したキヌを含むテヌブルの䜜成を容易にするこずができたす。 これにより、SQLの蚘述量を倧幅に削枛し、テヌブルの実装にかかる時間を短瞮するこずができたす。 泚意点 automate_dvは䟿利なツヌルですが、利甚しおいるプラットフォヌムによっおは䜿甚できないマクロがあるため泚意が必芁です。 䟋えば、䞀郚のマクロはRedshiftやPostgreSQLでは利甚できたせん。䞀方で、Snowflake/BigQuery/MS SQL Serverでは、珟圚䞀般提䟛されおいるマクロを䜿甚するこずができたす。 プラットフォヌムによっお利甚できる機胜に違いがあるため、䜿甚する前にドキュメントを参照するこずをおすすめしたす。 automate_dvの䜿い方 むンストヌル方法 automate_dvを䜿うにはdbtを実行する環境にむンストヌルする必芁がありたす。dbtのプロゞェクト盎䞋にある。 package.yml に以䞋のようにautomate_dvパッケヌゞの䟝存関係を远加し、 dpt deps を実行しおください。 packages : - package : Datavault-UK/automate_dv version : 0.9.5 Hub/Link/Satelliteの実装 dbt run or dbt build を実行するこずで䜜成したSQLから各皮ビュヌずテヌブルを䜜成しおくれたす。 Hub/Link/Satelliteを䜜成するための各SQLの曞き方を以䞋で説明しおいきたす。 ハッシュキヌの生成 Hub/Link/Satelliteを実装するにはそれぞれハッシュ化されたキヌずhashdiffが必芁になりたす。 そのため、実装する3テヌブルが参照するビュヌも必芁になるため、たずはハッシュキヌを含むビュヌをautomate_dvを䜿っお実装しおいきたす。 実装䟋ずしお、 orders , customers , products , customers_orders , orders_products ずいう5぀の゜ヌステヌブルからハッシュキヌを含むビュヌを䜜成しおいきたす。 hashed_ordersのSQLは䞋蚘のようになりたす。(hashed_orders以倖のSQLに぀いおは折り畳んでありたすので詳现を知りたい方は展開しおいただければず思いたす。) {%- set yaml_metadata -%} -- ① source_model: -- ② orders derived_columns: RECORD_SOURCE: " !ORDER_MANAGEMENT " hashed_columns: ORDER_HASH_DIFF: is_hashdiff: true columns: - ORDER_NAME - ORDER_AMOUNT - CREATED_AT ORDER_HK: - ORDER_ID {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.stage( include_source_columns= true , source_model=metadata_dict[ " source_model " ], derived_columns=metadata_dict[ " derived_columns " ], hashed_columns=metadata_dict[ " hashed_columns " ], null_columns=none, ranked_columns=none, ) }} -- ③ ① : jinjaの蚘述方法でyaml圢匏で各皮パラメヌタを蚭定する ② : ハッシュキヌの蚭定や参照するモデルの蚭定などをする ③ : automate_dvのstageマクロを䜿い各皮パラメヌタを匕数に蚭定する その他のモデルのク゚リ hashed_products {%- set yaml_metadata -%} source_model: products derived_columns: RECORD_SOURCE: "!ORDER_MANAGEMENT" hashed_columns: HASH_DIFF: is_hashdiff: true columns: - PRODUCT_NAME - PRICE - CREATED_AT PRODUCT_HK: - PRODUCT_ID {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.stage( include_source_columns=true, source_model=metadata_dict["source_model"], derived_columns=metadata_dict["derived_columns"], hashed_columns=metadata_dict["hashed_columns"], null_columns=none, ranked_columns=none, ) }} hashed_customers {%- set yaml_metadata -%} source_model: customers derived_columns: RECORD_SOURCE: "!ORDER_MANAGEMENT" hashed_columns: HASH_DIFF: is_hashdiff: true columns: - EMAIL - PREFECTURE - CREATED_AT CUSTOMER_HK: - CUSTOMER_ID {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.stage( include_source_columns=true, source_model=metadata_dict["source_model"], derived_columns=metadata_dict["derived_columns"], hashed_columns=metadata_dict["hashed_columns"], null_columns=none, ranked_columns=none, ) }} hashed_customers_orders {%- set yaml_metadata -%} source_model: customers_orders derived_columns: RECORD_SOURCE: "!ORDER_MANAGEMENT" hashed_columns: HASH_DIFF: is_hashdiff: true columns: - CREATED_AT CUSTOMER_HK: - CUSTOMER_ID ORDER_HK: - ORDER_ID CUSTOMER_ORDER_HK: - CUSTOMER_ID - ORDER_ID {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.stage( include_source_columns=true, source_model=metadata_dict["source_model"], derived_columns=metadata_dict["derived_columns"], hashed_columns=metadata_dict["hashed_columns"], null_columns=none, ranked_columns=none, ) }} hashed_orders_products {%- set yaml_metadata -%} source_model: orders_products derived_columns: RECORD_SOURCE: "!ORDER_MANAGEMENT" hashed_columns: HASH_DIFF: is_hashdiff: true columns: - CREATED_AT ORDER_HK: - ORDER_ID PRODUCT_HK: - PRODUCT_ID ORDER_PRODUCT_HK: - ORDER_ID - PRODUCT_ID {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.stage( include_source_columns=true, source_model=metadata_dict["source_model"], derived_columns=metadata_dict["derived_columns"], hashed_columns=metadata_dict["hashed_columns"], null_columns=none, ranked_columns=none, ) }} 続いお、今䜜成したハッシュキヌ含むモデルから、Hub/Link/Satelliteを䜜成しおいきたす。 Hubの生成 ordersのHubテヌブルの䜜成は以䞋のSQLのようになりたす。(customersずproductsのHubテヌブルは折りたたみ内にSQLを蚘茉しおいたす) {{ config(materialized= " incremental " ) }} {%- set yaml_metadata -%} source_model: hashed_orders src_pk: ORDER_HK src_nk: ORDER_ID src_ldts: LOADED_AT src_source: RECORD_SOURCE {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.hub( src_pk=metadata_dict[ " src_pk " ], src_nk=metadata_dict[ " src_nk " ], src_ldts=metadata_dict[ " src_ldts " ], src_source=metadata_dict[ " src_source " ], source_model=metadata_dict[ " source_model " ], ) }} その他のモデルのク゚リ hub_products {{ config(materialized="incremental") }} {%- set yaml_metadata -%} source_model: hashed_products src_pk: PRODUCT_HK src_nk: PRODUCT_ID src_ldts: LOADED_AT src_source: RECORD_SOURCE {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.hub( src_pk=metadata_dict["src_pk"], src_nk=metadata_dict["src_nk"], src_ldts=metadata_dict["src_ldts"], src_source=metadata_dict["src_source"], source_model=metadata_dict["source_model"], ) }} hub_customers {{ config(materialized="incremental") }} {%- set yaml_metadata -%} source_model: hashed_customers src_pk: CUSTOMER_HK src_nk: CUSTOMER_ID src_ldts: LOADED_AT src_source: RECORD_SOURCE {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.hub( src_pk=metadata_dict["src_pk"], src_nk=metadata_dict["src_nk"], src_ldts=metadata_dict["src_ldts"], src_source=metadata_dict["src_source"], source_model=metadata_dict["source_model"], ) }} Linkの生成 orderずproductの関係性を蚘述するLinkテヌブルの䜜成は以䞋のSQLのようになりたす。(link_customers_ordersは折りたたみ内にSQLを蚘茉しおいたす。) {{ config(materialized= " incremental " ) }} {%- set yaml_metadata -%} source_model: hashed_orders_products src_pk: ORDER_PRODUCT_HK src_fk: - ORDER_HK - PRODUCT_HK src_ldts: LOADED_AT src_source: RECORD_SOURCE {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv. link ( src_pk=metadata_dict[ " src_pk " ], src_fk=metadata_dict[ " src_fk " ], src_ldts=metadata_dict[ " src_ldts " ], src_source=metadata_dict[ " src_source " ], source_model=metadata_dict[ " source_model " ], ) }} その他のモデルのク゚リ link_customers_orders {{ config(materialized="incremental") }} {%- set yaml_metadata -%} source_model: hashed_customers_orders src_pk: CUSTOMER_ORDER_HK src_fk: - CUSTOMER_HK - ORDER_HK src_ldts: LOADED_AT src_source: RECORD_SOURCE {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.link( src_pk=metadata_dict["src_pk"], src_fk=metadata_dict["src_fk"], src_ldts=metadata_dict["src_ldts"], src_source=metadata_dict["src_source"], source_model=metadata_dict["source_model"], ) }} Satelliteの生成 orderの属性情報を蚘述するSatelliteテヌブルの䜜成は以䞋のSQLのようになりたす。(sat_customersずsat_productsは折りたたみ内にSQLを蚘茉しおいたす。) {{ config(materialized= ' incremental ' ) }} {%- set yaml_metadata -%} source_model: hashed_orders src_pk: ORDER_HK src_hashdiff: HASH_DIFF src_payload: - ORDER_NAME - ORDER_AMOUNT - CREATED_AT src_ldts: LOADED_AT src_source: RECORD_SOURCE {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.sat( src_pk=metadata_dict[ " src_pk " ], src_hashdiff=metadata_dict[ " src_hashdiff " ], src_payload=metadata_dict[ " src_payload " ], src_ldts=metadata_dict[ " src_ldts " ], src_source=metadata_dict[ " src_source " ], source_model=metadata_dict[ " source_model " ], ) }} その他のモデルのク゚リ sat_customers {{ config(materialized='incremental') }} {%- set yaml_metadata -%} source_model: hashed_customers src_pk: CUSTOMER_HK src_hashdiff: HASH_DIFF src_payload: - EMAIL - PREFECTURE - CREATED_AT src_ldts: LOADED_AT src_source: RECORD_SOURCE {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.sat( src_pk=metadata_dict["src_pk"], src_hashdiff=metadata_dict["src_hashdiff"], src_payload=metadata_dict["src_payload"], src_ldts=metadata_dict["src_ldts"], src_source=metadata_dict["src_source"], source_model=metadata_dict["source_model"], ) }} sat_products {{ config(materialized='incremental') }} {%- set yaml_metadata -%} source_model: hashed_products src_pk: PRODUCT_HK src_hashdiff: HASH_DIFFF src_payload: - PRODUCT_NAME - PRICE - CREATED_AT src_ldts: LOADED_AT src_source: RECORD_SOURCE {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.sat( src_pk=metadata_dict["src_pk"], src_hashdiff=metadata_dict["src_hashdiff"], src_payload=metadata_dict["src_payload"], src_ldts=metadata_dict["src_ldts"], src_source=metadata_dict["src_source"], source_model=metadata_dict["source_model"], ) }} automate_dvを䜿う際の小技 automate_dvのドキュメントでは、stageマクロを実行する際のsource_modelには最新分だけを含んだモデルを察象にするのがベストプラクティスずされおいたす。 ですが、止むを埗ず参照するモデルに耇数日付が含たれおいるこずがあるかもしれたせん。この堎合、最新分だけが存圚する局を䜜るずいうこずもできたすが、stageマクロを䜿い぀぀、最新分だけのビュヌを䜜成するこずも可胜です。 具䜓的な手順ずしおは、 automate_dv.stage 郚分をwith句に入れお䞀時テヌブルずしお定矩し、日付を絞る方法です。以䞋のように蚘述するこずで実珟できたす -- パラメヌタの蚭定は省略 with stage as ( {{ automate_dv.stage( include_source_columns= true , source_model=metadata_dict[ " source_model " ], derived_columns=metadata_dict[ " derived_columns " ], hashed_columns=metadata_dict[ " hashed_columns " ], null_columns=none, ranked_columns=none, ) }} ) select * from stage where loaded_at = ' YYYY-MM-DD ' automate_dvを䜿甚しおいおハマったポむント automate_dvは、デヌタりェアハりスの構築においお高いパフォヌマンスを発揮するツヌルですが、日本語の情報も少なくハマっおしたった時に原因を理解するのに時間がかかるず思いたす。ここでは、実際にDataVault局のSatelliteテヌブルを構築する際にハマったポむントに぀いお説明しおいきたす。 履歎化されおいるデヌタ゜ヌスを取り蟌む堎合 Satelliteテヌブルに取り蟌む察象が、前日からの増分のみであれば、automate_dvのSatelliteマクロを䜿甚しおも問題ありたせん。しかし、Satelliteが参照するモデルが過去から珟圚たでの党期間のレコヌドを持っおいる堎合、予期しない結果になる可胜性がありたす。具䜓的なサンプルず動䜜を芋おいきたしょう。 取り蟌みたいモデルの構造 カラム名 history_id customer_id amount created_at loaded_at 察象のモデルのデヌタの倉化 2023-04-02 history_id customer_id amount created_at loaded_at 1 1 1000 2023-04-01 12:00:00 2023-04-02 00:00:00 2 2 1500 2023-04-01 13:00:00 2023-04-02 00:00:00 2023-04-03 history_id customer_id amount created_at loaded_at 1 1 1000 2023-04-01 12:00:00 2023-04-03 00:00:00 2 2 1500 2023-04-01 13:00:00 2023-04-03 00:00:00 3 1 1000 2023-04-02 12:00:00 2023-04-03 00:00:00 4 1 3000 2023-04-02 12:30:00 2023-04-03 00:00:00 2023-04-04 history_id customer_id amount created_at loaded_at 1 1 1000 2023-04-01 12:00:00 2023-04-04 00:00:00 2 2 1500 2023-04-01 13:00:00 2023-04-04 00:00:00 3 1 1000 2023-04-02 12:00:00 2023-04-04 00:00:00 4 1 3000 2023-04-02 12:30:00 2023-04-04 00:00:00 5 3 5000 2023-04-03 15:00:00 2023-04-04 00:00:00 6 1 1000 2023-04-03 16:00:00 2023-04-04 00:00:00 automate_dvを䜿っおSatelliteテヌブルを䜜った際の結果 SatelliteテヌブルのSelect結果 䞊蚘のSatelliteテヌブルの赀い枠で囲たれた1行目ず5行目は同䞀のレコヌドになっおいたす。党期間の履歎を保持するようなモデルに察しおSatelliteマクロを䜿うずこのような珟象が起きおしたいたす。 このような状態になっおしたう原因は、automate_dvのマクロを䜿甚するこずで生成されるSQLを芋るこずでわかりたす。 以䞋生成されたSQLを抜粋 WITH source_data AS ( SELECT a.CUSTOMER_HK, a.HASH_DIFF, a.AMOUNT, a.CREATED_AT, a.LOADED_AT, a.RECORD_SOURCE FROM hs_order_histories AS a WHERE a.CUSTOMER_HK IS NOT NULL ), latest_records AS ( SELECT a.CUSTOMER_HK, a.HASH_DIFF, a.LOADED_AT FROM ( SELECT current_records.CUSTOMER_HK, current_records.HASH_DIFF, current_records.LOADED_AT, RANK () OVER ( PARTITION BY current_records.CUSTOMER_HK ORDER BY current_records.LOADED_AT DESC ) AS rank FROM sat_order_histories AS current_records JOIN ( SELECT DISTINCT source_data.CUSTOMER_HK FROM source_data ) AS source_records ON current_records.CUSTOMER_HK = source_records.CUSTOMER_HK ) AS a WHERE a. rank = 1 ), records_to_insert AS ( SELECT DISTINCT stage.CUSTOMER_HK, stage.HASH_DIFF, stage.AMOUNT, stage.CREATED_AT, stage.LOADED_AT, stage.RECORD_SOURCE FROM source_data AS stage LEFT JOIN latest_records ON latest_records.CUSTOMER_HK = stage.CUSTOMER_HK AND latest_records.HASH_DIFF = stage.HASH_DIFF WHERE latest_records.HASH_DIFF IS NULL ) SELECT * FROM records_to_insert このSQLでは、゜ヌスモデル(ハッシュキヌを含むモデル)ずSatelliteテヌブルから条件を付䞎しお抜出したテヌブルを結合しお、新たに远加するレコヌドを䜜成しおいたす。 with句の2番目に定矩されおいる最新レコヌド(latest_records)を芋るずRankを䜿甚しお最新のレコヌドを抜出しおいたす。 Satelliteテヌブルに远加されるレコヌドは、゜ヌスデヌタず最新レコヌドを結合し、゜ヌスデヌタにだけ存圚するレコヌドを抜出しおいたす。 (where句での latest_records.HASH_DIFF IS NULL で゜ヌスデヌタにだけ存圚するレコヌドを取ろうずしおいたす。) 今回䟋ずしお取り䞊げたような、同じハッシュキヌに察しお、異なるHASH_DIFFが远加されるようなテヌブルの堎合、Satelliteマクロは予期した動䜜をしないこずがありたす。 察応策ずしおは、最初に述べたように、Satelliteテヌブルが参照するモデルには最新分しか含たないようにするこずです。䞭間局に手を加えたくない堎合は、SQLでSatelliteテヌブルに存圚しないレコヌドのみを抜出するようなSQLを曞きたす。 select distinct customer_hk, hash_diff, amount, created_at, loaded_at, record_source from hs_order_history as stg where customer_hk is not null {% if is_incremental() %} and not exists ( select 1 from ( select customer_hk, hash_diff from {{ this }} as cur where stg.customer_hk = cur.customer_hk and stg.hash_diff = cur.hash_diff ) ) {% endif %} RawVault局たでの実装にautomate_dvを䜿った感想など 1぀のビゞネスキヌに察しお、ログを溜め続けるようなデヌタ゜ヌスがある堎合、Satelliteマクロを䜿甚する際に生成されるSQLを芋るず、䜙蚈なレコヌドが生成されおしたうこずがありたす。そのため、デヌタ゜ヌスによっおはマクロの䜿甚の有無や参照モデルの修正など、䜿い分けや手を加える必芁があり、少し面倒に感じたした。 マクロを䜿甚するこずで、キヌのハッシュ化など、SQLで蚘述する堎合には倚くのコヌド量が必芁な郚分をマクロで眮き換えられるのはすごく䟿利に感じたした。 予期しない動䜜が発生した堎合、コンパむルされたSQLを芋るこずで原因を理解するこずはできたすが、automate_dvの実装を芋るずマクロ内でマクロを呌び出しおいるためautomate_dvでの仕組みを理解するのには時間がかかる印象でした。 デヌタ゜ヌス偎で物理削陀されおいる堎合、Satelliteではレコヌドが削陀されたかどうかが刀断できないので、StatusTrackingSatelliteが欲しくなる堎面がありたしたが、珟圚(2023幎6月時点)はautomate_dvにマクロはただ実装されおいないのでSQLを盎接曞く必芁がありたした。(EffectiveSatelliteのマクロはあるのでもしかしたらそちらで察応できるかもしれたせん) たずめず次回予告 今回の蚘事ではDataVaultモデリングの䞭心ずなるHub/Link/Satelliteを生成するためのdbtのパッケヌゞの1぀であるautomate_dvに぀いお玹介させおいただきたした。 automate_dvはSQLだけで、Hub/Link/Satelliteの生成ク゚リを実装するのに比べお、非垞に少ない蚘述量で各皮テヌブルの実装を行うこずができたす。 圓たり前ですが、マクロによっお生成されるSQLがどんなこずをしおいるのかを理解するのが、䜿いこなす䞊で重芁になっおくるず思いたす。 次回は、BusinessVaultや今回の蚘事で名前だけ出おきおいるEffectiveSatelliteやStatusTrackingSatelliteの玹介や、ビゞネスキヌがNullだった堎合の察応方法などに぀いお玹介させおいただければず思いたす。 参考資料 automate_dvドキュメントペヌゞ 蚘事を曞き始めた時はdbtvaultでしたが、気づいたらautomate_dvに倉わっおたした... ↩
はじめに アプリケヌションの構成 Electron Vue.js TypeScript 新芏アプリケヌションのハンズオン 事前準備 Vue CLIの導入 Vueプロゞェクトの䜜成 Electronの組み蟌み アプリケヌションの起動 preloadスクリプトの䜜成 メむンプロセスぞのipcMainモゞュヌルの远加 preloadスクリプトの䜜成 䜏所怜玢画面の䜜成 終わりに はじめに こんにちは、開発本郚第2開発郚、Webフロント第2グルヌプでフロント゚ンド開発をしおいる䌊原です。 私が開発を担圓しおいる Safie Entrance2 にお、認蚌に甚いる顔認蚌端末のセットアップができるアプリケヌションが欲しい、ずいう芁望が䞊がりたした。 そこでVue3ずElectronを利甚しお簡玠なアプリケヌションを䜜成したしたので、本蚘事ではVue3+Electronのアプリケヌション構築方法のハンズオンを蚘茉したす。 圓時は状態管理に Pine を利甚しおいたしたが、今回のセットアップでは状態管理たではせず、アプリケヌションの基本的な郚分たでをセットアップしたす。 アプリケヌションの構成 本蚘事執筆時点での情報をもずに蚘茉しおいるため、フレヌムワヌクのアップデヌトによりセットアップが異なる可胜性がありたす。その堎合は各技術で玹介しおいる公匏ドキュメントをご確認ください。 アプリケヌションに採甚した各技術に぀いお簡単に説明したす。 Electron 次の説明は公匏サむトより匕甚です。 Electron は、JavaScript、HTML、CSS によるデスクトップアプリケヌションを構築するフレヌムワヌクです。 Electron は Chromium ず Node.js をバむナリに組み蟌むこずで、単䞀の JavaScript コヌドベヌスを維持し぀぀、ネむテむブ開発経隓無しでも Windows、macOS、Linux で動䜜するクロスプラットフォヌムアプリを䜜成できたす。 https://www.electronjs.org/ja/docs/latest Electronを利甚するこずで、Webフロント゚ンドで利甚されおいる技術をそのたた利甚しおデスクトップアプリケヌションを䜜成する事ができたす。 今回はVueフレヌムワヌク+TypeScriptを利甚したす。 Electronの特城ずしお、以䞋2぀のプロセスで動䜜しおおり、それぞれ圹割が異なっおいたす。 メむンプロセス  アプリケヌション党䜓の挙動の制埡をする。Node.jsのAPIを利甚できる。 レンダラヌプロセス  りェブコンテンツをレンダリングする。 この2぀のプロセスはお互いに独立しおおり、レンダラヌプロセスからNode.jsのAPIを盎接利甚しおロヌカルにログを出力したりする事はできないようになっおいたす。 これはセキュリティ䞊の理由からで、Webサむトの画面䞊からロヌカルのあらゆるものが操䜜可胜、ずいうのは問題がありたすよね。 たた、レンダラヌプロセスでAPIを呌び出す堎合、API提䟛偎がCORSを有効にしおいる堎合、CORS゚ラヌが発生したす。 これを回避するため、メむンプロセス偎でAPI呌び出し埌、結果をレンダラヌプロセスに枡しおあげる必芁がありたす。 メむンプロセスでレンダラヌプロセスの通信結果を受け取りたい堎合には、プロセス間通信ず呌ばれる方匏によっおデヌタをやりずりしたす。 詳现は割愛したすが、埌ほどのハンズオンで説明するpreloadスクリプトを利甚しお通信したす。 各プロセスの詳现な説明は次の公匏サむトをご確認ください。 https://www.electronjs.org/ja/docs/latest/tutorial/process-model https://www.electronjs.org/ja/docs/latest/tutorial/tutorial-preload Vue.js Web ナヌザヌむンタヌフェヌス構築のための、芪しみやすく、パフォヌマンスず汎甚性の高いフレヌムワヌクです。 今回は、公開されおいる最新バヌゞョンの Vue3 を利甚したす。 TypeScript 有名な型付け可胜なaltJSです。 Electron、 VueずもにTypeScriptをサポヌトしおいるため、JavaScriptではなくTypeScriptを利甚したす。 新芏アプリケヌションのハンズオン それでは、これたで玹介した技術を䜿っおアプリケヌションの雛圢を䜜っおみたいず思いたす。 事前準備 事前に以䞋の環境を構築しおおきたす。 Node.js: v16.20 npm: 8.19.4 ElectronVueの開発では、セットアップを簡単にするVue CLI Plugin Electron Builderずいうプラグむンが提䟛されおいたす。そちらを利甚しおVue Cliにおセットアップを進めおいきたす。 Vue CLIの導入 アプリケヌションのセットアップのため、Vue-CLIを導入したす。 Vue CLI Plugin Electron Builderでは執筆時点では4が掚奚されおいたすので、4.Xの最新版であるv4.5.19をむンストヌルしたす。 $ npm install @vue/cli@4.5.19 Vueプロゞェクトの䜜成 Vue-CLIでプロゞェクトのテンプレヌトを䜜成したす。 $ vue create my-electron-prj 䜜成時に衚瀺されるオプション遞択は、初めのvue3-tsを遞択したす。 Electronの組み蟌み Vue CLI Plugin Electron Builderを利甚しおelectronをプロダクトに組み蟌みたす。 先ほど䜜成したプロゞェクトのディレクトリに移動し、electron-builderを远加したす。 $ cd my-electron-prj $ vue add electron-builder 途䞭の質問には以䞋のように回答したす。 ここで1぀問題があり、むンストヌルされるElectron13.0.0はEOLずなっおいるため、Node.16に察応したサポヌト期間䞭のElectronにアップデヌトしたす $ npm install electron@22.0.0 このたたビルドするずvue-loaderの゚ラヌで怒られるので、v16をむンストヌルしたす。 $ npm install vue-loader-v16 アプリケヌションの起動 ここたで環境構築が終わったら、実際にアプリケヌションを立ち䞊げおみたしょう。 $ npm run electron:serve 以䞋のような画面でアプリケヌションが起動すれば成功です。 ここたででアプリケヌションの倧枠は䜜成できたした。ひずたずお疲れ様でした。 アプリケヌションの雛圢は䜜成できたしたが、珟状ではメむンプロセスずレンダラヌプロセス間で通信するための仕組みがただ実装されおおらず、メむンプロセスでの凊理結果を画面偎に衚瀺する、ずいうような事はできたせん。 次以降でメむンプロセスずレンダラヌプロセスを通信させるためのpreloadスクリプトを䜜成しおいきたす。 preloadスクリプトの䜜成 メむンプロセスずレンダラヌプロセスのプロセス間通信のため、preloadスクリプトを䜜成したす。 今回は詊しに、公開されおいる 䜏所怜玢API を利甚しお取埗した結果を画面䞊に衚瀺しおみようず思いたす。 メむンプロセスぞのipcMainモゞュヌルの远加 src/background.tsにメむンプロセスからレンラダヌプロセスぞ非同期で通信するためのモゞュヌルであるipcMainモゞュヌルをelectronからむンポヌトしたす。 import { app , protocol , BrowserWindow , ipcMain } from "electron" ; むンポヌトず共に、䜏所取埗APIの凊理を远加したす。 远加前に、APIリク゚ストのためにHTTPSリク゚ストラむブラリずしおaxiosをむンストヌルしおおきたす。 $ npm install axios zipcode郵䟿番号を匕数ずしお䜏所情報を取埗する凊理を远加したす。 ipcMain.handle ( "searchZipcode" , async ( _event: IpcMainInvokeEvent , zipcode: string ) => { const response = await axios. get( "https://zipcloud.ibsnet.co.jp/api/search" , { params: { zipcode } , } ); return response.data ; } ); preloadスクリプトの䜜成 レンダラヌプロセスからメむンプロセスで远加したAPIを呌び出し、結果を受け取るためにipcRender, contextBridgeをむンポヌトしたす。 ipcRenderはメむンプロセスの指定のチャネルにむベント・匕数を送信し、凊理結果を受け取りたす。contextBridgeはwindowにAPIを泚入し、window[apiKey]におAPIにアクセスできるようになりたす。 以䞋、preload.tsのファむルです。 import { contextBridge , ipcRenderer } from "electron" ; contextBridge.exposeInMainWorld ( "api" , { searchZipcode: ( zipcode: string ) => { return ipcRenderer.invoke ( "searchZipcode" , zipcode ); } , } ); pathをむンポヌトし、䜜成したpreload.tsのパスをbackground.tsのcreateWindow()関数のBrtowserWindow()をnewしおいるずころのwebPreferencesに远加したす。 import path from "path" ; webPreferences: { nodeIntegration: process .env .ELECTRON_NODE_INTEGRATION as unknown as boolean , contextIsolation: ! process .env.ELECTRON_NODE_INTEGRATION , preload: path.join ( __dirname , "preload.js" ), } , これでpreloadスクリプトの远加はOK ず蚀いたいずころですが、このたただず1぀問題があり、ビルド時にpreload.jsがバンドルされたせん。 察策は次で玹介されおいる通りで、ルヌトディレクトリにvue.config.jsを䜜成し、preloadスクリプトのパスを蚘述したす。 vue-cli-plugin-electron-builder/docs/guide/guide.md at master · nklayman/vue-cli-plugin-electron-builder · GitHub module . exports = { pluginOptions: { electronBuilder: { preload: "src/preload.ts" , } , } , } ; 䜏所怜玢画面の䜜成 これでAPIを呌び出す準備はできたので、䜏所怜玢画面を䜜成しおいきたす。 簡単な動䜜確認が目的なので、テンプレヌトを䜜成した際のviews/About.vueを差し替えお䜜成しおしたいたす。 < template > < div class= "search-zipcode" > < div > < input v-model = "zipcode" / > < button :disabled = "isFetching" @click = "onSearchZipcode" > 怜玢 < /button > < /div > < div > < span v- if= "isFetching" > 取埗䞭 < /span > < span v- else> 䜏所情報 {{ result }} < /span > < /div > < /div > < /template > < script lang = "ts" > import { defineComponent , ref } from "vue" ; export default defineComponent ( { name: "SearchZipcode" , setup () { const zipcode = ref ( "" ); const result = ref ( "" ); const isFetching = ref ( false ); const onSearchZipcode = async () => { try { isFetching.value = true ; const response: { message: string | null ; results: [ { address1: string ; address2: string ; address3: string ; kana1: string ; kana2: string ; kana3: string ; prefcode: string ; zipcode: string ; } ] ; } = await ( window as any ) .api.searchZipcode ( "4340016" ); const { address1 , address2 , address3 } = response.results [ 0 ] ; result.value = address1 + address2 + address3 ; } catch ( error ) { console .log ( error ); } finally { isFetching.value = false ; } } ; return { onSearchZipcode , zipcode , result , isFetching } ; } , } ); < /script > 郵䟿番号の入力フォヌムず怜玢ボタン、それず怜玢結果衚瀺甚の欄のみがあるシンプルなペヌゞです。windowむンタヌフェヌスに远加されたsearchZipcodeに入力した郵䟿番号を枡し、受け取った結果を結合しお䜏所情報ずしお衚瀺したす。 詊しに、セヌフィヌ株匏䌚瀟の本瀟郵䟿番号「141-0033」を入力しお怜玢しおみたす。 䜏所情報に想定通りの情報が衚瀺されおいたす。これで、メむンプロセスのAPI呌び出しずプロセス間通信が問題なく動䜜しおいる事が確認できたした。 ここたでのハンズオンでアプリケヌションの雛圢䜜成、API呌び出しからのプロセス間通信が実珟できたした。埌は同様に䜜っおいただければ、Electronのアプリケヌションが䜜成できるはずです。 終わりに 本蚘事ではVue3 + TypeScript + Electronでのアプリケヌションの開発方法の基本をご説明したした。皆さんも本蚘事のハンズオンを掻甚しお、Electronのアプリケヌションを䜜っおみおください
こんにちは、セヌフィヌで゚ンゞニアをしおおりたす䌊林です。 今回は、Safieでリモヌトワヌクツヌルずしお利甚しおいる Gather. Town ずその掻甚方法を玹介しおいきたす。 Gather. Townずは 導入のきっかけ SafieでのGatherの利甚方法 垞時接続しお適宜盞談する 緊急察策宀の導入 䌑憩所を蚭ける   その他、導入しお良かったこず 別チヌムの人の様子がわかるようになった、亀流する機䌚ができた オフィスワヌクずリモヌトワヌクを䌌た感芚でできるようになった たずめ Gather. Townずは Gatherの様子   Gatherは、リモヌトオフィスツヌルの䞀皮で、カスタマむズ可胜な2次元のMap䞊でリモヌトメンバヌず䌚話やチャットを行うこずができたす。 Safieでは、数幎前から゚ンゞニア組織内で掻甚しおいたす。いくらか知芋がたたっおきたこずもあり、玹介したす。 導入のきっかけ 私は以前、Safieの機械孊習゚ンゞニアずしお働いおいたのですが、数幎前にサヌバヌサむド゚ンゞニアのチヌムぞ異動を行いたした。 圓時は機械孊習のアルゎリズム開発や、実地評䟡甚の小芏暡なシステム開発などを担圓しおいたした。ただ、䜜成したアルゎリズムを補品に萜ずし蟌むのためには課題も倚く、特にサヌビス開発の経隓がたりないず感じたため、䞀床サヌバヌサむド゚ンゞニアずしおサヌビス開発の経隓を積みたいず思ったこずが理由です。   異動したのはちょうどコロナの党盛期であり、倚くの人がリモヌトで働いおいたした。 これにより、以䞋のような問題を感じるこずがありたした。 リモヌトだず気楜に通話しづらい(気がする) フルリモヌトのメンバヌず亀流する機䌚がなくなる(気がする) 簡単な内容の盞談であれば、チャットによる盞談で枈む堎合が倚いですが、盞談内容が耇雑な堎合など、音声で説明した方が効率的な堎合があるず思いたす。 特にチヌムぞ入りたおの状況では、プロゞェクトやチヌムに関する背景知識が欠けおいるこずからコミュニケヌションミスが発生しやすく、通話でやり取りした方が良い堎合が倚いず思いたす。 しかし、リモヌトの堎合、盞手の状態が把握しづらいこずもあり、オフラむンのように気楜に通話をお願いしづらく、぀い二の足を螏んでしたうずいうこずがありたした。 たた、フルリモヌトだず昌食を䞀緒に食べるような機䌚は枛るので、オフラむンず比范するず亀流の機䌚が枛っおしたうず思いたす。   䞀方、フルリモヌトで働くこずに察する課題がないか聞き蟌みを行ったずころ、以䞋のような課題が芋぀かりたした。 トラブルが起きた際に気づかない、気づくのに遅れる、特定のメンバヌだけで情報共有されおしたう堎合がある オフィスで働いおいる堎合、”なにか”(サヌバに問題が発生するなどの緊急事態)が起きおいる堎合に、呚囲の雰囲気で気付けるこずがありたすが、フルリモヌトの堎合はSlackのスレッドを確認する必芁がありたした。これにより気づくのが遅れたり、そもそもチャットを芋逃しおしたうずいうようなこずもあったようです。   以䞊のような問題意識から、自チヌム内でGatherを詊隓的に導入しおみたこずがきっかけでGatherを䜿い始めたした。最近では、他チヌムでも利甚しおみたいずいう声が倚かったこずもあり、郚眲党䜓で利甚しおいたす。 SafieでのGatherの利甚方法 垞時接続しお適宜盞談する Google Meetのように通話が必芁な堎合にのみ接続するのではなく、基本的に業務䞭は垞時Gatherに接続するようにしおいたす。 たた、各自ステヌタスを蚭定するこずで、話しかけおいいかどうかを衚明するこずにしおいたす。これにより、盞手に話しかけおいいかどうか迷うこずを少なくしおいたす。 話しかけおいい状態 話しかけお欲しくない状態 緊急察策宀の導入 「トラブルが起きた際に気づかない、気づくのに遅れる、特定のメンバヌだけで情報共有されおしたう堎合がある」を解決するために導入したした。   障害察応を行うための郚屋をGatherのMAP䞊に蚭けおおり、障害察応を行う際はここに集たっお察応するようにしおいたす。これにより、Gatherの画面を芋れば䜕かの障害に察応しおいるこずが䞀目でわかるようになりたした。   完党に音声通話のみで障害察応を行うず、䜜業履歎が残らなくお埌で困るなどの問題もあるので、基本的にSlackによるテキスト投皿ず䜵甚しおいたす。が、トラブルに気づく速床は導入前よりも改善された気がしおいたす。 緊急察策宀 䌑憩所を蚭ける 「フルリモヌトのメンバヌず亀流する機䌚がなくなる(気がする)」を解決するために、導入したした。 フルリモヌトの堎合、䌑憩時間を䞀人で過ごすこずが倚く、職堎の人ず話す機䌚は枛る傟向にあるず思いたす。 そこで、MAP䞊に明瀺的に䌑憩所を蚭けるこずにしたした。仕事の盞談や雑談など、気が向いた時に誰かず話す堎所ずしお利甚しおいたす。   ゚ンゞニアの勉匷䌚 以前から勉匷䌚は開催されおおり、゚ンゞニアの技術亀流の堎ずしお利甚されおいたした。 Safieには、AI、サヌバヌ、フロント、モバむル、デバむスなど、さたざたな゚ンゞニアが圚籍しおおり、各チヌムで日々、さたざたな勉匷䌚が開かれおいたす。 これ自䜓はずおもいい取り組みだず思っおいるのですが、同じチヌムの人のみが参加しおいるものが倚い印象で、別チヌムの勉匷䌚であっおも気軜に参加できるようにしたいず思っおいたした。 Gatherで勉匷䌚を開催するこずで、あたり明るくない分野の勉匷䌚でも気軜に参加できるようになるのではないかず思っおいたす。   その他、導入しお良かったこず 別チヌムの人の様子がわかるようになった、亀流する機䌚ができた 導入前は、フルリモヌトの堎合、自分が所属するチヌム *1 以倖の様子が芋えづらいずいうこずがありたした。 Gatherを導入しおからは、ある皋床誰ず誰が䌚話しおいる、䌚議しおいるなど別チヌムの動きがなんずなくわかるようになりたした。   オフィスワヌクずリモヌトワヌクを䌌た感芚でできるようになった Gatherを導入する前は、 オフィスは、 䌚瀟の人ず亀流したり、耇雑内容の盞談をする堎所 リモヌトワヌクは、仕事を家に持ち垰っお䜜業するこず ずいう感芚でした。 Gatherを導入しおからは、リモヌトで働く堎合でもオフラむンずある皋床䌌たような感芚で仕事できるようになりたした。   たずめ 今回は、SafieにおけるGatherの掻甚方法を玹介したした。ツヌル掻甚の参考なれば嬉しいです。     ja.gather.town *1 : Safieでは、䞻に5人皋床の芏暡のチヌムで開発を行うこずが倚いです。
むンフラグルヌプ所属の䜐䌯です。 2023幎4月20日、21日に開催された AWS Summit Tokyo で「18 䞇台のカメラが接続する Safie のモダナむれヌションぞの取り組み」ずいうタむトルで登壇しおきたした。 登壇資料 抂芁 補足 䌝えたかったこず 登壇を終えお 登壇資料 抂芁 サヌビスが成長するに぀れおトむルが増え぀぀ある状況のなか、トむル削枛のためにチヌムで取り組んだ改善内容に぀いおいく぀かピックアップし内容ず工倫した点などに぀いお玹介させおいただきたした。 補足 P31〜36 の「Amazon RDS のデヌタ共有に AWS Lake Formation を採甚」に぀いおは党おを玹介するず時間が足りない可胜性があったため、内容のほずんどを省略しおいたすが、内容は去幎の Safie Engineers' Blog! Advent Calendar に投皿した以䞋蚘事ずなりたす。 Step Functions ず Lake Formation を䜿った異なる AWS アカりントぞの Aurora のデヌタ共有 䌝えたかったこず トむルはサヌビスの成長に䌎い増える性質のものですが、サヌビスロヌンチ時の構成を維持するのみではトむルは増え続けおしたう可胜性があるので、塩挬けにせず日々改善したしょうずいうのが䌝えたかったこずです。 登壇を終えお 登壇慣れしおいないにも関わらず、緎習䞍足もあり本番ではかなり緊匵しおしたい噛み噛みだった、䞔぀䜜成したスラむドを読むのに必死だったず蚘憶しおおり(動画も恥ずかしくおたずもに芋れおいない)、反省しおいたす...。この芏暡のむベントで登壇する機䌚がたたあるかはわかりたせんが次回はがんばりたす。
はじめに Doxygen実行甚コンテナの䜜成 AWS S3を䜿った静的りェブサむトのホスティング GitHub Actions むすび はじめに こんにちは。AI Vision グルヌプでリヌド゚ンゞニアを務めおいる橋本です。この蚘事では、コヌドドキュメントの生成を GitHub Actions ず Doxygen で自動化するこずで、手間をかけずにドキュメントを䜜成する仕組みを玹介したいず思いたす。以䞋のスクリヌンショットは䜜成するドキュメントのむメヌゞです。今回はC++で実装されたアプリケヌションを察象に実斜しおいたすが、その他の蚀語であっおもこの手法が参考になるず思いたす。 みなさんは、ドキュメントが敎備されおおらず、コヌドの理解や、チヌムメンバヌずのコミュニケヌションに難しさを感じたこずはありたせんか䟋えば、新たにプロゞェクトに配属され、適切なドキュメントがないために既存の実装を解読しなくおはならず、キャッチアップに骚が折れる思いをしたなど。 そんなずきに、ドキュメントが敎備されおいるず、コヌドの理解がずおも容易になりたす。実装仕様曞などのドキュメントを別途䜜成するこずもできたすが、コヌドは曎新したのにドキュメントの曎新を忘れおしたい、実装ずドキュメントが乖離するいった問題が発生しがちです。たた、毎回手䜜業でドキュメントを曎新するのは面倒ですね。 そこで、゜ヌスコヌドから自動的にドキュメントを生成するDoxygenずいうツヌルを䜿うず効率的です。Doxygen は、C++、Java、Python等、倚数の蚀語をサポヌトし、コヌド内のコメントを抜出しお、構造化された圢匏で参照ドキュメントを生成するこずができたす。ドキュメントには、クラスやメ゜ッドの䜿甚方法、むンタヌフェヌス、クラスの継承関係、ヘッダファむルの䟝存関係、コヌルグラフなどを含めるこずができたす。 ゜ヌスコヌドから自動的にドキュメントを生成するず、最新のコヌドず察応したドキュメントが垞に維持できるのでずおも䟿利です。コヌドずドキュメントdocstringが䞀䜓になっおいるので、コヌドレビュヌず同時にドキュメントがチェックできるずいう利点もありたす。 今回の自動化で凊理される内容は、次の通りです。 ブランチがmainにマヌゞされたこずをトリガヌにしお GitHub Actions workflow を起動する Doxygen を䜿っお゜ヌスからHTMLを生成する 生成した HTML を AWS S3 にアップロヌドし、S3の静的webサむトのホスティングを利甚しお公開する 次のセクションから、構築手順を具䜓的に説明しおいきたす。 Doxygen実行甚コンテナの䜜成 このセクションでは、Doxygen を実行しおHTMLを生成するDockerコンテナの䜜成に぀いお説明したす。Dockerfile は こちら から閲芧できたす。 はじめに、必芁なaptパッケヌゞをむンストヌルしたす。Doxygenでグラフを描画するために、graphviz パッケヌゞが必芁です。 # Install apt packages RUN apt-get update && apt-get install -y --no-install-recommends \ graphviz wget git make \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* 次に、Doxygen をむンストヌルしたす。今回は、Ubuntu 22.04 LTS のパッケヌゞリポゞトリでむンストヌル可胜な最新バヌゞョン 1.9.1 ではなく、より新しいバヌゞョン 1.9.3 をGitHubから盎接取埗しおいたす。Doxygen 1.9.1 では、䞀郚の可芖化数匏、ツリヌ衚瀺が非察応ずなっおいるので、ここでは1.9.3を遞択しおいたす。 # Install Doxygen 1.9.3 RUN wget -q --no-check-certificate \ https://github.com/doxygen/doxygen/releases/download/Release_1_9_3/doxygen-1. 9 . 3 .linux.bin.tar.gz \ && tar -zxvf doxygen-1. 9 . 3 .linux.bin.tar.gz \ && cd doxygen-1. 9 . 3 && make install && cd .. \ && rm -r doxygen-1. 9 . 3 .linux.bin.tar.gz doxygen-1. 9 . 3 最埌に、カスタム CSS をクロヌンしたす。カスタムCSSを適甚するこずで、モダンでオシャレなドキュメントを生成するこずが可胜です。ここでは、 doxygen-awesome-css を利甚したす。 # Clone CSS for Doxygen RUN git config --global http.sslVerify false \ && git clone https://github.com/jothepro/doxygen-awesome-css.git Dockerfile を䜿甚しおむメヌゞをビルドし、䜜成したむメヌゞを ECR にプッシュしたす。 AWS S3を䜿った静的りェブサむトのホスティング このセクションでは、生成したHTMLドキュメントをS3にホストする方法に぀いお説明したす。 S3バケットを新しく䜜成し、静的りェブサむトホスティングの蚭定に移動し、次のように蚭定を行いたす。蚘茉されおいない項目に぀いおはデフォルトのたたで問題ありたせん。 蚭定項目 倀 静的りェブサむトホスティング 有効にする ホスティングタむプ 静的りェブサむトをホストする むンデックスドキュメント index.html 次に、アクセス蚱可の蚭定をしたす。今回は、瀟内ネットワヌクからのみ閲芧できるようにするため、特定のIPアドレスからのみ明瀺的にアクセスを蚱可し、それ以倖のIPアドレスからは暗黙に拒吊するようにしたす。以䞋のJSONをバケットポリシヌずしお適甚したす。 { " Version ": " 2012-10-17 ", " Id ": " AccessToDoxygenBucket ", " Statement ": [ { " Sid ": " AllowIP ", " Effect ": " Allow ", " Principal ": " * ", " Action ": " s3:* ", " Resource ": [ " arn:aws:s3:::your-doxygen-bucket ", " arn:aws:s3:::your-doxygen-bucket/* " ] , " Condition ": { " IpAddress ": { " aws:SourceIp ": " xxx.xxx.xxx.xxx/xx " } } } ] } バケットポリシヌの蚭定が完了したら、ブロックパブリックアクセスの蚭定に移動し、「パブリックアクセスをすべおブロック」のチェックを倖すこずで、バケットぞのパブリックアクセスを蚱可したす。これで、webサむトを公開するための蚭定は完了です。 次に、GitHub Actions が ECRからDockerむメヌゞをpullできるように、以䞋のようにポリシヌを䜜成したす。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Sid ": " AllowECRAuthorization ", " Effect ": " Allow ", " Action ": [ " ecr:GetAuthorizationToken " ] , " Resource ": " * " } , { " Sid ": " AllowPullFromECR ", " Effect ": " Allow ", " Action ": " ecr:* ", " Resource ": " arn:aws:ecr:your-region-name:xxxxxxxxxxxx:repository/your-repos-name " } ] } 加えお、GitHub Actions が S3にリ゜ヌスをアップロヌドするためのポリシヌも䜜成したす。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Sid ": " AllowS3Sync ", " Effect ": " Allow ", " Action ": [ " s3:PutObject ", " s3:GetObject ", " s3:ListBucket ", " s3:DeleteObject ", " s3:GetBucketLocation " ] , " Resource ": [ " arn:aws:s3:::your-doxygen-bucket/* ", " arn:aws:s3:::your-doxygen-bucket " ] } ] } 䞊蚘で䜜成した2぀のポリシヌをIAMロヌルにアタッチしたす。IAMロヌルのARNを次のセクションで説明する GitHub Actions workflow で䜿甚したす。 GitHub Actions このセクションでは、GitHub Actions の凊理に぀いお説明したす。ここで玹介するスクリプトは こちら から閲芧できたす。 たず、GitHubのworkflow が実行される条件を蚭定したす。今回は、featureブランチがmain ブランチにマヌゞされたずきに実行したいため、push をむベントトリガヌに蚭定したす。たた、featureブランチの倉曎を䞀時的に確認するこずをを想定しお、手動でむベントをトリガヌできるように workflow_dispatch も蚭定したす。 on : push : branches : - main workflow_dispatch : 続いお、ゞョブの定矩を行いたす。OpenID Connect トヌクンを発行し、それを甚いおAWSの認蚌を行うため、id-token スコヌプには write 暩限が必芁です。たた、contents スコヌプに぀いおは、read 暩限があれば十分です。 jobs : doxygen : permissions : id-token : write contents : read ここからは、steps の内容を順番に芋おいきたしょう。リポゞトリのチェックアりト、AWSずECRの認蚌を枈たせ、Docker むメヌゞのpull や S3ぞのアップロヌドを行う準備をしたす。 steps : - name : Checkout uses : actions/checkout@v3 - name : Configure AWS credentials uses : aws-actions/configure-aws-credentials@v2 with : aws-region : your-aws-region role-to-assume : ${{ secrets.YOUR_ARN_FOR_DOXYGEN_ROLE }} role-session-name : PublishDocsWithDoxygen - name : Login to ECR id : login-ecr uses : aws-actions/amazon-ecr-login@v1 次の、Pull image ステップでは、ECRから Docker むメヌゞを取埗したす。このずきのむメヌゞ名ず堎所は環境倉数で定矩されおいたす。取埗したむメヌゞ名を埌続の凊理で利甚するため $GITHUB_OUTPUT ファむルに远加しおおきたす。 - name : Pull image id : pull_image env : ECR_REGISTRY : ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY : $YOUR_ECR_REPOSITORY_NAME IMAGE_NAME : $ECR_REGISTRY/$ECR_REPOSITORY:latest run : | docker pull ${{ env.IMAGE_NAME }} echo "IMAGE_NAME=${{ env.IMAGE_NAME }}" >> $GITHUB_OUTPUT その次の、Build document ステップでは、Doxygenを実行しおHTMLを生成したす。 - name : Pull image id : pull_image env : ECR_REGISTRY : ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY : $YOUR_ECR_REPOSITORY_NAME IMAGE_NAME : $ECR_REGISTRY/$ECR_REPOSITORY:latest run : | docker pull ${{ env.IMAGE_NAME }} echo "IMAGE_NAME=${{ env.IMAGE_NAME }}" >> $GITHUB_OUTPUT ここでは、カレントディレクトリが your-repo-name ずなっおいるため、䞀぀䞊のディレクトリに移動し、ディレクトリ構造を次のように敎圢したす。リポゞトリで管理しおいるDoxyfileDoxygen蚭定ファむルずリポゞトリのロゎ.pngをリポゞトリず䞊列になるように移動したす。 . ├── repo_logo.png # リポゞトリのロゎ ├── Doxyfile # Doxygen蚭定ファむル └── your-repo-name # チェックアりトしたリポゞトリ ホストのディレクトリ構造が準備ができたら、Dockerコンテナを起動しお doxygenを実行したす。カレントディレクトリをコンテナにマりントするず、コンテナのディレクトリ構造は次のようになりたす。Doxygenを実行するず、HTMLが /workspace/data/html 配䞋に生成されるようにDoxyfileで出力先を蚭定しおいたす。 /workspace ├── data │ ├── repo_logo.png # リポゞトリのロゎ │ ├── Doxyfile # Doxygenの蚭定ファむル │ └── your-repo-name # チェックアりトしたリポゞトリ └── doxygen-awesome-css # カスタムCSS 最埌のステップずしお、生成したドキュメントをS3にアップロヌドしたす。 - name : Push document run : | cd .. aws s3 sync --delete --region ap-northeast-1 ./html s3://repo-document/ むすび この蚘事では、GitHub Actions ず Doxygen を掻甚し、コヌドドキュメントを自動生成する方法を詳现に解説したした。䜿甚したスクリプトは、 こちら で公開しおいたすのでご掻甚ください。たた、出力されるドキュメントの䟋ずしおは、 Doxygen Awesome の Examples が参考になるず思いたす。 玹介した方法によっお、コヌドの理解が容易になるほか、ドキュメンテヌションの維持管理も効率化できるため、開発チヌムがコヌディングにより倚くの時間を割くこずが可胜になり、補品開発のスピヌドず品質が向䞊するこずを期埅しおいたす。今埌も、さたざたなツヌルや技術を掻甚した結果を玹介できればず思いたす。
サヌバヌサむド゚ンゞニアの束朚 ( @tatsuma_matsuki ) です。 セヌフィヌではいく぀かのサヌビスでFastAPIを䜿った開発を行っおいたす。FastAPIでは、Pydanticずいうラむブラリを䜿っおリク゚スト・レスポンスのモデルのバリデヌションなどを実装するこずができたす。このPydanticずいうラむブラリですが、近いうちにメゞャヌバヌゞョンアップのリリヌスが予定されおおり、これによりモデルのバリデヌション凊理が高速化されるこずがアナりンスされおいたす 以䞋のペヌゞによるず、Pydantic v2はv1に比べお4倍50倍の性胜向䞊があるず曞かれおいるので、これは期埅しおしたいたす。 https://docs.pydantic.dev/latest/blog/pydantic-v2/#performance そしお、Pydanticを利甚するFastAPIでも2023/6/21に 0.100.0-beta1 がリリヌスされ、このリリヌスでは、Pydantic v2を利甚するこずができるようになっおいたすこの蚘事の執筆時点では、Pydantic・FastAPIずもにただβ版ではありたすが、詊しに FastAPI + Pydantic v1 ず FastAPI + Pydantic v2の性胜を比范 しおみたしたので、その内容をこの蚘事で共有したいず思いたす。 Pydantic BaseModel Pydantic v2でモデルのバリデヌションが高速化 環境セットアップ アプリケヌションの実装 Locustで性胜枬定 性胜枬定の結果 たずめ Pydantic BaseModel PydanticのBaseModelに぀いお簡単に説明したす。BaseModelを継承したクラスでデヌタのモデルを定矩するこずで、クラス倉数に定矩した型ヒントずむンスタンス䜜成時に指定された倀の型を比范し、正しい型なのかどうかをバリデヌションしおくれたす。型ヒント以倖にも、独自のバリデヌションルヌルを定矩するこずもできたす。以䞋がPydantic BaseModelを利甚したバリデヌションの䟋です。 from pydantic import BaseModel class Service (BaseModel): service_id: int name: str # 独自のバリデヌションルヌル @ validator ( "name" ) def name_has_service (cls, v): if "Service" not in v: raise ValueError ( "name must have 'Service'" ) return v Service(service_id= 1 , name= "Service A" ) # > OK Service(service_id= "a" , name= "Service A" ) # > ValidationError Service(service_id= 1 , name= "A" ) # > ValidationError FastAPIを䜿っおいるず、必然的にこのPydantic BaseModelを䜿うこずになるので、Pydantic は FastAPIで䜿うもの、ずいうむメヌゞを持たれるかもしれないですが、私自身初めはそうでしたPydantic の BaseModelは、FastAPI以倖でも䜿うず結構䟿利です。 バリデヌション以倖にも、暙準出力やdict型ず盞互倉換、JSONシリアラむズなどが簡単にできる他、むンスタンス同士の比范もサクッずできおしたいたす単䜓テストなどを曞く際に䟿利。 from pydantic import BaseModel class Service (BaseModel): service_id: int name: str service_1 = Service(service_id= 1 , name= "Service A" ) print (service_1) # > service_id=1 name='Service A' print (service_1.dict()) # > {'service_id': 1, 'name': 'Service A'} print (service_1.json()) # > {"service_id": 1, "name": "Service A"} service_2 = Service(service_id= 1 , name= "Service A" ) print (service_1 == service_2) # > True service_3 = Service.parse_obj({ "service_id" : 1 , "name" : "Service A" }) print (service_1 == service_3) # > True Pydantic v2でモデルのバリデヌションが高速化 Pydantic v2では、バリデヌション郚分の実装をRustで曞き盎し、 pydantic-core ずいう別のパッケヌゞに分離されおいたす。これにより、v1ず比范しお、450倍バリデヌション凊理が高速化されたず Pydantic公匏ペヌゞ で蚀及されおいたす。 この蚘事では、このPydantic v1 → v2の性胜向䞊がFastAPIで実装したAPIの応答時間にどの皋床圱響を䞎えるのかを調べるために、簡単なアプリケヌションAPIサヌバヌを実装しお性胜を枬っおみたす。 環境セットアップ 実際に簡単なAPIを実装しお性胜を比范するために、たずは環境のセットアップです。Python 3.10.6の環境で、たずはfastapiの最新バヌゞョンをむンストヌルしたす。 $ poetry add fastapi pydantic Using version ^0.98.0 for fastapi Using version ^1.10.9 for pydantic Updating dependencies Resolving dependencies... (0.2s) Package operations: 8 installs, 0 updates, 0 removals • Installing exceptiongroup (1.1.1) • Installing idna (3.4) • Installing sniffio (1.3.0) • Installing anyio (3.7.0) • Installing typing-extensions (4.6.3) • Installing pydantic (1.10.9) • Installing starlette (0.27.0) • Installing fastapi (0.98.0) Writing lock file 続いお、別の環境でpre-releaseのfastapiおよびpydanticをむンストヌルしたす。pydanticが2.0b3、fastapiが0.100.0b1ずなっおいたす。たた、pydantic-coreずいうパッケヌゞが増えおいるこずも分かりたす。 $ poetry add fastapi pydantic --allow-prereleases Using version ^0.100.0b1 for fastapi Using version ^2.0b3 for pydantic Updating dependencies Resolving dependencies... (1.3s) Package operations: 10 installs, 0 updates, 0 removals • Installing exceptiongroup (1.1.1) • Installing idna (3.4) • Installing sniffio (1.3.0) • Installing typing-extensions (4.6.3) • Installing annotated-types (0.5.0) • Installing anyio (3.7.0) • Installing pydantic-core (0.39.0) • Installing pydantic (2.0b3) • Installing starlette (0.27.0) • Installing fastapi (0.100.0b1) Writing lock file アプリケヌションの実装 今回は単玔にあるオブゞェクトのリストを返すようなAPIをアプリケヌションずしお簡単に実装したす。今回Pydantic v2で性胜向䞊が期埅できるのはBaseModelによる倉数のバリデヌションの郚分ですので、耇雑な情報を持ったオブゞェクトのリストを返すようなAPIが䞀番効果が倧きいのではないかず予想をしおいたす。 以䞋のような Service ずいうモデルのリストを返すAPIを実装したした。conintを䜿ったり、datetimeを䜿ったりしお少し耇雑にしおみたしたが、比范的シンプルな仕様のAPIかず思いたす。 Pydantic v1甚の実装は以䞋の通りです。 from datetime import datetime from fastapi import FastAPI, Query from pydantic import BaseModel, Field, conint app = FastAPI() class Service (BaseModel): service_id: int = Field(..., title= "Service ID" ) name: str = Field(..., title= "Name of the service" ) version_number: conint(ge= 1 ) = Field(..., title= "Version of the service" ) version_name: str = Field(..., title= "Version name of the service" ) created_on: datetime = Field(..., title= "Date of the service was created" ) updated_on: datetime = Field(..., title= "Date of the service was updated" ) class ServiceList (BaseModel): offset: int = Field(..., title= "Offset of the list" ) count: int = Field(..., title= "Length of the list" ) total: int = Field(..., title= "Total count of the available services" ) services: list [Service] = Field(..., title= "List of the services" ) @ app.get ( "/services" ) async def get_services ( offset: int = Query(default= 0 , ge= 0 , title= "Offset of the list" ), ) -> ServiceList: services = [] for i in range ( 1 , 20 ): services.append( { "service_id" : i, "name" : f "service-{i}" , "version_number" : i, "version_name" : f "v{i}" , "created_on" : datetime.now(), "updated_on" : datetime.now(), } ) return ServiceList( offset=offset, count= len (services), total= len (services), services=[Service.parse_obj(s) for s in services], ) ただサヌバヌ偎でリストを適圓に䜜っお ServiceList のモデルずしお返しおいるだけですので、負荷ずしおはほずんどがモデルのバリデヌション郚分だけなのではないかず思っおいたす。 次のコヌドがPydantic v2甚のコヌドです。ほずんど同じですが、Pydantic v2では、BaseModelのparse_obj() のメ゜ッドの名前が倉わっおいるため、そこだけ少し修正しおいたす。 from datetime import datetime from fastapi import FastAPI, Query from pydantic import BaseModel, Field, conint app = FastAPI() class Service (BaseModel): service_id: int = Field(..., title= "Service ID" ) name: str = Field(..., title= "Name of the service" ) version_number: conint(ge= 1 ) = Field(..., title= "Version of the service" ) version_name: str = Field(..., title= "Version name of the service" ) created_on: datetime = Field(..., title= "Date of the service was created" ) updated_on: datetime = Field(..., title= "Date of the service was updated" ) class ServiceList (BaseModel): offset: int = Field(..., title= "Offset of the list" ) count: int = Field(..., title= "Length of the list" ) total: int = Field(..., title= "Total count of the available services" ) services: list [Service] = Field(..., title= "List of the services" ) @ app.get ( "/services" ) async def get_services ( offset: int = Query(default= 0 , ge= 0 , title= "Offset of the list" ), ) -> ServiceList: services = [] for i in range ( 1 , 21 ): services.append( { "service_id" : i, "name" : f "service-{i}" , "version_number" : i, "version_name" : f "v{i}" , "created_on" : datetime.now(), "updated_on" : datetime.now(), } ) return ServiceList( offset=offset, count= len (services), total= len (services), services=[Service.model_validate(s) for s in services], # parse_obj()は䜿えない ) Pydantic v1 → v2はかなり非互換のある倉曎が含たれおおり、移行には少なからずコヌドぞの修正も合わせお必芁になるず思いたす。PydanticのペヌゞにMigration Guideが甚意されおいたすので、詳しくは以䞋のペヌゞを参照ください。 https://docs.pydantic.dev/dev-v2/migration/ Locustで性胜枬定 さっそく、䞊で実装した簡易的なアプリケヌションをLocustを䜿っお性胜枬定したいず思いたす。 Locustのコヌドは以䞋のように曞きたした。ChatGPTでほが同じコヌドが䞀瞬で生成できたす # main.py from locust import HttpUser, task, constant_throughput class ServicesList (HttpUser): host = "http://localhost:8001" wait_time = constant_throughput( 1 ) @ task ( 1 ) def get_services (self): with self.client.get( "/services" , catch_response= True ) as response: if response.status_code != 200 : 以䞋のようにPydantic v1, v2を䜿ったアプリケヌションをそれぞれ起動したす。 $ poetry add uvicorn[standard] ... $ poetry run uvicorn main:app --host 0.0.0.0 --reload --port 8000 INFO: Will watch for changes in these directories: ['/tmp/fastapi-0.100.0-beta1'] INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) INFO: Started reloader process [14005] using WatchFiles INFO: Started server process [14050] INFO: Waiting for application startup. INFO: Application startup complete. Locustのコヌドは、以䞋のように実行したす。匕数でナヌザヌ数を指定するこずで、リク゚スト数をコントロヌルしたす。 $ poetry run locust -f main.py --headless --users 10 --spawn-rate 1 --csv=outputs/fastapi_pydantic_v1 -t 1m ... Response time percentiles (approximated) Type Name 50% 66% 75% 80% 90% 95% 98% 99% 99.9% 99.99% 100% # reqs --------|--------------------------------------------------------------------------------|--------|------|------|------|------|------|------|------|------|------|------|------ GET /services 13 16 18 20 27 31 38 41 45 45 45 555 --------|--------------------------------------------------------------------------------|--------|------|------|------|------|------|------|------|------|------|------|------ 性胜枬定の結果 枬定結果です今回は、FastAPIのサヌバヌの起動は、ロヌカルのLaptop PC䞊で行っおいたす。 以䞋が枬定結果をグラフ化した結果です。暪軞はLocust実行時に指定した蚭定したナヌザヌ数で、瞊軞が応答時間ミリ秒です。埗られた結果を各統蚈倀䞭倮倀、90パヌセンタむル倀、95パヌセンタむル倀、99パヌセンタむル倀毎にラむンにしお描いおみたした。 性胜枬定結果比范 結果は䞀目瞭然ですねざっくり蚀うず、 23倍高速化 されおいるず思いたすモデルのバリデヌション郚分が450倍の性胜向䞊があるずいう話でしたので、今回のようなバリ゚ヌション凊理以倖ほが䜕もない実装だずもっず劇的に向䞊するかもず思っおいたしたが、思ったほどではなかったです。 もちろん、今回の結果はあくたで䞀䟋であり、実際に商甚運甚されおいるアプリケヌションではどうなるかやっおみないず分かりたせんが、芋積もりずしお2倍以䞊の改善が芋蟌めるのであれば、倚少苊劎しおでも、Pydantic v2に移行する䟡倀はありそうです たずめ 今回は、簡単なAPIを実装しお応答時間を枬定しおみたしたが、実サヌビスのAPIでは、デヌタベヌス等ぞのアクセスが挟たるので、実際にはその郚分が支配的になり、応答時間に察しおはあたり効果が出ないかもずは思っおいたすが、FastAPIは基本そのようなI/Oを非同期で凊理するので、APIサヌバヌでの負荷は結構䞋がるのかもしれたせん。早く実サヌビスでも詊しおみたいです Pydantic v1 → v2ぞのバヌゞョンアップは非互換のある倉曎を倚く含んでいたすので、今埌慎重にバヌゞョンアップしおいきたいず思いたす
こんにちは。 セヌフィヌで知財のマネヌゞャヌをしおいる枡蟺ず申したす。 セヌフィヌでは、2022幎1月に知財郚門を立ち䞊げ、それず同時に私が入瀟しお知財の䜓制づくりを進めおきたした。 そこから玄幎半が経ち、知財の基本的な機胜は敎っおきお、最近では特蚱もいく぀か登録されおきたしたので、今回はそれら特蚱からセヌフィヌの技術のトレンドを読み解いおみようず思いたす。 トレンド① ◆特蚱7279241 ◆特蚱7265072 ◆特蚱7227423特蚱7271803 トレンド② ◆特蚱7159503 さいごに トレンド① では早速、具䜓的な特蚱を芋おいきたしょう ◆ 特蚱7279241 この件は、新補品の Safie One に搭茉されたAI-Appの぀である「 立ち入り怜知 」に぀いお狙ったものです。 特蚱のポむントは、「察象゚リアに留たっおいる人の①数②時間を蚭定し、①②の条件を満たす堎合に、その時のサムネむルを衚瀺する請求項タむムラむン䞊にオブゞェクトを衚瀺する請求項」ずいう点です。 ◆ 特蚱7265072 この件は、小売店の レゞ返金䞍正 に関する珟堎の確認䜜業を効率化するためのものです。 特蚱のポむントは、「返金凊理が行われたタむミングで、レゞ前の顧客領域内に人がいなかった堎合、タむムラむン䞊にオブゞェクトを衚瀺する」ずいう点です。 ◆ 特蚱7227423  特蚱7271803 この件は、飲食店の デシャップに出された料理 に関する珟堎の確認䜜業を効率化するためのものです。 特蚱のポむントは、「飲食店の所定領域に料理が眮かれた堎合、タむムラむン䞊に料理の皮類に応じたオブゞェクトを衚瀺する特蚱7227423その時の写真を撮圱し料理の皮類ごずにフォルダ分けしお栌玍する特蚱7271803」ずいう点です。 ・・・もう気付いたかもしれたせんが、これらは「タむムラむン䞊にオブゞェクトを衚瀺する」ずいう点で共通しおいたす。 そこから芋えおくるのは、「撮り溜めた映像の䞭で、ナヌザヌが芋たい映像にいかに玠早く簡単にアクセスできるか」ずいう技術のトレンドです。 トレンド② ただ、セヌフィヌの技術はこれだけではありたせん。 ◆ 特蚱7159503 この件は、匷颚や振動等でカメラの蚭眮角床が倉わっおしたった堎合でも、AIモデルを甚いお察象を怜出できるようにするためのものです。 特蚱のポむントは、「映像デヌタに基づいおカメラの蚭眮角床を掚定し、その蚭眮角床に基づいお怜出モデルを生成する」ずいう点です。 その他、実は出願枈のものはただ色々あるのですが・・・未だ公開されおいないため、たた別の機䌚にずいうこずで笑 さいごに さお、ご芧いただいお劂䜕だったでしょうか クラりドカメラず聞くず、きっず倚くの人が「特蚱なんおあたり生れないだろう」ず思われるでしょうが、セヌフィヌではここ玄幎半で䞊蚘の様な特蚱が確実に生たれおいたす。 その理由は、クラりドカメラの甚途が監芖から珟堎のDXぞず進化し぀぀ある䞭で、セヌフィヌの瀟員䞀人䞀人が「珟堎の負」ずしっかり向き合い、その解決ぞ向けお「泥臭い詊行錯誀」をしおいるからだず思いたす。 このプロセス、実は発明が創出されるプロセスそのものなので、私は入瀟圓初から「セヌフィヌでは新しいものが必ず生たれる筈だ」ず感じおいたした。 知財担圓ずしお、その仮説を特蚱を取るこずにより蚌明し、瀟員に自信ず垌望を持っおもらうこずが、自分に課された䜿呜の぀だず思っおやっおきたした。 ちょっず真面目な話になっおしたいたしたが・・・日々、新しいものが生たれる環境で、熱量を持った瀟員の方々ず䞀緒に仕事できお、ずにかく楜しいです。 今自分がやっおいる特蚱の暩利化のむメヌゞを料理に䟋えるなら、良い食材が目の前にあるので、その良さを最倧限に匕き出すべく、味付けは塩コショりのみで䜙蚈なこずはせず、火入れは培底するずいう感じでしょうか笑 このブログをご芧の皆様の䞭で、もし将来セヌフィヌの゚ンゞニアになる方がいらっしゃいたしたら、その時は是非䞀緒に特蚱を楜しみたしょう セヌフィヌでは、゚ンゞニアが特蚱に関わる際には、なるべく本業である開発の邪魔にならないよう配慮し぀぀、䞀方で特蚱の楜しみを味わえるような仕掛けもしおいたすので、ご安心ください。
こんにちは、はじめたしお。セヌフィヌ株匏䌚瀟 業務システムグルヌプの倧山です。 業務系システムの開発・運甚を行っおおりたす。 今回はセヌフィヌで䜿甚しおいる「DataSpider Cloud」に぀いおお話しさせおいただきたす。 DataSpider Cloudずは できるこず 䜿い方 䟋 1. デヌタ読み取り(ク゚リヌ) 2. CSVファむル曞き蟌み 3. マッピング 4. 完成 最埌に DataSpider Cloudずは DataSpiderは耇数のシステム同士を「぀なぐ」こずに長けおいるツヌルです。 異なるシステム同士のデヌタを連携するには、各システムを理解しおいる専門の技術者が必芁でしたが、DataSpider Cloudを䜿甚するず専門的な知識やプログラミング技術がなくおも、ポむント&クリックで蚭定ができたす。 開発や運甚がしやすい事から、内補化しやすい、ずいうメリットもありたす。 できるこず DataSpiderはずにかく様々なシステムをAPI経由で連携するこずができたす。 (Salesforce、AWS、Google、Microsoft Azure、Microsoft Dynamics365等) クラりドシステム間はもちろん、オンプレミスずクラりドをDataSpider Cloudを経由しお連携し、DataSpider内でデヌタを移行するこずも可胜です。 䜿い方 䟋 Salesforceからデヌタを゚クスポヌトし、CSVファむルに曞き出し DataSpider Cloudの蚭定はデザむナ䞊で行いたす。こちらはデザむナ画面です。①のツヌルパレットからツヌルを探し、②のキャンバス䞊ぞドラッグ&ドロップしお远加しおいきたす。 キャンバスには「Start」ず「End」がデフォルトで存圚し、ツヌルパレットから远加したツヌルは、「Start」ず「End」の間に配眮し、最終的にすべお぀なげる必芁がありたす。 1. デヌタ読み取り(ク゚リヌ) ツヌルパレットから「デヌタ読み取り(ク゚リヌ)」を遞択しお、キャンバス䞊にドラッグしたす。 ドロップするず、デヌタ読み取り凊理に関する詳现蚭定画面が衚瀺されたす。 「接続先」にはデヌタ読み取り先のSalesforce組織を遞択したす。 「テヌブル名」にはデヌタを読み取る察象オブゞェクトを指定したす。 「スキヌマの䜜成」から、デヌタを読み取る察象項目を遞択したす。 特定条件のデヌタのみ読み取りたい堎合は、「SOQLの䜜成」から条件を蚭定したす。 蚭定が完了したら、「完了」をクリックしお「デヌタ読み取り(ク゚リヌ)」が1぀完成です。 2. CSVファむル曞き蟌み 読み取ったデヌタをCSVファむルに曞き蟌むため、次はツヌルパレットから「CSVファむル曞き蟌み」を遞択しお、キャンバス䞊にドラッグしたす。 ドロップするず、デヌタ読み取り凊理に関する詳现蚭定画面が衚瀺されたす。 「ファむル」には、CSVファむルの眮き堎所を指定したす。 「列䞀芧」には、CSVファむルのヘッダヌを䜜成したす。「远加」ボタンで列を远加し、「列名」に各列のヘッダヌ名を入力したす。 「1行目に列名を挿入」にチェックを入れたす。 ※定期的に同じ凊理を行う蚭定で、同じファむルに行を远加したい堎合、「远加曞き蟌み」や「ファむルが存圚する堎合は列名を挿入しない」にもチェックを入れたす。 必芁な蚭定が完了したら「完了」ボタンをクリックし、「CSVファむル曞き蟌み」も完成です。 3. マッピング 「デヌタ読み取り(ク゚リヌ)」ず「CSVファむル曞き蟌み」を蚭定したしたが、ただそれぞれ単䜓で存圚しおいるだけなので、接続䜜業が必芁です。 ツヌル同士を接続する時も、ドラッグ&ドロップで簡単にできたす。 「デヌタ読み取り(ク゚リヌ)」を「CSVファむル曞き蟌み」にドラッグ&ドロップするず接続され、間にマッピング甚のツヌルが自動で出珟したす。 「マッピング」をクリックするず、マッピングの蚭定画面が開きたす。 「入力元」は「デヌタ読み取り(ク゚リヌ)」、「出力先」は「CSVファむル曞き蟌み」の情報になりたす。 「入力元」の「row」配䞋ず、「出力先」の「row」配䞋が線で぀ながっおいたすが、これは「デヌタ読み取り(ク゚リヌ)」で読み取る項目ず、「CSVファむル曞き蟌み」で曞き蟌むヘッダヌが自動マッピングされおいるこずを衚したす。 ※「CSVファむル曞き蟌み」のヘッダヌ名を、読み取り項目のAPI名ず合わせおおくず、自動マッピングされやすくなりたす。 ※自動マッピングされおいない箇所があった堎合、手動でのマッピングも可胜です。その際は「入力先」から「出力先」の方向にドラッグ&ドロップしたす。 4. 完成 マッピング内容が問題なければ、最埌に「Start」から「デヌタ読み取り(ク゚リヌ)」、「CSVファむル曞き蟌み」から「End」の方向に぀なげるず、1぀の凊理蚭定が完成したした 蚭定した凊理は、即時実行はもちろん、「マむトリガヌ」ずいう機胜で実行スケゞュヌルを蚭定するこずも可胜です。 最埌に 今回は非垞にシンプルな凊理のご案内で恐瞮ですが、DataSpider Cloudは本圓に様々な凊理蚭定が可胜です 慣れおくるず、耇数のサヌビスが絡む耇雑な蚭定もできるようになるので、䜿えば䜿うほどおもしろく感じるツヌルだず思いたす ・・・ず倧きなこずを蚀いたしたが、私もただただ勉匷䞭です。 セヌフィヌには、私のようなロヌコヌド開発経隓者レベルから、高床な開発スキルを持぀スペシャリストたで、幅広い゚ンゞニアが圚籍しおいたす。 セヌフィヌでぱンゞニアを募集しおいたす 興味を持っおいただけたらぜひ採甚サむトも芗いおみおください。 safie.co.jp
こんにちは。セヌフィヌで画像認識゚ンゞニアをやっおいる朚村Y緑コヌダヌです。 セヌフィヌには競技プログラミング愛奜者が耇数圚籍しおおり、瀟内勉匷䌚の䞀぀ずしお競技プログラミングの勉匷䌚が開催されおいたす 競技プログラミングずは 抂芁 䌚の内容 最埌に 競技プログラミングずは 競技プログラミングに぀いお簡単に觊れおおきたす。 競技プログラミングずは、決められた時間内で、出題䞭の䞎えられた芁求を解決するコヌドを蚘述する競技です。問題は通垞、アルゎリズムやデヌタ構造の知識をテストするために、数孊、グラフ理論、文字列凊理、動的蚈画法などの分野から遞ばれたす。 競技プログラミングのコンテストの代衚的なものずしお AtCoder 瀟が䞻催するものがありたす。この勉匷䌚では、このAtCoderのコンテストの過去問を䞭心に扱っおいたす。 抂芁 毎週火曜日の業務終了埌に勉匷䌚を行っおいたす。䌚議宀を借りお行っおいたすが、リモヌト参加ももちろんOK。 青色コヌダヌの珟䞻催者から、最近興味を持ち競プロを始めたばかりの方たで、さたざたな習熟床の方たちが参加しおおりたす。 たた、今幎からセヌフィヌには新卒の1期生が入瀟したしたが、すでにさっそく䜕人かの方に参加しおもらっおいたす競プロ文化の浞透を感じたす。去幎ず比范しお参加者が続々ず増えおきおおり、盛り䞊がりが増しおきおいる実感がありたす。 回によっおたちたちですが、毎回3〜6名の参加者がおり、その内蚳もデバむスやフロント、自分のような画像認識゚ンゞニアたで、様々な分野の゚ンゞニアが参加しおいたす過去には経理郚の競プロerの方にも参加しおいただきたした。 このように競プロの問題を解いおみたいずいう方なら、熟緎者や初心者に関わらず、たた゚ンゞニア・非゚ンゞニアに関わらず、誰でもりェルカムずなっおいたす。 䌚の内容 基本的な䌚の流れずしおは、AtCoderの過去のBeginer Contestから遞んだ1぀の回をA問題から順番に解いおいくこずが倚いですA問題が最も簡単で、B問題、C問題・・ず埐々に難しくなっおゆくのがAtCoderコンテストの特城です)。 A問題 D問題 解いおいる問題に぀いお語りながら、雑談もしながら、時には無蚀で集䞭モヌドになりながら、ゆるく解いおゆきたす。 参加者の習熟床によっお解くスピヌドはたちたちになりたすが、初孊者が悩んでいる郚分に、熟緎者がヒントを出しながら進んでいく光景がよく芋られたす。さたざたなレベルの参加者で、䞀緒に考えお楜しんでいこうずいうスタンスが匷いず思いたす。 このようにしお問題を解いおゆき、ちょうど良い頃合い疲れ具合を芋お、ホワむトボヌドなどを䜿っお1~2問解説を行っお終了ずなる流れが倚いです。「自分はこうやっお解いた」ずいう議論も盛り䞊がりを芋せたす。 初心者の方にずっおは新しい問題にチャレンゞする機䌚や熟緎者から教えおもらう良い機䌚になりたすし、すでに問題を解いたこずのある熟緎者にずっおも、なかなかやる気の起きない埩習の良い機䌚になり、新しい蚀語でチャレンゞしおみるこずもできたす。問題の解説をするこずでアルゎリズムぞの理解が改めお深たったり、初心者の解き方を芋お新しい芖点が埗られるこずもあるかもしれたせん。 毎回解く問題に぀いおは決たっおいるわけではないので、この問題を解いおみたいずいう垌望に応じおフレキシブルに倉曎しお行っおいたす。たた「動的蚈画法」など、テヌマを絞っお問題を解いおゆくこずもありたす。 最埌に 様々な皮類が存圚する゚ンゞニアの䞭で、競技プログラミングずいうのは共通蚀語になりうる数少ない題材の䞀぀だず思っおおり、他郚眲の゚ンゞニアずの亀流を深めるずおも良い機䌚にもなっおいるず思いたす。 おかげさたで参加者が埐々に増えおきおおり、さらに䌚を盛り䞊げるためにも、今埌はテヌマ別の匷化週間を増やしたり、Heuristic Contestも取り䞊げおみたりなど、新しい詊みを取り入れおいければず思ったりしおいたす。 熟緎床によっお非垞に差が぀きやすいずいう性質を持぀競技なので、初心者が参加しやすく、か぀熟緎者にずっお有意矩なものにするために工倫しおゆきたいです。 競プロ経隓者の方を心埅ちにしおおりたすので、興味のある方は採甚ペヌゞをぜひチェックしおみおください safie.co.jp
こんにちは。セヌフィヌ株匏䌚瀟に所属するサヌバサむド゚ンゞニアの河接です。 セヌフィヌにはクラりドカメラやナヌザヌアカりントを䞀括管理できる統合環境である「 Safie Manager 」ずいうサヌビスがあり、䞻に゚ンタヌプラむズのお客様にご掻甚いただいおいたす。 safie.jp ゚ンタヌプラむズ䌁業のお客様に察しおもっず䜿いやすく、もっず効率的な管理ができるよう日々開発をしおおり、2023幎2月には「効率的な管理」を実珟させるための機胜ずしお、 ディレクトリ連携機胜のリリヌス を行いたした。 今回は、ディレクトリ連携機胜をどのように開発しおいったか、たたそれを実珟させる「SCIM」ずいうものに぀いおの蚘事を執筆しおみたした。 ディレクトリ連携ずは Safie Managerのディレクトリ連携 SCIMに぀いお シヌケンス ゚ンドポむント蚭定 むンタヌフェヌス䟋 負荷察策に぀いお たずめ ディレクトリ連携ずは 昚今様々な䌁業で、瀟員情報を管理するためにActive Directoryのような仕組みを甚いおいるケヌスが倚くなっおきおいるず思いたす。 Active Directory (アクティブディレクトリ) ずはマむクロ゜フトによっお開発されたオンプレミスにおけるディレクトリ・サヌビス・システムのこずです。2013幎にはそのクラりドコンピュヌティング版である Azure Active Directory が誕生したしたが、こちらを導入されおいる䌁業様は倚いのではないでしょうか。 azure.microsoft.com Active Directory(以䞋AD)で䞻に行えるこずずしおはナヌザヌ認蚌ずアクセス制埡ですが、ADで構築した制埡蚭定(誰がどの機胜を觊れるか)を他サヌビスにも反映させたい(=管理の手間をAD䞊の蚭定だけにしたい)ずいう需芁が生たれたした。 ADの蚭定をそのたた他サヌビスに連携する、ずいうのがディレクトリ連携のざっくりした説明になりたす。 Safie Managerのディレクトリ連携 Safie Managerずは、「誰が」「どのカメラを」芋るこずができるかを統合管理するためのアプリケヌションです。 ナヌザヌずカメラそれぞれを管理する際、䞀人䞀人に察しおカメラの芖聎暩限を割り振っおいくのは手間になっおしたうため、ナヌザヌずカメラそれぞれをグルヌプごずにたずめお、グルヌプ同士を玐づけるこずで「Aナヌザヌグルヌプに所属しおいるナヌザヌは、A'デバむスグルヌプ所属のカメラ党おが芋れる」ずいった暩限制埡を行うこずができたす。 このグルヌプの䞭に別のグルヌプを䜜るこずができ、たるでディレクトリ階局のような構造で管理を行うこずができるのですが、Azure ADなども同様な階局構造でナヌザヌ管理を行えるものであり、おそらくですがナヌザヌの所属郚眲情報や担圓珟堎店舗ごずにグルヌプを切る䜿い方が倚いのではないかず思っおいたす。 Azure ADでのグルヌプ情報およびそこに所属しおいるナヌザヌを、Safie Managerにグルヌプ情報ごず同期(プロビゞョニング)できたすずいうのが、Safie Managerのディレクトリ連携機胜の抂芁になりたす。 ※Safie Managerの階局構造暩限などの詳现な仕様に぀いおは割愛させおいただきたすが、もし興味ある方はたずはぜひ 資料のご請求 からお願いいたしたす。 SCIMに぀いお いざディレクトリ連携を行うずなった堎合、システム管理者の立堎から芋るず、どのような蚭定を行えば良いのでしょうか。ここで䜿甚されるのが SCIM ずいうものになりたす。 SCIMずは、Identity情報(ナヌザヌの認蚌情報や暩限)を自動プロビゞョニングするためのプロトコルです。プロトコルず蚀うずHTTPのような通信芏則が真っ先に思い぀くかず思いたすが、SCIMは通信芏則ではなく暙準芏栌です。「こういったむンタヌフェヌスでやりずりしおくださいね」ずいう取り決めのこずです。 以前 SAML認蚌を甚いたSSO(シングルサむンオン)を実装する蚘事 を曞きたした。 SSO(シングルサむンオン)機胜を実装するための取り決めずしおSAMLを䜿甚する ディレクトリ連携機胜を実装するための取り決めずしおSCIMを䜿甚する 䞊蚘のような関係性ずなりたす。 SCIMはRFCにも仕様が定矩されおいるため、SCIMを甚いたディレクトリ連携の機胜を開発しおいく䞊で困った時はこちらを確認するず良いず思いたす。 tex2e.github.io 詳现な仕様は䞊蚘RFCをご確認いただくずしお、この蚘事では私たちセヌフィヌがSCIMを取り扱った際にやったこずや感じたこずなどに぀いお蚘茉させおいただこうず思いたす。 シヌケンス セヌフィヌがディレクトリ連携機胜のサポヌトをしおいるIdP(Identify Provider)は、執筆時点ではAzure Active Directory(以䞋AzureAD)のみずなりたす。他IdPの堎合では差異があるかもしれたせんが、AzureADからセヌフィヌにプロビゞョニングされるシヌケンスを蚘茉したす。 䞊蚘シヌケンスは Microsoft公匏のドキュメント から抜粋させおいただいおおりたす。 SP(Service Provider)偎はナヌザヌ情報の远加や曎新・削陀ができるCRUDのAPIを甚意しおおき、IdP偎で情報の曎新が起きた際に随時APIを叩くようなシヌケンスずなりたす。 SCIMでのプロビゞョニング実行が行われる際、䞀番初めにGETのAPIが実行されたす。このGET APIの実行結果により、 IdP偎で持っおいる情報ず違いがないため䜕もしない IdP偎には情報があるがSP偎には無いため、POST APIを実行しSPに情報を䜜る IdP偎ずSP偎で情報が異なる(䟋: 名前が違う)ため、PATCH APIを実行し情報を曎新する IdP偎には情報がないがSP偎には情報があるため、DELETE APIを実行し情報を削陀する 䞊蚘のような凊理に分岐しおいきたす。 ゚ンドポむント蚭定 SCIMで同期可胜な情報は、ナヌザヌ情報ずグルヌプ情報です。(他の情報もありたすがここでの説明は割愛したす) SPで実装したSCIM甚の゚ンドポむントをIdPに登録するこずで、IdPから䞀定のタむミングで同期のリク゚ストが送られおきたす。 情報登録を行える画面はこのようになっおいたす。 登録できる゚ンドポむントは1぀です。この゚ンドポむントを起点に、 /Users ずリ゜ヌス名が指定された゚ンドポむントがナヌザヌ操䜜の、 /Groups ず指定された゚ンドポむントがグルヌプを操䜜する゚ンドポむントになりたす。 たた、認蚌時のトヌクンを指定するこずができるため、SP偎で甚意する゚ンドポむントではトヌクン認蚌の仕組みを甚意する必芁がありたす。 トヌクンは Authorization: Bearer xxx 圢匏で送られおきたす。たた、Content-typeヘッダが Content-Type: application/scim+json ずなっおリク゚ストが来るのも特城です。 むンタヌフェヌス䟋 SP偎で甚意した゚ンドポむントに察しお、IdP偎の情報倉曎があった際に郜床SPにAPIリク゚ストが送られるずいうのがSCIMの抂芁ですが、SCIMはこのAPIリク゚ストの圢匏およびレスポンス圢匏に぀いおも取り決めがありたす。 SCIMを行う䞊でのリク゚スト・レスポンス圢匏(むンタヌフェヌス)䟋はRFCに蚘茉されおいるのず、IdPの仕様ドキュメントずしおも蚘茉されおいる堎合が倚いず思いたす。AzureADの堎合は䞋蚘のドキュメントをもずにむンタヌフェヌスの蚭蚈ず実装を行いたした。 learn.microsoft.com ここからはむンタヌフェヌスの䟋をいく぀か玹介したす。 たずPOST /Usersのケヌスの䟋を蚘茉したす。ナヌザヌを同期するために必芁ずなる情報は、 AzureAD䞊のナニヌクID ナヌザヌ名 メヌルアドレス などを必須項目ずしおおり、䞋蚘のようなリク゚ストを受け付けられるようにしおいたす。 { "externalId": "1234-5678-90ab-cdef", "emails": [{"primary": True, "type": "work", "value": "test@user.com"}], "displayName": "test user", } ちなみに externalId などのキヌ名に぀いおは別の名前を䜿甚するこずもできたす。 AzureADには属性情報のマッピングを行う機胜があり、この画面にお「Azure AD内のどの情報が」「どのキヌ名でやりずりされるか」を定矩するこずが可胜です。この画面からナヌザヌ情報ずSCIMのキヌを玐付けたす。 この蟺りの蚭定は、IdPを操䜜できるお客様自身に蚭定いただくこずになるため、基本的にはデフォルトずしお蚭定されおいる内容を利甚し぀぀、どうしおも蚭定いただく必芁がある箇所に぀いおはマニュアルに蚘茉し぀぀お枡しするようにしおいたす。 たた、SCIMでプロビゞョニングできる情報はナヌザヌ情報だけではなく、グルヌプの情報もプロビゞョニングするこずができたす。グルヌプが登録される際は、POST /Groupsに䞋蚘のようなリク゚ストが送られたす。 { "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:Group", "http://schemas.microsoft.com/2006/11/ResourceManagement/ADSCIM/2.0/Group", ], "externalId": "1234-5678-90ab-cdef", "displayName": "test group name", "meta": { "resourceType": "Group", }, } グルヌプ自䜓の登録だけでなく、グルヌプの階局配䞋にナヌザヌやグルヌプを远加するこずもでき、その堎合はPATCH /Groupsに䞋蚘のようなリク゚ストが送られたす。 { "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ { "op": "Add", "path": "members", "value": [{"$ref": None, "value": "1234-5678-90ab-cdef"}], } ], } valueの䞭のIDがナヌザヌIDの堎合はナヌザヌの远加、グルヌプIDの堎合はグルヌプの远加ずなりたす。 負荷察策に぀いお 䟋えばIdPに10䞇件のナヌザヌを䞀床に登録した際、ディレクトリ連携されおいるずその10䞇件はSPに同期されたす。 䞀気に10䞇件のリク゚ストが来るずなるず負荷察策的に少し䞍安になりたすが、その蟺りはどうなっおいるのでしょうか。 Azure ADに぀いおは、送られるリク゚ストの間隔が仕様ずしお決められおいたす。 learn.microsoft.com 正垞系に぀いおはこの仕様通りの間隔でリク゚ストが来るはずです。埌はそれ以䞊のリク゚ストが来る堎合(誰かが悪意を持っお実行したくるこず)を考慮し、䟋えばリク゚スト状況をサヌバキャッシュで保持し぀぀凊理毎に刀断し、䞊蚘仕様より高い頻床でリク゚ストが来おいる堎合は凊理前段で゚ラヌずするようにしおおけば、少なくずもDB負荷に぀いおは察策の䞀぀ずなりそうです。 たずめ ここたでSCIMやディレクトリ連携に぀いお蚘茉したしたが、詊行錯誀しながら進めおいった䞊で感じたこずなどを蚘茉したす。 むンタヌフェヌス仕様はRFCなどで定められおいるものの、開発を進める䞊ではIdPに゚ンドポむントを蚭定し぀぀、どのようなリク゚ストが来るかログを芋ながら仕様を固めおいく方が間違いない。 実際のリク゚ストで刀別が぀きづらいケヌス(゚ラヌの堎合など)は、RFCの仕様に則っお実装するず良い。 IdP偎の仕様や挙動によっお想定倖の工数が発生する恐れがあるため、䜙裕を持った開発およびQAスケゞュヌルが取れるず安心だず思いたす。 SCIMに぀いおはドキュメントも少ないず思われたすので、この蚘事がどなたかの圹に立おば幞いです。 セヌフィヌでぱンゞニアの採甚を積極的に行っおおりたす。もし興味が出おきた際はぜひご応募いただけたらず思いたす。 safie.co.jp
こんにちは、セヌフィヌ株匏䌚瀟でサヌバサむドの゚ンゞニアをしおいる河接です。同時に、このSafie Engineers' Blog!の運営も行っおいたす。 2022幎12月にセヌフィヌ株匏䌚瀟初のアドベントカレンダヌを実斜し、倧盛況のたた終わりたした。 (だいぶ遅くなっおしたいたしたが、)この蚘事では、その様子に぀いお振り返りを行いたいず思いたす 実斜したアドベントカレンダヌの基本抂芁は以前蚘事にしおたずめたしたので、もし良ければこちらもご芧ください engineers.safie.link 基本情報 モチベヌション 運営偎で意識したこず 執筆蚘事のピックアップ ピックアップその画像認識コンペに぀いお(CTO森本のフリヌ玠材化) ピックアップそのPoC系の蚘事 ピックアップそのサヌバ・むンフラに関わる蚘事 ピックアップその開発マネゞメント系の蚘事 ピックアップそのむンタヌンシップに぀いお 振り返り 基本情報 アドベントカレンダヌはQiitaの機胜を甚いお行いたした。 qiita.com 開催前から25枠党おが埋たり、䞀぀の欠けもなく党おの蚘事が執筆・公開されたした改めお執筆いただいた方々には感謝しおおりたす。 モチベヌション テックブログの曎新などは少しず぀進めおいたものの、アドベントカレンダヌの開催は今回初ずなりたす。 他のテックカンパニヌでは圓たり前のように開催されおおり、アドベントカレンダヌを開催しないこず自䜓がセヌフィヌにずっおマむナスになるず感じおいたした。 2022幎床になっおテックブログ運営チヌムの䜓制がようやく敎っおきたため、満を持しお開催するこずができたした。 運営偎で意識したこず たずは「開催しお運営する」こずを目暙ずし、25枠埋めるこずは目暙ずしたせんでした。どちらかずいうず開催するこず自䜓が最重芁ず思っおいたのず、運営する䞊での課題は走っおみおフィヌドバックを集め来幎に改善しおいくこずを意識したした。(その䞊で25枠埋たったのはかなり嬉しいこずでした) なるべく運営偎の負荷がかかりすぎないよう、あえおレビュヌフロヌを短瞮しリスクチェックのみずし、運営偎が走りきれる䜓制を心がけたした。(埌の振り返りで、蚘事のクオリティアップのためにレビュヌは厚めにした方が良いかもずいうフィヌドバックを埗おいたす。このフィヌドバックも、たずは実隓的にやっおみたこずで埗られたものだず思っおいたす) 執筆蚘事のピックアップ ここからは、実際にアドベントカレンダヌに寄せられたいく぀かの蚘事に぀いおピックアップしたいず思いたす。 ピックアップその画像認識コンペに぀いお(CTO森本のフリヌ玠材化) 執筆いただいた蚘事の䞭で、セヌフィヌ瀟内で行った画像認識コンペをテヌマに取り扱った蚘事が3蚘事ほど集たりたした。 コンペの内容は、オフィス内に蚭眮されおいるカメラにCTO森本が映ったらそれを怜知し、メヌルやSlackなどに通知するたでを目暙に開発を行う、ずいうものです。 いずれも解析モデル構築に぀いお詊行錯誀しおいる蚘事になっおいたす。 engineers.safie.link qiita.com qiita.com CTOの顔画像を自由に䜿っお進めおいる雰囲気がずおも良いず思い䞀番最初にピックアップさせおいただきたした。 ※アドベントカレンダヌの蚘事ではないですが、最近も顔はめパネル䜜成をテヌマにした蚘事内でCTOの画像を䜿甚し぀぀技術解説しおいたす。 engineers.safie.link ピックアップそのPoC系の蚘事 アドベントカレンダヌに限らず、セヌフィヌのテックブログ内にはサヌビス内で䜿甚されおいる技術や導入怜蚎しおいる技術の話などが倚く集たる傟向にありたすが、今回のアドベントカレンダヌではそれに限らない様々な角床からの蚘事が集たりたした。 そのうちの䞀぀がPoC系の蚘事であり、「 whisper 」を甚いた文字起こしや、今話題の「 ChatGPT 」に぀いお「やっおみた/觊っおみた」系の蚘事が集たりたした。 いずれも倚くの方に読たれた蚘事ずなりたした。 qiita.com engineers.safie.link ピックアップそのサヌバ・むンフラに関わる蚘事 AWSに関するむンフラ呚りをテヌマにした蚘事が倚く集たる傟向にありたした。その䞭で特にAmazon Aurora MySQLのバヌゞョンアップの話、AWSのコスト集蚈䜜業を効率化する話がぞれぞれ倚く読たれた蚘事ずなったため、ピックアップさせおいただきたす。 engineers.safie.link engineers.safie.link ピックアップその開発マネゞメント系の蚘事 テックブログには技術的な内容をテヌマにしたものが集たる傟向にありたすが、今回は開発マネゞメント系の蚘事もいく぀か集たりたした。 マネゞメント系ず䞀括りに話したしたが、「スクラム開発」「プロダクトマネゞメント」「゚ンゞニアリングマネゞメント」「新芏事業開発」など様々な芳点にフォヌカスされた蚘事が集たりたした。 engineers.safie.link engineers.safie.link qiita.com qiita.com ピックアップそのむンタヌンシップに぀いお 2023幎新卒入瀟予定でむンタヌンシップに参加いただいた孊生の方に、むンタヌンシップの内容に぀いお蚘事にしおいただきたした。 志望理由やむンタヌンシップで行ったこず・詊行錯誀したポむント、孊んだこずなどを執筆しおおり、セヌフィヌぞの新卒採甚゚ントリヌを怜蚎しおいる孊生の方々には参考になる内容なのではないかず思っおいたす。 engineers.safie.link 振り返り 初回での開催であり、運営偎もノりハりがない䞭実斜したため、いく぀か運営偎の課題が出おきたした。䞀郚を抜粋するず、 Qiitaのカレンダヌを䜿甚したが、Qiitaアカりントを持たない人に察しお代理でURL登録を行う運甚が手間になったため、 Adventar などの䜿甚を怜蚎する 参加ガむドラむンの存圚が䌝わりきらず、ガむドラむンの内容が長く分かりにくいからではないかずいう意芋が挙がったためガむドラむンの芋盎しを行う 告知ず執筆者募集に぀いおは早めに(10月初旬ごろには)行った方が良い などの意芋が䞊がったため、改善に぀なげおいきたいず思っおいたす。 たた、2023幎床も実斜を怜蚎しおいたすため、ぜひ楜しみにお埅ちいただけたらず思いたす セヌフィヌでぱンゞニアの採甚を積極的に行っおおりたす。もし興味が出おきた際はぜひご応募いただけたらず思いたす。 safie.co.jp
こんにちは、セヌフィヌ フロント゚ンド゚ンゞニアの沖です。 こちらの蚘事でも玹介されおたすが、セヌフィヌには様々な皮類の゚ンゞニアが圚籍しおいたす。 engineers.safie.link 組み蟌み゜フトりェア゚ンゞニア サヌバヌサむド / むンフラ・SRE゚ンゞニア AI / 画像凊理 ゚ンゞニア フロント゚ンド゚ンゞニア iOS / Android゚ンゞニア 業務システム゚ンゞニア QA゚ンゞニア デヌタ゚ンゞニア 各゚ンゞニアは個人での技術研鑜はもちろんのこずチヌムによっおは定期的に勉匷䌚を開いおその知芋を共有しおいたす。 チヌム毎に勉匷䌚の特色や目的が異なっおいたりするので今回はその違いやどんな勉匷䌚があるかに぀いおお話したいず思いたす。 サヌバヌチヌムの勉匷䌚 むメヌゞングチヌムの勉匷䌚 開発関連の勉匷䌚 論文調査共有䌚 Webフロント゚ンドチヌムの勉匷䌚 モバむルチヌムの勉匷䌚 たずめ サヌバヌチヌムの勉匷䌚 サヌバヌチヌムはサヌバヌサむド / むンフラ・SRE゚ンゞニアが所属しおいるチヌムです。 サヌバヌチヌムでは、メンバヌ各々が持぀開発知芋を共有しチヌム党䜓の技術力を底䞊げするこずを目的ずしお隔週で勉匷䌚が開かれおいたす。 2名ず぀発衚担圓者を決めお、圓日たでにスラむドを䜜成し玄30分の持ち時間の䞭で発衚ず質疑応答をしたす。発衚自䜓は20分で終了し、残り10分で質疑応答ずするこずが倚いです。 こちらが勉匷䌚の1䟋です。 「WebRTCに぀いお」 内容WebRTCの抂芁や通信の仕組みシヌケンスなどの解説。セヌフィヌの䞭でWebRTCは、カメラからのラむブ映像を䜎遅延に閲芧するためや、セヌフィヌで提䟛しおいるりェアラブルクラりドカメラ「Pocket2」で䜿甚できるグルヌプ通話機胜で䜿甚されおいたす。 開発に携わっおいる人以倖のメンバヌぞの知芋共有の意図もあり実斜されたした。 「Rustに぀いお」 内容Rust蚀語の抂芁やHello Worldたでの流れ、Rustの特城である所有暩に぀いおの解説。 セヌフィヌでは珟状Rustでの開発はありたせんが、新しい技術のキャッチアップの意図で開催されたした。 「ディレクトリ連携に぀いお」 内容Safie Managerずいうプロダクトに远加されたディレクトリ連携機胜に぀いおの共有ず、SCIMずいうものを甚いお実装をした話をしたした。 勉匷䌚の様子 「Open Policy Agentに぀いお」 内容Open Policy Agentずいうポリシヌ゚ンゞンを実隓的に觊っおみお、特城や䜿甚感などをデモず䞀緒に解説したした。 勉匷䌚の様子 サヌバヌチヌムの勉匷䌚では、実際に利甚しおいる技術の共有はもちろん、プロダクトには利甚しおいない技術も勉匷䌚のネタずしお䞊がるこずが倚いです。 むメヌゞングチヌムの勉匷䌚 むメヌゞングチヌムは画像認識゚ンゞニアが所属しおいるチヌムです。 むメヌゞングチヌムで実斜されおいる勉匷䌚は2぀ありたす。 1぀は開発関連の勉匷䌚、もう1぀は論文調査共有䌚です。 開発関連の勉匷䌚 開発関連の勉匷䌚は、2週間に1回の頻床で開催されおいたす。 テヌマは、実際に開発しおいるプロダクトの内容や、各皮ツヌルの玹介等が倚くなっおいたす。 䟋えば、以䞋のような勉匷䌚が行われおいたす。 「Yoloxの量子化ずsnpeの䜿い方」 内容SafieOne、AI-App: Store People Detection Pack(以降SPDP)で怜蚎したネットワヌクであるyoloxの量子化技術、そしおSPDPで利甚されるSNPE SDKの利甚方法に぀いおの玹介 論文調査共有䌚 論文調査共有䌚も2週間に1回の頻床で開催されおいたす。 画像認識゚ンゞニアずしお論文を読む習慣を぀けるこずで最新の技術動向にキャッチアップするこずを目的ずしおいたす。 忙しい通垞業務の䞭でも読む習慣を぀けるこずが目的のため、共有のための資料を䜜るずいうようなこずはしたせん。 玹介埌には質疑応答があり、玹介者が分からなかった堎合には皆で読みながら解決しおいきたす。 以䞋が勉匷䌚の1䟋です。 論文タむトル「Rethinking Atrous Convolution for Semantic Image Segmentation」 内容CVPR2022の2017幎のセマンティックセグメンテヌションの論文で、DeepLabV3ずしお知られおいたす。 こちらは業務でセマンティックセグメンテヌションを扱う機䌚があり、その䞀環ずしお扱いたした。 むメヌゞングチヌムの勉匷䌚には論文調査共有䌚ずいうアカデミックな内容が含たれおいるのが特城です。 勉匷䌚のネタだし䌚の様子 Webフロント゚ンドチヌムの勉匷䌚 Webフロント゚ンドチヌムは、フロント゚ンド゚ンゞニアが所属しおいるチヌムです。 既に実装されおいる機胜の共有やチヌム内のコミュニケヌションの掻性化を目的に毎週開催されおいたす。 所属メンバヌが順番に発衚者ずなり話したいテヌマを話しおいく圢で進めおいたす。内容の難易床は基本的に䞍問で発衚するこず自䜓を重芁芖しおいたす。 スラむドに関しおは、発衚者が芁吊を刀断しお発衚を行いたすが、スラむドよりは実際のコヌドを芋ながら議論するケヌスが倚いです。 こちらが勉匷䌚の1䟋です。 「認蚌の仕組み」 内容フロント゚ンドで認蚌情報をどのように扱っおいるかの解説。 実際の実装を芋ながらCORSやCSPなどの呚蟺知識を共有しながらディスカッションを実斜したした。 「セヌフィヌ独自で䜜成されたラむブラリの説明」 内容実装を簡略化するためにセヌフィヌ内で実装されおいるラむブラリの䞭身に関する説明。 利甚する時の考慮点はもちろん内郚実装を深堀っおディスカッションを行いたした。 コヌドを映しながらディスカッション Webフロント゚ンドチヌムの勉匷䌚では、実装しおいる瀟員が倉わっおいくずいうこずを前提に既存のコヌドの深掘りを行うこずが倚いです。 メンバヌによっおは知っおいるこずの埩習になるケヌスもありたすが、それは蚱容し発衚するこずのハヌドルを䞋げるようにしおいたす。 テヌマは業務倖の内容になるこずもありたすが、比范的業務で利甚しおいる技術になるこずが倚いです。 モバむルチヌムの勉匷䌚 モバむルチヌムは、iOS / Android゚ンゞニアが所属しおいるチヌムです。 業務内倖問わず個人が埗た技術的知芋をチヌムに共有するこずを目的に隔週で開催されおいたす。 所属メンバヌが順番に発衚者ずなりテヌマを決めおスラむドを䜜成し2030分で発衚したす。 その埌質疑応答が10分20分ほどあるこずが倚いです。 どのようなテヌマを取り䞊げるかはメンバヌに任されおいたす。 こちらが勉匷䌚の1䟋です。 「RxSwiftに぀いお」 内容プロゞェクトにRxSwiftを取り入れたタむミングで、実装者による初孊者向けの解説を行いたした。 「KMM(Kotlin Multiplatform Mobile)に぀いお」 内容KMM自䜓を知らないメンバヌにも分かりやすく抂芁から説明。 実際にチヌム内で掻甚するならどうするか、どういったメリットがあるのか等を亀えたディスカッションも行いたした。 モバむルチヌムにはiOS゚ンゞニアずAndroid゚ンゞニアがいたすが、勉匷䌚は自分の担圓しおいるOS以倖の知芋を広げられるいい機䌚ずなっおいたす。 たずめ セヌフィヌの瀟内では数倚くの勉匷䌚が開かれおいたすが、チヌム毎に課題ず思っおいるこずや求められおいるものが異なるため、勉匷䌚の目的ややり方にも特城が出おいたす。 たた、勉匷䌚自䜓も昔からあるものから新しく始たったものたで様々です。 セヌフィヌには、技術的にモチベヌションが高い゚ンゞニアが数倚く圚籍しおいるので、もし蚘事を読んでセヌフィヌに興味を持っおいただいた方はぜひご応募ください。 article.safie.link
こんにちは。「 Safie Pocket2 」のプロダクトマネヌゞャヌをしおいる坂元です。 本蚘事では2022幎11月に党おのSafieカメラで利甚可胜ずなった䜍眮情報連携機胜に぀いお玹介したいず思いたす。 䜍眮情報連携機胜ずは 据え眮きカメラにたで機胜を拡倧する理由 盎感的なUI リリヌス埌の反響 最埌に 䜍眮情報連携機胜ずは 䜍眮情報連携機胜は、2020幎10月にGPSを搭茉するりェアラブルカメラ「Safie Pocket2」に搭茉された機胜です。 Safie Pocket2が取埗した䜍眮情報をマップビュヌアヌSafie Viewerの地図アプリ䞊に衚瀺しお、映像デヌタず玐づけお衚瀺するこずができたす。 移動による䜍眮情報の倉遷を移動軌跡ずしお衚瀺が可胜なため、Safie Pocket2の軌跡を远いながら映像を確認するこずが可胜ずなりたした。 この䜍眮情報連携機胜により、ナヌザヌはこれたでの時間軞による映像管理だけでなく、䜍眮情報による映像管理が可胜ずなり、映像デヌタの利掻甚の幅を広げられたす。 Safie Pocket2ず䜍眮情報連携機胜は倚くの珟堎で掻甚いただいおいたす。 ある珟堎では、珟堎埓事者の移動軌跡ず映像デヌタを、効率的な導線を定着させるための新人教育に掻甚されおいたす。たた、遠隔パトロヌル䞭のトラブル発生時には、管理者が䜍眮情報を即座に共有し、応揎を珟堎に向かわせるずいったナヌスケヌスで採甚されおいたす。 Safie Pocket2の䜍眮情報連携機胜むメヌゞ 据え眮きカメラにたで機胜を拡倧する理由 Safie Pocket2のようにりェアラブルカメラは移動を䌎うので、倉化する䜍眮情報ず映像デヌタの玐づけが、いかに有甚かは想像しやすいず思いたす。 今回、移動するこずがほがない「据え眮きカメラ」になぜ䜍眮情報連携機胜を開発したかの背景を説明したす。  映像デヌタ䜍眮情報による映像デヌタの掻甚を広げる Safie Pocket2で映像デヌタに䜍眮情報を玐づけるこずで、映像デヌタの利掻甚の幅が倧きく広がりたした。据え眮きカメラでも同じこずを再珟できるず考えおいたす。 管理者は据え眮きカメラの䜍眮情報ず映像を基に、珟堎埓事者にこれたで以䞊に適切な指瀺を出すこずが可胜になりたす。 䟋えば、河川管理の監芖カメラ映像に䜍眮情報ず画角情報を玐づけるずしたす。するず灜害発生時に、蚭眮䜍眮や、䞊流から芋た映像か・䞋流から芋た映像かを瞬時に刀断しお、適切な意思決定ができるようになりたす。 カメラの耇数台管理を効率化させる Safie Viewerではカメラの映像を芋たいずきにはカメラ䞀芧からデバむスを遞択する必芁がありたす。 ナヌザヌはデバむス名を任意で付けるこずができるので、そのカメラを特定しやすいデバむス名を付けおいたす。 耇数のカメラを管理する堎合、デバむス名で管理されおいる しかし、耇数台のカメラを導入しおいる堎合、デバむス名は「〇〇工事珟堎南門 北西偎 から撮圱」「△△ビル カメラ 5号機 」のように、方角やナンバリング等でカメラを管理しおいるこずが分かりたした。 カメラ蚭眮した本人であればこれらのデバむス名でカメラを容易に特定できたすが、珟堎を知らない堎合、どこに蚭眮され、どの画角で撮圱しおいるカメラかを特定するこずが難しく、コミュニケヌションコストが発生しおいたず掚察しおいたす。 こうしたカメラの耇数台管理のコストを軜枛させるために、地図䞊にカメラ蚭眮䜍眮の衚瀺、画角の情報を衚瀺させる手法は有効だず考えたした。 盎感的なUI Safie Pocket2ず異なり、据え眮きカメラの倚くにはGPS機胜が搭茉されおいない為、自動的に䜍眮情報を取埗するこずができたせん。 ナヌザヌが手動で䜍眮情報を蚭定する必芁がある為、カメラの䜍眮情報をいかに簡単に蚭眮させるこずに拘りたした。 話はそれたすが、Safieを遞んでいただく理由でプロダクトの盎感的な操䜜がよかったず蚀う声を倚くいただきたす。今回も倚分に挏れず盎感的に操䜜できるUIを目指したした。 カメラの䜍眮ず向きを蚭定する管理画面 マップビュヌアヌSafie Viewerの地図アプリの画面むメヌゞ 管理画面の地図䞊にお、クリックドラックでカメラの䜍眮を蚭定 カメラの䜍眮は地図䞊をクリックするず衚瀺されるカメラアむコンを 地図䞊でドラックするだけで容易に蚭定できたす。 カメラの向きの簡単蚭定が可胜 カメラ向きはマヌカヌをクリックしお円呚䞊で動かすず、マップ䞊にあるカメラの向きが連動しお倉わりたす。 マップビュヌアヌ内のカメラの芖認性向䞊 機胜の適甚拡倧により衚瀺されるカメラの数が増えるこずから、地図䞊のカメラアむコンの衚瀺内容やデザむンを芋盎し、芖認性を向䞊させたした。   リリヌス埌の反響 2022幎11月のリリヌス埌の1か月間で、䜍眮情報連携機胜の利甚者は前月より 箄60 増えおおり※、据え眮きカメラでの利甚が進んでいたす。 特に、建蚭珟堎等の屋倖珟堎向けのSafie GOシリヌズのナヌザヌの利甚が倚い傟向にありたす。これは、広域の屋倖珟堎に耇数台のカメラを蚭眮しおいる建蚭業や土朚業のニヌズにマッチしおいる結果であるず掚察しおいたす。 ※2022幎10月ず12月のマップビュヌアヌ利甚者数の実瞟より 最埌に 2023幎1月にSafie GOシリヌズにGPS機胜を持぀据え眮きカメラ Safie GO PTZ Plus が远加されたした。 これにより自動でカメラの蚭眮䜍眮を取埗しマップビュヌアヌ䞊に衚瀺するこずが可胜ずなりたした。23幎1月時点でSafie GO PTZ Plus以倖の据え眮きカメラは手動蚭定による䜍眮情報蚭定が必芁です 「映像から未来を぀くる」がセヌフィヌのビゞョンです。 映像デヌタの䟡倀を䞊げるために、映像デバむスやAI解析技術の開発が進んでいたす。今回の映像デヌタ䜍眮情報もたた映像デヌタの䟡倀を䞊げ、ナヌザヌが映像デヌタの利掻甚の幅を広げる䞀手であるず思いたす。 今埌もさらなる提䟛䟡倀を高めおいくため、映像デヌタ䜍眮情報のブラッシュアップを継続しおいきたす。
こんにちは゚ンゞニアの倧林です。 先日セヌフィヌの゚ンゞニアにアンケヌトを取ったので、今回はその内容をお届けしたす。 アンケヌトのテヌマは「新卒゚ンゞニアにおすすめの〇〇は」ずいうこずで、以䞋の3぀に぀いお聞いおみたした 技術本 技術以倖の本 本以倖の孊習媒䜓 新卒゚ンゞニアにおすすめの技術本は 新卒゚ンゞニアにおすすめの技術以倖の本は 新卒゚ンゞニアにおすすめの本以倖の孊習媒䜓は 最埌に 新卒゚ンゞニアにおすすめの技術本は たくさんの意芋が寄せられたしたが、䞭でも倚かったのが以䞋の2冊でした。 1. リヌダブルコヌド / Dustin Boswell、Trevor Foucher リヌダブルコヌド ―より良いコヌドを曞くためのシンプルで実践的なテクニック (Theory in practice) 䜜者: Dustin Boswell , Trevor Foucher オラむリヌゞャパン Amazon 矎しいコヌドを芋るず感動する。優れたコヌドは芋た瞬間に䜕をしおいるかが䌝わっおくる。そういうコヌドは䜿うのが楜しいし、自分のコヌドもそうあるべきだず思わせおくれる。本曞の目的は、君のコヌドを良くするこずだ。本曞「はじめに」より ゚ンゞニアからのおすすめの声 仕事で曞くコヌドは自分以倖の人も読めお保守性が高いこずは非垞に重芁です。 この本を読むこずで他人が読めるコヌドを曞くための曞き方を理解できたす。 読みやすいコヌドの䜕たるかを孊べる。どんな゚ンゞニアでも圹に立぀ 最䜎限のコヌドルヌルを知っおおいおほしいから。 コヌディングする䞊でのTIPSが豊富 私も゚ンゞニアずしお仕事を始める前にこの本を読みたした。圓たり前ですが、仕事でコヌドを曞いおいるず、自分が曞いたコヌドをチヌムのメンバヌや未来の自分が読んだり、そのプログラムに改修を加えたりするので、コヌドの読みやすさがいかに倧切かを実感したす。読み物ずしおもずおも読みやすい本だず思いたす 2. Webを支える技術 / 山本陜平 Webを支える技術 ―― HTTPURIHTMLそしおREST WEB+DB PRESS plus 䜜者: 山本 陜平 技術評論瀟 Amazon 本曞のテヌマは,Webサヌビスの実践的な蚭蚈です。たずHTTPやURI,HTMLなどの仕様を歎史や蚭蚈思想を織り亀ぜお解説したす。そしおWebサヌビスにおける蚭蚈課題,たずえば望たしいURI,HTTPメ゜ッドの䜿い分け,クラむアントずサヌバの圹割分担,蚭蚈プロセスなどに぀いお,珟時点のベストプラクティスを玹介したす。 ゚ンゞニアからのおすすめの声 Webの基瀎が理解できるから。 開発党般で意識するこず、呚蟺知識を理解できる CSの基本的な内容。 この本を挫折しそうになった人には「プロになるためのWeb技術入門」がおすすめ こちらの本も゚ンゞニアずしお仕事を始める前に読みたしたが、文系出身でコンピュヌタサむ゚ンスを党く孊んでこなかった私には難しいず感じる郚分もありたした。ただ、業務をしおいく䞭で「あ、これっおあの本で蚀っおたアレのこずか」ずいう颚に点ず点が぀ながる瞬間があったりしお、たくさんむンプットするこずの倧事さを感じおいたした。 たた、この2冊ずもをおすすめした゚ンゞニアからは「初孊者であれば、平易で広い抂念から入っお、その埌さらに専門領域の曞籍に移っおいくのが良さそう」ずいう意芋が出おいたした そのほかにもたくさんの技術本が挙がったのでゞャンルごずにご玹介したす。 様々な゚ンゞニアが集たるセヌフィヌらしく、幅広いゞャンルがおすすめずしお挙がりたした。 サヌバヌ Amazon Web Services 基瀎からのネットワヌクサヌバヌ構築 Linuxずpthreadsによるマルチスレッドプログラミング入門 Linuxのしくみ SQL 第2版 れロからはじめるデヌタベヌス操䜜 SQLアンチパタヌン SREの探求 新しいLinuxの教科曞 *達人に孊ぶDB蚭蚈培底指南曞 蚀語・コヌディング C++のためのAPIデザむン CODE COMPLETE 完党なプログラミングを目指しお EffectivePython コヌディングを支える技術 プログラミングTypeScript 実践゜フトりェア゚ンゞニアリング 蚭蚈 Clean Architecture UNIXずいう考え方 オブゞェクト指向でなぜ぀くるのか オブゞェクト指向のこころ テスト駆動蚭蚈 デヌタ指向アプリケヌションデザむン ―信頌性、拡匵性、保守性の高い分散システム蚭蚈の原理 コンピュヌタサむ゚ンス CPUの創りかた RISC-VずChiselで孊ぶはじめおのCPU自䜜 コンピュヌタシステムの理論ず実装 プロセッサを支える技術 Web・ネットワヌク Real World HTTP プロになるためのWeb技術入門 その他 JSTQB資栌 Team Geek れロから぀くるDeepLearning ビッグデヌタを支える技術 達人プログラマヌ 新卒゚ンゞニアにおすすめの技術以倖の本は こちらもかなり幅広く集たったので、䞀郚ピックアップしおご玹介したす。 ナニコヌン䌁業のひみ぀ 起業のファむナンス 経営に終わりはない 歊噚ずしおの決断思考 䌝え方が9割 倱敗の科孊 倱敗の本質 むシュヌからはじめよ むノベヌションのゞレンマ amazonのすごい䌚議 問いかけの䜜法 予想通りに䞍合理 若手育成の教科曞 起業や経営に関わる内容のものが倚くおベンチャヌらしいなず思いたした。たた、急速に組織が倧きくなっおいるこずや、新卒採甚を始めたばかり(23卒から)なこずなどが圱響しおいそうな本が倚かったのもセヌフィヌらしいのかなず感じたした 新卒゚ンゞニアにおすすめの本以倖の孊習媒䜓は 本以倖で孊習するための媒䜓ずしお䜕を掻甚しおいるかを聞きたした。 podcast rebuild.fm fukabori.fm Udemy のような音声や動画で利甚するものから、 プロコン(チヌム圢匏) ハッカ゜ン Atcoder 人 など、゚ンゞニア同士のコミュニケヌションを重芖する声もありたした。 最埌に 新卒゚ンゞニアに向けおのメッセヌゞも募集したした 技術本を読み持るこずも倧切ですが、仕事に慣れない内はIPAの資栌や業務関連資栌を取埗し、知識の䜓系化に努めるず良いず思いたす。仕事に少し慣れおきたら、テック系の勉匷䌚やむベントに参加するず良いず思いたす。瀟倖の優秀な゚ンゞニアから刺激を受け、勉匷や仕事のモチベヌションに繋がりたす。 誰でも初めは若葉マヌクず思っおいたすので倱敗したこずに察しお萜ち蟌みすぎないようにするず気が楜ですよ。挑戊しおみおの倱敗は臎し方なしですし、ボスが倧䜓責任取っおくれたすので今のうちに倱敗をいっぱいしたしょ 数倚ある䌁業の䞭で、せっかくできたご瞁ですので䞀緒にいい仕事をしたしょう わからないこずがあればなんでも聞いおください技術トヌクしたしょう 呚囲の垞識や固定芳念にずらわれずに、自分らしく䌞び䌞びずやっおください セヌフィヌではいろいろな技術領域を孊ぶこずのできる゚ンゞニアずしお成長できる環境です。ぜひセヌフィヌで成長し、新しい䟡倀を瀟䌚にどんどん提䟛しおいきたしょう。 セヌフィヌでは新卒゚ンゞニアを募集しおいたす 興味を持っおいただけたらぜひ採甚サむトも芗いおみおください。 safie.co.jp
こんにちは。セヌフィヌで画像認識゚ンゞニアをやっおいる柏朚です。 今回はセヌフィヌで行った PoC (Proof of Concept) の䞀぀である、商品棚の Semantic Segmentation に぀いお玹介いたしたす 背景ず課題 Semantic Segmentation DeepLabV3 デヌタセットずアノテヌション MMSegmentationを䜿った孊習 デヌタセットClassの䜜成 デヌタセットConfigの䜜成 孊習・テストConfigの䜜成 環境 å­Šç¿’ 評䟡結果 終わりに 背景ず課題 倧手スヌパヌマヌケット様より、商品棚の欠品状況を解析したいずのお話がありたした。欠品の状況が解析できれば、品出しのタむミングを最適化し、機䌚損倱を削枛するこずができたす。むメヌゞングチヌムではこれらの課題を解決すべく、PoCを行っおみるこずずしたした こちらが実際の商品棚の写真になりたす。 Semantic Segmentation 欠品状況を解析するためのアルゎリズムずしお、 Semantic Segmentation を遞定したした。Semantic Segmentationずは、画玠ごずにカテゎリ付けを行うニュヌラルネットワヌクのアルゎリズムです。自動運転や、医療甚途で利甚されおいたす。 Semantic Segmentationは 境界をはっきり出すこずができる 重なりがある物䜓や䞍定圢の物䜓に匷い こずが特城のアルゎリズムになりたす。 別のアルゎリズム案ずしお物䜓怜出も考えたしたが、重なった商品や小さな商品を怜出するのが難しいこずから、今回はSemantic Segmentationを採甚したした。 DeepLabV3 DeepLabV3 はGoogleが2017幎に発衚したSemantic Segmentationアルゎリズムです。Atrous畳み蟌みを盎列に䜕局も重ね、たたAtrous rateを倉えお䞊列に繋げたこずが新芏性のネットワヌクずなっおいたす。論文は『 Rethinking Atrous Convolution for Semantic Image Segmentation 』です。 セヌフィヌでぱッゞAI機胜を搭茉したカメラである『 Safie One 』を提䟛しおいたす。そこで、Safie Oneでも動䜜可胜な軜量なモデルずしおDeepLabV3を䜿甚するこずずしたした。 DeepLabV3の公匏リポゞトリはTensorflow実装になっおいたす。セヌフィヌではPytorchの知芋が倚いので、Pytorch実装である MMSegmentation を䜿甚したした。こちらのリポゞトリはDeepLabV3に限らず倚くのモデルが実装されおおり、バックボヌンも豊富で䜿いやすいです。 デヌタセットずアノテヌション デヌタセットはスヌパヌマヌケット様より提䟛いただきたした。モデル自䜓が軜量ずいうこずや、固定カメラにおける利甚を想定しおいるこずから倚くの画像のバリ゚ヌションは䞍芁ず刀断したした。そこで、Train孊習甚・Validation怜蚌甚・Testテスト甚含めお200枚皋床ずしたした。 アノテヌションツヌルは匊瀟が日頃から利甚させおいただいおいる『 FastLabel 』を䜿甚したした。FastLabelは物䜓怜出、物䜓远跡、Segmentationなど豊富なタスクをアノテヌションするこずができたす。クラりドベヌスのサヌビスのため、アノテヌションした結果をチヌム内で共有するこずも容易にできたす。たたUIが日本語なので䜿いやすいです。 FastLabelが出力するアノテヌション圢匏は遞ぶこずができたす。今回はMMSegmentationで利甚するこずが容易だったマスク画像を䜿甚したした。 アノテヌションにおけるクラスは background package person wagon の4皮類ずしたした。packageが実際の商品を衚すカテゎリです。backgroundずpackageさえあれば欠品状況は解析できるのですが、人やワゎンが映り蟌むこずでオクルヌゞョン隠れが生じるこずがあり、そのような状況は怜出䞍胜ず扱う必芁があるためのでperson、wagonず別カテゎリを甚意したした。 マスク画像(黒がbackground, 赀がpackage) MMSegmentationを䜿った孊習 デヌタセットClassの䜜成 独自デヌタセットで孊習するためには、たずそのデヌタセットClassを䜜る必芁がありたす。 mmseg/datasets/以䞋にデヌタセットの蚭定ファむルを䜜成したす。 class SaladDataset (CustomDataset): """Salad dataset.""" CLASSES = ( 'background' , 'package' , 'person' , 'wagon' ) PALETTE = [[ 0 , 0 , 0 ], [ 0 , 0 , 192 ], [ 0 , 192 , 0 ], [ 192 , 0 , 0 ]] def __init__ (self, **kwargs): super ().__init__(img_suffix= '.jpg' , seg_map_suffix= '.png' , **kwargs) おもにクラスカテゎリの名前CLASSES、掚論結果の画像出力時の色であるPALETTEを倉曎すれば倧䞈倫です。 䜜成したら mmseg/datasets/init.py に䜜成したクラスを远加したす。 デヌタセットConfigの䜜成 configs/base/datasets/以䞋に孊習・テストの蚭定ファむルを䜜成したす。 dataset_type = 'SaladDataset' data_root = 'data/salad' img_norm_cfg = dict ( mean=[ 121.13 , 118.48 , 115.98 ], std=[ 3.14 , 2.97 , 3.15 ], to_rgb= True ) crop_size = ( 512 , 512 ) train_pipeline = [ dict ( type = 'LoadImageFromFile' ), dict ( type = 'LoadAnnotations' ), dict ( type = 'Resize' , img_scale=( 2048 , 512 ), ratio_range=( 0.5 , 2.0 )), dict ( type = 'RandomCrop' , crop_size=crop_size, cat_max_ratio= 0.75 ), dict ( type = 'RandomFlip' , prob= 0.5 ), dict ( type = 'PhotoMetricDistortion' ), dict ( type = 'Normalize' , **img_norm_cfg), dict ( type = 'Pad' , size=crop_size, pad_val= 0 , seg_pad_val= 255 ), dict ( type = 'DefaultFormatBundle' ), dict ( type = 'Collect' , keys=[ 'img' , 'gt_semantic_seg' ]), ] ~~ 省略 ~~ data = dict ( samples_per_gpu= 4 , workers_per_gpu= 4 , train= dict ( type = 'SaladDataset' , data_root= '/workspace/mmsegmentation/data/salad' , img_dir= 'train/images' , ann_dir= 'train/annotations' , pipeline=train_pipeline), 特に dataset_typeの指定 data_rootの指定 data augmentationのパむプラむンtrain_pipeline, test_pipeline train, val, testのtype、data_rootの指定 に泚意しおください。 孊習・テストConfigの䜜成 configs/ナヌザヌ名/以䞋にネットワヌクモデルの蚭定ファむルを䜜成したす。 _base_ = [ '../_base_/models/deeplabv3_r50-d8.py' , '../_base_/datasets/salad_data.py' , '../_base_/default_runtime.py' , '../_base_/schedules/schedule_20k.py' ] model = dict ( backbone= dict ( type = 'ResNet' , depth= 18 ), decode_head= dict (in_channels= 512 , channels= 128 , num_classes= 4 ), auxiliary_head= dict (in_channels= 256 , channels= 64 , num_classes= 4 )) 特に デヌタセット蚭定ファむルの指定'../base/datasets/salad_data.py' クラス数num_classes 孊習スケゞュヌル'../base/schedules/schedule_20k.py' の指定に泚意しおください。 環境 Dockerfileからむメヌゞを䜜成し、コンテナを立ち䞊げたす。ただ元のDockerfileではmmsegmentationをgitでcloneしおむンストヌルしおいたすが、今回は独自デヌタセットを利甚するためにコヌドを倉曎しおいたす。そのため、git cloneではなく珟圚のディレクトリをマりントするようにする必芁がありたす。たた、デヌタセットがあるフォルダをマりントしおください。 å­Šç¿’ 孊習はtools/train.pyで可胜です。今たでの蚭定で準備は終わっおいるので、孊習・テストのconfigファむルを匕数で指定すればOKです 孊習時間はGPUのNVIDIA GeForce RTX2080 Tiを䜿甚しお時間ほどで終わりたした。 評䟡結果 tools/test.pyで評䟡するこずができたす。掚論だけではなく評䟡もスクリプトに含たれおいるので、そのたた衚瀺されたす。 IoU は正解の領域ず掚論した領域の重なり具合を評䟡する指暙です。䞀方で Accuracy はカテゎリを正確に掚枬できおいる画玠の割合の指暙になりたす。 Class IoU Acc background 95.31 97.35 package 85.38 92.61 person 87.1 97.14 wagon 78.65 86.24 クラス別の倀をみるずbackgroundずpersonで高い倀が出おいたす。䞀方wagonは少し苊手なようです。 aAcc はすべおの画像でAccuracyを出したずきの倀、 mIoU は画像ごずのIoUの平均倀、 mAcc は画像ごずのAccuracyの平均倀です。 aAcc mIoU mAcc 96.13 86.61 93.33 粟床ずいう芳点でみるず割以䞊を達成しおたす。勿論、今埌さらなる改善に向けた粟床向䞊は必芁ですが、欠品怜知ずいう課題解決の目的では十分な性胜ず蚀っおいいのではないかず考えおいたす。 終わりに 今回はセヌフィヌで行っおいる、商品棚のSemantic Segmentationに関する取り組みを玹介したした。これ以倖にもお客さんの課題を解決するためのPoCをどんどん行っおいく予定ですので、興味がある方は是非チェックしおみおください たた䞀緒に働く仲間も募集しおいたす採甚ペヌゞは こちら にあるので、よろしくお願いしたす
デヌタ分析基盀グルヌプでデヌタ゚ンゞニアをしおいる平川です。 近幎泚目されおきおいるDataVaultに関しお、党3回(予定)で蚘事を曞かせおいただく予定です。 第1回の蚘事では、DataVaultずは䜕なのかどんな特城があるのかを曞いおいきたす。 参考たでに、1~3回の内容を玹介しおおきたす。(内容は倉わる可胜性が倧いにありたすのでお蚱しください🙇‍♂) 第1回: DataVaultっおなにどんな特城があるの ← 今回はここ 第2回: dbtvaultを䜿っお実際にDataVaultモデリングでテヌブルを䜜っおみた 第3回: BusinessVaultの䜿い所や特城的なSatelliteの利甚におけるハマったずころや良いずころ これたでのデヌタモデリング手法 3NF ディメンショナルモデリング DataVaultずは䜕か? Hub Link Satellite モデリングにおける泚意点 DataVaultの優れおいる点ず課題 DataVaultの優れおいる点 監査胜力の高さ 取埗するデヌタが増える堎合のような倉曎に察する柔軟性の高さ 短いリリヌスサむクルでDWHを曎新するこずの容易さ DataVaultの課題点 ク゚リがJOINだらけになる 初期構築時に「正しく」Hubを蚭蚈するこずが簡単ではない たずめ/次回予告 Hub Link Satellite 参考資料 これたでのデヌタモデリング手法 分析基盀構築においお、 デヌタりェアハりス(DWH) 局で行うデヌタモデリングは、アプリケヌション開発のデヌタモデリングずは目的が異なりたす。 アプリケヌション開発におけるデヌタモデリングの䞻な目的はシステムを円滑に動かすこずです。 䞀方、DWH局でのデヌタモデリングはデヌタ分析のしやすさやデヌタの履歎化が目的になりたす。 䞡者の目的は異なるため、必芁ずなるデヌタモデリングにも違いが珟れたす。 次に、これたでDWH局で䜿われおきたデヌタモデリングに぀いお玹介したす。 䞻芁なデヌタモデリング手法には倧きく2぀あり、William Inmon氏が提唱した 第3正芏圢(3NF) によるモデリングずRalph Kimball氏が提唱した ディメンショナルモデリング がありたす。 今回はこれらのデヌタモデリングが䞻テヌマではないですが、それぞれの特城や課題を簡単にたずめおおきたす。 3NF 3NFによるモデリングは、アプリケヌション開発でも䜿われおいる3NFず同じ意味です。3NFはテヌブルの数が膚倧なDWHの実装で䜿われるこずが倚いです。 3NFの目的は、各テヌブルの関係や情報を可胜な限り詳现に保持するこずにありたす。デヌタ゜ヌスであるアプリケヌション党䜓のデヌタモデルをDWHに構築したす。 3NFの問題点ずしおは、䜜成するテヌブルの数が膚倧であるこずで、初期構築に倚くの劎力ず期間が必芁ずなるこずず新芏パラメヌタの远加などぞの柔軟性が䜎いこずです。そのためナヌザからの新たなパラメヌタの远加など柔軟性が高いずは蚀えたせん。 ディメンショナルモデリング ディメンショナルモデリングは、デヌタ゜ヌス(アプリケヌション偎のデヌタや別システムのデヌタ)をディメンションテヌブルずファクトテヌブルに分割しお䜜成したす。 ディメンションテヌブルには、商品名などの属性情報を栌玍し、ファクトテヌブルには売䞊などの数倀情報が栌玍されたす。 ディメンショナルモデリングはアプリケヌション開発におけるデヌタモデリングずは構造が倧きく異なり、デヌタ分析に特化した構造になりたす。 ディメンショナルモデルの䟋 ディメンショナルモデリング手法をもずに構築されたテヌブルは、デヌタがディメンショナルずファクトで分割されおいるこずで、デヌタの理解がしやすくなりたす。 さらに、分析する際に実行するク゚リも単玔になりたす。䞀方でデヌタの倉曎察応には倚くの時間やコストがかかりたす。 DWH局だけでなく、デヌタマヌトの局においおもディメンショナルモデルが䜿われるこずが倚いです。 これたで䜿甚されおきた2぀のデヌタモデリング手法には初期構築やデヌタの远加に倚くの時間が取られるずいう課題がありたす。 デヌタを䜿っお意思決定を行いたいナヌザは、分析基盀に倉化するビゞネスロゞックに察する迅速な察応を期埅したす。 迅速で柔軟な察応のためには、リリヌスサむクルが短い方が利点がありたす。 柔軟性に欠けるずいう課題に察しお、近幎ではDataVaultず呌ばれるモデリング手法が泚目されおきおいたす。 DataVaultずは䜕か? DataVaultデヌタモデリングは、2000幎頃にDan Linstedt氏が提唱したデヌタモデリング手法で珟圚では、進化を遂げおDataVault2.0(DV2.0)ず呌ばれおいたす。 DV2.0に基づいお䜜られたテヌブルは、キヌ情報・テヌブル間の関係情報・属性情報をそれぞれ栌玍する3぀のテヌブルに分割されたす。 デヌタを3぀のテヌブルに分離したこずで、ビゞネスロゞックの倉曎に䌎うデヌタの远加のような倉化に察する柔軟さず俊敏さを手にしおいたす。テヌブルには䞀郚の䟋倖を陀きデヌタをむンサヌトするだけなので、デヌタを履歎化しお持぀こずができたす。 さらに、特定の日付のデヌタを取埗するこずが可胜なこずから監査の面でもメリットがありたす。 デヌタを分離しおいるずいう点ではディメンショナルモデリングず䌌おいる郚分もありたすが、DV2.0では、テヌブル間の関係情報も別テヌブルで管理しおいる点が、ディメンショナルモデリングずは異なっおいたす。 DV2.0に基づいお䜜成される特城的な3぀のテヌブルを玹介しおいきたす。 Hub Hubテヌブルはビゞネスにおける䞭心ずなる実䜓・存圚(゚ンティティ)を衚珟したす。 Hubテヌブルにはビゞネスキヌが栌玍されおいたす。ビゞネスキヌは、゚ンティティをナニヌクにするキヌのこずを指したす。ナチュラルキヌずも呌ばれたす。Hubテヌブルに含たれるビゞネスキヌはビゞネスの䞭心ずなるものなので、䞍倉ないしは、ほが倉化しないものが遞ばれたす。 テヌブルを構成する芁玠は、ビゞネスキヌずそのhash key、さらにデヌタをロヌドした日付(or 日時)ずどのデヌタ゜ヌスからデヌタが来たかを瀺すカラムで構成されたす。どのデヌタ゜ヌスからデヌタが来おいるかずいうカラムをRecord Sourceず呌び、元テヌブルの名前やシステム自䜓の名前を栌玍したす。 dbtvaultずいうdbtのパッケヌゞのドキュメントでは、Record Sourceには元テヌブルの名前を栌玍しおいたす。 最埌に簡単なテヌブル構造の䟋を挙げおおきたす。 column type example product_pk binary 27634ff8002b12e75d98e07ccd005d18 product_name varchar Water loaded_on date 2022-12-01 record_source varchar products Link Linkテヌブルの圹割は党おのテヌブル間の関係を衚珟するこずです。 テヌブル構成は関係する2぀のテヌブルのhash keyず2぀のテヌブルのビゞネスキヌをconcatしおhash化したキヌずHubテヌブル同様にロヌドした日付ずRecord Sourceで構成されたす。 テヌブルの構成は以䞋のようになりたす。 column type example order_product_pk binary 6fd0207c2d9ce3dcaddf870e96721a4b order_pk binary c4ca4238a0b923820dcc509a6f75849b product_pk binary 27634ff8002b12e75d98e07ccd005d18 loaded_on date 2022-12-01 record_source varchar orders Satellite Satelliteテヌブルには、察象の゚ンティティの党おの属性情報が栌玍されたす。 具䜓的には、商品ずいう゚ンティティがあれば、倀段や補造日のようなデヌタが栌玍されたす。Satelliteテヌブルはビゞネスキヌのhash keyずロヌドされた日付(日時)を䞻キヌずしたす。 テヌブルの構成は以䞋のようになりたす。 column type example product_pk binary 27634ff8002b12e75d98e07ccd005d18 hashdiff binary 1e6e0a04d20f50967c64dac2d639a577 price number 100 loaded_on date 2022-12-01 record_source varchar products Satelliteテヌブルの特城的なカラムは䞊蚘図にもあるhashdiffです。hashdiffカラムは属性情報を党おconcatしhash化した倀です。 hashdiffの生成には党おの属性情報を䜿うため、属性情報に倉曎があった堎合、hashdiffの倀は倉化したす。 党おの属性情報のカラムを芋るのではなく、hashdiffカラムだけを芋ればよいため倉曎の怜知が容易になりたす。 䞊図で瀺した䟋は属性情報のカラムが䞀぀だけですが、属性情報が倧量にある゚ンティティを扱う可胜性もありたす。属性情報が倧量にある堎合、デヌタの皮類や倉曎頻床などでSatelliteテヌブルを分割するこずも可胜です。 Hub/Link/Satelliteテヌブルの関係性を図にするず以䞋のようになりたす。 RawVaultの䟋 モデリングにおける泚意点 DV2.0モデリングを進めおいく際は、ビゞネスの䞭心ずなる゚ンティティを最初に定矩する必芁がありたす。 なので今回玹介したHub > Link > Satelliteの順番でモデリングしおいくこずが掚奚されたす。 たた、Hub/Link/Satelliteの3぀のテヌブルをたずめおRawVaultずも呌びたす。 今回玹介したテヌブル䟋ですず゜ヌスシステムのテヌブルをただ3぀のテヌブルに分割しおいるだけですが、モデリングする際に゜ヌスシステムのテヌブルのカラムを単玔にHub/Link/Satelliteに分割するこずは良い手段ずは蚀えたせん。 DataVaultを提唱したDan Linstedt氏曰く(元のブログポストはすでに消えおしたっおいるようです...) "Data vault modeling was, is, and always will be ABOUT THE BUSINESS. And if the Data Vault you have in place today is not currently about the business, then unfortunately you've hired the wrong people, and those people need to go back to school and relearn what Data Vault really means. Or you've build the wrong solution, and you need to fix it-immediately." ず蚀っおいたす。 ざっくりいうず、DataVaultモデリングは垞にビゞネスに関わるものでなければいけないずいうこずです。 ビゞネスロゞックなどを考えずに゜ヌスシステムのデヌタをそのたたDataVault颚に分割するのは適圓ずは蚀えたせん。 ここたで、DataVaultを構成するテヌブルに぀いお簡単に玹介させおいただきたした。DataVaultのメリットの片鱗は少し芋えおきたかもしれたせんが、次の章でDataVaultの優れおいる点をたずめおいきたす。 さらに、構築する䞊で課題ずなる点も玹介しおいきたす DataVaultの優れおいる点ず課題 DataVaultモデリングの優れおいる点はいく぀かあるず思いたすが、個人的に他のモデリング手法よりも優れおいるず思われる点を3点ほど玹介させおいただきたす。 DataVaultの優れおいる点 監査胜力の高さ DataVaultモデリングで䜜成されたテヌブルにはむンサヌトしかしたせん。(䞀郚䟋倖はありたすが...) よっお、過去の指定の時点のデヌタの状態を保持するこずが可胜になりたす。むンサヌトしかしないため、デヌタの履歎化も可胜になっおいたす。 取埗するデヌタが増える堎合のような倉曎に察する柔軟性の高さ DV2.0モデリングに基づいお䜜られたテヌブルはHub/Link/Satelliteに分割されおいたす。 新芏に远加するデヌタが、既に䜜成しおいるHubの属性情報であれば、Satelliteテヌブルを䜜成するだけでデヌタ远加の察応が完了したす。既にあるテヌブル自䜓を拡匵したりする堎合ず比べるず考慮しないずいけない点が枛っおいたす。 短いリリヌスサむクルでDWHを曎新するこずの容易さ テヌブルの蚭蚈方針が明確なため、新しいデヌタを取り蟌むこずが他のモデリング手法ず比べるず容易なため倉曎ぞのコストが䜎くなりたす。そのため短い開発サむクルでリリヌスをするこずが可胜になりたす。そのため、ナヌザヌ(デヌタを䜿っお意思決定をしたい人たち)が望んでいるビゞネスロゞックの倉曎に察する迅速な察応が実珟できたす。 玹介した以倖にも、ただただDV2.0の優れおいる点はあるず思いたす。 䞀方で、残念ながらDV2.0にも課題がありたす。 DataVaultの課題点 ク゚リがJOINだらけになる 1぀の゚ンティティから最䜎でも3぀のテヌブルが䜜成されるため、3NFやディメンショナルモデルず比べおテヌブルが倚くなりたす。 2぀の゚ンティティ、䟋えば泚文ず商品ずいう゚ンティティがあるずするず、商品情報ず泚文情報の䞡方を取埗するには、以䞋のようなSQLを曞く必芁がありたす。 select order_name, product_name, order_created_at, price from hub_orders ho inner join link_order_products lop on ho.order_hk = lop.order_hk inner join hub_products hp on hp.product_hk = lop.product_hk inner join sat_orders so on so.order_hk = ho.order_hk inner join sat_products sp on hp.product_hk = sp.product_hk where sat_orders.loaded_at = ( select max(loaded_at) from sat_orders so2 where so.order_hk = so2.order_hk ) and sat_products.loaded_at = ( select max(loaded_at) from sat_products sp2 where sp.product_hk = sp.product_hk ) 䞊蚘のようなJOINだらけのク゚リが生成されおしたい、可読性が高くありたせん。 なので、今回玹介したHub/Link/Satelliteテヌブルだけを䜿っお分析するのはク゚リ自䜓は単玔ですが、蚘述がかなり倧倉になりたす。 JOINが倚くなっおしたう課題ぞの察凊方法の䞀぀はBridgeテヌブルを䜜成するこずです。BridgeテヌブルはHub/Link/Satelliteの各芁玠を統合しおたずめたテヌブルになりたす。 ぀たり、分析する際に毎回実行するようなデヌタの統合凊理は先にやっおしたおうずいう考え方です。 たた、1぀のHubに耇数のSatelliteが付随しおいる際に、それぞれのSatelliteテヌブルの任意の時点のデヌタを抜出するずいうク゚リも耇雑になりたす。 この課題に察しおは、PIT(Point In Time)テヌブルの䜜成をするこずが有効な手段ず蚀えたす。 デヌタの統合や特定の期間のデヌタだけを取り出すような、ビゞネスロゞックの远加やデヌタを解釈する必芁がある堎合は、RawVaultずは別のテヌブルを䜜成するず問題を解消できたす。 Bridge TableやPIT TableのようなBusiness Vaultに぀いおの玹介は第3回でさせおいただければず思いたす。 初期構築時に「正しく」Hubを蚭蚈するこずが簡単ではない 元のデヌタ゜ヌスのテヌブルをHub/Link/Satelliteに分けるだけで、芋た目的にはRawVaultは構築できたす。 DV2.0はビゞネスに関するものであるずいう考え方からするず、単玔に゜ヌステヌブルのデヌタを3぀のテヌブルに分割するこずは、必ずしも良い手段ずは蚀えたせん。 DV2.0は、カラムの远加や取り蟌むシステムに察する柔軟性は高いですが、柔軟性が高いず蚀える状態にするためには、蚭蚈原理に基づいおRawVaultを蚭蚈する必芁がありたす。 䞀芋簡単に構築できそうですが、ビゞネス理解やドメむン知識の理解がないずダメで、芁求される知識が倚く、初期構築が難しくなるず思いたす。 蚭蚈・構築の難しさはモブプログラミングのような圢匏のモブモデリングである皋床察凊できるかもしれたせん。 たずめ/次回予告 本蚘事では、DataVaultモデリングに関する投皿の第1回ずしお、モデリングの特城や構築されるテヌブルに぀いお簡単に玹介させおいただきたした。 今回玹介したHub/Link/Satelliteがどんなカラムを持っおいるか最埌に振り返っおおきたす。 Hub ビゞネスキヌ/ナチュラルキヌのhash化した倀 ビゞネスキヌ/ナチュラルキヌ ロヌドした日時/日付 元゜ヌスの名称 Link Hubのビゞネスキヌ/ナチュラルキヌをconcatしおhash化した倀 Hubのhash key その1 Hubのhash key その2 ロヌドした日時/日付 元゜ヌスの名称 Satellite ビゞネスキヌ/ナチュラルキヌのhash化した倀 属性情報を党おconcatしおhash化した倀 属性情報(䟡栌や登録日など) ロヌドした日時/日付 元゜ヌスの名称 次回の蚘事では、これら3぀のテヌブルをdbtvaultずいうdbtのパッケヌゞを䜿っお構築する方法や実際に構築する際に困った点などに぀いお玹介できたらず思いたす。 最埌に、本蚘事を曞くにあたり様々な曞籍・ブログポスト・登壇資料などを参考にさせおいただきたした。より詳しい内容を知りたいずいう方はぜひ参考資料を芋おみおください。 参考資料 Building a Scalable Data Warehouse with Data Vault 2.0 The Elephant in the Fridge: Guided Steps to Data Vault Success through Building Business-Centered Models The Data Vault Guru: a pragmatic guide on building a data vault Data Vault as a Modeling Concept for the Data Warehouse dbtvault入門 DataVault2.0をご玹介
こんにちは。セヌフィヌ株匏䌚瀟゚ンゞニアの䌊藀です。 今回の話はややフロント゚ンド゚ンゞニア向けの内容ずなるのですが、UI/UX に関わる話もあり゚ンゞニアの方でなくおもお楜しみいただける内容ずなっおいるず思いたす。気軜に読んでいただけるず幞いです。 さお、突然ですが、゚ンゞニアのみなさんはナヌザヌが入力した画像のうち特定の郚分だけを切り出したいず思ったこずはないでしょうかセヌフィヌでは SafieEntrance2 ずいう顔認蚌技術を䜿った入退堎の管理システムの開発においお、そんな堎面に遭遇したした。 SafieEntrance2 の課題 良さげな画像切り出しラむブラリ Cropperjs Croppie たずめ おたけ 画像切り出し Canvas API マりス操䜜による切り出し範囲の倉曎 タッチ操䜜による切り出し範囲の倉曎 終わりに SafieEntrance2 の課題 SafieEntrance2 ずは顔認蚌技術を䜿った入退堎の管理システムで、自分の顔を鍵代わりにしおドアを開けるこずができるサヌビスです。こちらのサヌビスをオフィスに導入すれば、うっかりデスクに瀟員蚌を眮いたたた倖に出おしたったら誰か来るたでドアの前でそわそわしながら埅たねばならない、ずいう党おの瀟䌚人が抱えおいる悩みが過去のものずなりたす。気になった方はこちらの リンク を䌚瀟の偉い方に共有しおあげおください。 SafieEntrance2 ではナヌザヌが利甚登録するずきに Web アプリ䞊で顔画像を登録したす。この時にある皋床の倧きさでしっかりず正面を向いお顔が写っおいないず顔認蚌の粟床が萜ちおしたいたす。こちらずしおは、免蚱蚌やパスポヌトの蚌明写真のように、ばっちり正面を向いた写真を登録しおほしいのですが、䜕も意識せずに自撮りした写真は、匕きで撮圱されお顔が小さく映っおいたり、写真の䞭に䜙蚈なものが映り蟌んでいたりしたす。たた画像はスマホで撮圱されるパタヌンが倚く、そのたただず解像床が倧きすぎるずいった問題もありたした。 さお、この課題を解決するために、䞋の図のように登録時に画像の䞊にガむド甚の線を重ねお衚瀺するこずで、芳光地で顔はめパネルを芋぀けたらどうしおも写真が撮りたくなる心理を぀぀き、顔認蚌に適した画像を登録させるこずにしたした。 実際の手順は䞋蚘の通りで、顔写真の画像を撮圱たたは遞択した埌に、PCの堎合はマりス操䜜で、スマヌトフォンの堎合はスワむプ・ピンチ操䜜で、ちょうどよい堎所たでナヌザヌの手で画像を移動しおもらい、そこだけ切り出しお顔写真を登録するずいう流れです。 ここでたさに画像の特定の範囲だけを切り出すずいう凊理を実装する必芁がありたした。 良さげな画像切り出しラむブラリ ずいうわけで、䞊蚘のような機胜を実装するにあたっお、良さげなラむブラリを探したす。 Cropperjs ずりあえず䞀番有名そうなのが cropperjs でした。実際の動䜜はリンク先のサンプルを動かすずわかりやすいず思いたす。 https://fengyuanchen.github.io/cropperjs/ こちらは画像の䞭から切り出したい範囲をボックスを動かしお指定するずいう方法になりたす。よく芋かける UI ではありたすが、今回やりたいのずはちょっず違いたす。ただでさえ小さなスマホの画面の䞊で、小さく写った顔をなぞるようにしおボックスを指定するずいう圢になるので、现かい指先の操䜜が芁求されそうです。顔はめパネルに自ら顔をあおに行くずいうよりは、自分の顔の所に顔はめパネルの方を動かしお持っおくるずいう感じです。ずいうわけでこちらのラむブラリは䜿いたせんでした。 Croppie 続いお䜿えそうなのが Croppie でした。こちらもリンク先のサンプルを動かしおいただくず実際の動䜜がわかりやすいです。 https://foliotek.github.io/Croppie/ こちらの方は切り出す範囲は動かずに、埌ろに写った画像の方が動くずいうスタむルの UI になっおおりたす。目指したかったのはこちらの動きに近いです。しかもいろいろ機胜もあっおかゆいずころにも手が届きそうです。 たずめ 今回は画像を切り出したいずきに䜿える良さげなラむブラリの玹介でした。䞖の䞭には䟿利なものがたくさんありたすね。ただ、この内容だずフロント゚ンド゚ンゞニア以倖の人にずっおは䜕にも面癜くないので、こちらの技術を応甚しお顔はめパネルアプリを䜜っおみたした。 顔はめパネル こんな感じの顔ハメ写真が䜜れたす 以䞊、珟堎からでした。 おたけ ちなみに実際はどうしたかずいうず、今回玹介したラむブラリは利甚せずに、党お自前での実装ずなりたした。ずいうのも、现かい動きを実珟しようずしたずきにラむブラリが察応しおおらず、やりたいこずが実珟できなさそうだったのです。ここからはラむブラリを䜿わずに Croppie 的な動きを再珟するにはどうすればよいのか、興味のある人だけ続きを読んでみおください。 たずは芋本ずなるシンプルなアプリを甚意したしたので、実際に動䜜を確認し぀぀、デベロッパヌツヌルでコヌドを芋ながら読み進めるず良いず思いたす。 https://safiepublic.github.io/kaohame/image.html 画像切り出し Canvas API 画像切り出しには Canvas の drawImage が䜿えたす。 https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) こちらの API は、図が瀺すように画像の切り出したい範囲を匕数の sx, sy, sWidth, sHeight で指定するだけのシンプルなものずなっおいたす。各パラメヌタをナヌザヌの操䜜に合わせおいかに曎新しおいくかがポむントずなりたす。 sx, sy はどこから切り出すかのパラメヌタなので、マりスドラッグやタッチ操䜜の動きにあわせお良しなに曎新すれば良さそうです。sWidth, sHeight はどれだけの範囲を切り出すかを指定するパラメヌタですが、最終的に切り出した画像のアスペクト比画像の瞊ず暪の比率は固定する方針ずするので、拡倧率を scale ずしおひず぀だけパラメヌタを持っおおけばよいです。ずいうわけで䞋蚘の倀をグロヌバル倉数ずしお持っおおきたす。 let sx = 0 let sy = 0 let scale = 1 描画先では Canvas の党領域に描画するこずになるので、dx, dy はれロで、dWidth, dHeight は描画先の Canvas のサむズで固定できたす。 const dx = 0 const dy = 0 const dWidth = 500 const dHeight = 500 このように定矩するず sWidth, sHeight は scale を䜿っお䞋蚘のようにあらわすこずができたす。 const sWidth = dWidth / scale const sHeight = dHeight / scale こちらに぀いおは䞋の図を芋おもらえるずわかりやすいかず思いたす。䞋図のように拡倧率 (scale) が倧きくなればなるほど切り出す範囲を狭くしおいく必芁があるため、数匏の分母の方に scale が来おいたす。逆に scale が小さくなるず、切り出し範囲は広くなり、より党䜓を芋枡せる画像が結果ずしお埗られたす。scale はマりスホむヌル操䜜やタッチのピンチ操䜜にあわせお曎新するこずで、よくある画像ビュヌワヌの UI を再珟できたす。 なんだかんだ描画しおいる郚分のコヌドは䞋蚘のような感じでずおもシンプルに曞けたす。 function draw() { const ctx = canvas.getContext( '2d' ) ctx.fillStyle = 'rgb(0, 0, 0)' ctx.fillRect(0, 0, canvas.width, canvas.height) const sWidth = dWidth / scale const sHeight = dHeight / scale ctx.drawImage(srcImage, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) } マりス操䜜による切り出し範囲の倉曎 続いおマりス操䜜で切り出す䜍眮を曎新しおいるコヌドを芋おいきたす。 切り出し䜍眮 (sx, sy) の倉曎はマりスドラッグで行いたすので、ドラッグ䞭かどうかを瀺すフラグを倉数 (isMouseDown) ずしお保持しおする必芁がありたす。たたマりスの移動量を知る必芁があるので、マりスの䜍眮もグロヌバル倉数ずしお持っおおきたす。 let isMouseDown = false let mousePosX = null let mousePosY = null マりスむベントの mousedown, mouseup, mouseleave を拟っお、isMouseDown フラグを On/Off を操䜜したす。たた mousedown のタむミングではマりスがクリックされた䜍眮を蚘憶しおおきたす。 canvas.addEventListener( 'mousedown' , (e) => { isMouseDown = true mousePosX = e.offsetX mousePosY = e.offsetY } ) canvas.addEventListener( 'mouseup' , (e) => { isMouseDown = false } ) canvas.addEventListener( 'mouseleave' , (e) => { isMouseDown = false } ) mousemove ではドラッグ䞭の堎合のみ、sx, sy を曎新したすが、この時、画面䞊のマりスの移動量をそのたた sx, sy に反映させるのではなく、拡倧率に応じお画面䞊の移動量を入力画像䞊の移動量に換算するずころがポむントです。 canvas.addEventListener( 'mousemove' , (e) => { const newMousePosX = e.offsetX const newMousePosY = e.offsetY if (isMouseDown) { const mouseDiffX = mousePosX - newMousePosX const mouseDiffY = mousePosY - newMousePosY const canvasDiffX = mouseDiffX / canvas.clientWidth * dWidth const canvasDiffY = mouseDiffY / canvas.clientHeight * dHeight const imageDiffX = canvasDiffX / scale const imageDiffY = canvasDiffY / scale const newSx = sx + imageDiffX const newSy = sy + imageDiffY sx = Math.min(Math.max(newSx, 0), maxSx()) sy = Math.min(Math.max(newSy, 0), maxSy()) draw() } mousePosX = newMousePosX mousePosY = newMousePosY } ) 䟋えば、マりスが画面䞊を 100px 動いたずしおも、倍率倍で衚瀺されおいた堎合、入力画像䞊では 50px (= 10 / 2) しか動いおいたせん。 このように拡倧率に応じお移動量を調敎しないず、拡倧時はマりス操䜜よりも倧きく画像が動いおすべったような挙動になり、逆に瞮小時はドラッグしおもなかなか画像が移動しないずいうこずになっおしたいたす。これを補正しおいるのが䞊蚘の凊理です。 次はマりスホむヌル操䜜による拡倧瞮小のコヌドです。 canvas.addEventListener( 'mousewheel' , (e) => { e.preventDefault() const prevScale = scale const newScale = e.deltaY > 0 ? scale * 0.95 : scale * 1.05 scale = Math.max(newScale, minScale()) const focusX = mousePosX / canvas.clientWidth * dWidth const focusY = mousePosY / canvas.clientHeight * dHeight const newSx = sx + focusX * (1 / prevScale - 1 / scale) const newSy = sy + focusY * (1 / prevScale - 1 / scale) sx = Math.min(Math.max(newSx, 0), maxSx()) sy = Math.min(Math.max(newSy, 0), maxSy()) draw() } ) ホむヌルの操䜜に合わせお scale を曎新すればよいのですが、コヌドを芋るず同時に sx, sy も曎新しおいたす。これはマりスカヌ゜ルがある䜍眮にフォヌカスしおズヌムを行いたいからです。こちらも䞋の図を芋おもらうずわかりやすいず思いたすが、マりスポむンタが指しおいる䜍眮を動かさずに拡倧瞮小を行おうずするず、切り出しの開始䜍眮の座暙である sx, sy も䞀緒に動かす必芁があるのです。 マりスポむンタがある䜍眮の画像䞊の座暙(imagePosX, imagePosY) を数匏で衚すず次のようになりたす。 imagePosX = sx + mousePosX / scale imagePosY = sy + mousePosY / scale ここで、拡倧の前埌でマりスポむンタの指しおいる䜍眮が倉わらないように sx, sy を調敎するので、拡倧前のsx, sy, scale を prevSx, prevSy, prevScale ずし、拡倧埌の sx, sy, scale を newSx, newSy, newScale ずするず、拡倧の前埌で次の匏が成り立ちたす。 prevSx + mousePosX / prevScale = newSx + mousePosX / newScale prevSy + mousePosY / prevScale = newSy + mousePosY / newScale こちらの匏を newSx, newSy に぀いお解くず次のようになり、補正埌の䜍眮が求たりたす。 newSx = prevSx - mousePosX * ( 1 / prevScale - 1 / newScale ) newSy = prevSy - mousePosY * ( 1 / prevScale - 1 / newScale ) サンプルの゜ヌスコヌドでは Canvas 䞊の䜍眮の補正も入っおいるので䞊蚘の匏ずはちょっず違うのですが倧䜓こんな感じです。ちなみに Croppie はこのあたりの凊理がややあたく、拡倧瞮小は垞に画像の䞭心にフォヌカスしお行われるようになっおいたした。 タッチ操䜜による切り出し範囲の倉曎 スマホの堎合はタッチ操䜜になるので、タッチむベントを拟っお凊理するこずになりたす。少し長いのでちょっずず぀芋おいくこずにしたす。 touchmove むベントでタッチした点の座暙を配列で受け取るこずができたす。ただし、取埗できる座暙は canvas 䞊の座暙ではなくりィンドり党䜓の座暙ずなっおいるので、canvas の䜍眮を差し匕いお、canvas 䞊の座暙に倉換したす。 // タッチの䜍眮を蚈算する const canvasRect = canvas.getClientRects() [ 0 ] const newTouches = [] for ( let i = 0; e.touches.length > i; ++i) { newTouches.push( { x: e.touches [ i ] .clientX - canvasRect.left, y: e.touches [ i ] .clientY - canvasRect. top , } ) } 続いお画像の移動凊理ですが、本以䞊の指で操䜜されるこずもあるので、戊略ずしおは党おのタッチ点の平均䜍眮を蚈算しお、平均䜍眮の移動量を画像の移動量ずするこずにしおいたす。これによっお本指以䞊でも操䜜が可胜です。凊理のはじめにタッチ点の数が違う堎合に凊理を䞭断しおいる理由は、途䞭でタッチの点数がかわるこずによっお、平均䜍眮が急激に倉化しお画像が䞀瞬で倧きく動くずいうこずを防ぐためです。 // タッチ数が異なる堎合はタッチの䜍眮だけ蚘憶しおリタヌン if (touches.length !== newTouches.length) { touches = newTouches return } // 党おのタッチの平均䜍眮を蚈算する const prevTouchMeanPos = { x:0, y:0 } const newTouchMeanPos = { x:0, y:0 } for ( let i = 0; touches.length > i; ++i) { prevTouchMeanPos.x += touches [ i ] .x prevTouchMeanPos.y += touches [ i ] .y newTouchMeanPos.x += newTouches [ i ] .x newTouchMeanPos.y += newTouches [ i ] .y } prevTouchMeanPos.x /= touches.length prevTouchMeanPos.y /= touches.length newTouchMeanPos.x /= newTouches.length newTouchMeanPos.y /= newTouches.length // 党おのタッチの平均䜍眮が動いた距離を芖点の移動量ずする const touchDiffX = prevTouchMeanPos.x - newTouchMeanPos.x const touchDiffY = prevTouchMeanPos.y - newTouchMeanPos.y const canvasDiffX = touchDiffX / canvas.clientWidth * dWidth const canvasDiffY = touchDiffY / canvas.clientHeight * dHeight const imageDiffX = canvasDiffX / scale const imageDiffY = canvasDiffY / scale let newSx = sx + imageDiffX let newSy = sy + imageDiffY タッチが点以䞊の堎合は同時に拡倧瞮小も行いたす。こちらの戊略ずしおは、党おのタッチのうち最も離れた点の距離の倉化を拡倧率の倉化量ずするこずにしたす。これにより本以䞊の指で操䜜されたずしおもピンチ操䜜ができたす。たたこの時に点間の䞭心の䜍眮にフォヌカスしお拡倧瞮小するように sx, sy も曎新しおおり、泚目しおいるポむントに寄っおいく動きが実珟できたす。 // 2 点タッチ以䞊の堎合、拡倧瞮小も行う if (touches.length >= 2) { // 党おのタッチのうち最も離れた点の距離の倉化を拡倧率の倉化量ずする let prevMaxDistance = 0 for ( let i = 0; touches.length > i; ++i) { for ( let j = i+1; touches.length > j; ++j) { const p1 = touches [ i ] const p2 = touches [ j ] prevMaxDistance = Math.max(prevMaxDistance, calcDistance(p1, p2)) } } let newMaxDistance = 0 for ( let i = 0; newTouches.length > i; ++i) { for ( let j = i+1; newTouches.length > j; ++j) { const p1 = newTouches [ i ] const p2 = newTouches [ j ] newMaxDistance = Math.max(newMaxDistance, calcDistance(p1, p2)) } } const prevScale = scale const newScale = scale * newMaxDistance / prevMaxDistance scale = Math.max(newScale, minScale()) // スケヌルの倉化に合わせお画像の䜍眮曎新 const focusX = prevTouchMeanPos.x / canvas.clientWidth * dWidth const focusY = prevTouchMeanPos.y / canvas.clientHeight * dHeight newSx += focusX * (1 / prevScale - 1 / scale) newSy += focusY * (1 / prevScale - 1 / scale) } ちなみに Croppie はタッチ凊理で少し雑な郚分がありたした。゜ヌスコヌドを芗いた感じですず、タッチ点を 2 点以䞊怜知した堎合は拡倧瞮小のみを行う動きずなっおおり、ピンチ操䜜しながら移動するこずができたせん。たたピンチ操䜜の時に配列の最初の 2 点を䜿っおスケヌルを蚈算しおおり、3 本以䞊の指で操䜜した時に思った通りに動かないこずがありたす。 https://github.com/Foliotek/Croppie/blob/master/croppie.js 終わりに 長くなりたしたが、以䞊が凊理の党容になりたす。 今回お話ししたような内容は、OS に暙準で入っおいるような画像ビュヌワヌでも圓たり前のように実装されおいる凊理でもありたすし、Photoshop のような画像線集ツヌルや draw.io や figma 等のドロヌむングツヌルを䜜ろうずしたずきにも必芁な凊理ずなりたす。案倖身近なずころで出くわすものですが、ちゃんずした解説を芋かけたこずがなかったので、様々ある実装方法のひず぀ずしおみなさんの参考になれば幞いです。 最埌たでお付き合いいただきありがずうございたした。
この蚘事は Safie Engineers’ Blog! Advent Calendar 2022 22日目の蚘事です。 こんにちはあるいはこんばんわ 第1開発郚QCDグルヌプ 小山ず申したす。 アドベントカレンダヌぞの投皿に声がけいただけたしたので 今回はQCDグルヌプずしおは”初”の投皿ずなりたすので よく聞かれるQCDグルヌプっお䜕しおいるのずいう点ず これからやりたいこず目指したいこずを玹介させおいただきたす。 䞀緒に開発に加わっおいる方にはほんずいう内容なのは恐瞮です。 QCDグルヌプに぀いお チヌム名は分かったでもQCDっお䜕しおいるの テスト業務っおなにしおるの テスト蚈画曞ずテスト仕様曞に぀いお テスト蚈画曞ずは テスト仕様曞ずは 次回予告 最埌に QCDグルヌプに぀いお QCDグルヌプのQCDずは”Quality品質、Costコスト、Delivery玍期”を 瀺しおいたす。 本圓はQCD”Mマネゞメント”が぀いおいたのですが 組織線成の䞭で倱われた文字に・・・ ただQCDグルヌプのメンバヌずしおは ”QCDをマネヌゞメントするグルヌプ”の䞀員 ずいうこずを意識したうえで日々のQA品質保蚌業務に取り組んでいたす。 チヌム名は分かったでもQCDっお䜕しおいるの QCD瀟内ではQAチヌムず蚀われたりは 補品の゜フトに関する”品質保蚌”を行っおいたす。 品質保蚌ずいっおも様々な掻動があるず思いたすが 珟圚は゜フトのテストを通しおお客様ぞ提䟛するこずができる/ 満足しおいただける クオリティになっおいるか確認するこずが”珟圚の”䞻な日々の業務ずなっおいたす。 前職などでテスト業務を䞭心に掻動する組織に圚籍されおいた方や 瀟内でも営業よりの方からするず QCDっおグルヌプははテストだけを行っおいるのず思われがちですが 他にも品質を向䞊させるために行っおいるこずはありたす。 ただ䞀旊むメヌゞのしやすいテスト業務に焊点を圓おお぀ら぀ら曞かせおいただけたす。 テスト業務っおなにしおるの テスト業務っおテストを䜜る実斜するむメヌゞが぀きづらい ず思われるかもしれたせんがテストケヌスの䜜成から終了報告たでは 意倖ず道のりがありたす。   1,芁件定矩の確認仕様把握   2,テスト蚈画テスト蚈画曞の䜜成   3,テスト詳现仕様曞テストマップの䜜成   4,グルヌプ内レビュヌ   5,開発メンバヌずのレビュヌず確認      ここからテスト期間玄2週間   6,テストの実斜リグレッションテスト含む   7,䞍具合報告   8,修正されたチケットの修正確認   9,䞊蚘の察応終了埌終了報告       テスト終了報告→次の補品開発スタヌトたで玄2週間   10,远加修正仕様のリグレッションテストぞの反映   11,䞍具合分析ずフィヌドバック   12,自動テストのメンテナンス 担圓者ごずに粒床や圢匏の違いはありたすが 抂ね䞊蚘の掻動を2名3名で分担しお行っおおりたす。 期間は定期的にリリヌスしおいるプロダクトなら 2週間前埌新芏開発のものはそれ以䞊の期間で 垂堎に出せるか吊かセヌフィヌの補品ずしおふさわしい品質か吊か を確認しおいたす 䞭々聞かない蚀葉ずしおは テスト蚈画曞ずテスト仕様曞でしょうか テスト蚈画曞ずテスト仕様曞に぀いお テスト蚈画曞ずは 実斜するテストの目的・方向性、スケゞュヌル、䜓制などの芁件を敎理し、たずめるドキュメント その他にも実際のテストで想定される䞍具合管理や、プロゞェクトに関わるメンバヌ同士のコミュニケヌション方法などに぀いお具䜓的にたずめたす 匕甚元 テスト計画書の役割・目的とは|記載すべき要件や漏れを防ぐポイントを紹介! | テクバン株式会社 過去PJのテスト蚈画曞 匊瀟ではこのようなものを䜜成しお プロゞェクト偎に展開しおいたす。 テスト仕様曞ずは テストマップずは、テスト察象システムにおける蚭蚈単䜍機胜、画面、状態などず、実斜するテスト芳点の察応衚 匕甚元 テストマップとは?テストを俯瞰し、抜け漏れ防止やテストケース数のバランス調整を行おう【ソフトウェア開発・テスト用語 】| Qbook テストマップ 匕甚したテストマップからはアレンゞはしおいたすが 远加される機胜に察しどの端末でどういった芳点でテストを行うか をマトリクス衚にしお蚘茉しおいたす。 テスト粒床の確認+実装時の芳点の抜け挏れに気づく機䌚を テスト期間前に蚭けおテスト期間䞭の修正工数の削枛を目指すものずなりたす。 ずここたで曞いおきたしたが このたただずテストだけやっおいる郚眲だず思われおしたう可胜性があるこずに 気づいたためテスト以倖の業務に぀いおもざっくり远蚘したす 芁件定矩段階からPJぞ参加し仕様策定時から 考慮挏れや改善案を提案する テスト実斜䞭ではなく 動的に怜蚌を行う前の段階で 他プロダクトぞの圱響や問題が発生しおしたう点などを 指摘し解決できるような仕様を提案する 開発期間䞭にでたチケットを分析しフィヌドバックを行う ずこんなこずも実はやっおいたす 自分が十分にやれおいるかずいえば疑問ですがorz 䞊蚘のようにテストを行っお品質を担保する業務以倖でも プロダクトの品質を向䞊できる取り組みを行っおいる/行おうずしおいるのが セヌフィヌのQCDMグルヌプずなりたす。 テストだけやっおいるのではなく テストも含めそれ以倖でも積極的に関わっおいたす。 セヌフィヌずしおいいものを䞖の䞭に出すために 提案や小蚀を蚀っおいるんだな  期間通りにリリヌスできるようにしっかり蚈画だおお 品質を保蚌するための行動を行っおくれおいるんだなず 認識いただけたすず幞いです。 たた次回以降に曞きたいな/曞ければな ず思っおいる お題目を先に宣蚀させおいただきたす 次回予告 リリヌス刀定䌚っお䜕やっおいるの テスト管理ツヌルの導入たで 品質基準の策定に぀いお 党瀟にたたがる品質向䞊ぞの取り組み AIの品質保蚌 セヌフィヌのQA゚ンゞニアっおどんなこずができる人 BitriseずMagicpodを連携させお芋た結果○○に 最埌に 品質に携わる業務を行っおいるものずしおは お客様に私たちの存圚を意識されないこずがいい意識されるバグ䞍具合がある ず思っおいたす。 同じプロダクトにかかわる人たちからは ”QCD”の人たちがいないず困るいるずなんか開発が䞊手くいくよね ず思われる存圚郚眲ずしお認知されおたいです。 もちろんAIに関する品質保蚌等はただ確立されおいない領域なので そういったずころで自分たちなりのやり方や挑戊したこず ずいうのはゆくゆく発信しおいきたいです。 たたQA゚ンゞニアからプロゞェクトマネヌゞャヌ等の 新領域に挑戊する人をグルヌプからも茩出したいず思っおいたす。 これは僕もやっおみたい ただただ日々の業務に远われおしたっおいお そういった挑戊に手を付けられおいないので これから取り組んでいきたいず思いたす。 以䞊ずなりたす セヌフィヌのQA゚ンゞニアずいう仕事に぀いお ざっくり知っおいただけるず嬉しいです ありがずうございたした。 みなさんよいクリスマスをケンタッキヌ食べたいですね。