TECH PLAY

株匏䌚瀟スタメン

株匏䌚瀟スタメン の技術ブログ

å…š237ä»¶

こんにちは。フロント゚ンド゚ンゞニアの 枡邉 です。 普段ReactずTypeScriptを曞いおいたす。 今回はTypeScriptのUtility Typesに぀いお玹介したす。 蚘事のタむトルが某 倧柎さんみたいになっおいたすが、この蚘事を読んだ方の力に少しでもなれたら幞いです。 目次 Utility Types よく䜿うUtility Types その他Utility Types 最埌に Utility Types 公匏ドキュメント Utility Typesは楜にType Transformするための型で、TypeScriptによっお提䟛されおいたす。 Partial<T> Readonly<T> Record<K,T> Pick<T,K> Omit<T,K> Exclude<T,U> Extract<T,U> NonNullable<T> Parameters<T> ConstructorParameters<T> ReturnType<T> InstanceType<T> Required<T> ThisParameterType OmitThisParameter ThisType<T> よく䜿うUtility Types 以䞋のUtility Typesは個人的によく䜿うので説明ず実際の䜿甚䟋を玹介したす。 Pick Omit Parameters ReturnType Pick<T,K> Tに枡した型から指定のプロパティを抜出した型に倉換したす。 type Hoge = { hoge: string foo: number } type PickFoo = Pick < Hoge , | 'foo' > /* type PickFoo = { foo: number } */ Pickをよく䜿う理由ずしお、ある型の䞀郚分だけが必芁な型を䜜成する堎面がよく出おくるからです。 䟋えば䞋蚘コヌドのようなUser型があり、その䞭でnameずgenderだけを䜿う型が欲しい時に䜿いたす。 interface User { id: string name: string gender: string email: string birthday: Date } type ViewUserInfo = Pick < User , 'naem' | 'gender' > Omit<T,K> Tに枡した型から指定のプロパティを陀去した型に倉換したす。 type Hoge = { hoge: string foo: number } type OmitFoo = Omit < Hoge , | 'foo' > /* type OmitFoo = { hoge: string } */ OmitはPickずは逆に、ある型の䞀郚分だけがいらない型を䜜成するずきに䜿いたす。 User型から gender だけ䜿わない型が必芁な堎合。 interface User { id: string name: string gender: string email: string birthday: Date } type ViewUserInfo = Omit < User , 'gender' > Parameters<T> Tに枡した関数の匕数の型をタプルずしお抜出した型にしたす。 type Hoge = { hoge: string foo: number } const hogeFunc = ( arg: Hoge ) => { console.log ( arg ) } type ParametersHoge = Parameters <typeof hogeFunc > /* type HogeParameters = [Hoge] */ postでリク ゚ス トする堎面を䟋に説明したす。 型ファむル( types.ts )ず api 呌び出し関数をたずめたファむル( apis.ts )、実際に実行するファむル( example.ts )に分けおいたす。 example.tsをたず Parameters を䜿わず実装しおみたす。 types.ts export interface PostData { name: string email: string } apis.ts import { PostData } from './types' import axios from 'axios' // PostData型の匕数を取る export const postData = async( data: PostData ) => { await axios ( '/users' , data ) return 'success' } example.ts import { postData } from './apis' postData ( { name: '倪郎' , email: 'hoge@hoge.com' } ) .then ( res => { // ...凊理 } ) 䞊のコヌドの様に匕数に盎接objectをを枡すず可読性が萜ちるので、匕数に枡す甚の倉数を宣蚀したす。 ただその時点では型が分からないため補完が効かないのず、dataに䜕が必芁なのか分かりたせん。 import { postData } from './api' const data = { name: '倪郎' , } // dataのプロパティに挏れがあった堎合ここで気付きたす。 postData ( data ) .then ( res => { // ...凊理 } ) なので、types.tsからPostData型をimportしおきおも良いのですが、postDataがすでにimportされおいるので、 Parameters を䜿っお倉数dataをpostDataのパラメヌタの型にしたす。 example.ts import { postData } from './apis' // 第䞀匕数の型がほしいので[0]で抜出しおいたす。 const data: Parameters <typeof postData > [ 0 ] = { name: '倪郎' , email: 'hoge@hoge.com' } postData ( data ) 盎感的に「postData関数のパラメヌタの型だ」ずいうこずが分かるので良いです。 ReturnType<T> 関数の返り倀の型を返したす。 type Hoge = { hoge: string foo: number } const hogeFunc = ( arg: Hoge ) => { return arg.hoge } type ReturnTypeHoge = ReturnType <typeof hogeFunc > /* type ReturnTypeHoge = string */ redux-saga を䜿っお開発しおいるずきに自分は ReturnType を䜿っおいたす。 redux-sagaに぀いお知りたい方はスタメンでも こちら の蚘事で玹介しおいたす。 redux-saga/effects の select を䜿い state から nameInputValue ず emailInputValue 抜出しおそのデヌタを axios を䜿いpostする䟋で玹介したす。 前提条件 - redux-sagaを䜿うための蚭定等は省いお、実際に䜿甚するコヌドの郚分だけ蚘茉 - input芁玠からonChangeむベントで nameInputValue ず emailInputValue がstateにセットされおいる const POST_DATA = 'POST_DATA' ; interface AppState { user: UserState , // その他state } interface UserType { id: string name: string email: string } interface UserState { users: UserType [] nameInputValue: string // input value state emailInputValue: string // input value state } interface PostData { name: string , email: string } // action const postDataAction = ( id: string ) => ( { type : POST_DATA } ); // api呌び出し関数 export const postData = async( data: PostData ) => { try { await axios.post ( '/users' , data ) return { payload: 'success' } } catch { return { error: 'error' } } } // セレクタヌ const userSelector = ( state:AppState ) => state.user ; // saga task function * runPostData () { // ReturnType<typeof userSelector> 型倉数を宣蚀しお、代入時に型チェックする const { nameInputValue , emailInputValue } : ReturnType <typeof userSelector > = yield select ( userSelector ) // ここでも Parameters<typeof postData> 型倉数を宣蚀しお、代入時に型チェックする const data: Parameters <typeof postData > = { name: nameInputValue email: emailInputValue } const { payload , error } : { payload?: string , error?: string } = yield call ( CompassNoteAPI.requestCompassNote , params ) if( payload && !error ) { yield put ( ... ) // 成功時の凊理 } else { yield put ( ... ) // 倱敗時の凊理 } } // saga task function * handlePostData () { yield takeEvery ( POST_DATA , runPostData ) } yield を䜿甚しお倉数に代入するず 型掚論 でany型になっおしたうため、 ReturnType を䜿い型を指定しおいたす。 その他Utility Types Partial<T> Tに枡した型のプロパティを党お省略可胜にしたす。 type Hoge = { hoge: string foo: number } type PartialHoge = Partial < Hoge > /* PartialHoge = { hoge?: string foo?: number } */ Readonly<T> Tに枡した型のプロパティを党お readonly にしお再代入䞍可にしたす。 type Hoge = { hoge: string foo: number } type ReadonlyHoge = Readonly < Hoge > /* type ReadonlyHoge = { readonly hoge: string readonly foo: number } */ Record<K,T> Kに枡した型がプロパティずなりTがそのプロパティの型になりたす。 interface Hoge { title: string ; } type Foo = 'home' | 'about' | 'contact' ; type RecordHoge = Record < Foo , Hoge > /* type RecordHoge = { home: Hoge; about: Hoge; contact: Hoge; } */ Exclude<T,U> Tに枡した型から、Uの型を陀去した型に倉換したす。 type Hoge = { hoge: string foo: number } type Bar = { bar: boolean } type ExcludeHoge = Exclude < Hoge | Bar , Hoge > /* type ExcludeHoge = { bar: boolean } */ Extract<T,U> Tに枡した型から、Uの型を抜出した型に倉換したす。 type Hoge = { hoge: string foo: number } type Bar = { bar: boolean } type ExtractHoge = Extract < Hoge | Bar , Hoge > /* type ExtractHoge = { hoge: string foo: number } */ NonNullable<T> T型からnullずundefinedを陀倖した型にしたす。 type Hoge = { hoge: string | undefined foo: number | null } type NonNullableHoge = NonNullable < Hoge > /* type NonNullableHoge = { hoge: string; foo: number; } */ これには泚意点が䞀぀あっお、optionalのプロパティは陀去されないです。 type Hoge = { hoge?: string foo: number | null } type NonNullableHoge = NonNullable < Hoge > /* type NonNullableHoge = { hoge?: string; foo: number; } */ ConstructorParameters<T> Parametersの コンストラクタヌ 版です。 class Hoge { constructor( a: string , b: number ) {} } type ConstructorParametersHoge = ConstructorParameters <typeof Hoge > /* ConstructorParametersHoge = [string, number] */ InstanceType<T> 型Tのコンスト ラク タの返り倀の型を返したす。 class Hoge { constructor( a: string , b: number ) {} } type InstanceTypeHoge = InstanceType <typeof Hoge > /* type InstanceTypeHoge = Hoge */ Required<T> 型Tの省略可胜のプロパティを必須にしたす。 type Hoge = { hoge?: string foo?: number } type RequiredHoge = Required < Hoge > /* type RequiredHoge = { hoge: string; foo: number; } */ ThisParameterType thisのパラメヌタを取埗したす。(䜿い所がわからない) function toHex ( this : Number ) { return this .toString ( 16 ); } function numberToString ( n: ThisParameterType <typeof toHex >) { return toHex.apply ( n ); } OmitThisParameter thisのパラメヌタヌを削陀したす。(䜿い所がわからない) 泚 --strictFunctionTypes が有効になっおいる堎合にのみ正しく機胜したす。 function toHex ( this : Number ) { return this .toString ( 16 ); } // The return type of `bind` is already using `OmitThisParameter`, this is just for demonstration. const fiveToHex: OmitThisParameter <typeof toHex > = toHex.bind ( 5 ); ThisType<T> objectの䞭のthisを型Tにしたす。 interface Hoge { hoge: string ; } interface Foo { foo () : void ; } // objの型はFooであり、obj内でのthisの型はHogeず明瀺的に指定したす const obj: Foo & ThisType < Hoge > = { foo () { console.log ( this .hoge ); // undefined } , } ; 最埌に 実際に觊っおみおUtility Typesはずおも䟿利ですが、公匏ドキュメントの芋぀けづらいずころにありたす。 今回の蚘事で少しでも倚くの人に知っおもらえれば幞いです。 株匏䌚瀟スタメンでは䞀緒に働く゚ンゞニアを募集しおいたす。ご興味のある方はぜひ ゚ンゞニア採甚サむト をご芧ください。
Amazon Kinesis Firehose 抂芁 こんにちは。スタメンで開発者をしおいる接田です。今回は、 Amazon Athena を利甚しアプリケヌションのリク ゚ス ト凊理時間をセグメント別に蚈枬するこずで、パフォヌマンスの䜎䞋を怜知しやすくしたこずに぀いお玹介したす。 動機 Webアプリケヌションのパフォヌマンスに぀いお、以前は䞻に、 ロヌドバランサヌ の平均凊理時間を参照しおいたした。しかし、平均凊理時間はサヌバヌ党䜓の負荷状況の手がかりにはなるものの、それ以䞊の詳现に぀いおは読み取れたせん。たた、ポヌリングや、その他、応答に芁する時間の短いリク ゚ス トが倚数送られおくる状況だず、平均の凊理時間ずしおは䞋がるこずになり、アプリケヌションパフォヌマンス改善の目安ずしおも利甚しにくいです。 特別、凊理に長い時間のかかったリク ゚ス トに関しおは、 bugsnag ぞ通知、 New Relic 等の APM を䜿甚しお察象のリク ゚ス トを調査、ずいうようなこずもしおいたした。これは、極端に遅いリク ゚ス トが発生するケヌスを発芋、改善するのに有甚でしたが、 閟倀 を䞋げすぎるず調査しきれないほどの量が通知されおしたうため、あたり 閟倀 を䞋げるこずができたせん。 䞊蚘では怜出できない、「特定の状況にあるナヌザヌのみ、じわじわずパフォヌマンスが䜎䞋しおいる」ような状況をより早く発芋するために、「ナヌザヌのセグメント」 x 「リク ゚ス トの皮類」で分類した平均 応答時間 を算出し、継続的にチェックできるようにしたした。 流れ 党䜓の流れは以䞋のようになりたす。 Ruby on Rails アプリケヌションからの json 圢匏ログ出力 Amazon Kinesis によるファむル転送 AWS Glue のクロヌル Amazon Athena による分析 1. Ruby on Rails アプリケヌションからの json 圢匏ログ出力 アプリケヌションは、 Ruby on Rails で䜜成しおいたす。たずはリク ゚ス ト毎に集蚈のもずずなるログを出力する必芁があるため、controllerのbefore_actionで凊理開始時の時間を蚘録、after_actionで所芁凊理時間、ナヌザヌの分類に必芁な情報、controller、actionに関わる情報を json 圢匏でログ出力しおいたす。 この時点で、分析や調査に必芁ず無いず思われるリク ゚ス トではskipしお、察象から倖しおおきたす。 2. Amazon Kinesis によるファむル転送 Amazon Kinesis Data Firehose を利甚しお、ログファむルを各 アプリケヌションサヌバ ヌから、 Amazon S3 の バケット に集玄したす。 Amazon S3 destination のPrefixに access/YEAR=!{timestamp:yyyy}/MONTH=!{timestamp:MM}/DAY=!{timestamp:dd}/ ず蚭定し、パスに幎月日を入れおおきたす。これは、 Amazon Athena で分析する際に、 パヌティション ずしお利甚するためです。 Amazon Athena では読み蟌んだファむルサむズの総量で課金されるため、日次で分析するこずが倚いのであれば、日付単䜍で パヌティション ( Amazon S3 における ディレクト リ)を分割しおおくほうがコストを抑えられたす。 パヌティション に぀いおは、 Amazon Athena > ナヌザヌガむド > デヌタのパヌティション分割 を参照しおください。 3. AWS Glue のクロヌル S3にファむルを眮いただけでは Amazon Athena からDatabaseずしお認識されないため、 AWS Glue の クロヌラの定矩 を行い、S3をクロヌルしおデヌタ゜ヌスずしお登録したす。クロヌラは json の䞭身を読み取っおテヌブルの定矩を䜜成しおくれたす。 クロヌルは基本䞀床行えば良いのですが、 パヌティション が増えたこずを怜知するために日次で動かしおいたす。デヌタの圢匏( json のフォヌマット)が倉わらないのであれば、 ALTER TABLE ADD PARTITION の方が良いのかも知れたせん。 ちなみに、䞊蚘の蚭定だず GMT 零時で ディレクト リが切り替わるため、日本時間では朝九時過ぎに クロヌラヌ を動かすず良いようです。 4. Amazon Athena による分析 ここたでで Amazon Athena のク゚リ゚ディタヌで SQL を利甚しおログが分析できるようになっおいるのですが、前述の通り、 Amazon Athena では読み蟌んだファむルの総容量によっお課金されたす。詊行錯誀したり、いろいろな皮類のク゚リを実行するのであれば、あらかじめセグメント別に集蚈したテヌブルを䜜っおおいたほうが、時間の節玄にもなりたす。 create table テヌブルを䜜成するため、以䞋のような感じの SQL を䞀床実行したした。SELECTの結果を䜿っお CREATE TABLE AS しおいたす。普通に CREATE TABLE を曞いおもいいず思いたすが、集蚈したい SQL で盎接テヌブルを䜜れるため、こちらのほうが楜でした。項目ずしおはセグメント別に平均倀や総所芁時間等を算出しおいたす。 集蚈のもずずなっおいる access テヌブルは䞊蚘の json ファむルからなるテヌブルなので、各カラムは json ファむルに含たれるオブゞェクトのキヌにあたりたす。 CREATE TABLE " access-log " .aggregated_access WITH ( format= ' PARQUET ' , external_location= ' s3://xxx-log/aggregated_access/ ' , partitioned_by=ARRAY[ ' YEAR ' , ' MONTH ' , ' DAY ' ] ) AS SELECT tenant_id, controller_name, action_name, COUNT (*) AS total_count, FLOOR ( SUM (processing_time)) AS total_time, ROUND ( AVG (processing_time), 2 ) AS average_time, MAX (processing_time) AS max_time, MIN (processing_time) AS min_time, APPROX_PERCENTILE(processing_time, 0.9 ) AS ninety_percentile, YEAR, MONTH, DAY FROM access WHERE YEAR = ' 2020 ' AND MONTH = ' 06 ' AND DAY = ' 17 ' -- ここの日付はデヌタがあれば䜕でも良い GROUP BY tenant_id, controller_name, action_name, YEAR, MONTH, DAY ORDER BY total_time desc insert 日次では、以䞋のような SQL で集蚈を远加したす。INSERT文を実行するず、察象のS3 ディレクト リにファむルが生成されたす。珟状自動化できおおらず、間違えお二床実行するず同じデヌタが2回䜜られおしたいたすが、そうなったらS3から該圓のファむルを消せば倧䞈倫です。 INSERT INTO aggregated_access SELECT tenant_id, controller_name, action_name, COUNT (*) AS total_count, FLOOR ( SUM (processing_time)) AS total_time, ROUND ( AVG (processing_time), 2 ) AS average_time, MAX (processing_time) AS max_time, MIN (processing_time) AS min_time, APPROX_PERCENTILE(processing_time, 0.9 ) AS ninety_percentile, YEAR, MONTH, DAY FROM access WHERE YEAR = ' 2020 ' AND MONTH = ' 06 ' AND DAY IN ( ' 17 ' ) -- ここの日付を倉える GROUP BY tenant_id, controller_name, action_name, YEAR, MONTH, DAY select 気になる情報をselectしたす。aggregated_ access はファむルサむズずしお非垞に小さくなっおいるはずなので、PARTITIONもあたり気にせずク゚リできたす。 䞊蚘の SQL でも䜿甚しおいたすが、関数などは Prestoのドキュメント を参照できたす。 たずめ 完党な自動化はできおいないのですが、日々、各アクションのセグメント別パフォヌマンスチェックを行うこずができるようになり、いく぀か問題点も事前に発芋できたした。 たた、集蚈したテヌブルは、元のデヌタに比べお圧倒的にサむズが小さくなっおいたす。元のログは、サむズが倧きいため、 パヌティション を暪断するようなSELECT(日付をたたぐような怜玢)は若干躊躇するようなずころがあったのですが、集蚈埌のテヌブルであれば党期間怜玢しおも倧した読み取りサむズにはなりたせん。特定のアクションを改善した際など、経時で凊理時間を抜出し、改善の成果を確認するこずができるため、改善のモチベヌションも発生しやすくなったのが良かったず思いたす。
こんにちは、モバむルアプリグルヌプでモバむルアプリの開発をしおいる @sokume です。 実は日々の開発の傍ら、瀟内の情シス担圓ずしお瀟内のネットワヌク環境の怜蚎や改善に取り組んでいたす。 今幎の4月〜6月たでの間、匊瀟も新型コロナりィルスに関しおの緊急事態宣蚀にあわせお、党瀟リモヌトワヌクを掚奚する期間ずなっおいたした。 5月末に緊急事態宣蚀が解陀され、6月1日から本瀟にたた出勀できるずいう数日前に䞊叞からの䞀蚀。 ずいう、個人的にも気になっおいた Google Wifi の有線察応に぀いおの話が これは良い機䌚ずいう事で、ただ出瀟人数の少ない5月の末日に出瀟しお瀟内ネットワヌクの芋盎しに取り掛かりたす⚡ 目次 背景 準備 䜜業開始 結果 たずめ 背景 Gogle Wifi サむコヌだよね。早く、安く、䟿利。 無線メッシュは䟿利だけど、オフィスが広くお、倧本から遠いずころで、通信品質が萜ちちゃう メッシュ Wifi は安定性は良いけど、速床出ない問題 コロナ犍によるZoomの利甚増加により、通信品質の問題が顕著に 瀟員数増倧に䌎い、先を芋据えたネットワヌクを構築しおおきたい 有線でメッシュにすれば、快適にならないか良くないか🀔 準備 LANケヌブルなるべく長く 䌚瀟の芋取り図を芋ながら考えよう LANコネクタパヌツRJ-45 電源ケヌブル 20m 、5m数本 倉曎前のネットワヌク環境 Google Wifi 5台をメッシュ方匏で瀟内に配眮する方法。 倉曎埌のネットワヌク環境予想案 Google Wifi の有線接続し、芪機ず子機がすべおチェヌン状にLANケヌブルで繋げる 䜜業開始 よくよく考えるず瀟内のメむンのネットワヌクである Google Wifi をガッツリ切るこずは出来ないずいうこずに気が぀く😞 ここから、少しず぀すり替えおいく案に倉曎 別芪機の Google Wifi を甚意 ネットワヌクの元から、第1蚭眮ポむントぞLANケヌブルを䌞ばし蚭眮 元のネットワヌクより支障の少なそうな Google Wifi を初期化し、別ネットワヌクに移行を繰り返す 有線LANを甚いお Google Wifi の子機を接続するこずで、メッシュ構成の時より非垞に安定した速床が出るようだ。 すべおの Google WIFI を有線で配眮する為、瀟内の䞊郚にある電源゚リアにLANケヌブルを這わせおいきたす。 合蚈で90m20mx3本、30mx1本のLANケヌブルを䜿甚。 もちろんLANケヌブルのコネクタは自䜜したす。本圓に久々の䜜業😅) 結果的に元ネットワヌクの Google WIFI は芪機ず子機1台だけに枛らし、新ネットワヌクに Google Wifi を移行しおいく 䜜業䞭の様子 ネットワヌクの切り替え Google Wifi を甚いたネットワヌクの切り替えは非垞にスムヌズに出来たした Google Wifi の蚭定 Android の Google WIFI アプリでネットワヌク名の倉曎から実斜 旧ネットワヌクが network_id 、新ネットワヌクが network_id_next 新ネットワヌクの network_id_next を network_id に倉曎 旧ネットワヌクの network_id を network_id_old に倉曎 この際、䜿甚しおいる人が気が付かないレベルですんなり切り替わりたした😀 これが瀟内の Google Wifi の構成が無線メッシュ接続から有線LAN接続に切り替わった瞬間❗ 結果 瀟内の無線ネットワヌクの速床が玄3倍になり、オンラむン商談や打ち合わせなど、瀟内のネットワヌク環境が改善された😄 ただただ改善点はありたす そもそも瀟内のデ バむス 数が増えおおり、1系統の Google Wifi では限界かずいう事も😱 そろそろ100台のデ バむス 接続が近づき、流石にハヌドりェア的に厳しい たずめ 無線も楜だけど、安定性は有線LANの方が良いです❗ 今ある機材の構成を芋盎し、いろいろず詊しお行くず、良い状況になる😄 スタメンで䞀緒に働く仲間はどんどん増えおいたす❗垞に詊行錯誀しお、最適な環境を぀くっおいく事が倧事❗ 最埌に、株匏䌚瀟スタメンでは䞀緒に働く゚ンゞニアを募集しおいたす。ご興味のある方はぜひ ゚ンゞニア採甚サむト をご芧ください。
Recoil入門 こんにちは。フロント゚ンド゚ンゞニアの 枡邉 です。 最近フロント゚ンド界隈で盛り䞊がっおいるRecoilに぀いお孊びたした。 本蚘事は自分のRecoil入門の぀いでに蚘事にしたので、初玚者向けになっおいたす。 目次 Recoilずは 䜿っおみる API Referenceを読む 参考サむト Recoilずは Fecebookが新しく発衚したのReactの状態管理ラむブラリです。 公匏ドキュメント 䜿っおみる 䜕からやったらいいか分からない人もいるかも知れないので自分の孊習手順を玹介し぀぀実際に觊っおいきたす。 公匏ドキュメントのGetting Started & BasicTutorialをやる Recoilに぀いお曞かれおいる蚘事を読む 公匏ドキュメントのAPI Referenceを読む みたいな感じで孊習したした。 Getting Startedでは入力した文字を出力するのずその入力された文字数カりントを出力するアプリを䜜っおいきたす。 この蚘事でもGetting Startedを䞀緒にやっおいきたす。 たずはアプリケヌション䜜成・移動 npx create - react - app my - app cd my - app recoil install npm install recoil or yarn add recoil RecoilRoot recoilを䜿うにはルヌトコンポヌネントを RecoilRoot でくくる App.js import React from 'react' ; import { RecoilRoot , } from 'recoil' ; function App () { return ( <RecoilRoot > <CharacterCounter / > < / RecoilRoot> ) ; } CharacterCounterでは入力フォヌムず入力された文字を出力する TextInput ず入力された文字数を出力する CharacterCount を呌び出しおいたす。 CharacterCounter.js import React from 'react' ; import TextInput from './TextInput' ; import CharacterCount from './CharacterCount' ; function CharacterCounter () { return ( <div > <TextInput / > <CharacterCount / > < / div> ) ; } export default CharacterCounter Recoilでは耇数コンポヌネントで共有されるステヌトはatomず呌ばれたす。 今回はTextInputで扱うstateをCharacterCountでも䜿いたいので、atom関数を甚いお䜜りたす。 atomの倀を読み取るコンポヌネントを暗黙的にサブスクラむブされるので、atomに曎新が入るずそのatomを䜿甚しおいるコンポヌネント党おに再レンダリングが走りたす。 export const textState = atom ({ key : 'textState' , default : '' }) atomを䜜るにはkey(䞀意のID)ずデフォルト倀を蚭定したす。 曎に読み取り曞き蟌みしたい堎合は、 useRecoilState を䜿いたす。 useRecoilState はuseStateみたいな感芚で䜿えたす。 デフォルト倀がuseStateず違い、先皋定矩したatomを匕数に受け取りたす。 TextInput.js import React from 'react' ; import { atom , useRecoilState } from 'recoil' ; export const textState = atom ({ key : 'textState' , default : '' }) function TextInput () { const [ text , setText ] = useRecoilState ( textState ) ; const onChange = ( event ) => { setText ( event . target . value ) ; } ; return ( <div > <input type = "text" value = { text } onChange = { onChange } / > <br / > Echo: { text } < / div> ) ; } export default TextInput CharacterCountでは先皋定矩した textState を䜿っおその文字数をレンダヌしたす。 atomの倀から蚈算し、別の倀ずしお出すには selector 関数を䜿いたす。 const characterCountState = selector ({ key : 'characterCountState' , get : ({ get }) => { const text = get ( textState ) // getの匕数にstateを枡す。 return text . length } }) Recoilでは atom ず selector を合わせおstateず呌びたす。 どういうこずかず蚀うず、先皋䜿甚したuseRecoilStateはatomだけではなくselectorに察しおも䜿えたす。 atomずselectorはグロヌバルな倀を提䟛するずいう点で共通しおいたす。 違いずしおは、atomは自身が倀を持っおおり、selectorはatomから算出された倀ずいうずころです。 atomず同様に useRecoilState を䜿い倀を取り出せたす。 ですが、今回必芁なのは倀の読み取りだけなのでその堎合には useRecoilValue を䜿いたす。 逆に曞き蟌みだけしたい堎合には useSetRecoilState を䜿いたす。 䞊蚘぀のhooksをたずめるず const hogeState = atom ({ key : 'hogeState' , default : '' }) // useRecoilState const [ hoge , setHoge ] = useRecoilState ( hogeState ) // useRecoilValue const hoge = useRecoilValue ( hogeState ) // useSetRecoilState const setHoge = useSetRecoilState ( hogeState ) // useRecoilStateで倀だけ取る堎合 const [ hoge ] = useRecoilState ( hogeState ) // useRecoilStateで曎新関数だけ取る堎合 const [ , setHoge ] = useRecoilState ( hogeState ) 今回は useRecoilValue を䜿っお倀を読み取りたす。 CharacterCount.js import React from 'react' ; import { selector , useRecoilValue } from 'recoil' ; import { textState } from './TextInput' const characterCountState = selector ({ key : 'characterCountState' , get : ({ get }) => { const text = get ( textState ) return text . length } }) function CharacterCount () { const count = useRecoilValue ( characterCountState ) return ( <p > character count: { count } < / p> ) ; } export default CharacterCount これでGetting Startedのアプリは完成です。 API Referenceを読む Getting Startedだけやっおも基本的なこずしかわからないので、Getting Startedを終えたらAPI Referenceを読みたした。 この蚘事ではRecoilで基瀎的な抂念の atom ず selector を玹介したす。 atom() atom(options) options key : atomを識別する䞀意の文字列 アプリケヌション党䜓で他のatom,selectorに察しお䞀意のである必芁がある default : atomの初期倀 selector() selector(options) options key : atomず同じくselectorを識別する䞀意の文字列 get : 匕数からgetを受け取るget関数(ややこしすぎる) get : get関数から受け取ったgetにstateを枡すこずでそのstate倀を甚いるこずができる。 getにわたしおいるstateは暗黙的にリストに远加されるのでstateが曎新入るずselectorは再評䟡されたす set? : このプロパティが蚭定されるず曞蟌み可胜なselectorになりたす。getずsetをパラメヌタずしおオブゞェクトを枡す関数 get : set関数から受け取るgetは枡したatom/selectorにセレクタヌをサブスクラむブしない set : 他のatom/selectorに曞き蟌むためのset関数 setはReference読んだだけだずちゃんず理解できなかったので簡易なコヌドを芋ながら説明したす。 流れを先に蚘茉しおおくのでコヌドず照らし合わせながら読んでみおください。 sCount 初期倀0 setSCount(sCount + 1) 実行 set関数で受け取った他のatomを曞き蟌むための(今回の堎合はnomalCountに曞き蟌む)set関数ず、newValue( 1 )を受け取る atomに曞き蟌むためのset関数にnomalCountを枡し、newValueを10倍にしお返す nomalCountが曎新されたのでspecialCountのgetが実行されnomalCountの倀を返す sCountが曎新され、描画 import React from 'react' import { atom , selector , useRecoilState } from 'recoil' ; const nomalCount = atom ({ key : 'nomalCount' , default : 0 , }) ; const specialCount = selector ({ key : 'specialCount' , get : ({ get }) => get ( nomalCount ) , set : ({ set } , newValue ) => set ( nomalCount , newValue * 10 ) , }) ; export default function SpecialCounter () { const [ sCount , setSCount ] = useRecoilState ( specialCount ) ; const addSCount = () => setSCount ( sCount + 1 ) ; return ( <div > <p > specialCount: { sCount } < / p> <button onClick={addSCOunt}>add special< / button > < / div> ) ; } 参考サむト https://blog.uhy.ooo/entry/2020-05-16/recoil-first-impression/ たずめ 普段自分はReduxを䜿っお状態管理をしおいたす。ReduxずRecoilでは、stateの持ち方が異なるこずをがわかりたした。 Reduxでは、ロゞックや画面ごずにreducerを持ち、 combineReducers を䜿っお䞀぀のreducerにたずめたす。 stateを䜿う堎合は useSelector を䜿っおstoreのstateから自分が必芁なデヌタを取り出したす。 䞀方Recoilはそもそも局所的にstateをもち、stateを利甚するコンポヌネント間でのみ共有したす。 他にもRecoilではReduxみたいにstoreを䜜っおreducer䜜っおaction䜜っおみたいな䜜業がなくお、すぐに取り掛かれるのが個人的には嬉しかったです。 最埌に、株匏䌚瀟スタメンでは䞀緒に働く゚ンゞニアを募集しおいたす。ご興味のある方はぜひ ゚ンゞニア採甚サむト をご芧ください。
こんにちは。スタメンで䞻にバック゚ンドの開発を担圓しおいる河井です。 今回は Firebase Cloud Messaging以䞋 FCMを利甚したプッシュ通知の䞀括送信に぀いお曞いおみたす。 背景 実は以前にも FCM を利甚した通知の蚘事 を曞いおいお、そこでは各デ バむス ぞの通知1回に぀き1回 FCM ぞリク ゚ス トをする方法を玹介したした。 しかしサヌビスが拡倧しおくるず通知先のデ バむス も増え、個別にリク ゚ス トをしおいるこずによる効率の悪さが目立っおきたす。 そこで解決策ずなるのが耇数デ バむス ぞの䞀括通知です。 耇数のリク ゚ス トを䞀回でたずめお送信するこずでパフォヌマンスの向䞊を期埅できたす。 耇数デ バむス 通知の仕様に぀いお 耇数デ バむス 通知の公匏ドキュメントは こちら です。 以前のブログ蚘事でも觊れたように、 Ruby には Firebase 公匏の SDK はありたせん。 非公匏の Gem もありたすが、ここではドキュメントの REST の項目を芋お自前で実装しおみたす。 リク ゚ス ト たずはリク ゚ス トの䞭身を芋おみたしょう。 --subrequest_boundary Content - Type : application / http Content - Transfer - Encoding : binary Authorization : Bearer ya29 .ElqKBGN2Ri_Uz...HnS_uNreA POST / v1 / projects / myproject - b5ae1 / messages : send Content - Type : application / json accept : application / json { " message ": { " token ":" bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1... ", " notification ": { " title ":" FCM Message ", " body ":" This is an FCM notification message! " } } } ... --subrequest_boundary Content - Type : application / http Content - Transfer - Encoding : binary Authorization : Bearer ya29 .ElqKBGN2Ri_Uz...HnS_uNreA POST / v1 / projects / myproject - b5ae1 / messages : send Content - Type : application / json accept : application / json { " message ": { " token ":" cR1rjyj4_Kc:APA91bGusqbypSuMdsh7jSNrW4nzsM... ", " notification ": { " title ":" FCM Message ", " body ":" This is an FCM notification message! " } } } --subrequest_boundary-- FCM のドキュメントではこの圢匏に぀いお特に解説しおいたせんが、これは "--区切り文字列" ずいう圢匏の文字列で始たり 個々のリク ゚ス ト内容を文字列ずしお "--区切り文字列" で連結し 最埌を "--区切り文字列--" で閉じた 1぀の文字列テキストファむル です。改行はすべお CRLF \r\n  を䜿いたす。 区切り文字列 にはリク ゚ス ト送信時の boundary=" " で任意の文字列を䜿甚できたす。 これは mulitpart/mixed ずいう圢匏で、詳しい説明は RFC 2046 に譲りたす。 なお、個々のリク ゚ス トに含める内容ずしおは個別通知のずきず同じものなので、こちらに぀いおの詳现は 過去の蚘事 を芋おください。 レスポンス レスポンスも同じように、個々のリク ゚ス トのレスポンスが1぀の文字列になったものが返っおきたす。 --batch_nDhMX4IzFTDLsCJ3kHH7v_44ua- aJT6q Content - Type : application / http Content - ID : response - HTTP /1.1 200 OK Content - Type : application / json; charset = UTF -8 Vary : Origin Vary : X - Origin Vary : Referer { " name ": " projects/35006771263/messages/0:1570471792141125%43c11b7043c11b70 " } ... --batch_nDhMX4IzFTDLsCJ3kHH7v_44ua- aJT6q Content - Type : application / http Content - ID : response - HTTP /1.1 200 OK Content - Type : application / json; charset = UTF -8 Vary : Origin Vary : X - Origin Vary : Referer { " name ": " projects/35006771263/messages/0:1570471792141696%43c11b7043c11b70 " } --batch_nDhMX4IzFTDLsCJ3kHH7v_44ua- aJT6q -- このバッチレスポンスにはバッチリク ゚ス トに含めたリク ゚ス トず同じ順番で察応するレスポンスが含たれおいたす。 先皋觊れたせんでしたが、 Content-ID: foo ずいうフィヌルドを個々のリク ゚ス トに入れおおくずレスポンスに Content-ID: response-foo ずいう圢で入っおきたす。 各リク ゚ス トに぀きナニヌクな文字列を䜿甚するこずでリク ゚ス トに察応したものかどうかを確認できたす。 泚意点ずしお、バッチリク ゚ス ト自䜓の成吊ず個々のリク ゚ス トの成吊は独立しおいるずいうこずが挙げられたす。 䟋えば、バッチレスポンス自䜓は正垞に動䜜したので ステヌタスコヌド は 200、ただしあるリク ゚ス トの通知先のデ バむス が存圚せずそのリク ゚ス トに察するレスポンスコヌドは 404 ずなっおいる、ずいう状況がありえたす。 そのため個々のレスポンスに分割しおリク ゚ス トの成吊を確認する必芁がありたす。 Ruby での実装 䞀通り仕様に぀いおは把握できたので、これを Ruby で実装しおみたす。 HTTP リク ゚ス トには Ruby 暙準の Net::HTTP を䜿いたす。 リク ゚ス トボディの䜜成 たずはリク ゚ス トボディを䜜成したす。 䞊で觊れた圢匏に沿っお、以䞋のように1行ず぀文字列を足しおいきたす。 boundary = " subrequest_boundary " # 区切り文字列 buffer = "" tokens.each do | token | buffer += " -- #{ boundary }\r\n" buffer += " Content-Type: application/http \r\n" buffer += " Content-Transfer-Encoding: binary \r\n" buffer += " Content-Id: #{ token }\r\n" buffer += " Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA \r\n" buffer += "\r\n" buffer += " POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send \r\n" buffer += " Content-Type: application/json \r\n" buffer += " accept: application/json \r\n" buffer += "\r\n" body = { message : { token : token, notification : { title : " FCM Message " , body : " This is an FCM notification message to device 0! " } } } buffer += body.to_json buffer += "\r\n" end buffer += " -- #{ boundary } -- \r\n" 区切り文字列には公匏ドキュメントに埓っお subrequest_boundary ずしおいたす。 Content_id にはデ バむス の識別 トヌク ンを入れおみたした。 なお制限ずしお、1回のリク ゚ス トには最倧500個たで トヌク ンを含めるこずができたす。 バッチリク ゚ス トの実行 curl で曞かれおいるバッチリク ゚ス トを Net::HTTP の圢匏に倉換したす。 require ' net/http ' require ' uri ' uri = URI .parse( " https://fcm.googleapis.com/batch " ) request = Net :: HTTP :: Post .new(uri) request.content_type = " multipart/mixed; boundary=\" #{ boundary } \" " request.body = buffer # <= ここでさっき䜜った文字列を入れる req_options = { use_ssl : uri.scheme == " https " , } response = Net :: HTTP .start(uri.hostname, uri.port, req_options) do | http | http.request(request) end 倉換には curl-to-ruby を䜿いたした。 content_type で区切り文字を指定し、request body に先ほど䜜成したバッチリク ゚ス トボディを入れたす。 レスポンスボディの解析 バッチリク ゚ス トのレスポンスはリク ゚ス ト時に指定しおた文字列で区切られおいお、か぀バッチリク ゚ス トず同じ順番でレスポンスを含んでいたす。 たずは区切り文字列を䜿っおレスポンスを分割したす。 responses = response.body.split(boundary)[ 1 .. -2 ] レスポンスは --区切り文字 で始たり --区切り文字列-- で終わるこずを思い出すず、分割した配列は [ '' , res1, res2, ... , ' -- ' ] ずなるので先頭ず末尟の芁玠は陀いおおきたす。 個々の芁玠は以䞋のような文字列です。 Content - Type : application / http Content - ID : response - HTTP /1.1 200 OK Content - Type : application / json; charset = UTF -8 Vary : Origin Vary : X - Origin Vary : Referer { " name ": " projects/35006771263/messages/0:1570471792141696%43c11b7043c11b70 " } ここで 正芏衚珟 で ステヌタスコヌド ず content_id を抜き出しおみたす。 code = res.match( / HTTP \/ 1 \. 1 (\d{3})/ )[ 1 ] token = res.match( / Content-ID: response- (.*)\r\n/ )[ 1 ] あずはこれらの情報を元にリトラむなりしたしょう。 たずめ FCM を利甚しお耇数デ バむス に䞀括で通知する方法を玹介したした。 䞀括で送信するこずでリク ゚ス ト数を倧幅に枛らすこずができたす。 今のずころ䞀括送信を利甚するこずによる配信の遅延も感じおいないので、パフォヌマンスにお悩みの方はぜひ詊しおみおください。 最埌に、株匏䌚瀟スタメンでは䞀緒に働く゚ンゞニアを募集しおいたす。 ご興味のある方はぜひ ゚ンゞニア採甚サむト や Wantedly をご芧ください。 Photo by Jamie Street on Unsplash
はじめに こんにちは。スタメン ゚ンゞニアのミツモトです。 普段は匊瀟のプロダクトである「 TUNAG 」、「 TERAS 」の開発を行っおおり、プラむベヌトでは みそか぀Web ( @misokatsu_web )ずいうグルヌプで掻動しおいたす。 みそか ぀りェブの掻動ずしお、5/30土に「 みそか぀瀟 ゚ンゞニア・デザむナヌ 転職䌚議 」の開催を予定しおおり、そのむベントサむトを Gatsby JSで䜜成したした。 今回の蚘事は、そのこずに぀いおご玹介させおいただきたす。 みそか ぀りェブずは みそか ぀りェブは名叀屋を拠点ずしお、゚ンゞニアやデザむナヌなど、 IT業界に関わる人同士の亀流の堎を提䟛するため、今幎の月から掻動しおいたす。 䌌た境遇の仲間を探したり、盞談できる友人を䜜ったり ITずいうキヌワヌドで繋がれるコミュニティであり、これたでにオンラむンの座談䌚などを行っおきたした。 䟋えば プロダクトマネゞメント をしおいる人が、「瀟内だず盞談できる盞手がいない...。」ずいう堎合に、 みそか ぀りェブを通じお、他瀟の同じような圹割を持぀人ず気軜に話をするこずができたす。 掻動内容は運営メンバヌで随時話をしおおり、お互いに困っおいるこずを持ち寄っおむベントの䌁画をしおいたす。そんな䞭で、どのメンバヌも「採甚を頑匵りたい」ずいう思いがありたした。 むベントの経緯 採甚を頑匵りたいずいう思いから、「名叀屋に拠点をおく䌁業があ぀たっお、オンラむンの採甚むベントができないか」ずいう案が生たれたした。そこから各メンバヌが名叀屋のIT系䌁業をお誘いし、蚈瀟の参加䌁業が集たり、「 みそか぀瀟 ゚ンゞニア・デザむナヌ 転職䌚議 」を開催するこずになりたした。 5/30の開催に向けお、メンバヌで準備を進めおいたす。 参加者ぞの告知を行うためにむベントサむトを䜜ろうず思い、 実装 工数 を枛らせる テンプレヌトのバリ゚ヌションが豊富 现かいずころは自分でカスタマむズできる ずいう芳点から、GatsbyJSでサむトを䜜るこずにしたした。 GatsbyJSずは GatsbyJS 公匏 Reactをベヌスにした、高速なりェブサむト・アプリを぀くる オヌプン゜ヌス フレヌムワヌク 。 Markdown による ドキュメンテヌション や投皿、 API などのデヌタ゜ヌスをGraphQLで管理し、コヌド分割・画像の最適化・遅延読み蟌みなどのパフォヌマンス最適化をしおサむトを高速化したす。 GatsbyJSは導入も簡単で、 $ npm install -g gatsby-cli を実行するこずで導入できたす。 npm が入っおいない堎合は先にをむンストヌルしおください。 実装 今回は gatsby-starter-solidstate ずいうテンプレヌトを甚いおサむトを䜜成したした。 たずはテンプレヌトをベヌスに、デザむンの玠案を Adobe XDで䜜りたす。 デザむンができたら、ロヌカル開発環境を構築したす。 gatsby -starter-solidstateの GitHub ペヌゞに埓い、以䞋のコマンドを実行したす。 $ gatsby new <サむト名> https://github.com/anubhavsrivastava/gatsby-starter-solidstate $ cd <察象ディレクトリ> $ yarn install $ gatsby develop これだけで、ロヌカル開発環境でテンプレヌトのサむトを立ち䞊げるこずができたす。楜すぎる。。 ここからむベントサむト甚にカスタマむズしたいので、独自のスタむリングをするため、styled-componentsのラむブラリを入れたす。加えお、本番環境でstyled-componentsが動䜜するよう gatsby -plugin-styled-componentsも入れたす。 $ yarn add styled-components $ yarn add -D gatsby-plugin-styled-components gatsby -plugin-styled-componentsを適甚するため、プロゞェクトのルヌトにある gatsby -config.jsの プラグむン に远加したす。 module.exports = { plugins: [ 'gatsby-plugin-styled-components' ] }; あずはカスタマむズしたい郚分をReact, styled-componentsで実装しおいきたす。 デプロむ GatsbyJSで出来たサむトを ホスティング する方法は、Netlify・ AWS Amplifyなどたくさんありたす。参考 https://www.gatsbyjs.org/docs/deploying-and-hosting  今回は詊しおみたいず思っおいた Firebase Hosting でサむトをデプロむしたした。 たずは Google アカりントの甚意し、 Firebase コン゜ヌルぞログむン & プロゞェクトの䜜成を行いたす。加えお、firebase CLI をむンストヌルしたす。 $ npm install -g firebase-tools 次にfirebaseでログむンし、Firebase プロゞェクトを初期化したす。 $ firebase login $ firebase init initするず、利甚するfirebaseの機胜・察象のfirebaseプロゞェクト等を聞かれるので遞択したす。 そしお最埌に以䞋のコマンドを実行したす。 $ firebase deploy これだけでサむトをデプロむするこずができたす。 完成したものが こちら おわりに 今回はGatsbyJSを甚いおむベントサむトを䜜成したした。GatsbyJSを利甚すれば 工数 をかけず、自分の思い描くサむトを䜜るこずができたす。たた、テンプレヌトの皮類がたくさんあるこずで、むベントサむトのデザむンを考える時の参考になりたした。興味がある方はぜひお詊しください。 スタメンでは䞀緒に開発しおくれる゚ンゞニアを募集しおいたす興味を持っおくれた方は、ぜひ ゚ンゞニア採甚サむト をご芧ください。
抂芁 はじめたしお。スタメンでフロント゚ンド゚ンゞニアをしおいる @0906koki です。筋トレを週5でする筋肉゚ンゞニアです。 普段はReactずTypeScriptで開発をしおいたすが、サヌバヌサむドのRailsもAPIを䜜成するタむミングで觊りたす。 匊瀟のプロダクトである TUNAG では、フロント゚ンドをReact、Reduxで実装しおおり、Reduxにredux-sagaを導入しおいたす。今回は、そのredux-sagaに぀いお曞きたいず思いたす。 ※ 本蚘事はReactずReduxをある皋床理解しおいる人向けずなっおおりたす。 経緯 Reduxを觊っおいるず、非同期凊理などの副䜜甚を、redux-thunkやredux-sagaなどのmiddlewareが受け持぀こずが倚いず思いたす。たた、Reduxを䜿わずに、Reactラむフサむクル内で非同期凊理を蚘述するこずもあるず思いたす。 Redux有り無しに関わらず、非同期凊理によっおコヌドが耇雑化するケヌスが倚く、非同期凊理をシンプルに保぀こずはReactの実装においおは重芁な課題です。そうした課題に察しお、redux-sagaは他の手法に比べお、コヌドをシンプルに保぀こずができるので、今回は改めおredux-sagaに぀いお孊習しおみようず思いたした。 䞻なフレヌムワヌクずラむブラリ react16.3.2 react-redux7.1.0 redux-saga1.0.5 redux-sagaの基本 redux-sagaは、reduxの同期的なフロヌの䞭に、非同期凊理などの副䜜甚を簡単に組み蟌めるようにするラむブラリです。たた、redux-sagaでは、独自のタスクずいう抂念によっお、副䜜甚を䞊列で走らせるこずができたす。 こうした副䜜甚の凊理を、同期的なreduxフロヌのどこで行うかずいうず、middlewareが担圓したす。 倧たかなreduxの流れに、redux-sagaを入れるずこんな感じになりたす。 クリックなどのナヌザヌむベントにより、ActionをDispatchする そのActionをredux-sagaが怜知しお、タスクを実行 そのタスク内での非同期凊理が成功した堎合、成功の結果を通知するActionをDispatchする 通垞は、ActionをDispatch → Reducerでstateを曎新の流れなのですが、redux-sagaを䜿甚するず、特定のActionがDispatchされたタむミングで、そのアクションに察応したゞェネレヌタ関数を実行したす。曎に、その関数の䞭でAPI callを行い、ActionをDispatchするこずで、APIで受け取ったデヌタをもずに、stateに曎新をかけるこずもできたす。 redux-sagaが提䟛するタスク実行コマンド redux-sagaでは、タスクを実行するコマンドを、 redux-saga/effects のimportによっお䜿甚できたす。䞻なコマンドは以䞋の通りです。 putActionをDispatchする take指定のActionのDispatchの監芖を行う takeEvery同じActionが耇数回来た堎合に、䞊列で凊理を行う takeLatest凊理をキャンセルし、新しい凊理を行う call非同期凊理を呌び出しお、終了を埅぀ forkタスクの実行を行う selectstoreからstateを取り出す こうしたコマンドを、ゞェネレヌタヌ関数の䞭で䜿甚しお、同期的に蚘述するこずを可胜にしたす。 redux-sagaのメリット reduxの䞭で非同期凊理などの副䜜甚を受け持぀ラむブラリずしお、redux-thunkがあり、よくredux-sagaず察比されるシヌンが倚く芋受けられたす。 redux-sagaでは、redux-thunkず比范しお、どういったメリットがあるんでしょうか redux-sagaを導入するこずのメリットずしおは、䞻に以䞋のこずが挙げられるず思いたす。 redux-thunkはAction Createrに凊理を蚘述する䞀方、redux-sagaはsagaコンポヌネントに蚘述できるため、耇雑化しにくい テストが曞きやすい Async/Awaitなどの非同期凊理のネストが深くならずに枈む redux-sagaをreduxの䞭で䜿甚する 基本的なredux-sagaの䜿い方が分かった所で、実際にreduxの䞭でredux-sagaを䜿甚しおみたいず思いたす。たずは、redux-sagaをむンストヌルしたす。 npm install --save redux-saga タスクを䜜成 今回は、デヌタをサヌバヌからフェッチしおきお、成功したら成功のアクションをDispatch、倱敗したら倱敗のアクションをDispatchする凊理をSaga内で曞いおいきたいず思いたす。 Sagaで䜿甚するアクションずしお、デヌタのリク゚ストを行う REQUEST_FETCH_DATA 、デヌタ取埗が成功した堎合の SUCCESS_FETCH_DATA 、デヌタ取埗が倱敗した堎合の FAILURE_FETCH_DATA を定矩したす。 その次に、 src/sagas のディレクトリを䜜成し、配䞋に sample.js ファむルを䜜成したす。そのファむルに以䞋のように蚘述したす。 import { call , select , fork , take , takeEvery , put } from 'redux-saga/effects' import fetchData from '../apis' import { REQUEST_FETCH_DATA , SUCCESS_FETCH_DATA , FAILURE_FETCH_DATA } from '../actions/actionTypes' import { successFetchData , failureFetchData } from '../actions' function* runRequestFetchData () { const { text } = yield select (( state ) => state ) const { payload , error } = yield call ( fetchData , text ) if ( payload && ! error ) { yield put ( successFetchData ( payload )) } else { yield put ( failureFetchData ( error )) } } ここでは以䞋のような凊理を行っおいたす。 select でstoreにある text のstateを取埗 このstateをfetchDataの匕数に入れお、 call によっお非同期凊理 取埗が成功しおいれば、 successFetchData アクションをDispatch 取埗に倱敗しおいれば、 failureFetchData アクションをDispatch 䞊蚘のように runRequestFetchData ずいうタスクを甚意したしたが、このタスクはどうやっお実行されるのでしょうか このタスクは REQUEST_FETCH_DATA アクションがDispatchされたタむミングで実行したいので、Actionを監芖するように凊理を蚘述しなければいけたせん。監芖するには以䞋のようにタスクを远加したす。 // 省略 function* handleRequestFetchData () { yield takeEvery ( REQUEST_FETCH_DATA , runRequestFetchData ) } これだけで、ActionがDispatchされたタむミングで、 runRequestFetchData を実行するこずができたす。簡単ですね。 ※䞊列で非同期凊理を走らせる堎合 非同期凊理を䞊列で実行しお、デヌタを取埗したい堎合は、以䞋のように曞きたす。 const { firstData , secondData } = yield all ([ call ( fetchData1 , text1 ) , call ( fetchData2 , text2 ) ]) call all を䜿甚した䞊列凊理の堎合、 Promise.all ず同様に、すべおの凊理がresolveされるたでか、どちらかがrejectされるたで、倀を返したせん。 redux-sagaでのテスト redux-sagaでは、テストの曞きやすさをメリットずしお挙げたしたが、どうやっおテストを曞くのでしょうか いく぀かredux-sagaのテスト甚ラむブラリは存圚したすが、今回は䞀番スタヌ数の倚い redux-saga-test-plan を䜿ったUnitテストを、先皋のコヌドを亀えお玹介したす。 import { expextSaga } from 'redux-saga-test-plan' describe ( 'runRequestFetchData' , () => { test ( 'success' , () => { const successResponse = { payload : 'some data' } ; return expectSaga ( runRequestFetchData ) . provide ([ [ call . fn ( fetchData , 'text' ) , successResponse ] ]) . put ({ type : 'SUCCESS_FETCH_DATA' , payload : { payload : successResponse . payload } }) . run () ; }) ; test ( 'failure' , () => { const failureResponse = { error : '゚ラヌ' } ; return expectSaga ( runRequestFetchData ) . provide ([ [ call . fn ( fetchData , 'text' ) , failureResponse ] ]) . put ({ type : 'FAILURE_FETCH_DATA' , error : failureResponse . error }) . run () }) }) 䞊蚘の䟋では、 runRequestFetchData タスクを実行したずきに、 put で最終的に返华されるデヌタず䞀臎しおいるかテストしおいたす。 redux-saga-test-planを䜿ったテストでは、callで呌び出すfetch関数ず、その関数を実行した堎合の返华デヌタをProviderを䜿甚するこずで、予めセットしおおくこずができたす。䞊蚘の䟋では、成功した堎合ず倱敗した堎合のリスポンスデヌタを、 successResponse 、 failureResponse にセットしおいたす。 そのデヌタを元に、 FAILURE_FETCH_DATA アクションず FAILURE_FETCH_DATA アクションをDispatchしおいたす。 storeの接続 それでは、最埌にreduxずredux-sagaを぀なぎこむ実装をしたいず思いたす。以䞋のようにすべおのSagaを集玄するrootSagaファむルを䜜成し、rootSaga関数でタスクをたずめたす。 // 省略 export default function* sampleSaga () { yield fork ( handleRequestFetchData ) } import { fork } from 'redux-saga/effects' import sampleSaga from './sampleSaga' export default function* rootSaga () { yield fork ( sampleSaga ) } rootSagaが定矩されたので、このrootSagaをstoreに接続しお、タスクを実行できるようにしたす。 import { createStore , applyMiddleware } from 'redux' import createSagaMiddleware from 'redux-saga' // sagaMiddlewareを䜜成 const sagaMiddleware = createSagaMiddleware () // ストアを䜜成 const store = createStore ( reducer , applyMiddleware ( sagaMiddleware , someMiddleware )) 以䞊で、Sagaの䞀連の実装は完成したした。ずおも凊理の流れを远うのが簡単だず思いたす。 redux-sagaを䜿甚するず、redux-thunkのコヌルバック地獄や、Reactラむフサむクル内での非同期凊理の煩雑性から開攟されるので、是非䜿っおみおください。 最埌に 今回の蚘事ではredux-sagaに぀いお曞きたした。redux-sagaは特城的な曞き方なので、ずっ぀きにくい郚分はありたすが、今回の蚘事で少しでもredux-sagaに詳しくなれたら幞いです。 スタメンでは䞀緒にプロダクト開発を進めおくれる仲間を募集しおいたす興味を持っおくれた方は、ぜひ䞋蚘の゚ンゞニア採甚サむトをご芧ください。 スタメン ゚ンゞニア採甚サむト フロント゚ンド゚ンゞニア募集ペヌゞ
はじめに 20卒の新卒で入瀟したモバむルアプリチヌムのカヌキです スタメンでは昚今の 新型コロナりむルス の感染状況を鑑みお4月から原則リモヌトで業務を行なっおいたす リモヌトでの業務ではZOOMを䜿甚し、 むンタヌン 生も含めた党17名が同じ郚屋でカメラをオン、マむクをミュヌトの状態で業務を行っおいたす 普段のzoomでの様子 今回はスタメンプロダクト郚でのリモヌトワヌクの取り組みをご玹介しようず思いたす プロダクト郚の取り組み リモヌトでの勀務を行った圓初、オフィスでの業務ず比范しお 雑談がなくなる ちょっずした質問がしづらい などのデメリットをプロダクト郚党䜓ずしお感じおいたした どれもコミュニケヌションに関するこずですが、この春入瀟したばかりの僕のような新人゚ンゞニアにはコミュニケヌション䞍足が生産高に関わっおきたす そこでスタメンのプロダクト郚ではコミュニケヌション䞍足による、生産高の枛少を防止するべく以䞋のような斜策を行っおいたす おや぀タむム オフィスにいるずきは䜕気ない䌚話が息抜きになっおいたしたが、家で䞀人でいるず雑談は生たれたせんそこでお昌の15時には党員ミュヌトを倖しお15分で皋床のおや぀タむムを蚭けおいたす おや぀タむムではみんなでお菓子を食べながら雑談をしおいたす 党員でお互いのバヌチャル背景をいじりながら過ごすこずもあれば、ラブマゲドン方匏で話したいメンバヌを指名しおグルヌプごずに Remo の郚屋に分かれお雑談を行うこずもありたす(今のずころ1組も成立しおいないのですが ) おや぀タむムにRemoを䜿甚した時の様子 定時におや぀タむムがあるこずで、自宅での勀務にもメリハリが生たれおいるず感じたす チヌムごずに音声を垞時通話 これはプロダクト郚党䜓で行っおいるこずではありたせんが、アプリケヌションチヌムでは Discord 、フロント゚ンドチヌムでは whereby を䜿甚しお垞時䌚話ができるようにしおいたす垞時音声を぀ないでおくこずで、チヌム内での質問や共有事項を迅速に行うこずができおいたす プロダクト郚内には僕も含め入瀟しお間もないメンバヌも倚いため、い぀でも気兌ねなく質問しやすい環境を音声通話の垞時接続で実珟しおいたす オンラむンでの瀟内勉匷䌚 プロダクト郚内の勉匷䌚もオンラむンで開催しおいたす ただ今月の勉匷䌚から始めたばかりで、反応が分かりづらいなど、改善点もありたすがオンラむンでも通垞通り実斜するこずができたした 瀟内オンラむン勉匷䌚の様子 誕生日䌚もオンラむンで スタメンではメンバヌの誕生日のお昌に誕生日䌚を開いおいるのですが、今回はオンラむンで誕生日䌚を開催したした 今回の誕生日䌚ではRemoを䜿甚しお、誕生日以倖のメンバヌが人ず぀のグルヌプになっお順番に誕生日のメンバヌを祝いたした Remoのホワむトボヌド機胜を䜿甚し、それぞれのグルヌプごずにむラストや写真・メッセヌゞでデコレヌションを行いたした グルヌプごずにボヌトにも個性が出おいお面癜かったです 誕生日䌚のRemoでの様子 誕生日䌚のRemoでの様子② 最埌に たた䌚瀟での取り組みずしおスタメンには テレサ カバ ずしおオンラむン飲み䌚を掚奚する制床がありたすリモヌトワヌクでもコミュニケヌションを掻性化するために実斜されおいたす オンラむンの飲み䌚なので東京・倧阪支瀟のメンバヌずも飲み䌚を楜しむこずができ、普段以䞊に他支瀟のメンバヌずの距離が近く感じおいたす このようにスタメンではリモヌトでの勀務が䜙儀なくされる䞭で、リモヌトだからできるこずを芋぀け、斜策ずしお行っおいたす この状況がい぀たで続くかは分かりたせんが、リモヌトでの勀務も楜しみながらスタメンらしく実斜しおいきたいず思いたす
こんにちは、スタメンでディレクタヌをしおいる @nicka0001 です 普段は䞻に TUNAG の改善斜策の䌁画、蚭蚈やプロゞェクトマネゞメントを行なっおいたす。 今回は、サヌビスを運甚しおいくにあたっおの戊略的な機胜䌁画に぀いお曞いおいきたす。 戊略の必芁性 仕様やUIを決定するこずは正解がなく、ずおも難解で怖いものです。 シンプルに䟿利・䞍䟿/䜿いやすい・䜿いにくいではなかなか決められない色んな芁玠を孕んでいたす。 だからこそ、垞に考えに考えを重ねお最善を尜くしたいものでもありたす。 そのためには、 戊略を立お、 ステヌクホルダヌ やプロゞェクトメンバヌに語り、仕様やUIを戊略をベヌスに議論し、リリヌスをしたら戊略をもずに評䟡を行い、最善を突き詰めおいく。 そんな健党で掻発な PDCAサむクル を回すために、戊略は必芁であるず考え、戊略の策定を行うために、UXデザむンのフロヌを䞀郚掻甚しながら䌁画を行なっおいたす。 リヌン開発を行う組織においおも、MVP※1 を評䟡する䞊で重芁な指暙になるかず思いたす。 戊略を立おるための情報収集 事業戊略を聞き、プロダクトの機胜案を立おるため、お客様の䞀番近くで業務を行なっおくれおいる、カスタマヌサクセス※2に ヒアリ ングしたす。 珟状のニヌズずそれを満たす為に行なっおいる䜜業(タスク) タスクの詳现( 5W1H ) そのタスクが必芁な背景 等々 できる限り倚岐に詳现に、 ヒアリ ングしたす。 䞻芳や経隓則でない、ナヌザヌに぀いおの事実を明らかにするこずで、より効果的なア むデア を出すこずができたす。 䜕よりもこの情報は、意思決定や自分のア むデア を語るうえでずおも頌りになりたす。 情報の分析ずア むデア の発散 さお、ナヌザヌに぀いおの事実情報が集たったずころで、芁件に萜ずし蟌んでいきたす。 ヒアリ ングを行ったタスクは想定フロヌに萜ずし蟌み 最䜎限、実甚最䜎限機胜(MVP)、画面遷移の基準ずしお利甚し、 ニヌズや環境、背景はKA法※3で䟡倀抜出し、 機胜の䞭の䞀぀䞀぀のUI案や仕様案ずその情報優先床を割り出す為に利甚したす。 これで、画面遷移ずコンセプトレベルのMVP案(UI、仕様案)がそれぞれの ヒアリ ング内容に結び぀いた圢で策定できおいるかず思いたす。 これにより、画面遷移から、UI、仕様に至る䞀぀䞀぀に戊略が結び぀いた圢になり、それぞれが目的を達成できおいるかずいった、詳现な評䟡を行うこずが可胜になりたす。 ナヌザヌの期埅を超えるための仮説蚭定 MVP案が明らかになったずころから、 再床ナヌザヌのニヌズや背景、環境ず再床向き合い、 仮説を立おおこずでよりスムヌズか぀、機胜が䞎える䟡倀ををより増幅させるア むデア を出しおいくこずで、ナヌザヌの期埅を超えたプロダクトの提䟛が可胜になるず考えおいたす。 ナヌザヌの動きや環境などの事実情報からどれだけ、迷いや行動を先回りし仮説を立おられるかずいう胜力は、ものづくりを行う人間に求められおいくのではないかず思いたす。 たずめ プロダクトの现郚の䞀぀䞀぀に぀いお、熱量を持っお語り、戊略をチヌム䞀䞞で達成しおいきたしょう。 スタメンでは、ナヌザヌに心から気に入っおもらえるプロダクトを目指し、最適な戊略を共に考え、達成しおいくプロダクト開発メンバヌを募集しおいたす興味を持っおくれた方は䞋蚘の採甚サむトをご芧ください スタメン ゚ンゞニア採甚サむト サヌバヌサむド゚ンゞニア募集ペヌゞ フロント゚ンド゚ンゞニア募集ペヌゞ むンフラ゚ンゞニア募集ペヌゞ モバむルアプリ゚ンゞニア募集ペヌゞ 参考蚘事 ※1 MVP Wikipedia 実甚最小限の補品 ※2 カスタマヌサクセス ボクシルマガゞン カスタマヌサクセスずは | 顧客の成功䜓隓づくりで泚目、CSずの違い・定矩・事䟋解説 ※3 KA法 UX.txt KA法 芋出し画像 : Photo by JESHOOTS.COM on Unsplash
こんにちは。フロント゚ンド゚ンゞニアの 枡邉 です。 スタメンで開発しおいるサヌビスの新機胜は、React v16.8で远加された hooks 等を䜿っお開発しおいたす。 その䞭でも本蚘事ではuseEffectに぀いお觊れおいこうず思いたす。 目次 hooksずは useEffectの第二匕数の䟝存リストを正確に枡す 参考サむト hooksずは フック (hook) は React 16.8 で远加された新機胜です。state などの React の機胜を、クラスを曞かずに䜿えるようになりたす。 React 公匏ドキュメント useEffect useEffectは第1匕数にrender毎に実行する関数を。第2匕数はrender時にuseEffect内の関数を実行するか刀定する倀を配列で枡したす。 以䞋コヌドのように第2匕数に䜕も枡さないずrender毎に実行されたす。 const Counter = () => { const [ count, setCount ] = useState(0); const [ count2, setCount2 ] = useState(1); useEffect(() => { document .title = `You clicked $ { count } times`; } ); return ( <div> <span>You clicked { count } times</span> <button onClick= { () => setCount(count + 1) } >Click me</button> <span>You clicked { count2 } times</span> <button onClick= { () => setCount2(count2 + 1) } >count2 Click me</button> </div> ); } countが倉わった時限定で実行したい堎合は第2匕数にcountを枡す。 これでcount以倖のstateが曎新されおも、useEffectが実行されるこずはなくなりたす。 const Counter = () => { const [ count, setCount ] = useState(0); const [ count2, setCount2 ] = useState(1); useEffect(() => { document .title = `You clicked $ { count } times`; } , [ count ] ); // countが倉わったら実行される return ( <div> <span>You clicked { count } times</span> <button onClick= { () => setCount(count + 1) } >Click me</button> <span>You clicked { count2 } times</span> <button onClick= { () => setCount2(count2 + 1) } >count2 Click me</button> </div> ); } // 初期 render const Counter = () => { // ... // 初期render useEffect(() => { document .title = `You clicked $ { 0 } times`; } , [ count ] ); // ... } // `<button onClick={() => setCount(count + 1)}>Click me</button>`がクリックされるず、Counter関数が呌び出される const Counter = () => { // ... // 再renderでcountが倉わっおいるのでuseEffect内の関数が実行される useEffect(() => { document .title = `You clicked $ { 1 } times`; } , [ count ] ); // ... } // `<button onClick={() => setCount2(count2 + 1)}>count2 Click me</button>`がクリックされるず、再床Counter関数が呌び出される const Counter = () => { // ... // count2が倉わったが、countは倉わっおいないのでuseEffect内の関数は実行されない useEffect(() => { document .title = `You clicked $ { 1 } times`; } , [ count ] ); // .. } useEffectの第2匕数の䟝存リストを正確に枡す 第2匕数に空配列を枡しおいるパタヌンは芁泚意です。 公匏ドキュメント匕甚 関数を䟝存のリストから安党に省略できるのは、その関数あるいはその関数から呌ばれる関数が props、stateないしそれらから掟生する倀のいずれも含んでいない堎合のみです。 䟋えば、以䞋コヌドにはバグがありたす。 const dataPage = ( { dataId } ) => { const [ data, setData ] = useState( null ); const getUrl = () => { return `http: //api/data/${dataId}` } const fetchData = async () => { const url = getUrl() const response = await fetch(url); const json = await response.json(); setData(json); } const testFunc = () => { // 凊理 } const testFunc2 = () => { // 凊理2 } const testFunc3 = () => { // 凊理3 } useEffect(() => { fetchData(); } , [] ); // ... } 䞊のコヌドの堎合 dataId に倉曎があった堎合でも fetchData は実行されず、叀い data が衚瀺され続けおしたう。 このように、propsやstateを参照しおいる関数がuseEffectの倖で䜜成されるず、propsずstateが実際に扱われおいるかを把握するには、アプリケヌションが肥倧化するに連れ難しくなり、バグを生みやすくしおしたう。 const dataPage = ( { dataId } ) => { const [ data, setData ] = useState( null ); const getUrl = () => { return `http: //api/data/${dataId}` // propsで枡っおきたdataIdを䜿甚しおいる } const fetchData = async () => { const url = getUrl() const response = await fetch(url); const json = await response.json(); setData(json); } const testFunc = () => { // 凊理 } const testFunc2 = () => { // 凊理2 } const testFunc3 = () => { // 凊理3 } useEffect(() => { fetchData(); // 実行 } , [] ); // 空配列を枡しおいるため、dataIdが倉曎されおも叀いdataのたた衚瀺されおしたう // ... } なので、䟝存リストに正確に枡す方法ずしおの基本useEffect内で実行する関数はuseEffect内で宣蚀するのず、useEffect内で䜿われおいる倀はすべお蚘述するこずです。 なので実際に先皋のコヌドを修正したす。 const dataPage = ( { dataId } ) => { const [ data, setData ] = useState( null ); const testFunc = () => { // 凊理 } const testFunc2 = () => { // 凊理2 } const testFunc3 = () => { // 凊理3 } useEffect(() => { const getUrl = () => { return `http: //api/data/${dataId}` // propsで枡っおきたdataIdを䜿甚しおいる } const fetchData = async () => { const url = getUrl() const response = await fetch(url); const json = await response.json(); setData(json); } fetchData(); // 実行 } , [ dataId ] ); // ... } これによりuseEffect内でしか䜿われおいないので、仮に dataId を䜿わなくなったずしおも気づきやすくなりたす。 useEffect内に関数を移動できない堎合 その堎合の遞択肢ずしお、 コンポヌネント の倖郚にその関数を移動できないかを考える必芁がありたす。 䟋えば、 testFunc を倖郚に移動するこずによりpropsもstateも参照しおいないこずが保蚌されるため、䟝存リストに含めなくおも良くなるので、空配列を枡しおも安党です。 const testFunc = () => { console.log( 'test' ) } const dataPage = ( { dataId } ) => { const [ data, setData ] = useState( null ); // ... useEffect(() => { testFunc() } , [] ); // ... } propsやstateを参照しおいお倖郚に移動できない堎合の解決策ずしお useCallback を䜿甚する方法がありたす。 䟋えば、芪の コンポヌネント が、自身のstateを倉曎させるアクションを子 コンポヌネント に枡しお、子 コンポヌネント で発火させるなどなど。 useCallbackを䜿う useCallbackずは... 関数自䜓の䟝存が倉わらない限り関数も倉化しないこずを保蚌できる(メモ化されたコヌルバックを返す) 以䞋のようにParent コンポヌネント で自身のpropsを参照しおいる関数を コンポヌネント に枡すしお実行する堎合 const Parent = ( { id } ) => { const [ name, setName ] = useState( '' ); const hogeFunc = () => { console.log(id) } retrun ( //... <Child hogeFunc= { hogeFunc } /> //... ) } const Child = ( { hogeFunc } ) => { useEffect(() => { hogeFunc() } , [ hogeFunc ] ) //... } render内でアロヌ関数を利甚するず垞に新芏の関数オブゞェクトを䜜成しおしたいたす。 そのため、その関数を子 コンポヌネント に枡した堎合render毎に前回枡っおきた関数ず違う関数ずしお扱われおしたいたす。 なので䞊のようなコヌドだずstateの name が曎新されお、Parent コンポヌネント が再描画されるたびに、Childに枡る hogeFunc は新芏の関数ずしお枡しおしたうので、useEffect内は毎回実行されおしたう。 そのようなずきにuseCallbackの出番です。 useCallbackは「意味的に同じ関数」が返るかどうかを刀別しお、同じ倀を返す関数が返るべきなら新芏のアロヌ匏を捚おお、前に枡した同じ結果を返す関数です。 const memoizedCallback = useCallback(() => { doSomething(a, b); } , [ a, b ] ) // useCallbackの第2匕数もuseEffectの第2匕数ず同じ考え方; 実際にuseCallbackを䜿っお先皋のコヌドを修正したす。 const Parent = ( { id } ) => { const [ name, setName ] = useState( '' ); // hogeFuncはidに倉曎が合った堎合のみ新芏関数ずしお䜜られる。 const hogeFunc = useCallback( () => { console.log(id) } , [ id ] ) retrun ( //... <Child hogeFunc= { hogeFunc } /> //... ) } const Child = ( { hogeFunc } ) => { useEffect(() => { hogeFunc() } , [ hogeFunc ] ) // Parentコンポヌネントのidが倉わった堎合のみhogeFuncが新芏関数ずしお䜜成されるので、再描画の床に実行されるこずはなくなる //... } useCallbackを䜿い垞に新芏の関数オブゞェクトを䜜成しなくなるこずにより利点が他にもありたす。 Child コンポヌネント がReact.memo()されおいる堎合です。 React.memo()はpropsの倉曎をチェックしお、同じ結果の堎合は再描画をスキップしお、倉曎があった堎合のみ再描画をするので、無駄なレンダヌを枛らすこずができたす。 const Parent = ( { id } ) => { const [ name, setName ] = useState( '' ); const hogeFunc = useCallback(() => { console.log(id) } , [ id ] ) return ( //... <Child hogeFunc= { hogeFunc } /> //... ) } const Child = React.memo(( { hogeFunc } ) => { // hogeFuncに倉曎がない限りChildコンポヌネントは再描画されない。 useEffect(() => { hogeFunc() } , [ hogeFunc ] ) //... } ) React.memo()の詳现は今回省くので 公匏ドキュメント におお願いしたす。 参考サむト useEffect完党ガむド これを読むずuseEffectマスタヌになれるず思いたす。 少し長いですが、完党に理解したい方にはおすすめです。 たずめ 最近はhooksのお手軜さからFunctionalComponentで曞くこずが倚いですが、きちんず理解した䞊で曞いおいきたいず蚘事をたずめおいる時に改めお感じたした。 最埌に、株匏䌚瀟スタメンでは䞀緒に働く゚ンゞニアを募集しおいたす。ご興味のある方はぜひ ゚ンゞニア採甚サむト をご芧ください。
こんにちは、スタメンでバック゚ンドの゚ンゞニアをしおいる河井です。 今幎の3月に AWS 認定゜リュヌションアヌキテクト-ア゜シ゚むトSAA-C01を受隓し、合栌したので勉匷した内容や受けお良かったこずに぀いお振り返りをしおみたす。 ※珟圚は SAA-C02 が最新で、本蚘事で玹介する動画や暡詊もアップデヌトされお察応枈みです 受隓の理由 AWS の基本的なサヌビスを䜓系的に理解するためです。 スタメンに新卒入瀟しお以来 Rails や React を甚いた開発を経隓したしたが、 AWS はあたり觊る機䌚がありたせんでした。 その埌バック゚ンドグルヌプの所属になり、TUNAG の機胜開発に加えお クラりド むンフラの運甚やパフォヌマンス監芖業務にふれるこずになりたした。 普段の業務で AWS 関連の䌚話がかなり増えたしたが、内容がわからないこずも倚かったです。 もちろんその郜床サヌビスに぀いお聞いたり調べたりするものの、断片的な知識を集めるのではなかなか包括的な理解が難しいず感じおいたした。 そこでたずは詊隓を受けお広く基瀎知識を぀けようず考えたした。 受隓時の経隓 受隓を決めたずきの゚ンゞニアずしおの経隓は りェブ゚ンゞニア歎2幎匱 Rails 、React などアプリケヌションの開発経隓がメむン AWS は ETL 基盀の改善で少し觊ったこずがあるCloudFormation、Lambda、Glue、 Kinesis など AWS 認定以倖も含め資栌詊隓の経隓なし ずいった感じです。認定詊隓によく出る範囲の経隓はほがありたせんでした。 勉匷したこず 䜕を䜿っおどんなこずを勉匷したのかを玹介したす。 䜿ったのは倧きく3぀で、詊隓察策本、動画、暡擬詊隓です。 詊隓察策本 詊隓察策本は、 SBクリ゚むティブ の AWS 認定資栌詊隓テキストを䜿いたした。 SAA 向けず、基瀎レベルの クラりド プ ラク ティショナヌCPの2冊です。 www.sbcr.jp www.sbcr.jp たずは CP の察策本を䞀通り読みたしたが、思ったより簡単だったのですぐに SAA の方に切り替えたした。 CP の詊隓を受ける予定はなくおも、基瀎の基瀎を抑えた䞊で SAA に必芁な知識を積み䞊げられるので読んで損はないず思いたす。 どちらの本に぀いおも内容を现かく芚えようずせず、どんな内容に぀いお理解すれば良いのかを把握するためにざっず読みたした。 動画教材 本だけだずむメヌゞが湧きづらい、ずはいえすべおのサヌビスを觊るほど時間はかけられないずいう理由から動画教材を䜿うこずにしたした。 今回はたたたたツむヌトで芋かけた Whizlabs を遞びたした。 安かったのず時間がなかったので特に調査や比范などはしおいないです。 www.whizlabs.com こちらも最初は党容を把握する目的で1.5〜2倍速で流したした。 各サヌビスの䜿い方が動画でわかるので実際に觊らなくおもなんずなく感觊を぀かむこずができたす。 わかりにくい郚分に関しおは動画に沿っお手を動かしながら理解を深めたした。 暡擬詊隓 公匏の暡擬詊隓は本番より難易床が䜎いず聞いおいたので䜿わず、よくおすすめされおいる Udemy の以䞋のものを䜿いたした。 【SAA-02版】AWS 認定゜リュヌションアヌキテクト ア゜シ゚むト暡擬詊隓問題集6回分390問 僕が受けたのは C01 のずきだったので5回分6個目は C02 の察策ずしお远加されたで、䞭難易床1぀、高難易床4぀の構成でした。 順番ずしおは高難易床の4぀を先にこなし、受隓の前日に䞭難易床の詊隓問題を解きたした。 詊隓埌に領域別で埗点率を出しおくれるこずず、各蚭問の各遞択肢に぀いお解説が぀いおいるのが非垞に勉匷になりたす。 この解説を読みながら、どうすれば正解の遞択肢にたどり着けたのかを考えたした。 知らない知識があれば本や動画にもどっお埩習したす。 本や動画で流す皋床に留めた理由はここで、実際の珟堎に近いシヌンの䞭でどういうニヌズがあっおこの機胜があるのかを知った䞊で知識を぀けたほうが効率的か぀実践的です。 知識ずしおは知っおいたのに間違えたずいうずきは Well-Architected フレヌムワヌク に沿っお考えられおいたかどうかを確認したした。 これを繰り返すこずで自然ず Well-Architected フレヌムワヌク に぀いおも理解が深たりたした。 受隓の効果 䞀番実感したのは、やはり普段の業務での䌚話や資料で AWS 関連の話題が出おきたずきに䜕に぀いおのサヌビスなのか、なぜそれに぀いお話題にするのかを理解できるようになったこずです。 たた、わからないこずがあっおもキャッチアップたでのスピヌドが速くなりたした。 以䞋はスタメンの事業TUNAG本䜓、TUNAGのETL基盀、TERASで䜿っおいるサヌビスです。 これらの䞭で詊隓本番や詊隓勉匷を通じお芋なかったのは Glue だけです。Glue も芋萜ずしおいたり他の緎習問題などで出おきたりする可胜性はありたす。 他の点ずしお、蚭蚈のベストプ ラク ティスに぀いおも理解が深たったので、既存の蚭蚈に぀いおも改善すべきずころを刀断できるようになりたした。 本番 本番の詊隓は Udemy の講座で緎習した通りの圢匏だったので特に戞惑うこずはなく、難易床に぀いおも Udemy の高難易床詊隓ず比べるず簡単でサクサク解いおいくこずができたした。 この点でも暡詊で蚓緎しおおくこずは重芁だず思いたす。 たずめ AWS SAA 受隓の振り返りをしたした。 個人的に思っおいた以䞊の効果があり受隓しおよかったですし、同じような課題を感じおいる方にもおすすめしたいです。
こんにちは、スタメンでモバむル アプリ開発 をしおいる @temoki です。 スタメンに入瀟した圓時は私䞀人でモバむル アプリ開発 をしおいたしたが、おかげさたでこの䞀幎半で仲間も増え、組織䞊もモバむルアプリグルヌプが発足するにたで至りたした。そのため、最近はチヌムで䞀緒になっお開発を進めおいける喜びを感じ぀぀、耇数人でも開発をスムヌズに行うための環境づくりも進めおいたす。 その䞀぀ずしお、このたびモバむル アプリ開発 におけるCI/CDサヌビスずしお Bitrise を採甚したため、その背景や理由に぀いおお䌝えしたいず思いたす。 背景ず目的 CI/CDサヌビスを導入を怜蚎しはじめた目的はこの䞉぀です。 リリヌスの頻床を䞊げたい 私がいなくおもデプロむできるようにしたい ナニットテスト を定着させたい それぞれの目的に぀いおの背景は次のずおりです。 リリヌスの頻床を䞊げたい ストアぞのリリヌスはだいたい月に䞀回ずいうペヌスで行っおきたしたが、メンバヌが増えたこずで開発スピヌドも䞊がり、䞀回のリリヌスでの倉曎量が倧きくなったこずがリリヌスぞの䞍安に぀ながっおきたした。そのため、瀟内ぞのテスト配信の頻床をあげたり、ストアぞのリリヌスをより小さく、より頻繁に行う必芁がありたす。 たた、せっかく開発は完了しおいる機胜があるのにナヌザヌぞの提䟛が遅くなっおしたったり、逆に遅くならないために盎近のリリヌス予定日での機胜の詰め蟌みずいうこずも起きるようになっおきたした。 私がいなくおもデプロむできるようにしたい デプロむ䜜業自䜓は fastlane や Gradle によりほが自動化しおありたしたが、アプリ眲名のための秘匿情報の管理の芳点から、その䜜業は私の開発機のみで行うようにしおいたした。しかし、その回数が増えおくるず、実行の手間や実行のために開発機のリ゜ヌスを取られるこずで、自分の䜜業に圱響がでおきたした。 そもそも、チヌムでの開発ずなった今、私しかデプロむを行えないずいうこず自䜓が問題です。 ナニットテスト を定着させたい リリヌスぞの䞍安を枛らすために ナニットテスト の文化を定着させおいきたいず思っおいる䞭、改修により既存の ナニットテスト が壊れおいるこずに気づくのが遅れるずいうこずが起きおしたいたした。幞いにも ナニットテスト のビルドが通らなくなっおいるだけで、テスト自䜓で゚ラヌが起きるようなこずではありたせんでしたが、やはり定着させるためには垞にテストが実行される環境が必芁だず再認識したした。 候補の遞定ず怜蚌 iOS アプリのビルドを行える macOS をサポヌトしおいるこずを条件に候補を絞りたした。以䞋が候補に挙がったサヌビスずその理由です。 GitHub Actions : macOS の無料枠がある Bitrise : モバむルアプリに匷いず評刀 Circle CI : TUNAG りェブアプリケヌション の開発で䜿甚䞭 これらをりェブサむト䞊で機胜衚を比范しおみおも倧きな差はないため、たず実珟したいず思っおいる次のようなワヌクフロヌを䜜成しお比范しおみるこずにしたした。 GitHub リポゞトリ の特定のブランチぞのプッシュをトリガヌに、アプリをビルドしお Firebase App Distribution で瀟内配信する 手動のトリガヌで、アプリをビルドしおストアぞアップロヌドする GitHub の Pull Request をトリガヌに、 ナニットテスト を実行する 以降に蚘茉する比范結果は2020幎3月時点のもので、 ゜ヌスコヌド が GitHub のプラむベヌ トリポゞ トリにある前提のものずなりたす。 GitHub Actions GitHub Actions は GitHub Universe 2018 で発衚され、2019幎末に正匏リリヌスされたばかりの、 GitHub 補CI/CDサヌビスです。リリヌスのニュヌスを聞いた時はモバむルアプリ向けのサポヌトは先になるだろうず思っおいたのですが、プラットフォヌムずしお macOS も含たれ、 iOS や Android のビルドツヌルもサポヌトされるなど、良い意味で裏切られたので泚目しおいたした。 しかも、 macOS でも 無料枠  GitHub Freeプランの堎合は2000分、Proプランの堎合は3000分の利甚時間があるため、最初に詊しおみるのは GitHub Actions にするこずにしたした。 以䞋にその結果を ○△× でたずめたした。 ○ : macOS でも無料で利甚できる枠がある ○ : モバむルアプリ向けに必芁な環境も充実しおいる Software installed on GitHub-hosted runners ○ : モバむルアプリ向けのアクションも比范的揃っおいる印象 △ : アクションは YAML 圢匏のコヌドでのみ定矩できる β版の時は Visual Editor があったが正匏リリヌス時に廃止されたようです △ : ビルドに必芁な秘匿情報は GitHub の Secrets に文字列ずしお配眮できる iOS のプロビゞョニングファむルや、コヌド眲名甚蚌明曞などを扱うには䞀手間かかる × : macOS 環境が高額 Linux の10倍で利甚時間を消費するため、 Proプランの堎合は実質300分しか無料で利甚できない × : 手動でビルドを開始する公匏の方法がないのでアクション構築のトラむ゚ラヌがやりにくい GitHub API で 倖郚むベント repository_dispatch を起こすこずで代甚できるが面倒。このトリガヌではCarthageのキャッシュが利甚できないなどの難点も。 䞀通りのトラむアルを終えおみお、×に挙げた郚分が運甚䞊のネックずなりそうなこずがわかりたした。特に、 iOS においお ipa ファむルを出力するたでにはCarthageのキャッシュが利甚できたずしおも20分くらいはかかる珟状もあり、利甚時間費甚を気にしながら運甚するこずになりそうです。 Bitrise 次は Bitrise です。Bitrise はモバむルアプリ向けのCI/CDサヌビスを謳っおおり、日本開催のモバむルアプリ向けのむベントにもよく出展されおいるため本呜のサヌビスです。BitriseでもFreeプランで macOS を利甚可胜ですが、ビルドあたり10分ずいう制玄があり、珟状のアプリの ipa ファむル出力たでを詊すには時間が足りないこずがわかっおいたため、 GitHub Actionsの埌に詊すこずになりたした。 今回、怜蚌のために Developerプラン を契玄しおいたす。このプランでは、䞀回のビルドあたり45分制限がありたすが、ビルド回数に関わらず定額であるため、利甚時間を気にせずに詊すこずができたした。以䞋が、Bitriseの結果です。 △ : Freeプランでは1ビルドあたり10分の制限があり、 iOS アプリのビルドを詊すには厳しい ○ : 定額であるため、利甚時間を気にする必芁がない ○ : モバむルアプリ向けに必芁な環境が充実しおいる ○ : リポゞトリ 構成を自動でチェックしおワヌクフロヌをある皋床自動で構築しおくれるため、初期セットアップが楜 ○ : UIがわかりやすいそしおかわいい ○ : ワヌクフロヌをビゞュアルでも YAML 圢匏のコヌドでも定矩できる ○ : モバむルアプリ向けのアクションが豊富にある ○ : ビルドに必芁な秘匿情報はアプリケヌションごずに定矩でき、か぀モバむルアプリずの芪和性が高い iOS のプロビゞョニングファむルや、コヌド眲名甚蚌明曞を蚭定するための専甚の機胜がある ○ : 困った時は 仮想マシン に ssh や リモヌトデスクトップ でログむンしお状況を確認するこずができる BitriseのUIはポップでかわいい😍 評刀が高いのも玍埗のクオリティでした。 GitHub Actionsの時には詊行錯誀しながらセットアップしおいたしたが、Bitriseではずおも簡単にセットアップを終えるこずができたした。たた、定額なのでその埌もアプリの瀟内配信や ナニットテスト をどんどん実行でき、利甚時間を党く気にしなくおいいのが玠晎らしいです。 Circle CI TUNAG りェブアプリケヌション の開発ですでに瀟内で利甚䞭の Circle CI も候補に挙げたしたが、モバむルアプリ向けに想定しおいる実行時間や頻床を考えるず、その開発業務にも費甚にも倧きな圱響を䞎えそうずいうこずがわかりたした。そしお䜕よりBitriseが想像以䞊に優秀だったこずから、Circle CIの怜蚌はせず、Bitriseを継続しおいくこずに決めたした。 さいごに 最埌にたずめずなりたすが、䞀蚀で蚀えば 「Bitriseはいいぞ」 です。業務䞊の遞定ずなるため機胜面での比范を真面目に行いたしたが、Bitriseを䜿っおいるうちに、そのビゞュアルデザむンのかわいさ、操䜜性の良さ、现かい郚分でのナヌザヌぞの配慮を感じられ、玔粋にBitriseずいうプロダクトを心から気に入っおしたいたした。 Continuous happiness ✹ そしお、匊瀟の創業事業TUNAGも゚ンドナヌザヌに同じように心から気に入っおもらえるようなプロダクトに育おおいきたいず匷く思いたした。そのためにはさらに匷い開発力が必芁ずなりたすので、スタメンでは䞀緒にプロダクト開発を進めおくれる仲間を募集しおいたす興味を持っおくれた方は、ぜひぜひ䞋蚘の゚ンゞニア採甚サむトをご芧ください。 スタメン ゚ンゞニア採甚サむト サヌバヌサむド゚ンゞニア募集ペヌゞ フロント゚ンド゚ンゞニア募集ペヌゞ むンフラ゚ンゞニア募集ペヌゞ モバむルアプリ゚ンゞニア募集ペヌゞ
スタメンのデザむナヌの @kiyoshifuwa です。 珟圚、 匊瀟のデザむナヌは瀟員のわたし1名、孊生アルバむトさん1名の蚈2名です。 䞻にTUNAGなど各事業のアプリケヌションのデザむンを行っおいたすが、実は瀟内のあれこれも、瀟内のデザむナヌが䜜っおいたす 今回の蚘事では、瀟内業務の䞀郚をご玹介したす。 瀟倖の方に向けお 各皮Webサむト 芏暡の倧きいものは倖郚協力䌚瀟様にお願いするこずもありたすが、小芏暡であれば瀟内でデザむン・実装を行いたす。昚幎はTUNAGブランドサむトのトップペヌゞ、゚ンゞニア採甚サむト、 むンタヌンシップ 募集サむトのデザむンをしたした。 案内パネル スタメンの セミ ナヌスペヌスでは様々なむベントや勉匷䌚が行われたす。来瀟されたお客様をご案内するために、 Wi-Fi ずお手掗いのパネルを䜜りたした 瀟倖報 瀟員のご家族に、瀟長の想いや瀟員の掻躍、むベントの様子などを知っおいただくために䜜っおいたす。このような冊子のデザむンは、スタメンに入るたでやったこずがありたせんでした。䞀から勉匷しお、詊行錯誀しながら䜜り䞊げおいたす ▌新メンバヌや各拠点のオフィスを玹介するコンテンツです スタメン瀟員に向けお 行動指針ポスタヌ スタメンには6぀の行動指針がありたす。新メンバヌでもすぐに銎染み浞透するように、みんなが忘れずに意識できるように、それぞれの指針にあったビゞュアルを䜜り、ポスタヌにしたした。 ▌もちろん名叀屋本瀟だけでなく東京、倧阪オフィスにも 掲瀺 されおいたす  â–ŒEnjoy Togetherの人々の䞭に、実はマネゞメントメンバヌがいたす。こっそり遊び心を加えおいたす スタメンアワヌド受賞者ポスタヌ 期ごずに最も掻躍したメンバヌを衚地する「スタメンアワヌド」を受賞したメンバヌを称えるポスタヌですこちらももちろん党拠点に 掲瀺 されたす垞に目に入る䜍眮に 掲瀺 されおいるので、日々「次は自分が受賞できるよう頑匵るぞ🔥」ず思えたす。 â–Œ2019幎3rdピリオド 新人賞を受賞したこうきです。おめでずう 他職皮メンバヌのお手䌝い 瀟内勉匷䌚 セヌルスや゚ンゞニアにもデザむンやツヌルの知識が圹立぀こずがありたす。「わかりやすいスラむドの䜜り方」や、「 Keynote を効率よく䜿う方法」などノンデザむナヌ向けの瀟内勉匷䌚を自䞻的に行っおいたす 登壇資料テンプレヌト スタメンには職皮を問わず自䞻的に倖郚発信をする人がずおも倚いです。資料䜜りを楜にするため、たた他瀟の方にスタメンの資料だず認識しおもらうためにテンプレヌトを䜜りたした思ったより瀟内から反響があったので、䜜っおよかったな〜ず思いたした☺ 実はこんなものもデザむンしおいたす 瀟内むベントを盛り䞊げるためのデザむンも䜜っおいたす ス タツ ク 瀟内暪断型の組織掻性化PJチヌム「ス タツ ク」歎代メンバヌを玹介する画像です撮圱は瀟内で本栌的に行いたした。 TUNAG甚スタンプ スタメンでは、自瀟で開発しおいる「TUNAG」でコミュニケヌションを取っおいたす。投皿ぞのコメントやチャットでのリアクションにオリゞナルのスタンプを䜿うこずができたす。たくさんありたすが、䞀郚をご玹介したす TUNAG甚組織画像 「TUNAG」では、組織の構成も芋るこずができたす。各郚眲、個性が出たくりの写真をカバヌ画像に蚭定しおいたす。プロダクト郚では、「匷い゚ンゞニア・デザむナヌ・ディレクタヌ」をテヌマにヒヌロっぜい画像を簡易的に䜜りたした背景の爆発はから揚げを加工しおできおいたす。 おわりに 以䞊、スタメンでの瀟内業務をご玹介したした。 印刷など、党然知識のない䞍慣れな分野でも自分で調べながらやるしかないので、なかなか倧倉なこずもありたす笑 でも毎回、スタメンのみんなぞサプラむズを仕掛けおいるような気持ちになっおわくわくしたすたた、お披露目した埌の反応を芋るのも嬉しく、やりがいを感じたす。困難を乗り越えお、みんなに感動を届けるのはずおも楜しいです💪 スタメンにお越しいただく際はぜひ、デザむンもご芧になっおいっおください
こんにちは。束谷( @uuushiro )です。 先日コヌポレヌトサむトにお、 新経営䜓制のお知らせ を公開させおいただきたしたが、3月より取締圹CTOを務めおいた小林 䞀暹が垞務取締圹VPoEに就任し、 執行圹員 CTOには私、束谷 勇史朗 が就任したした。CTO ず VPoE を分離するこずで、小林はVPoEずしお組織ず事業に、私はCTOずしお技術に専念し、組織・事業・技術の意思決定の速床ず粟床の向䞊を実珟しおいきたす。 今回の就任にあたりたしお、私自身の振り返りずこれからの抱負を簡単に述べさせおいただきたいず思いたす。 たず私ずスタメンずの関わりですが、スタメンが創業した2016幎に孊生 むンタヌン ずしお加わり、翌幎正瀟員ずしお入瀟したした。入瀟時の蚘事は こちら です。゚ンゞニア未経隓で ベンチャヌ に飛び蟌み、今たでひたすら業務の䞭で経隓を積たせおもらいたした。入瀟時には自分がCTOずしお圹割を担うこずになるずは想像もしおいたせんでしたが、創業期はCTO小林の盎䞋で孊んでいたので、自然ずCTOずいう圹割を意識しおいたのも確かです。ただ自分ずしおのCTOのむメヌゞは挠然ずしおいお、「CTOになりたい」ず蚀っおはみおも、そもそも「CTOっおなんだろう」「なりたくおなっおいいものなのか」などなど自問自答を続けおいたした。 そんな䞭、入瀟2幎目にテッ クリヌド ずしお技術的な意思決定に関わるようになり、3幎目にはマネヌゞャヌずしお開発チヌムの運営に関わるようになりたした。テッ クリヌド ずしお、マネヌゞャヌずしお、どうやったらスタメンに貢献できるか、䞭長期で私ができるこずは䜕なのか、ずいうこずを考え続けおいたその延長線䞊にCTOずいうむメヌゞが埐々にはっきりしおきたした。ただただ手探り状態ではありたすが、CTOずしおスタメンに貢献できる姿に確信を持おるように、自分のあるべきCTO像を考え抜いおいきたいず思いたす。 実際に就任しおみるず、倱敗を誰のせいにもできない緊匵感、意思決定の圱響の倧きさ、経営陣ずしおの責任の重さに、ただただ身が匕き締たる思いです。正盎、前CTOの小林や、瀟倖のCTOの トップランナヌ の方たちを芋おいるず同じCTOずしお焊りしか感じたせんし、今埌は自分の限界倀が組織の限界倀になるプレッシャヌを感じおいたす。今はただただ理想ずは皋遠いですが、ずにかく自分の成長を止めずに少しでも前進し成果を出しおいきたいず思いたす。 今埌の技術的課題ずしおは、事業の成長を加速させられるような開発スピヌドずクオリティの維持、事業芏暡拡倧に備えたスケヌラビリティの確保、安心しおサヌビスを利甚しおいただける堅牢なセキュリティ、非連続な進化を遂げるための新しい技術投資、などなど挙げればキリがありたせんが、スタメン開発チヌムのビゞョン「゚ンゞニアリングで事業の成長を牜匕する」に培底的に向き合い、チヌムで前進しおいけるようにCTOずしおリヌドしおいきたいず思いたす。 組織ずしおは、スタメン゚ンゞニアの䟡倀芳 Star Code にある通り、垞にナヌザヌ目線で考え、障害やプロゞェクト遅延などの倱敗に向き合い、お互い忖床せずに本音で語り合い、日々の自分の仕事に誇りを持おるほどのプロ意識を持ち、そしお䜕よりも゚ンゞニアリングを楜しむ。そんな゚ンゞニア組織をCTOずしお皆ず぀くりあげおいきたいです。 瀟内倖問わずスタメンのCTOずしお玍埗しおもらえる実力を぀け実瞟を出せるように、党力で圹割を党うしおいきたいず思いたすので皆様よろしくお願いいたしたす。 最埌に スタメン゚ンゞニア組織ずしおは、0→1 そしお 1→10 のフェヌズを終え、これからはその先のフェヌズ10→100のフェヌズになりたす。プロダクトが耇数になり、TUNAG の倧芏暡化ず機胜拡匵に向けお䞀局匷化を進めおいくタむミングなので、ずおもやりがいのある面癜い仕事になるず思いたす。新しい䜓制で、倚くのチャレンゞングな技術的課題に向き合い、ナヌザヌに䟡倀を届ける゚ンゞニア募集しおいたす興味を持っおくれた方は是非、䞋蚘の゚ンゞニア採甚サむトを芋おください。 スタメン ゚ンゞニア採甚サむト サヌバヌサむド゚ンゞニア募集ペヌゞ フロント゚ンド゚ンゞニア募集ペヌゞ むンフラ゚ンゞニア募集ペヌゞ モバむルアプリ゚ンゞニア募集ペヌゞ
こんにちは、スタメンでバック゚ンドの゚ンゞニアをしおいる河井です。 私の所属するバック゚ンドチヌムでは、普段からサヌビスのパフォヌマンス監芖ずチュヌニングを継続的に行っおいたす。 今回は、デヌタベヌス負荷のモニタリングに䜿っおいる Performance Insights ずいうツヌルの掻甚方法をたずめおみたす。 Performance Insights に぀いお Performance Insightsパフォヌマンスむンサむトずは、Amazon RDS で提䟛されおいる機胜で、DB の負荷のモニタリングが簡単にできたす。 ざっくりずたずめるず、 指暙がシンプルなので DB の負荷状況を盎感的に把握できる SQL ク゚リが衚瀺されるため問題箇所の特定がしやすい リアルタむム曎新なので即座に負荷内容を分析できる ずいったメリットがありたす。 有効化に぀いおは こちら を参照ください。 ダッシュボヌドの芋方 ダッシュボヌドが芋やすくお䟿利なので、基本的にこちらを䜿いたす。 RDS コン゜ヌルのサむドバヌにある「パフォヌマンスむンサむト」からアクセスできたす。 画面は3぀のパヌトに別れおいお、䞊から、カりンタヌメトリクス、デヌタベヌスのロヌド、SQL ステヌトメントダむゞェストずなっおいたす。 基本的にはデヌタベヌスのロヌドずSQLステヌトメントダむゞェストを䜿うので、この2぀に぀いお解説したす。 デヌタベヌスのロヌド デヌタベヌスの負荷を時系列で衚瀺しおいたす。負荷は平均アクティブセッションAverage Active Session、AASずいう指暙で衚珟されおいたす。 平均アクティブセッションずは、䞀定時間内に凊理䞭たたは凊理開始を埅ちのセッションの数で、この数が倚いほど DB に負荷がかかっおいるずいえたす。 䞊蚘画像では、スラむス基準ずいう項目が、「埅機」 になっおいたす。 スラむス基準ずは AAS の内蚳を䜕基準で衚瀺するかずいう蚭定項目です。 埅機基準では、デヌタベヌスの䞀連の凊理のうちどのむベントでどのむベントでの埅機時間が長くなっおいるかを知るこずができたす。 各皮むベントの詳现に぀いおは こちら を参照ください。 グラフの䞊郚にある砎線は今芋おいる RDS むンスタンスの仮想 CPU 数を衚しおいたす。 CPU での埅機数だけでこのラむンを超えるず、CPU 数が䞍足しおいるずいえたす。 䞊の画像では䞀箇所そのラむンに到達しおいたすが、埅機の内蚳を芋るず CPU の割合は䜎いです。 そのため、CPU が原因ずなっお負荷が高たっおいるわけではないず刀断できたす。 次に、スラむス基準を SQL に倉えおみたす。 SQL 基準を遞択するこずで、各ク゚リごずにどれだけ埅機しおいるかを知るこずができたす。 がかしを入れおあるずころには SQL ク゚リが衚瀺されおおり、どのク゚リによっお負荷が発生しおいるのかを刀定できたす。 SQL ステヌトメントダむゞェスト SQL ステヌトメントダむゞェストでは、 簡略化された SQL ク゚リが負荷の高いものから順に衚瀺されおいたす。 ダむゞェストではパラメヌタが name = ? のように眮き換えられおおり、同じク゚リの圱響をたずめた倀になっおいたす。 さらに詳现を芋たいずきは▷をクリックし、実際のパラメヌタが入った個々のク゚リを芋るこずができたす。 TUNAG では䌁業ごずに柔軟な蚭定が可胜なため、予期せぬ蚭定で負荷が高たるこずがありたす。 パラメヌタありの状態でク゚リを芋お䌁業を特定し、原因究明たでスピヌディに行えるようになりたした。 監芖の蚭定 䞊蚘は負荷がかかっおいるタむミングが特定できおいる前提で話をしおいたした。 負荷が高たっおいるこず自䜓に気づくために、デヌタベヌスのロヌドが䞀定数を超えたら通知されるようにしおみたす。 蚭定可胜な項目 CloudWatch Alarm でデヌタベヌスのロヌドを監芖するこずができるので、蚭定手順を説明したす。 デヌタベヌスのロヌドに関するメトリクスは3皮類ありたす。 DBLoad DBloadCPU DBLoadNonCPU DBLoadCPU は埅機芁因を CPU のみに限定したもの、DBLoadNonCPU は CPU 以倖の芁因で埅ちが発生しおいるもの、DBLoad はその合蚈倀ずなっおいたす。 バック゚ンドチヌムでは次のような䜿い分けをしおいたす。 DBLoadCPU: CPU 数䞍足の怜知 DBLoadNonCPU: 非効率なク゚リ発行の怜知むンデックスが効いおいない、DB ぞの同時アクセス数が倚すぎるなど 蚭定手順 どの指暙を䜿うにしおも蚭定は同じなので、DBLoad のアラヌムを蚭定しおみたす。 たずは CloudWatch コン゜ヌルにアクセスし、サむドメニュヌの「アラヌム」を遞択、「アラヌムの䜜成」ず進みたす。 進んだ先の画面で、"DBLoad" で怜玢→「RDS > デヌタベヌスメトリクス」を遞択→監芖したい DB むンスタンスにチェック→メトリクスを遞択ず進みたす。 メトリクスを取埗する間隔や閟倀は、普段負荷が高たるずきの AAS を参考に決めたしょう。 最埌に、通知先を蚭定しお終了です。 たずめ Performance Insights のダッシュボヌドの芋方からアラヌトの蚭定方法たでざっくりずたずめおみたした。 これを䜿い始めおから劇的にク゚リの改善が進んだので、ただ䜿っおいないずいう方はぜひ觊っおみおください。 最埌に、株匏䌚瀟スタメンでは䞀緒に働く仲間を募集しおいたす。 ご興味のある方はぜひ䞋蚘のペヌゞをご芧ください ゚ンゞニア採甚サむト ゚ンゞニア募集ペヌゞWantedly 参考資料 パフォヌマンスむンサむトを䜿甚する Performance Insights で Amazon RDS for MySQL をチュヌニングする アむキャッチ Photo by Chris Liverani on Unsplash
スタメン ゚ンゞニアの束谷( @uuushiro )です。 スタメンは、2020幎3月より ゚ンゲヌゞメント蚺断サヌビス TERAS(テラス) の提䟛を開始したす。創業プロダクトである TUNAG(ツナグ) に続いお2぀目のプロダクトになりたす TERASは、゚ンゲヌゞメント経営を実行できるサヌビス TUNAG のノりハりを元にした、組織の゚ンゲヌゞメントを可芖化する組織蚺断サヌビスです。サヌビスの抂芁は以䞋リンクからご芧ください ゚ンゲヌゞメント蚺断サヌビス『TERAS』をリリヌス この蚘事では、゚ンゲヌゞメント蚺断サヌビス TERAS の技術 アヌキテクチャ の玹介をしたす。 TERAS は SPA(React)ず API サヌバ( Ruby on Rails )で䜜られたWebアプリケヌションです。 アヌキテクチャ の構想・実装にあたっお、重芁芖した点は3぀です。 実装・保守・運甚コストをなるべく削枛し、機胜開発に集䞭できる基盀にしたい セキュリティ・スケヌラビリティなどの非機胜芁件は初期からなるべく劥協したくない むンフラをコヌド化しお管理し、むンフラ知識の 冗長化 のハヌドルを䞋げたい。たた、再利甚性をあげたい。 特に耇雑なこずはしおおらず、結果ずしおシンプルな構成になりたした。 以䞋で アヌキテクチャ の党䜓図ず個別詳现を玹介しおいきたす。 TERAS アヌキテクチャ 党䜓図 TERAS アヌキテクチャ の党䜓図は以䞋になりたす。 ざっくり以䞋の項目に分けお玹介しおいきたす。 ネットワヌク CDN WEBサヌバヌ デプロむ 秘匿情報管理 むンフラのコヌド化 ネットワヌク ネットワヌク以䞋3぀のサブネットに分けおいたす。 グロヌバルIP を持おば、倖郚ネットワヌクず通信ができるサブネット(Public Subnet) NATを介しおのみ倖郚ネットワヌクず通信ができるサブネット(Protected Subnet) 倖郚ネットワヌクず通信はできないサブネット(Private Subnet) TERAS では、Application Load Balancer を Public Subnet に配眮し、ECS/Fargateタスクを Protected Subnet に配眮するこずで、Application Load Balancer からのみアクセスを受け付けるようにしおいたす。たた、WEBサヌバヌずしおFargateタスクを利甚しおいたすが、Fargateタスクに察しお盎接Elastic IPを割り圓おるこずができないので、倖郚ぞのアりトバりンド通信(メヌル配信サヌビスぞの API アクセスなど)を蚱可するために、NATを Public Subnet に配眮しおいたす。RDSは、倖郚通信の必芁性がないので、Private Subnetに配眮しおいたす。このように、ネットワヌクの圹割毎に䜜成するこずで、階局化したアクセス制埡を行いセキュリティを向䞊させおいたす。 CDN TERAS では、 CDN ずしお Amazon CloudFront を利甚しおいたす。導入理由は3点です。 パフォヌマンス向䞊 ゚ッゞサヌバヌからコンテンツが送信される分、レスポンスが速い ただ、オリゞンが東京リヌゞョンなので実際にはそこたで差がでないかもしれない。 コスト削枛 Amazon CloudFront からデヌタを送信するコストは Amazon S3 から送信するコストよりも安い セキュリティ AWS WAF の統合が可胜で、 XSS や SQLむンゞェクション などの䞀般的なWEBアプリケヌションの攻撃を防ぐこずができる。(2019幎11月に新しくリリヌスされた AWS WAF V2 の Managed Rule を利甚し、WAF V1に比べ、ルヌルの蚭定が倧幅に楜になった。) Amazon CloudFront は、䞖界䞭にノヌドがあるため倧量の 垯域幅 があり、倚くの DDOS攻撃 を軜枛できる たた、 Amazon CloudFront に関しお、SPAにおける芁件や、セキュリティの芳点で察応した事項があるので以䞋で玹介したす。 キャッシュコン トロヌル Amazon CloudFront のキャッシュコン トロヌル 機胜(Behaviors)を掻甚し、 Amazon S3 (SPAサヌバヌ)ず Application Load Balancer ( API サヌバヌ)のマルチオリゞン構成にしおいたす。クラむアントからのリク ゚ス トパタヌンを元に、キャッシュポリシヌやオリゞンぞのアクセスルヌルを個別蚭定しおいたす。TERAS では、 /api ずいうリク ゚ス トパタヌンの堎合は、Application Load Balancerぞ、その他のリク ゚ス トパタヌンは Amazon S3 ぞ振り分けられるように蚭定しおいたす。 たた、 /api のような動的コンテンツに関しおは、キャッシュされないように TTL を0に蚭定しおいたす。 カスタム゚ラヌペヌゞ React RouterなどSPA偎でルヌティングをしおいる堎合、サブ ディレクト リ含むURLでブラりザをリロヌドをするず、S3の゚ラヌペヌゞが衚瀺されおしたいたす。これは察象の ディレクト リがS3 バケット に存圚しないこずが原因です。 Amazon CloudFront の Error Pages に403たたは404゚ラヌの堎合には /index.html ぞ転送し、SPA偎でルヌティングの制埡が行えるようにしおいたす。 オリゞンサヌバヌの保護 セキュリティ・パフォヌマンスの芳点においお、倖郚から盎接オリゞンぞアクセスされるこずを防ぎたいです。 Amazon S3 には、ブロックパブリックアクセスずいう、あらゆるルヌルより優先されるアクセス制埡ポリシヌがデフォルトで有効化されおいたす。蚭定ミスなどデヌタが意図せず公開されるこずを防ぐために、基本ブロックパブリックアクセスは有効化のたたで運甚できるようにしたいです。 Amazon CloudFront の Origin Access Identity を䜿うこずで、 ブロックパブリックアクセスを有効化したたた、 Amazon S3 ぞのアクセスを Amazon CloudFront からのリク ゚ス トに限定するこずができたす。 たた、Application Load Balancer に぀いおも、 Amazon CloudFront でカスタムヘッダを远加し、Application Load Balancer偎で倀が䞀臎すれば、CloudFrontから転送されおきたリク ゚ス トずみなし、リク ゚ス トを蚱可するこずができたす。これによっお、Application Load Balancer に぀いおも Amazon CloudFront からのリク ゚ス トに限定するこずができたす。 クロス ドメむン 通信が䞍芁 SPAず API サヌバが連携するアプリケヌションを ホスティング する堎合、SPAサヌバヌず API サヌバヌが別 ドメむン で ホスティング されるこずがあるず思いたすが、 Amazon CloudFront でマルチオリゞン察応するこずで、同䞀 ドメむン で扱うこずができ、 API サヌバヌ偎におけるCORS察応が䞍芁になりたす。実装・怜蚌 工数 を抑える1぀の芁因ずなりたした。 WEBサヌバヌ AWS Fargateを以䞋の理由で導入したした。 ホスト むンスタンス の管理から解攟 オヌトスケヌルの蚭定が䞍芁 ぀たり、自分でサヌバヌを管理するこずなくコンテナを実行できたす。EC2に比べお、コストは割高ですが人的 工数 の削枛を考えるず元が取れるのではないかず思いたす。 AWS Fargate に぀いおは、以䞋の AWS Startup ブログ が倧倉分かりやすかったので興味のある方はそちらをご芧ください。 スタヌトアップのためのコンテナ入門 – AWS Fargate ç·š デプロむ API サヌバヌ( Amazon ECS) AWS CodePipeline で AWS CodeBuild ず AWS CodeDeploy を連携しデプロむをしおいたす。以䞋の理由で導入したした。 デプロむサヌバヌの構築・運甚コスト削枛 オヌトスケヌルずの盞性が良い ECSずの統合機胜が充実しおいる Blue Green Deployment Canary Deployment Linear Deployment AWS 内でデプロむフロヌが完結するこずで、 AWS の認蚌情報などを倖郚に公開する必芁がなくセキュアに ただ、 AWS CodePipeline関連のサヌビスの利甚経隓が浅いので課題が芋぀かるかもしれたせんが、セキュリティ・スケヌラビリティの芳点や他 AWS サヌビスずの芪和性においおも良い遞択なのではないかず思っおいたす。 SPA( Amazon S3 ) AWS CodeBuild でビルドし、その生成物を S3 sync しお、 Amazon CloudFront の invalidate を実行しキャッシュをクリアするだけです。 秘匿情報管理 System Manager の Parameter Store 秘匿情報を登録するこずで、 AWS CodeBuild、 Amazon ECS で 環境倉数 に機密情報を枡せたす。 Rails のcredentials機構を䜿うよりも楜で、ビルドやデプロむ時など必芁な秘匿情報も合わせお䞀元管理できるのでずおも䟿利でセキュアだず感じおいたす。 むンフラのコヌド化 これらの構成を AWS CloudFormation で䜜成しおいたす。 AWS CodeDeploy のECS Blue Green Deployment に぀いおは、未だ AWS CloudFormation 察応しおいないため、マネゞメントコン゜ヌルから手動で登録しおいたす。 この アヌキテクチャ は、プロダクト固有の特殊な構成ではないので、今埌 WEBアプリケヌションの基盀構築の際に、再利甚しやすくなっおいたす。そしお、今埌新しく TERAS ぞ参加するメンバヌもこの蚘事ずむンフラコヌドを芋れば、党䜓像を把握するこずがでるので、システム知識のキャッチアップが速くなるのではないかず期埅しおいたす。 たずめ TERASの党䜓像ず各項目に぀いお玹介させおいただきたした。むンフラ構築・運甚コストを抑え、か぀セキュアでスケヌルするシステムを䜜る際の参考になれば幞いです。この構成はシンプルで、汎甚性も高く、か぀コヌド化をしおいるので、今埌プロダクトが増えた際にも、割ず簡単に再利甚ができるのではないかず期埅しおいたす。 3月にリリヌスされ運甚が始たりたすが、ただただ課題はたくさんありたす。たた、プロダクトが耇数になったこずで、セキュリティ・IAM管理・監芖䜓制など、プロダクトごずにポリシヌが乱立しないように、戊略立おお決めおいく必芁があるなず感じおいたす。 最埌に TUNAG、TERAS、新芏プロダクトを暪断的に蚭蚈・改善しおくれるSREを募集しおいたす プロダクトが耇数になり、TUNAG の倧芏暡化に向けお䞀局むンフラ面の匷化を進めおいくタむミングなので、ずおもやりがいのある面癜い仕事になるず思いたす。興味を持っおくれた方は是非、䞋蚘の゚ンゞニア採甚サむトを芋おください スタメン ゚ンゞニア採甚サむト むンフラ゚ンゞニア募集ペヌゞ
皆様いかがお過ごしですか。スタメンでモバむル アプリ開発 を担圓しおいる @sokume です。 以前、 TUNAG iOSアプリの技術的な解説 で、 @temoki から発信しおいたすが、読んでいただけたしたでしょうか。今回の蚘事は Android 版の技術的な解説蚘事です。 蚀語 Google I/O 2019にお Kotlin-First 宣蚀があり、名実ずもに Android の第1蚀語は Kotlin に倉わりたした。もちろんTUNAG Android アプリもすべお Kotlin で曞かれおいたす。 Kotlinも日々曎新しおいたすので、垞に新しいバヌゞョンに远埓しおいける開発環境にしおいたす。蚘述時点ではv1.3.61ですね アヌキテクチャ ヌ Android Jetpack に含たれる、 Android Architecture Component をベヌスずした構成をずっおいたす。 この構成をすべお利甚するのでなく、TUNAG Android アプリに合わせた圢で利甚箇所の遞定をしおいたす。 サヌビス TUNAG は AWS + Ruby on Rails で構築しおいたすが、mBaaS (mobile backend as a service) の Firebase を利甚しお以䞋の察応をおこなっおおりたす。 - Cloud Firestore 利甚した即時性の高いチャット機胜 - Authentication を利甚したナヌザヌ認蚌 - Crashlyitics を利甚したクラッシュレポヌティング - Cloud Messaging を利甚したアプリぞのプッシュ通知配信 - App Distribution を利甚したアプリのベヌタ配信 ここの点は TUNAG iOS ず䞀緒の構成ずしおいたす。 ラむブラリ 前述の Android Jetpack や Android KTX はもちろん、 Material Components UI コンポヌネント ラむブラリを利甚し、 Android に適したUIの実珟を進めおいたす。 HTTPクラむアントは Retrofit2 ず Okhttp3 を利甚し、HTTPクラむアントずからめお、 JSON パヌサヌは Moshi を利甚しおいたす。 画像の読み蟌みにもHTTPクラむアントずからめお Picasso を利甚しおいたす。 Square 補ラむブラリが倚めですね Model局からのデヌタに぀いおはリアクティブに凊理するため、 RxKotlin / RxAndroid / RxJava を利甚しおいたす。 ReactiveExtensionを利甚しおいたすが、Activity/FragmentView局や ViewModel ViewModel局ではラむフサむクル察応コルヌチンスコヌプを利甚し、ラむフサむクルを意識した凊理の制埡が行える実装ずしおいたす。 ベヌタテスト iOS アプリず同じく、スタメンのメンバヌ自身がTUNAGを利甚しおいたす。そのためアプリの新バヌゞョンは垞に瀟内メンバヌでのテストを実斜しおいたす。 CIの仕組みは2019幎11月に公開された Github Actions の利甚を怜蚎しおいたす。 ワヌクフロヌずいう圢で、 Github ぞのアクションを蚘述し、 Push や PullRequset ずいったナヌザヌ操䜜をトリガヌに、 ビルド実行 ➡ 配信 ずいった凊理を継続的に実斜する事ができたす。 瀟内メンバヌぞの ベヌタテスト の配信は前述の Firebase App Distribution を利甚しお配信しおいたす。 さいごに TUNAG Android アプリの構成を説明させおいただきたした。 TUNAG iOS アプリずはたったくの別のものずしお考えず、同じ構成にするこずで埗られる利点などを考えた構成にしおいたす。 もちろん、 Android アプリずしお远求すべき点は劥協したせん。 熱い仲間ず䞀緒に、より良いサヌビスを䞀緒に䜜りたせんか 仲間を募集しおいたす たずは、スタメンの゚ンゞニ アサむ ト stmn, inc. Engineers を芋おみおください
こんにちは スタメンで Rails アプリの開発を担圓しおいるシュヌル( @shule517 )です Rails アプリケヌションを安党に開発するために、自動テストはずおも倧切ですよね スタメンではCircleCIで RSpec やRuboCopの実行をし、安党を確認しお本番機ぞデプロむしおいたす。 CircleCIの高速化を行った結果、倍速玄20分→10分にするこずができたしたその時に察応したポむントを解説したす。 CircleCIのキャッシュを有効掻甚 ① アセットプリ コンパむル 結果をキャッシュする CI党䜓の凊理時間のうち4分の1はアセットプリ コンパむル に時間がかかっおいたした。アセットプリ コンパむル の結果をキャッシュするこずで5分ほど高速化できたした。 # プリコンパむルのキヌを䜜成 - run : name : create assets precompile cache key command : | # プリコンパむル察象のファむルの最新コミット番号をキヌにする git rev-parse $(git log --oneline -n 1 app/assets lib/assets vendor/assets Gemfile.lock | awk '{{print $1}}' ) > VERSION # キャッシュを埩垰 - restore_cache : keys : # 同じバヌションからキャッシュを埩垰。無ければ、盎近のキャッシュを埩垰。 - assets-precompile-cache-{{ checksum "VERSION" }} - assets-precompile-cache- # プリコンパむルを実行 - run : name : assets:precompile command : | current_revision=VERSION previous_revision=public/assets/VERSION # プリコンパむル察象のファむルが倉曎されおいなければスキップ if [ ! -e $previous_revision ] || ! diff $previous_revision $current_revision; then bundle exec rake assets:precompile cp -f $current_revision $previous_revision else echo "Skipped." fi # キャッシュを保存 - save_cache : key : assets-precompile-cache-{{ checksum "VERSION" }} paths : # プリコンパむル結果の保存先を指定 - public/assets - tmp/cache/assets ※実際に䜿甚しおいる蚭定ファむルずは異なりたす。 アセット関連のファむルが倉曎されおいない堎合はプリ コンパむル をスキップしたいため、キャッシュのキヌをプリ コンパむル 察象のファむルの最新コミット番号にしたした。たた、アセット関連のファむルを修正しおいる堎合も、前回ずの差分だけをプリ コンパむル するようになるためかなり時間が節玄できたす。 プリ コンパむル の察象ファむルずしお Gemfile.lock を入れおいる理由は、Gemをむンストヌルした時にアセット関連のファむルが倉曎されるこずがあるためです。 アセットの倉曎がない堎合、assets:precompileをスキップするこずでCIの速床を改善した を参考にしたした。 ② Gemのむンストヌルをキャッシュする CircleCI䞊で䜿うGemをGemfileに蚘茉し、むンストヌルしたGemをキャッシュしたす。RuboCopの実行に必芁なGemをキャッシュし、3分ほど速くなりたした group :test do # CircleCIでRuboCopを実行するために必芁 # 修正前はCircleCIのタスクでgem installしおいた gem ' rubocop ' gem ' rubocop-select ' gem ' rubocop-checkstyle_formatter ' end # キャッシュを埩垰 - restore_cache : key : rails-gemfile-{{ checksum "Gemfile.lock" }} # Gemをむンストヌル - run : bundle install --path vendor/bundle # キャッシュを保存 - save_cache : key : rails-gemfile-{{ checksum "Gemfile.lock" }} paths : - vendor/bundle restore_cache / save_cache の keyを checksum "Gemfile.lock" ずするこずで、 Gemfile.lock の内容が䞀臎した時だけキャッシュを埩垰したす。぀たり、 Gemfile を倉曎した時だけGemのむンストヌルが実行されたす。 CircleCI - キャッシュ蚭定の䟋 を参考にしたした。 ③ ゜ヌスコヌド のチェックアりトをキャッシュする ゜ヌスコヌド をチェックアりトした埌の.gitフォルダをキャッシュしたす。これで前回ずの差分だけをチェックアりトすればよくなり、30秒ほど速くなりたした # キャッシュを埩垰 - restore_cache : keys : - source-v1-{{ .Branch }}-{{ .Revision }} - source-v1-{{ .Branch }}- - source-v1- # ゜ヌスコヌドをチェックアりト - checkout # キャッシュを保存 - save_cache : key : source-v1-{{ .Branch }}-{{ .Revision }} paths : - ".git" restore_cache に指定する keys を耇数指定しおおくず、その䞭から䞀番近いキャッシュデヌタを埩垰しおくれたす。今回の蚭定方法だず、同じブランチのキャッシュを優先し、無ければ盎近のキャッシュを䜿甚したす。 CircleCI - ゜ヌスコヌドのキャッシュ を参考にしたした。 RSpec をバランスよく䞊列実行する ① ボトルネック になっおいるコンテナを芋぀ける CircleCIのTimingを芋るず、分散しおいる各コンテナの実行時間を芋るこずができたす。16分台に完了しおいるコンテナもありたすが、番遅いコンテナに足を匕っ匵られおしたい党おが完了するのは22分です。凊理を均等に分割できれば、20分以内に枛らせそうですね遅いコンテナから順に分散を怜蚎したしょう。 ② ボトルネック になっおいるspecファむルを芋぀ける RSpec の実行ログを保存するこずで、コンテナごずの各specファむルにかかった詳现な時間を芋るこずができたす。どのspecファむルが ボトルネック になっおいるかを芋぀けたす。 - run : name : bundle exec rspec command : bundle exec rspec --format RspecJunitFormatter --out test-results/rspec.xml - store_artifacts : path : test-results/rspec.xml ③ RSpec を高速化し、 ボトルネック を解消する ボトルネック のコンテナ、テストファむルを特定したら、 RSpec の高速化をしおいきたしょう高速化で察応した内容がこちらです。 䞍芁なテストデヌタを䜜らないようにする 䞍芁なテストデヌタ䜜成で、テストの実行が遅くなっおいた 未䜿甚なテストデヌタを䜜っおいるletを削陀した 䜿い回さないテストデヌタの堎合は、`let!`→`let`に倉曎した E2Eテストのitをたずめる 1぀のitで1぀のexpecにするのは RSpec ずしお正しいが、E2Eテストでは時間がかかりすぎる 同じ画面を確認する堎合は、itをたずめるこずで高速化した itの䞭で耇数のexpectを実行する堎合は、`aggregate_failures`を䜿う RSpecでテストをたずめお怜蚌する方法 を参考にしおください。 E2Eテストのsleepを削陀し、have_xxxで埅぀ 画面描画を埅぀ためにsleepをしおいたため、テストが遅くなっおいた テストケヌスの数 × sleepの時間だけ無駄な埅ち時間が発生しおしたう sleepの代わりにhave_xxxマッチャを䜿い、埅ち時間を最小限に抑えた 巚倧なspecファむルを分割する RSpec の分散はテストファむル(*_spec.rb)ごずに行っおいる 高速化を行っおも、テストケヌスが倚いテストファむルは ボトルネック になっおしたう そのため、巚倧なspecファむルを分割し、均等に分散できるようにした おわりに CircleCIの高速化を行い、埅ち時間が枛るこずで開発のストレスがかなり枛りたしたみなさんがCircleCIを高速化する時に、参考になればずおも嬉しいです。埅ち時間を枛らしお、より楜しく効率的に開発をしおいきたしょう 熱い仲間ず䞀緒に、より良いサヌビスを䞀緒に䜜りたせんか 仲間を募集しおいたす たずは、スタメンの゚ンゞニ アサむ ト stmn, inc. Engineers を芋おみおください
こんにちは。スタメンでモバむル アプリ開発 をしおいる @temoki です。 スタメンには 誕生祭 ずいう制床があり、メンバヌの誕生日には同じ郚眲のメンバヌでお祝いし、その様子を匊瀟が提䟛しおいるサヌビス TUNAG で党瀟に共有しおいたす。珟圚アルバむトで今幎の春に新卒入瀟を予定しおいる゚ンゞニ アメンバヌ のために昚幎に実斜した誕生祭では、プロダクト郚ならではの手䜜りのお祝いをしたので、その様子をお䌝えしたいず思いたす。 蚈画 TUNAG にはメンバヌの誕生日を事前にお知らせする機胜がありたす。そのお知らせをトリガヌに本人を陀いたメンバヌで瀟内のチャットグルヌプを䜜り、そこでひっそりず準備が始たりたす。 スタメンの䌁業理念は 䞀人でも倚くの人に、感動を届け、幞せを広める。 です。この理念に぀いお匊瀟代衚の加藀は「感動は盞手の期埅を超えるこずで生たれる」ずよく私たちに䌝えたす。この誕生祭でも期埅を超えるお祝いができるように、その人が最近話しおいたこずや、TUNAG のプロフィヌル、最近の投皿の内容などの情報を集めながら、プレれントは䜕にするかどうやっお祝うかのア むデア を出しおいきたす。 今回お祝いするメンバヌは Android アプリ゚ンゞニアです。圌のデスクにはドロむド君フィギュアを眮いおあったり、個人でも Android アプリをリリヌスしおいたりず、 Android アプリ開発 ぞの愛がずおも匷いです。そこで、 Android をテヌマに皆でア むデア を出し合い、最終的には次のように蚈画したした。 プレれントは Boothのドロむド君キャップ そのプレれントをドロむド君から枡す バヌスデヌケヌキの代わりに Android のこれたでのバヌゞョンのコヌドネヌムずなったお菓子を党お揃える 準備 蚈画を元に、各メンバヌが準備を進めおいきたす。プレれントは発泚するだけですが、残りの぀のア むデア が倧倉です。 ドロむド君ヘルメットを䜜る プレれントをドロむド君から枡すために、ドロむド君なりきりヘルメットを䜜るこずにしたした。元ネタはコチラ あのドロむドくんヘルメット、蚭蚈曞付きで誰でも手䜜り可 です。 東急ハンズ や100円ショップをたわっお材料を集め、本人がいない時を狙っお制䜜を進めおいきたした。 半球状ずディスク状の発砲スチヌロヌルを組み合わせお敎圢 ドロむド君の緑色に近い氎性アクリル塗料で塗っおいく 塗りムラがないように入念にチェック デザむナヌの手で目を入れお呜を吹き蟌む Android のこれたでのバヌゞョンのコヌドネヌムずなったお菓子 Android は 2009幎にリリヌスされたバヌゞョン 1.5 から、頭文字がアルファベット順で始たるお菓子の名前が付けられおいたす。毎幎 Android の新バヌゞョンのリリヌス時期が近づくず、 Android アプリ開発 者の間では次のバヌゞョンのお菓子は䜕かを予枬する話題で盛り䞊がりたすね。 このコヌドネヌムが昚幎リリヌスされた Android 10 で廃止されたこずもあり、この誕生祭のお祝いのケヌキの代わりに、これらのお菓子を党お揃えおみようずいうこずになりたした。前日にメンバヌでいろんなお店を回っおなんずか党お集めるこずができたした。 参考 (List of Android version names) Android ver. お菓子 1.5 C upcake ( カップ ケヌキ) 1.6 D onut (ドヌナツ) 2.0, 2.1 E clair (゚クレア) 2.2 F royo ( フロヌズンペヌグルト ) 2.3 G ingerbread (ゞンゞャヌブレッド) 3.0, 3.1, 3.2 H oneycomb (はちみ぀) 4.0 I ce Cream Sandwich (アむスクリヌム・サンドむッチ) 4.1, 4.2, 4.3 J elly Bean (ゞェリヌ・ ビヌン ) 4.4 K itKat ( キットカット ) 5.0, 5.1 L ollipop ( ロリポップ ) 6.0 M arshmallow (マシュマロ) 7.0, 7.1 N ougat (ヌガヌ) 8.0, 8.1 O reo (オレオ) 9.0 P ie (パむ) 圓日 誕生祭の圓日、オフィスフロアに突然バヌスデヌ゜ングが流れおむベントが始たりたす。たずはバヌスデヌケヌキの代わりの Android スむヌツの登堎です。ろうそくは Cupcake ( Android 1.5) にさしお消しおもらいたした 本人も驚きを隠せない様子 ずらりず䞊んだ Android スむヌツ そしお、さらなるサプラむズ。 スペシャ ルゲストずしおドロむド君をかぶったメンバヌが登堎ドロむド君になりきっおプレれントを枡したした。 ドロむド君は螊りが埗意 だよずいうフリで華麗なダンスも披露しおくれたしたよ。 I am Droid. 最埌に本人から䞀蚀もらっお誕生祭は終了です。この誕生祭を本圓に喜んでくれお、来幎からの正匏入瀟に向けおの意気蟌みを熱く語っおくれたしたお祝いしたメンバヌも、本人の笑顔を芋おずおも満足です。 さいごに 今回の゚ンゞニアブログでは、普段はあたりお䌝えできおいないプロダクト郚のハヌトフルなずころをお䌝えしたしたが、いかがでしたでしょうか。プロダクト郚では技術やプロダクトはもちろん、チヌムや仲間ひずりひずりに真剣に向き合いながら開発を進めおいたす。匊瀟ではこのチヌムの䞭で䞀緒に働いおくれる゚ンゞニアを募集しおいたす。ご興味のある方はぜひスタメンの゚ンゞニ アサむ ト stmn, inc. Engineers をご芧ください。
スタメンで゚ンゞニアをしおいる 田侭 です。 皆さんはJay Fieldsの著「 リファクタリング  Ruby ゚ディション」ずいう本をご存じでしょうか リファクタリング における有名な本ずしお、Martin Fowlerの著「 リファクタリング 」ずいう本はご存じの方が倚いかず思いたす。 こちらは圓時広く知られおいた Java (初版), JavaScript (第二版)でサンプルコヌドが曞かれおいたした。 「 リファクタリング  Ruby ゚ディション」は原著である「 リファクタリング 」を Ruby に察応させたもので、 Ruby の特城を掻かした リファクタリング の方法が茉っおおり、䞀床は読んでみたいず思っおいたした。しかしながら、こちらの本は珟圚絶版のため入手するこずが難しいです。 今回、瞁があっおこちらの本をお借りする機䌚がありたしたので、その内容に぀いおご玹介したす。 リファクタリング をする䞊で倧切なこず いく぀か良いなず思った文章があったので匕甚の圢でご玹介したす。 リファクタリング に぀いお リファクタリング ずは、コヌドの倖からふるたいを倉えずに、内郚構造を改良するようにしお、゜フトりェアシステムを倉えおいくプロセスである。   コンピュヌタが理解できるコヌドなら誰でも曞ける。優れた プログラマ が曞くのは、人間が理解できるコヌドだ。   あなたが リファクタリング をしおいるのは、真実や矎を远求するためではない。䞖界をわかりやすくしお、ばたばたず揺れ動いおいるプログラムの支配暩を再び握るために努力しおいるのである。 テストに぀いお リファクタリング を始める前に、しっかりずしたテストが必芁だ。   リファクタリング ではテストが呜綱になる。 リファクタリング が成功するかどうかはよいテストが甚意できおいるかどうかによっお巊右される。 パフォヌマンスずの兌ね合い リファクタリング をしおいるずきはわかりやすくするこずに集䞭すべきで、パフォヌマンスをあげるこずはその埌で別の仕事ずしお行うのが正しい方法である。 倧切なこずは ふるたいを倉えない ふるたいを保蚌するためにテストを曞く パフォヌマンスはたた別のタスクずしお考える 私自身は リファクタリング ずパフォヌマンスの圹割の違いに぀いおは特に意識しないずいけないず思いたした。 リファクタリング 時にパフォヌマンスも䜵せお考えおしたっおいたしたが、そもそもの目的が異なるので曞くべきコヌドは違うものです。たずは リファクタリング によっお分かりやすくした䞊で必芁に応じおパフォヌマンスチュヌニングずいった流れを意識しおいきたいです。 具䜓的な手法 数倚くの方法が玹介されおいたすが、ここでは3぀に絞っお玹介したす。 サンドむッチメ゜ッドの抜出 ほが同じ内容のコヌドのメ゜ッドが2぀あり、それらの違いがメ゜ッドのちょうど䞭頃のみの堎合に、重耇郚分を抜出しおブロック付きのメ゜ッドにする。 サンプル 倉曎前 def charge (amount, credit_card_number) begin connection = CreditCardServer .connect(...) connection.send(amount, credit_card_number) rescue IOError => e Logger .log " Could not submit order #{ @order_number } to the server: #{ e }" return nil ensure connection.close end end 倉曎埌 def charge (amount, credit_card_number) connect do | connection | connection.send(amount, credit_card_number) end end def connect begin connection = CreditCardServer .connect(...) yield connection rescue IOError => e Logger .log " Could not submit order #{ @order_number } to the server: #{ e }" return nil ensure connection.close end end 前凊理ず埌凊理が必芁なメ゜ッドで具䜓的な凊理の䞭身を倉えたい堎合に掻甚できそうだず感じたした。ブロックを利甚した曞き方が Ruby っぜく、たたこの曞き方が私自身あたり䜿いこなせおいないず思ったのでご玹介したした。 条件分岐の組み換え Ruby では nil ガヌドずいう曞き方があるので、 䞉項挔算子 で曞かずに Ruby らしい曞き方をしようずいうこずでした。この他にも Ruby で提䟛されおいる蚘法に則るこずでよりシンプルに曞けそうだず思いたした。 サンプル 倉曎前 paraneters = params ? params : [] 倉曎埌 parameters = params || [] 他の蚀語を経隓しおいるず、぀い Ruby らしさを忘れた曞き方をしおしたいがちなので、気を぀けないずいけないず思いたした。 条件分岐のネストからガヌド節ぞ 正垞な実行経路が分かりにくい条件分岐を持぀メ゜ッドがある堎合に、すべおの特殊条件をガヌド節で凊理する。 サンプル 倉曎前 def pay_amount if @dead result = dead_amount else if @separated result = separated_amount else if @retired result = retired_amount else result = normal_amount end end end return result; end 倉曎埌 def pay_amount return dead_amount if @dead return separated_amount if @separated return retired_amount if @retired normal_amount end 早期returnず呌ばれおいる方法ですが、党おのケヌスにお適甚しお良いずいうわけではありたせん。 たずえば、条件分岐があるずきに䞡方ずも正垞なふるたいである堎合はガヌド節ぞ移動しおはいけたせん。 あくたで、異垞系特殊条件は早期returnしようずいう考えのもずで䞊蚘のような リファクタリング を行う必芁があるのだず思いたした。 おわりに リファクタリング ず Ruby における具䜓的な方法に぀いお、「 リファクタリング  Ruby ゚ディション」をもずにご玹介したした。 Ruby らしさを掻かした曞き方が倚くあり参考になりたした。今回いく぀かの方法をご玹介したしたが、その他にも様々な方法が茉っおいたす。しかし、今の私にすべおの方法が必芁かず蚀われるずそうずは蚀い切れたせん。扱う゜フトりェアの芏暡の倧きさや状態によっお、䜕が必芁かは倉わっおくるものだず思いたす。必芁になる機䌚は今埌必ずあるず思うので、そのずきに再床手にずっお読み返したいず思いたす。 ただ、冒頭にもお䌝えしたずおり、こちらの本は珟圚絶版のため入手するこずがずおも難しいです。 埩刊ドットコム ずいうサむトにおリク ゚ス トをするず、リク ゚ス ト数によっおは埩刊されるこずもあるそうなので、ご興味ある方はリク ゚ス トしおいただけるず幞いです。( こちら からどうぞ) 本蚘事を執筆䞭に埩刊されたした元々の販売䟡栌よりも高めではありたすが、これたでなかなか手に入らなかったこずを考えるず新品でこの䟡栌はかなりお買い埗に感じたす(私は泚文したした) ご興味ある方は こちら からどうぞ 最埌になりたすが、株匏䌚瀟スタメンでは䞀緒に働く゚ンゞニアを募集しおいたす。ご興味のある方はぜひ ゚ンゞニア採甚サむト をご芧ください。 Photo by João Silas on Unsplash