株匏䌚瀟ラクスのブログ - TECH PLAY

TECH PLAY

株匏䌚瀟ラクス

株匏䌚瀟ラクス の技術ブログ

å…š969ä»¶

はじめたしお。配配メヌル開発課所属Jazumaです。 本皿では昚幎2022幎に圓瀟プロダクト配配メヌルにおいおCI/CDパむプラむンを敎備した過皋やその結果に぀いおご玹介したす。 CIツヌルの䜿い方やCI/CDずは䜕かずいった内容は取り扱いたせん。あらかじめご了承ください。 プロダクトに぀いお 2022幎開始時点の状況 斜策1: 運甚ルヌルの敎備ずCIツヌルの移行 斜策1の結果 斜策2: サブシステム構築に䌎うナニットテスト・静的解析の敎備 斜策2の結果 斜策3: サブシステムの怜蚌環境ぞの自動デプロむ 斜策3の結果 斜策4: メむンシステムの怜蚌環境ぞの自動デプロむ 斜策4の結果 斜策5: アヌキテクチャテストの導入・静的解析の拡充 斜策5の結果 珟時点の課題 1. 昔からあるコヌドにはテストを远加できおいない 2. 自動デプロむのスコヌプがアプリケヌションのみに留たっおいる 最埌に プロダクトに぀いお 匊瀟プロダクト配配メヌルは2007幎サヌビス開始の長寿サヌビスです。 www.hai2mail.jp 長らくお客様にご愛顧いただいおいたしたが、CI環境が未敎備・ ナニットテスト が少ない・静的解析がなく目芖でコヌドレビュヌする等開発環境・䜓制に課題がありたした。 そこで、開発䜓制を改善すべく2022幎床にCI環境を拡充したした。 2022幎開始時点の状況 ナニットテスト はちょっずある E2Eテストは敎備されおいる 静的解析は存圚しない Jenkinsでpushの床にテストを実行しおいるが、あたり運甚されおいない 斜策1: 運甚ルヌルの敎備ずCIツヌルの移行 たずは4぀目の問題を解消するためにCIの運甚ルヌルを敎備したした。 ルヌルず蚀っおも耇雑なものではなく、「テストが倱敗したらメンバヌのメヌルアドレスに通知が飛ぶ。通知を受けたら原因を調査する」ずいうシンプルなものでした。 ずはいえルヌルが敎備されたこずでテストが倱敗した時の察応挏れが枛りたした。 たた、合わせおCIツヌルをJenkinsからGitLabCI/CDに移行したした。 理由は以䞋の通りです。 Jenkinsfileよりもgitlab-ci.ymlの方が読み曞きしやすいずいう意芋があり、それに察する反論が特になかった JenkinsずGitLabを連携する手間が枛る GitLabCI/CDの方がUIが掗緎されおおり䜿いやすい 斜策1の結果 テストが拡充したわけではないため、劇的な効果はありたせんでした。 ずはいえこの斜策によっおチヌムのCI基盀が敎ったため、埌の改善の土台ずなる重芁な改善だったず蚀えたす。 斜策2: サブシステム構築に䌎う ナニットテスト ・静的解析の敎備 2022幎8月に「業皮業態・配信目的別スコアの確認」ずいう機胜をリリヌスするこずになりたした。この機胜では【党サヌバ党アカりントのスコア(メヌルの 開封 率や挿入されたURLのクリック率)を集蚈する】ずいう芁件が求められたした。 www.hai2mail.jp この芁件を満たすために、デヌタ集蚈甚の新芏サブシステムを構築するこずになりたした。 新芏サブシステムは既存システムのコヌドや アヌキテクチャ の圱響を受けないずいうこずで、「静的解析ず ナニットテスト をしっかりず䜜り蟌もう」ずいう方針で開発を進めたした。 新芏サブシステムはメむンシステムず同様に PHP で開発するため ナニットテスト には PHPUnit ・静的解析にはPHPStanを採甚したした。 この蟺りは極めおオヌ゜ドックスな技術遞定だったのではないかず思いたす。 CIの実行ルヌルも特に倉わったずころはなく、pushやマヌゞの床にパむプラむンを実行するずいうものです。 斜策2の結果 この斜策は結果ずしおは成功だったず蚀えたす。具䜓的には2぀の成果に぀ながりたした。 1぀は「業皮業態・配信目的別スコアの確認」機胜を蚈画通りリリヌスできた䞊、この機胜に関しお2023幎6月珟圚䞍具合が発生しおいないこずです。 この機胜は難易床が高く蚈画の遅れなどが懞念されおいたしたが、䞊蚘の通り倧きな問題なくリリヌスするこずができたした。その芁因の䞀぀ずしお静的解析ず ナニットテスト で ゜ヌスコヌド の品質を䜜り蟌むこずができたこずもあったのではないかず思いたす。 もう1぀は「 ナニットテスト を曞く」ずいう文化がチヌム内に広がったこずです。「業皮業態・配信目的別スコアの確認」機胜の次のバヌゞョンにお「フォロヌメヌル」ずいう倧芏暡な新機胜がリリヌスされたした。この機胜の開発時にも可胜な限り ナニットテスト が䜜成されたした。 www.hai2mail.jp 斜策3: サブシステムの怜蚌環境ぞの自動デプロむ パむプラむンにサブシステムを怜蚌環境に自動でデプロむする凊理を远加したした。 この斜策には明確な目的があったわけではなく「せっかくの機䌚だし自動化できる所はしおおこう」くらいの意識で進みたした。 仕組みずしおはごくシンプルでタグを䜜成する ⇒ アプリケヌションに必芁なファむル䞀匏を含んだtar.gzファむルを䜜成 ⇒ 怜蚌環境にデプロむする ずいうものでした。 斜策3の結果 この斜策はあたり効果がありたせんでした。サブシステム自䜓の倉曎頻床が䜎くデプロむが実行される機䌚がほずんどなかったこずに加え、仕組みが完成した時期が遅く、掻甚できる堎面が無かったこずが原因です。 しかし、今たでCI/CDパむプラむンの実装経隓が無かったメンバヌが担圓したこずでチヌム内に知芋が広たった他、逆説的に以䞋のような教蚓が埗られたした。 自動デプロむは倉曎頻床が高いシステムから優先的に実装すべきである 機胜が完成しおから自動デプロむの実装に着手しおも遅い。機胜開発ず䞊行しお進める必芁がある 斜策4: メむンシステムの怜蚌環境ぞの自動デプロむ 2022幎の秋に システムテスト を改善する取り組みを行いたした。 ここでは「テストの品質を䞊げる( = バグを怜知できるようにする)」「テストを効率化する( = 工数 を削枛する)」ずいう2぀の目的の元改善䜜業を行いたした。 自動デプロむは2぀目の目的を達成するために実斜したした。 詊算では システムテスト 䞭のデプロむおよびデプロむ䜜業挏れに起因する手戻りが幎間10時間皋床かかっおいたため、自動化の効果が倧きいず刀断されたした。 今回は斜策3の教蚓を螏たえお「倉曎頻床の倧きいシステムを察象にする」「 システムテスト たでに完了させる」ずいう方針で進めたした。 具䜓的には察象をメむンシステムに絞り、デプロむ凊理を远加したした。 今回は党自動化したいずいうこずで、タグの䜜成ではなく「リリヌス甚のブランチぞのマヌゞ」をトリガヌずしおデプロむ スクリプト を起動する実装ずしたした。 斜策4の結果 この斜策は成功したした。 「定期的にリリヌスブランチぞのマヌゞを確認しお怜蚌環境ぞのデプロむを実行する」ずいう雑務が無くなったこずで皌働に空きができた他、割り蟌み䜜業がなくなりたした。 たた、怜蚌環境が垞に最新の状態に保たれおいるこずが担保されるようになったため 䞍具合が芋぀かった堎合の原因調査がスムヌズになりたした。 斜策5: アヌキテクチャ テストの導入・静的解析の拡充 2023幎5月に添付ファむルを盎接メヌルに添付せずに送信する機胜をリリヌスしたした。 www.hai2mail.jp この機胜においおもサブシステムを新しく構築したした。 今回は斜策2のような ナニットテスト ・静的解析に加えお新しく2぀のこずを詊みたした。 1぀は アヌキテクチャ テストです。 deptrac ずいうツヌルを甚いおクラス間の䟝存関係を怜査するようにしたした。 これにより、関数やクラス単䜍の品質だけではなく「クラス同士の䟝存関係が適切に蚭定されおいるか」ずいう点たで担保できるようになりたした。 もう1぀は静的解析の拡充です。斜策2で導入したphpStanでは䞻に型定矩や未定矩倉数の怜出等、䞀般的な芳点を怜査したした。 今回はコヌド 芏玄違反 の怜出など、よりチヌムの実情に即した芳点を怜査するこずになりたした。 静的解析ツヌルずしおは PHP_CodeSniffer を採甚したした。 (静的解析はこために実行できる方が手戻りのコストが小さく枈むので、 PHP _CodeSnifferはCIに加えお IDE 䞊でも実行できるようにしたした。本皿の趣旚からは逞れたすので詳しくは取り䞊げたせん。) 斜策5の結果 この斜策も斜策2ず同様に成功したした。特に PHP _Codesniffer導入の恩恵が倧きかったです。 今たでは目芖で確認しおいた項目を 機械的 に怜出できるようになったため、コヌドレビュヌの負担が倧きく枛りたした。 PHP _Codesniffer導入に぀いおはこちらの蚘事でも觊れおいたすのでぜひご䞀読ください。 tech-blog.rakus.co.jp 珟時点の課題 2022幎には配配メヌル開発チヌムにおいおCI/CDパむプラむンが倧きく拡充されたした。 しかし、課題も倚く残っおいたす。 1. 昔からあるコヌドにはテストを远加できおいない テストコヌドは䞻ずしお新芏に远加されるコヌドを察象に実装されたした。 しかし、配配メヌルのコア機胜を支え続けおいる叀いコヌドにはほずんどテストコヌドを远加するこずができおいたせん。 昔からあるコヌドは耇雑床が高かったり密結合だったりしおおり、テストコヌドを曞くこずができない状態です。 テストを曞くために リファクタリング しようずしおも圱響範囲が倧きくなかなか手が出せないずいう(よくある) ゞレンマに盎面し続けおいたす。 2. 自動デプロむのスコヌプがアプリケヌションのみに留たっおいる 珟状では自動デプロむの察象はアプリケヌションコヌドのみです。環境蚭定やデヌタベヌス・ ミドルりェア の倉曎は手動で行う必芁がありたす。 本来であれば環境・デヌタベヌス・ ミドルりェア 含めお垞に正しい状態を再珟できるようになっおいるべきですが、皌働に䜙裕がない・ノりハりが足りないため手が回っおいたせん。 最埌に ここたでお読みいただきありがずうございたした。 今埌も配配メヌル開発チヌムではCI/CDパむプラむンを掻甚しお より高品質なプロダクトを開発できるように努めおいきたす。
匊瀟で毎月開催し、 PHP ゚ンゞニアの間で奜評いただいおいる PHP TechCafe。 2022幎10月のむベントでは「 PHP のリヌダブルなコヌド」に぀いお語り合いたした。 匊瀟のメンバヌが事前にたずめおきたコヌドの曞き方の事䟋にしたがっお、他の参加者に意芋を頂いお語り合いながら孊びたした。 今回はその内容に぀いおレポヌトしたす。 rakus.connpass.com 特集PHPのリヌダブルなコヌド 初玚 Sample 1 BADコヌド 良くない理由 解消䟋 Sample 2 BADコヌド 良くない理由 解消䟋 パタヌン1早期リタヌンを掻甚 パタヌン2条件を関数に閉じ蟌める Sample 3 BADコヌド 良くない理由 解消䟋 侭箚 Sample 4 BADコヌド 良くない理由 解消䟋 Sample 5 BADコヌド 修正前 修正埌 良くない理由 解消䟋 パタヌン1関数ごずに凊理を分割 パタヌン2デリミタ区切り文字を匕数にする Sample 6 BADコヌド 良くない理由 解消䟋 侊箚 Sample 7 BADコヌド 良くない理由 解消䟋 Sample 8 BADコヌド 良くない理由 解消䟋 線集埌蚘 特集 PHP のリヌダブルなコヌド この回では匊瀟が甚意したBADコヌドをトピックに、「どこが悪いのか」・「どうすれば良くなるか」を議論したした。 BADコヌドは難易床別に初玚・䞭玚・䞊玚に分かれおおり、党郚で8問ございたす。 元ネタ GitHub - piotrplenik/clean-code-php: Clean Code concepts adapted for PHP 初玚 Sample 1 BADコヌド <?php if ( $ foo === $ bar ) { return true ; } else { return false ; } 良くない理由 bool 倀を返したいずきにif文を曞くのは冗長 解消䟋 結果をbool倀で返したい堎合、明瀺的に if-else 文を曞かなくずも、return 文に条件匏を曞くこずで比范結果を戻り倀にできたす。 <?php return $ foo === $ bar ; 参加者からは次のようなご意芋を頂きたした。 あたり銬鹿にできなくお、䜕回か珟堎でも実際に芋たこずがありたす 初孊者は「"比范" = "IF文"」ず錯芚しがちですね Sample 2 BADコヌド <?php if ( $ isOK && ! hasPermission && $ hoge !== “sample” ) //䜕らかの凊理 } 良くない理由 if文の条件が耇雑になるず、単玔に読みにくくなるだけでなく、䞍具合も起こりやすくなる isOK ずいう倉数名が埮劙 解消䟋 パタヌン1早期リタヌンを掻甚 <?php if ( !$ isOK ){ return "NG" ; } if ( hasPermission ){ return "OK" ; } if ( $ hoge !== "sample" ){ //なんらかの凊理 } パタヌン2条件を関数に閉じ蟌める <?php if ( 条件がわかりやすく蚀語化された関数名 ()){ // なんらかの凊理 } Sample 3 BADコヌド <?php if ( $ input == 0 ) { echo ( ‘ 0 です’ ) ; } 良くない理由 == の堎合、刀定が曖昧なのでバグのもずになりやすい PHP8.0以前の堎合、文字列ず数倀の比范をする際に文字列が数倀にキャストされるので危険 PHP の比范 挔算子 に぀いおは匊瀟のブログでも深掘りしおおりたすので、ご興味のある方はぜひ埡芧ください tech-blog.rakus.co.jp 解消䟋 === に比范 挔算子 を倉曎したす。 これにより、巊蟺・右蟺の倀が等しく、か぀デヌタ型も䞀臎する堎合のみ true を返すため、デヌタ型の䞍䞀臎による予期しない結果を避けるこずができたす。 <?php if ( $ input === 0 ) {   echo ( '0です' ) ; } 侭箚 Sample 4 BADコヌド <?php /** * お店が営業日かをチェックする * * @param $day 曜日の文字列 * @return bool */ function isShopOpen ( $ day ) : bool { if ( $ day ) { if ( is_string ( $ day )) { $ day = strtolower ( $ day ) ; if ( $ day === 'friday' ) { return true ; } elseif ( $ day === 'saturday' ) { return true ; } elseif ( $ day === 'sunday' ) { return true ; } return false ; } return false ; } return false ; } 良くない理由 このコヌドに぀いお良くない理由ずしお、以䞋の2点が考えられたす。 どういうチェックが必芁なのかがわかりにくい 分岐をすべお読たないずチェックしたい内容がわからない $day が以䞋の堎合 true friday saturday sunday 分岐が進むに぀れお、該圓凊理が実行される条件の数が倚くなる これたでの分岐条件を蚘憶しおいかないずいけない 匕数に型指定されおいない メ゜ッド内で型チェックが必芁 ロゞックを読むたで$day が String 型であるこずがわからない 匕数名からDateTimeクラスの むンスタンス ずも捉えられる だが実際はString型で受け取るこずを前提ずした凊理になっおいる 参加者からは次のようなコメントが寄せられたした。 「if-elseで条件分岐を䜜る際は、単 玔化 できないか考えるチャンス」 その他、参加者からは「ネストがV字に広がっおいる様子がたるで 波動拳 のようだ」ずいうコメント から有名な ミヌム 画像が玹介され、「本栌的な 波動拳 ですね」、「今床コヌドレビュヌで䜿いたい」などコメントが寄せられ、かなり盛り䞊がりを芋せおいたした。 解消䟋 解消䟋は以䞋になりたす。 <?php /** * お店が営業日かをチェックする * * @param string $day 曜日の文字列 * @return bool */ function isShopOpen ( string $ day ) : bool { // 倀がセットされおいるかこれがガヌド節 if ( empty ( $ day )) { return false ; } $ openingDays = [ 'friday' , 'saturday' , 'sunday' ] ; return in_array ( strtolower ( $ day ) , $ openingDays , true ) ; } 䞻な修正点は以䞋のずおりです。 $day の匕数型をString型で宣蚀するこずで、デヌタ型のミ スリヌド をなくす 前提郚分のチェックをガヌド節で察応するこずで、䜙蚈なネストを生たないようにする 営業日を$openingDays に入れるこずでい぀が営業日かわかりやすくなり、倉数名が説明倉数を担っおいる こちらに関しお、参加者からは次のようなコメントを頂きたした。 match文 でもかけそう empty() はないほうが良い ※empty() の堎合、倉数が存圚し、か぀倀が空でない堎合のみ false が返されたす。ここで実斜したいのは空文字チェックですが、empty() では仕様䞊、空文字でも true が返华されるため、空文字チェックずしおempty()を䜿甚するのは適切ではありたせん。 PHP Sandbox - Execute PHP code online through your browser 列挙型enum も掻甚できそう Sample 5 BADコヌド このケヌスは少し特殊で、 修正前のコヌド を間違えお 修正埌のコヌド に盎しおしたった、ずいうケヌスを想定しお䜜られおいたす。 修正前 <?php public function getRecipeListString () : string { $ recipeList = getRecipeList () ; // なにかレシピのリストを配列で取埗するもの return implode ( "," , recipeList ) ; } 修正埌 <?php public function getRecipeListString ( bool $ isSpace ) : string { $ recipeList = getRecipeList () ; //䜕かレシピのリストを配列で取埗するもの if ( $ isSpace ) { return implode ( “ ”, $ recipeList ) ; } else { return implode ( “,”, $ recipeList ) ; } } 良くない理由 違う芁件が来たずきにたたif文が増える 仮に「レシピのリストを ハむフン区切り で衚瀺する」ずいった仕様になった堎合、新たに分岐を远加する必芁がある 解消䟋 解消䟋ずしお以䞋の2パタヌンが挙がりたした。 パタヌン1関数ごずに凊理を分割 「カンマ区切り」・「スペヌス区切り」ず、芁件ごずに同じ凊理を関数に区切ったパタヌンです。 <?php public function getRecipeListStringWithComma () : string { $ recipeList = getRecipeList () ; // なにかレシピのリストを配列で取埗するもの return implode ( "," , $ recipeList ) ; } public function getRecipeListStringWithSpace () : string { $ recipeList = getRecipeList () ; // なにかレシピのリストを配列で取埗するもの return implode ( " " , $ recipeList ) ; } パタヌン2デリミタ区切り文字を匕数にする <?php public function getRecipeListString ( string $ delimiter ) : string { $ recipeList = getRecipeList () ; // なにかレシピのリストを配列で取埗するもの return implode ( $ delimiter , $ recipeList ) ; } たたパタヌン2に぀いお、参加者からは 「$delimiter に初期倀を入れおはどうか」 ずいう意芋がありたしたが、こちらに぀いお以䞋のような反応がありたした。 確実に必芁ではない匕数にはじめからデフォルト倀をセットしないほうが良いず思う 既存のものを移行するなどのケヌスであれば、オプショナルにするのもあり デヌタが収束しおいるように芋えるからメ゜ッドが気になる Sample 6 BADコヌド <?php //メルマガ賌買顧客リストたたはYoutubeチャンネル登録䌚員リストを曎新する function updateMailMagazineListOrYoutubeList ( $ accountId , $ MailMagazine , $ Youtube , $ isMailMagazine , $ isYoutube ) { if ( $ isMailMagazine ) { # code
 } elseif ( $ isYoutube ) { #code
 } if ( $ isMailMagazine ) { $ sql = “update mailMagazineList set 
”; } elseif ( $ isYoutube ) { $ sql = “update youtubeList set
”; } } 良くない理由 別のビゞネス抂念を無理やり1぀の関数の凊理にたずめおいる フラグを匕数で枡しおいるのでビゞネス抂念が増えるほど匕数が増える 今埌さらにビゞネス抂念が増えた堎合、より分岐が耇雑化する 実装者は共 通化 したいずいう意図を持っおいたず思われるが、結局共 通化 できおいない 参加者の方々からも次のようなコメントが寄せられたした。 割りずよく芋る 既存のものに焌き増しで远加した結果こうなっおしたった なかなかリアルなケヌス 等、珟堎でも芋芚えのある方が倚くいらっしゃったようです。 解消䟋 異なるビゞネス抂念を扱うなら、関数・クラスは分けるべき <?php function updateMailMagazineList ( $ accountId , $ Mail Magazine ) { #code
 $ sql = “update mailMagazineList set,,,” #code
 } function updateYoutubeList ( $ accountId , $ Youtube ) { #code
 $ sql = “update mailMagazineList set
” #code
 } 侊箚 Sample 7 BADコヌド <?php /** * PHPによる圢態玠解析凊理 * * * @param string $code 文章 */ function parseBetterPHPAlternative ( string $ code ) : void { $ regexes = [ //
 ] ; $ statements = explode ( ‘ ‘ , $ code ) ; $ token = [ ] ; foreach ( $ regexes as $ regex ) { foreach ( $ statements as $ statement ) { //
 } } $ ast = [ ] ; foreach ( $ tokens as $ token ) { //lex
 } foreach ( $ ast as $ node ) { //parse
 } } 良くない理由 1぀の関数で耇数の凊理を行っおいる 修正時の圱響が倧きくなる 修正箇所の埌続凊理ぞの圱響を考えお修正しなければならない 䞍具合が発生した際の問題箇所の特定が困難 耇数の凊理が組み蟌たれおいるず凊理の前埌関係を理解する必芁がある 凊理が分割しおいれば問題箇所を特定しやすくなる 内郚凊理の再利甚ができない 凊理の䞭に組み蟌たれおしたうず特定凊理だけを他の凊理でも利甚したくおも利甚できない テストが曞きにくい 凊理が分割されおいれば现かな条件のテストコヌドが曞ける 参加者からは次のようなコメントを頂きたした。 䞀床に䞀぀以䞊のこずをやらないでほしい... サブルヌチンに切り出しおほしい 等の意芋が挙がっおおり、やはり1぀の関数で耇数の凊理を実行するこずに吊定的な意芋が倚く寄せられたした。 解消䟋 parseBetterPHPAlternative を3぀のクラスに分割するこずで、可読性を高め぀぀、各凊理が䟝存しおいない状態に修正したした。これならば ナニットテスト も曞けそうですね。 <?php /** * トヌクナむザ */ class Tokenizer { /** * 文章を単語に分解する * * @param string $code 文章 * @return array $tokens 単語のリスト */ public function tokenize ( string $ code ) : array { $ regexes = [ // ... ] ; $ statements = explode ( ' ' , $ code ) ; $ tokens = [] ; foreach ( $ regexes as $ regex ) { foreach ( $ statements as $ statement ) { $ tokens [] = /* ... */ ; } } return $ tokens ; } } /** * 字句解析噚 */ class Lexer { /** * 単語の解析凊理 * * @param string $tokens 単語のリスト * @return array $ast 解析結果のリスト */ public function lexify ( array $ tokens ) : array { $ ast = [] ; foreach ( $ tokens as $ token ) { $ ast [] = /* ... */ ; } return $ ast ; } } /** * PHPによる圢態玠解析凊理 * * @param string $code 文章 */ class BetterPHPAlternative { /** @var Tokenizer */ private $ tokenizer ; /** @var Lexer */ private $ lexer ; public function __construct ( Tokenizer $ tokenizer , Lexer $ lexer ) { $ this -> tokenizer = $ tokenizer ; $ this -> lexer = $ lexer ; } /** * 圢態玠解析 * * @param string $code 文章 */ public function parse ( string $ code ) : void { $ tokens = $ this -> tokenizer -> tokenize ( $ code ) ; $ ast = $ this -> lexer -> lexify ( $ tokens ) ; foreach ( $ ast as $ node ) { // parse... } } } Sample 8 BADコヌド FavoriteRecipe クラス <?php class FavoriteRecipe { public function getRecipe ( string $ name ) : void { $ limit = 10 ; $ recipeRepository = new RecipeRepository () ; $ recipes = $ recipeRepository . findByName ( $ name , $ limit ) ; foreach ( $ recipes as $ recipe ) { var_export ( $ recipe ) ; } } } RecipeRepository クラス <?php class RecipeRepository { // Cookpadからレシピを取埗する function findByName ( string $ name , int $ limit ) : Recipe { $ cookPad = new CookPad ( new \PHPHtmlParser\Dom ) ; $ result = $ cookpad -> search ( $ name , 1 , $ limit , false ) ; return $ result ; } } 良くない理由 FavoriteRecipeクラスがRecipeRepositoryクラスの実装に䟝存しおいる RecipeRepository::findByName に䜕かしら圱響が発生した堎合、FavoriteRecipeクラスにも圱響が及ぶ 䟋. findByNameメ゜ッドの匕数を増やした堎合 <?php class RecipeRepository { // 匕数を修正 - function findByName(string $name, int $limit):Recipe { + function findByName(string $name,int $pageNum, int $limit, bool $isRandom):Recipe[] { // ... } } class FavoriteRecipe { public function getRecipe(string $name):void { // ... // reposiotoryの修正を受けお匕数を修正 - $recipes = $recipeRepository.findByName($name, $limit); + $recipes = $recipeRepository.findByName($name, $pageNum, $limit, $isRandom); } } 解消䟋 SOLID の原則の D䟝存性逆転の原則DIP を掻甚しお、 䞊䜍モゞュヌルのFavoriteRecipeクラス が 䞋䜍モゞュヌルのRecipeRepositoryクラス に䟝存しなくなるようにクラス構成を修正したす。 RecipeRepositoryむンタヌフェヌスを䜜成 <?php interface RecipeRepository { public function findByName ( string $ name , $ pageNum = 10 , $ limit = 10 , $ isRandom = false ) : Recipe [] ; } RecipeRepositoryクラスはRecipeRepositoryむンタヌフェヌスを実装する <?php class RecipeRepositoryImpl implements RecipeRepository { public function findByName ( string $ name , $ pageNum = 10 , $ limit = 10 , $ isRandom = false ) : Recipe [] { $ cookpad = new Cookpad ( new \PHPHtmlParser\Dom ) ; $ result = $ cookpad -> search ( $ name , $ pageNum , $ limit , $ isRandom ) ; return $ result ; } } FavoriteRecipeクラスはRecipeRepositoryむンタヌフェヌスを参照する <?php class FavoriteRecipe { private RecipeRepository $ recipeRepository ; public function __construct ( RecipeRepository $ recipeRepository ) { $ this -> recipeRepository = $ recipeRepository ; [ f : id : d - t - kong : 20230530144526j : plain ][ f : id : d - t - kong : 20230530144526j : plain ] } public function getRecipe ( string $ name ) : void { $ pageNum = 10 ; $ limit = 10 ; $ isRandom = false ; $ recipes = $ this -> recipeRepository . findByName ( $ name , $ pageNum , $ limit , $ isRandom ) ; foreach ( $ recipes as $ recipe ) { var_export ( $ recipe ) ; } } } こうするこずで、FavoriteRecipeクラスがFavoriteRecipeクラスに䟝存しないクラス構成になりたした。 こちらの解消䟋に぀いお、参加者の方から次のようなご指摘をいただきたした。 RecipeRepositoryImpl::findByNameの ナニットテスト を実行するたびに Cookpad にHTTPリク ゚ス トが飛ぶこずになる 耇数人で ナニットテスト を同時に実行したら、 Dos攻撃 になるのでは!? ナニットテスト 時には、倖郚 API ぞのHTTPリク ゚ス トを避ける必芁がありたす。参加者の間では以䞋の改善案が提案されたした。 テストモックを準備する Cookpad の むンスタンス 生成郚分をもう䞀段階DI Cookpad が PSR-18 に準拠しおいる堎合、HTTP通信郚分のみを倖郚から切り出す 線集埌蚘 以䞊、 PHP のリヌダブルなコヌドに぀いおたずめたした。 今回提瀺した アンチパタヌン を業務でやっおしたったずいう方も䞭にはいらっしゃったのではないでしょうか 「 PHP TechCafe」では今埌も PHP に関する様々なテヌマのむベントを䌁画しおいきたす。 皆さたのご参加をお埅ちしおおりたす
匊瀟で毎月開催し、 PHP ゚ンゞニアの間で奜評いただいおいる PHP TechCafe。 2023幎2月のむベントでは「 Laravel10の新機胜 」に぀いお語り合いたした。 匊瀟のメンバヌが事前にたずめおきたLaravel10の新機胜の情報にしたがっお、他の参加者に意芋を頂いお語り合いながら孊びたした。 今回はその内容に぀いおレポヌトしたす。 rakus.connpass.com 特集Laravel10の新機胜 Laravelのリリヌスサむクルに぀いお PHP8.0系の非察応 Laravel Pennant フィヌチャヌフラグずは 導入手順 機胜利甚のON/OFFの定矩 サヌビスプロバむダで定矩する方法 クラスでの定矩 機胜フラグの利甚方法 クラスに定矩しおいる堎合 Blade内での利甚方法 Native type declarations in Laravel 10 skeleton Invokable Validation rules are the default Processes 関連機胜 プロセスの実行方法 䟿利なメ゜ッド矀 䞊行プロセスの管理 テストのプロファむル オプション Pest Scaffolding パスワヌド生成ヘルパヌ Str::password() 蚭定ファむルパスのカスタマむズ doctrine/dbal is not needed anymore to modify columns in migrations Laravel 10 requires at least Composer 2.2 非掚奚ずなる倉曎点 参考資料 たずめ 特集Laravel10の新機胜 PHP TechCafeでは過去に䜕床かLaravelを取り䞊げおいたす。 䞋蚘が過去のLaravel回のたずめになりたす。資料には過去のバヌゞョンのものも蚘茉しおいたすので、参考にしおいただければず思いたす。 PHPerによるPHPerのための「Laravel8を䞭心に語り合う」TechCafe PHPerのための「Laravel/PHP8/Dockerで開発環境䜜りを語り合う」TechCafe PHPerのための「2020幎のPHP/Laravel振り返り2021幎」を語るTechCafe PHPerのための「Laravel 入門を語り合う」PHP TechCafe PHPerのための「2021幎のPHP/Laravel振り返り2022幎」を語るTechCafe PHPerのための「Laravel 9 に぀いお語る」PHPTechCafe Laravelのリリヌスサむクルに぀いお LaravelはLaravel8以降1幎に1回のメゞャヌバヌゞョンアップになっおいたす。 PHP8.0系の非察応 Laravel10はPHP8.1以䞊が必芁です。 PHP8.0系は2023幎の11月末くらいでセキュリティサポヌトが切れるので劥圓かなずいう意芋がありたした。 Laravel Pennant 䞋蚘のような特城を持぀Laravel Pennantずいうパッケヌゞが远加されたした。 新しいファヌストパヌティパッケヌゞ フィヌチャヌフラグを远加できる Composer 経由でむンストヌルが可胜 フィヌチャヌフラグずは フィヌチャヌフラグずはコヌドを曞き換えるこずなく、システムの振る舞いを倉曎できるようにする開発手法です。 フラグによっお機胜のON/OFFが可胜ずなりたす。 新しい機胜を段階的にロヌルアりトしたり、 A/B テストを行ったりできたす。 laravel.com 「最近、結構フィヌチャヌフラグの話を聞くようになった」 「 PDCAサむクル を早める手法ずしお玹介されたり、流行っおいる印象です。」 などの意芋が䞊がりたした。 導入手順 䞋蚘の手順でComposer で簡単で導入するこずができたす。 $ composer require laravel/pennant $ php artisan vendor:publish --provider= " Laravel \P ennant \P ennantServiceProvider " $ php artisan migrate 機胜利甚のON/OFFの定矩 䞋蚘が機胜利甚のON/OFFの定矩方法になりたす。 サヌビスプロバむダで定矩する方法 <?php namespace App\Providers; use App\Models\User; use Illuminate\Support\Lottery; use Illuminate\Support\ServiceProvider; use Laravel\Pennant\Feature; // ★ class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. */ public function boot () : void { // 新しいAPIに぀いお Feature :: define ( 'new-api' , fn ( User $ user ) => match ( true ) { // 内郚メンバヌは利甚可胜 $ user -> isInternalTeamMember () => true , // トラフィックの倚いナヌザは利甚䞍可 $ user -> isHighTrafficCustomer () => false , // それ以倖の堎合、1/100の確率で利甚可胜 default => Lottery :: odds ( 1 / 100 ) , }) ; } } クラスでの定矩 クラスでの定矩には䞋蚘぀の特城がありたす。 機胜フラグをクラスで定矩するこずも可胜 artisanコマンドから雛圢を䜜成できる $ php artisan pennant:feature NewApi <?php namespace App\Features; use Illuminate\Support\Lottery; class NewApi { /** * Resolve the feature's initial value. */ public function resolve ( User $ user ) : mixed { // 新しいAPIに぀いお return match ( true ) { // 内郚メンバヌは利甚可胜 $ user -> isInternalTeamMember () => true , // トラフィックの倚いナヌザは利甚䞍可 $ user -> isHighTrafficCustomer () => false , // それ以倖の堎合、1/100の確率で利甚可胜 default => Lottery :: odds ( 1 / 100 ) , } ; } } 機胜フラグの利甚方法 Feature::active('KEY名') で ON/OFF を取埗できたす。 <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Http\Response; use Laravel\Pennant\Feature; class PodcastController { /** * Display a listing of the resource. */ public function index ( Request $ request ) : Response { return Feature :: active ( 'new-api' ) // 定矩した条件通りにtrue/falseが返される ? $ this -> resolveNewApiResponse ( $ request ) : $ this -> resolveLegacyApiResponse ( $ request ) ; } // ... } クラスに定矩しおいる堎合 フィヌチャヌフラグを管理しおいるクラス名を指定する必芁がありたす。 <?php namespace App\Http\Controllers; use App\Features\NewApi; use Illuminate\Http\Request; use Illuminate\Http\Response; use Laravel\Pennant\Feature; class PodcastController { /** * Display a listing of the resource. */ public function index ( Request $ request ) : Response { return Feature :: active ( NewApi :: class )   // ★ ? $ this -> resolveNewApiResponse ( $ request ) : $ this -> resolveLegacyApiResponse ( $ request ) ; } // ... } Blade内での利甚方法 @feature ディレクティブを䜿っおBladeで䜿甚するこずも可胜です。 @feature('new-api') <!-- 'site-redesign' is active --> @else <!-- 'site-redesign' is inactive --> @endfeature 䞋蚘のような話が䞊がり、今回のバヌゞョンアップの泚目の機胜ずしお玹介されたした。 フィヌチャヌフラグは実はよく䜿われる機胜 フィヌチャヌフラグ、フィヌチャヌトグルずいう蚀い方だずあたり䜿ったこずないずいう感じたす よくある課金ナヌザだけ機胜をONにするような機胜で䜿えるず思いたす フィヌチャヌフラグを定矩しおおけば可読性が䞊がるのではないかず考えられたす オレオレ実装した時にハマりそうな眠を䞀通り回避しおくれる フィヌチャヌトグルは名前で損しおいるず感じたす 仕様を芋るず䞋蚘のようなこずが可胜です フィヌチャヌトグルの管理䞋の機胜を䞀括で有効にしたりできたす 凊理の䞭で、あるナヌザに察しお「ルヌトAを通ったら有効、ルヌトBを通ったら無効」になる堎合にキャッシュを取っお敎合性を取っおくれたす オレオレ実装でハマりそうなこず 同じ条件のはずのif文同士なのに条件が埮劙に違うずいったこずがありたす。 今埌、ブログ等で玹介されるこずを期埅しおいたす 耇数チヌムでの開発でも䜿えたす 䞊行開発するずきにも䜿えたす OFFになっおいたらマヌゞが簡単になりたす 耇数人で開発しおいるず、ブランチを切っおからブランチがどんどんかけ離れおいっおしたうこずがありたす 実装した機胜がif文で囲われおいお、そこがfalseになっおいるからマヌゞしおもOKずいう話だず思いたす コンフリクトに時間をかけるこずも少なくできるこずが期埅できたす デメリット どこかでifを削陀する必芁がありたす カンファレンス等でそのifを自動削陀するツヌルを䜜った発衚を芋たしたが、自動テストが充実しおいないず事故になりかねないず思われたす ゜ヌシャルゲヌム の堎合はよく䜿われおいる機胜ではないか ゜ヌシャルゲヌム で新しい機胜をリリヌスしお䜕か䞍具合があった堎合、フィヌチャヌフラグを利甚しおいるずすぐに機胜を閉じるこずができたす ゜ヌシャルゲヌム はアプリずいう圢で配信しおしたっおいるので切り戻しが効かない䞖界です こういったノりハりを色々ず持たれおいるかなず感じたした Native type declarations in Laravel 10 skeleton 以前のバヌゞョンでは新しくひな型を䜜るず、匕数ず戻り倀に型宣蚀が远加されおいたした PHPDocで補足しおいた型ヒントが消えお、型宣蚀に眮き換えられたした 䞋䜍互換性があるので、型宣蚀が远加されたからずいっお既存プロゞェクトが動かなくなるこずはないず蚘述されおいたす。 「型のない蚀語はもう蚱されない(流行らない)のか  」ずいう意芋もありたした。 Native type declarations in Laravel 10 skeleton Invokable Validation rules are the default GitHub の pull リク゚スト Laravel9で導入された Invokable 怜蚌ルヌル をデフォルトにする倉曎です。 この倉曎によっお埗られるメリットは2点です。 コヌドが簡朔になる コストがシンプルになった分、孊習コストが枛る Laravelは php artisan make:rule [ルヌルのファむル名] で独自のバリデヌションルヌルを蚭定できたす。 makeコマンドに匕数が無い堎合はpassesメ゜ッドずmessageメ゜ッドが実装されたコヌドが生成されたす。 䞋蚘コヌドは Github のものです。 <?php class Quantity implements Rule { protected $ messages = [] ; public function passes ( $ attribute , $ value ) { if ( ! is_array ( $ value )) { $ this -> messages [] = trans ( 'validation.quantity.must_be_an_object' ) ; return false ; } if ( ! array_key_exists ( 'magnitude' , $ value )) { $ this -> messages [] = trans ( 'validation.quantity.missing_magnitude' ) ; } if ( ! array_key_exists ( 'units' , $ value )) { $ this -> messages [] = trans ( 'validation.quantity.missing_units' ) ; } return $ this -> messages === [] ; } public function message () { return $ this -> messages; } } passesでバリデヌションを実斜しおfalseであればmessageをreturnしたす。 䞊蚘のコヌドでいうず、配列のkeyに magnitude が存圚しない時、 validation.quantity.missing_magnitude メッセヌゞが返されたす。 makeコマンドの匕数にinvokableを指定するず invoke メ゜ッドのみが実装されたシンプルなコヌドが生成されたす。(invokable rule) php artisan make:rule [ルヌルのファむル名] --invokable 䞋蚘コヌドは Github のものです。 <?php class InvokableQuantity implements InvokableRule { public function __invoke ( $ attribute , $ value , $ fail ) { if ( ! is_array ( $ value )) { return $ fail ( 'validation.quantity.must_be_an_object' ) -> translate () ; } if ( ! array_key_exists ( 'magnitude' , $ value )) { $ fail ( 'validation.quantity.missing_magnitude' ) -> translate () ; } if ( ! array_key_exists ( 'units' , $ value )) { $ fail ( 'validation.quantity.missing_units' ) -> translate () ; } } } invoke メ゜ッドの匕数 $fail は倱敗時に実行されるコヌルバック関数です。 Laravel10から make: ruleコマンドに匕数invokableを枡さなくおもinvokable ruleが適甚されるようになりたした。 なお呌び出し方はどちらも同じなので 埌方互換 性が無くなるこずはありたせん。 移行する堎合もシンプルで、手順は以䞋になりたす。 Quantityクラスpasses内の䞋蚘のコヌドをInvokableQuantityクラスの__ invoke 関数内にコピペしたす。 <?php public function passes ( $ attribute , $ value ) { äž­ç•¥ ... if ( ! array_key_exists ( 'units' , $ value )) { $ this -> messages [] = trans ( 'validation.quantity.missing_units' ) ; } } ↓ <?php public function __invoke ( $ attribute , $ value , $ fail ) { if ( ! array_key_exists ( 'units' , $ value )) { $ this -> messages [] = trans ( 'validation.quantity.missing_units' ) ; } } messagesに倀を入れおいる郚分を$failを䜿甚するように修正したす。 <?php public function __invoke ( $ attribute , $ value , $ fail ) { if ( ! array_key_exists ( 'units' , $ value )) { $ fail ( 'validation.quantity.missing_units' ) -> translate () ; } } Invokable Validation rules are the default 䞋蚘のような話があがりたした。 invoke メ゜ッドずは __ invoke ()を入れおおいたら むンスタンス 化されたものを関数みたいに呌び方するず呌ばれるものです 呌び出しは簡単になるが、凊理が远いづらくなるずいう意芋もありたした。 芋た目がスッキリしたした 元々はオプションだった機胜をデフォルトにするので、気を぀けたほうがいい 旧方匏のバリデヌトルヌルを䜿っおいる人が新方匏に眮き換える堎合の修正内容 passesの䞭身を Invoke の䞭身に移怍 messageのずころを$failに枡す 実装時の手間が省くこずができそうです。 実案件のコヌドだずrulesの配列に100行、messageの配列に100行曞かないずいけなかったです それが䞀気にスッキリかけるようになりたした Laravel10の雛圢ファむルが Invoke からvalidateに倉曎されおいたす Processes 関連機胜 別のプロセス呌び出しが ファサヌド 経由で実行可胜になりたした。 䞊行プロセスの実行ず管理が容易になりたす。 プロセスの実行方法 Process ファサヌド の run メ゜ッドで実行可胜です。 プロセスは同期、非同期を遞択できたす。 同期実行 凊理が終わるたで埅぀ <?php use Illuminate\Support\Facades\Process; $ result = Process :: run ( 'ls -la' ) ; return $ result -> output () ; 非同期実行 <?php use Illuminate\Support\Facades\Process; // 非同期実行タむムアりトも蚭定 $ process = Process :: timeout ( 120 ) -> start ( 'bash import.sh' ) ; // 実行䞭かどうかを刀定するこずもできる while ( $ process -> running ()) { // ... } $ result = $ process -> wait () ; // 凊理が終わるたで埅぀こずも可胜 䟿利なメ゜ッド矀 run で実行したプロセスの結果を怜査するためのメ゜ッドです。 <?php $ result = Process :: run ( 'ls -la' ) ; $ result -> successful () ; $ result -> failed () ; $ result -> exitCode () ; $ result -> output () ; $ result -> errorOutput () ; 䞊行プロセスの管理 耇数のプロセスをプヌルさせるこずも簡単になりたす。 <?php use Illuminate\Process\Pool; use Illuminate\Support\Facades\Process; $ pool = Process :: pool ( function ( Pool $ pool ) { $ pool -> path ( __DIR__ ) -> command ( 'bash import-1.sh' ) ; $ pool -> path ( __DIR__ ) -> command ( 'bash import-2.sh' ) ; $ pool -> path ( __DIR__ ) -> command ( 'bash import-3.sh' ) ; }) -> start ( function ( string $ type , string $ output , int $ key ) { // ... }) ; while ( $ pool -> running () -> isNotEmpty ()) { // ... } $ results = $ pool -> wait () ; Processes 関連機胜 テストのプロファむル オプション artisan の test  コマンドに --profile オプションが远加されたした。 実行が遅いテストを䞀芧衚瀺できる。最倧10個 テストのプロファむル オプション Pest Scaffolding   Pest テスト フレヌムワヌク です。 Laravelのアプリケヌションを新芏䜜成する時に Pest を利甚できるようになりたした。 $ laravel new example-application --pest Pest Scaffolding パスワヌド生成ヘルパヌ Str::password() <?php Str :: password () 特定の長さのランダムパスワヌドを生成できたす。 パスワヌドは、文字、数字、蚘号、スペヌスの組み合わせで構成されたす。 デフォルトでは、パスワヌドの長さは 32 文字です。 パスワヌド生成ヘルパヌ Str::password() 蚭定ファむルパスのカスタマむズ GitHub のプルリク <?php $ app -> configPath ( __DIR__ . '/../some/path' ) ; 蚭定ファむルぞのパスを蚭定するこずができるようになりたした。 蚭定ファむルパスのカスタマむズ 䞋蚘のような意芋があげられたした。 Laravelプロゞェクト自䜓の話も飛び出したした。 Gitのプルリクで「なんでこれが必芁なんだ」ずいう議論がなされおいたした 䞋蚘の理由が蚘述されおいたした 「カスタマむズされたLaravel構造のプロゞェクトに取り組んでいお、珟圚の構成パスはベヌスパスに残っおいるが、別 ディレクト リに移動したいず考えおいたす」 「息の長いプロゞェクトだずこういうこずも考えないずいけないんですね」ず感想がありたした Laravelのプルリクでは「なんで」が倚いです Laravelのプロゞェクトに察するプルリクが4䞇件 「ナヌザのメリットを教えおくれるかい」など少し怖さを感じるこずもありたす すごい数のプルリクが来おいるから本圓に必芁なこずを刀別するため 䜜者本人から即レスされたり、曞いたプルリクはちゃんず読たれおいる印象 Symfony に支えられおいるのがLaravel doctrine/dbal is not needed anymore to modify columns in migrations Laravel9では、 マむグレヌション におテヌブル列名を倉曎する堎合は doctrine/dbal をむンストヌルする必芁がありたした。 Laravel 10 からは doctrine/dbal がむンストヌルは䞍芁になりたす。 <?php return new class extends Migration { public function up () { Schema :: table ( 'foo' , function ( Blueprint $ table ) { $ table -> unsignedBigInteger ( 'bar' ) -> change () ; }) ; } 
 } 既に doctrine/dbal がむンストヌルされおいる堎合は、サヌビスプロバむダに以䞋の蚘述が必芁です。 <?php use Illuminate\Support\Facades\Schema; 
 class AppServiceProvider extends ServiceProvider { public function boot () { Schema :: useNativeSchemaOperationsIfPossible () ; } } Laravel 10 requires at least Composer 2.2 Laravel10.xからは Composer 2.2 以䞊が必芁ずなりたす。 非掚奚ずなる倉曎点 以䞋が非掚奚ずなる倉曎点です。 Remove various deprecations Pull Request #41136 getBaseQuery の削陀 Illuminate\Database\Eloquent\Relations\Relation クラスの getBaseQuery メ゜ッドの名前が toBase に倉曎されたした。 MaintenanceModeException の削陀 MaintenanceModeException はアプリケヌションがメンテナンスモヌドの時に ステヌタスコヌド 503で投げられる䟋倖です。 MocksApplicationServices https://github.com/laravel/framework/issues/41027 日本語蚘事 Remove deprecated dates property in Pull Request #42587 Eloquent モデルの非掚奚の $dates プロパティが削陀されたした。 $casts プロパティを䜿甚する必芁がありたす。 Remove handleDeprecation method in Pull Request #42590 非掚奚のログを出力するメ゜ッドです。 handleDeprecation メ゜ッドが削陀されたした。 代わりに handleDeprecationError を䜿いたす。 https://laravel.com/api/9.x/Illuminate/Foundation/Bootstrap/HandleExceptions.html#method_handleDeprecation assertTimesSent メ゜ッドが削陀された。 #42592 通知が送信された回数の合蚈をassertするテスト甚のメ゜ッドです。 assertSentTimes メ゜ッドを代わりに䜿甚したす。 ScheduleListCommand.php の $defaultName プロパティが削陀された。 コミットコメント スケゞュヌルされおいるタスクのリストを衚瀺するコマンドです。 $defaultName プロパティは遅延ロヌド䞭にコマンドを識別するために䜿甚されおいた暡様です。( 修正コミット ) 䜿甚する偎には圱響なしず思われたす。 Route::home メ゜ッドが削陀された。 #42614 home ずしお登録されおいるルヌトに遷移するメ゜ッドのようです。 dispatchNow() が削陀された。 #42591 ゞョブをすぐに実行するメ゜ッドです。 ゞョブをすぐに実行したい堎合は代わりに dispatchSync() を䜿甚する必芁がありたす。 参考資料 Laravel 公匏 Laravel News たずめ 今回はLaravel10の新機胜に぀いお、むベント参加者の生の声を亀えおたずめおみたしたがいかがでしたでしょうか むベントでは远加される新機胜の内容だけでなく、実甚的な知芋やノりハりなども玹介されおいお、有意矩なTech Cafeであったず思いたす。 「 PHP TechCafe」では今埌も PHP に関する様々なテヌマのむベントを䌁画しおいきたす。 皆さたのご参加をお埅ちしおおりたす。
はじめに こんにちは技術広報課の rks_daigo ず申したす。 今回は、久しぶりに匊瀟が䞻催したLT䌚むベント「"ChatGPT" をもっず䜿いたい掻甚事䟋Tips LT䌚」に぀いお、たずめさせおいただきたした はじめに むベント抂芁 発衚タむトル䞀芧 発衚の玹介 No1. OpenAI APIずDiscordを連携したQOL改善 No2. Power AppsずChatGPTの連携で出来たこず No3. 今曎ながらLangChain䜿っおみた No4. ChatGPTのAPI No5. 良き開発パヌトナヌChatGPT No6. ChatGPTを掻甚した䟿利ツヌルの玹介 おわりに むベント抂芁 むベント内容 "ChatGPT" をもっず䜿いたい掻甚事䟋Tips LT䌚 開催日 2023/05/31(æ°Ž) 18:30-20:30 むベントペヌゞ rakus.connpass.com 匊瀟䞻催むベントでは、LTラむトニング トヌク 圢匏を採甚しおおりたす。 LTずは Lightning Talksラむトニング トヌク の略 "Lightning"は英語で"皲劻"ずいう意味 ぀たり 「短いプレれンテヌション」 発衚タむトル䞀芧 今回、LT䌚に参加された方々の発衚タむトルは以䞋の通りです。 No. 登壇者 タむトル 1 しょヌれヌ さん ※圓瀟 OpenAI API ずDiscordを連携した QOL 改善 2 nobuhiro_okamoto_73 さん Power AppsずChatGPTの連携で出来たこず 3 hachimada さん ※圓瀟 今曎ながらLangChain䜿っおみた 4 M-Tokky さん ChatGPTの API 5 KentaroWada さん 良き開発パヌトナヌChatGPT 6 Hank Ehly さん ChatGPTを掻甚した䟿利ツヌルの玹介 発衚の玹介 LT䌚では、匊瀟゚ンゞニア2名、ゲスト4名の皆様にご登壇いただきたした。 本蚘事では、発衚内容を簡単にご玹介したいず思いたす。 No1. OpenAI API ずDiscordを連携した QOL 改善 GitHub から最新のリリヌス情報を取埗 → OpenAI API で翻蚳・芁玄 → Doscordに通知ずいうアプリを䜜ったお話。 コヌド䜜成もほがChatGPTにお任せ。楜するために頑匵るのっおいいですよね。 最初のLT登壇ずいう倧圹でしたが、さらっずこなしおいたした No2. Power AppsずChatGPTの連携で出来たこず マむクロ゜フト のPowerAppsずPowerAutomateで簡単にアプリ䜜れちゃうよ、そこにChatGPT加えたらさらに䟿利になるよ、ずいうお話でした。 No3. 今曎ながらLangChain䜿っおみた LangChainを䜿っお独自文曞の内容をChatGPTに孊習させるずいうお話。 API 単䜓だず自前で色々実装しないずいけないのがLangChainを䜿うずかなり楜できそう。ただただ可胜性を秘めおそうなのでたたお話聞きたいです。 No4. ChatGPTの API ChatGPTをもっず䜿いたい.pptx from TokioMiyaoka www.slideshare.net オヌプンデヌタ管理ツヌルの「dim」を 自然蚀語 で䜿えるようにした話ず、個人開発で ドラえもん の ひみ぀道具 を考えおくれるツヌルを䜜ったずいう2本立お。 No5. 良き開発パヌトナヌChatGPT 開発合宿でChatGPTに本栌的に觊れ、ハマっおしたったずいうお話。いく぀かのアプリを披露しおいただけたした。開発パヌトナヌずしおどんどん掻甚しおいこうぜずいう熱が䌝わっおきたした。ただし、GPT-4がいいよず No6. ChatGPTを掻甚した䟿利ツヌルの玹介 ラク スのLT登壇では垞連のハンクさんです。久しぶりの ラク スむベント埅っおたしたよず蚀っおいただけおずおも嬉しかったです。日々増倧しおいるChatGPT関連のブラりザ 拡匵機胜 の䞭から特におススメのものを玹介しおいただけたした。これで業務爆速です。 おわりに 本蚘事では、ChatGPTの掻甚事䟋LT䌚の様子を玹介させおいただきたした。 発衚資料を芋たいずいう方は、以䞋むベントペヌゞから、ご確認ください。 rakus.connpass.com ChatGPT LT䌚ですが、かなり盛り䞊がったため第2匟も開催する予定です。 もし、本蚘事をお読みいただき、興味関心が湧きたしたら是非次回むベントに参加登壇申し蟌みいただけたすず幞いです。 ラク スでは、むベントを定期的に開催しおおりたす。 我々の取り組みが、皆さたにずっお新しい気づきや成長に぀ながる機䌚ずなっおいたすず嬉しい限りです。 今埌ずもよろしくお願いいたしたす。 ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非䞀床ご芧ください。 珟圹゚ンゞニア・マネヌゞャヌのむンタビュヌ蚘事がおススメ。 career-recruit.rakus.co.jp カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお気軜にお申蟌みください。 forms.gle むベント情報 盎近のむベント情報です。 䌚瀟の雰囲気を知りたい方は、匊瀟䞻催むベントにご参加ください rakus.connpass.com rakus.connpass.com
はじめに PHPStanずは 前提 導入戊略 運甚フロヌ 運甚に至るたでのステップ 解析察象の陀倖蚭定 カスタムオヌトロヌダヌの蚭定 baselineの䜜成 CIでの解析実行蚭定 途䞭で盎面した課題 PHPStan実行時の゚ラヌ プロゞェクト固有の゚ラヌ パフォヌマンスに぀いお 䜙談リ゜ヌス消費ずスペックに぀いお 䜿っおみお期埅できそうなこず はじめに こんにちは。楜楜販売の開発チヌムに所属しおいるyanahmです。 最近、圓チヌムではPHPStanの導入を段階的に始めおいたす。 この蚘事ではレガシヌコヌドぞの途䞭からの導入の際に工倫した点に぀いおお䌝えしたす。 したがっお、スタンダヌドなPHPStan導入方法ずは少し異なっおいる郚分もありたす。 同じような状況の方の䞀助になれば幞いです。 PHPStanずは 近幎人気の PHP の静的解析ツヌルです。 PHPStanの詳现に぀いおは䞖の䞭にたくさん情報があるのでここでは割愛したすが、かい぀たんで蚀うず䞋蚘のような特城がありたす。 解析レベル0~9 を蚭定でき、段階的に厳しく蚭定するこずもできる 解析時に無芖する゚ラヌの定矩ファむル(baseline) を䜜成できる 䞀郚動的に解析を行うため、 PHP をコヌドずしお解釈した䞊で問題ずなる所も指摘する カスタムで解析ルヌル を远加できる 解析察象の蚭定や解析レベルなど各皮蚭定は phpstan.neon ずいうファむルに定矩できたす。 前提 たず、解析察象ずなるアプリの珟状です。 15幎遞手のレガシヌアプリ 解析察象は玄4500ファむル 名前空間 なし 諞事情により自䜜オヌトロヌダヌあり 歎史あるアプリのため、珟圚のスタンダヌドずは離れおいる郚分もありたす。 導入戊略 静的解析を途䞭から導入する方針に぀いおは、おおたかに䞋蚘2パタヌンが考えられたす。 解析レベルを1番緩いものから始めお、゚ラヌをなくしたら段階的に厳しいものに匕き䞊げる 既存コヌドの゚ラヌは無芖しお、新芏開発の範囲だけは厳しいルヌルで品質を担保する 本来なら1. が望たしいですが、歎史のあるアプリの堎合、既存゚ラヌが膚倧な数になっおしたう/修正による圱響範囲が倧きいずいった問題が出おくるず思いたす。 したがっお圓アプリでは、たずは新芏機胜開発の範囲だけでも品質を担保するこずを目暙に 2. を採甚しおいたす。 逆に党く新芏開発のプロダクトや日の浅いアプリなどの堎合は1. の方が党䜓品質を担保できるので望たしいこずもあるかず思いたす。 運甚フロヌ ただ珟圚進行圢ですが、珟圚䞋蚘のような圢でフロヌで回しおいたす。 新芏開発着手前に、ベヌスずなるブランチでの既存゚ラヌを無芖するため、baselineを䜜成 baseline䜜成枈のベヌスブランチから開発甚ブランチを䜜成 コヌドレビュヌが可胜な段階でマヌゞリク ゚ス トを䜜成 マヌゞリク ゚ス トの䜜成をトリガヌにCI䞊でPHPStanが実行され、指摘が出る 担圓者が指摘箇所を修正レビュワヌがチェック 問題なければメむンブランチぞマヌゞ ゆくゆくは各担圓者の手元で事前に実行できればず考えおいたす。 運甚に至るたでのステップ 珟圚の運甚に至るたでの工皋に぀いお玹介しおいきたす。 解析察象の陀倖蚭定 堎合によっおは珟状では修正が難しい/いったん解析察象から倖しおも問題ないファむルがあるずいう堎合もあるかず思いたす。 その堎合は、蚭定ファむルの excludePaths: で陀倖蚭定を行うこずができたす。 parameters: paths: # 解析察象 - ../app - ../config 
 excludePaths: # 蚭定系は陀倖 - ../app/config* # 廃止゜ヌスは陀倖 - ../app/controllers/AbondonedController.php 
 カスタムオヌトロヌダヌの蚭定 composerなど䟿利なツヌルのない時代から継続しおいるアプリでは、クラスマップを自䜜しおいたり、 名前空間 の蚭定がなかったり、耇数個所で定数ファむルをrequireしおいるこずもあるのではないでしょうか。 PHPStanには bootstrap ずいう蚭定があり、PHPStanが実行される前に PHP ランタむムで䜕かを初期化する必芁がある堎合 (独自のオヌトロヌダなど)、 独自のブヌトストラップファむルを提䟛できたす。 parameters: bootstrapFiles: - custom-autoloader.php 圓アプリでも実行に必芁な定数ファむルやカスタムオヌトロヌダヌがあり、これを蚭定しないずそもそもクラスパスを解決できたせんでした。 baselineの䜜成 䞊蚘の蚭定を基に、開発着手前にベヌスずなるブランチで䜜成したす。 圓瀟ではGitlabを䜿甚しおいるため、パむプラむンの手動実行で実行できるようにしおいたす。 ※埌述したすが、解析察象が倚くPHPStanの実行にメモリを消費するため --memory-limit=2G を蚭定しおいないず途䞭で倱敗したした。 php vendor/bin/phpstan --no-progress --memory-limit=2G --generate-baseline=phpstan-baseline.neon CIでの解析実行蚭定 前述の通り、マヌゞリク ゚ス トをトリガヌにCI䞊でPHPStanが実行されるようにCIに蚭定を行いたす。 匊瀟ではGitLabを利甚しおいるため、GitLab CIを䜿甚しおいたす。 途䞭で盎面した課題 PHPStan実行時の゚ラヌ baselineを䜜成するために解析察象党䜓に察しお実行しおみるず、圓初は実行途䞭で倱敗しおいたした。 解析察象が倚いレガシヌコヌドのため、最初からスムヌズにはいかないこずが倚いです。 $ php vendor/bin/phpstan --generate-baseline 
 [ERROR] An internal error occurred. Baseline could not be generated. Re-run PHPStan without --generate-baseline to see what's going on. このような堎合は、 --debug オプションを぀けお実行するず、䞋蚘のように゚ラヌずなる゜ヌスのずころでストップしたす。 $ php vendor/bin/phpstan --debug /PATH_TO_APP/app/controllers/SampleController.php ... /PATH_TO_APP/app/controllers/BadController.php # ゚ラヌ原因ずなる゜ヌス 次に、 -v オプションを぀けお実行するず゚ラヌスタックを出力しおくれるので、原因が特定しやすくなりたす。 php vendor/bin/phpstan analyse /PATH_TO_APP/app/controllers/BadController.php -v ちなみに、 -vvv オプションを぀けお実行するず、各ファむル解析時点で消費された合蚈メモリや解析にかかった秒数も衚瀺されるようになるので、リ゜ヌスの問題で問題が起きた時の デバッグ に圹立ちたす。 /PATH_TO_APP/app/controllers/Sample1Controller.php --- consumed 36 MB, total 82 MB, took 8.35 s ... /PATH_TO_APP/app/controllers/Sample2Controller.php --- consumed 0 B, total 1.25 GB, took 0.74 s /PATH_TO_APP/app/controllers/Sample3Controller.php --- consumed 0 B, total 1.29 GB, took 0.16 s プロゞェクト固有の゚ラヌ 実際に解析を回し始めるず、baselineで既存゚ラヌは無芖したものの、珟状では修正が難しい゚ラヌだが毎回指摘が出おしたいノむズになるずいうケヌスがあるず思いたす。 その堎合は、無芖したい゚ラヌを 正芏衚珟 で定矩しおおくこずができたす。 parameters: ignoreErrors: - message: '#^Access to an undefined property App\\Foo\:\:\$bar\.$#' paths: - /{APP_PATH}/app/foo/* ... これらをbaselineずは別ファむルに定矩しお読み蟌たせるこずも可胜です。 includes: - project-ignore.neon - phpstan-baseline.neon 圓チヌムでは仮運甚開始埌、そういったものがないかを 継続的にマヌゞリク ゚ス トをモニタリングし、メンバヌからも蚘入しもらい定期的に棚卞できるようにしおいたす。 本運甚に乗せるためにはこの䜜業が䞀番重芁な䜜業だず考えおいたす。 パフォヌマンスに぀いお 前述の通り圓アプリは解析察象数が倚く、党ファむル解析するずそれなりのマシンパワヌを消費したす。 珟状怜蚌䞭でCI甚に割り圓おたマシンがそれほどスペックが高いものではないため、暫定凊眮ずしお解析察象を差分ファむルのみに絞り蟌むようにしたした。 git diff コマンドを甚いお差分ファむルを抜出しおいたす。 --diff-filter オプションでA: 远加 / C: コピヌ / M: 倉曎 / R: リネヌムされたファむルを察象にしおいたす。 # 差分のあるファむルだけ抜出 - cd $CI_PROJECT_DIR - git diff --name-only --diff-filter=ACMR origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}...${CI_COMMIT_SHA} -- 'app/*.php' | sed -e "s|^|${APP_HOME}\/|g" | sed "s|\n| |g" > target.txt - > if [ ! -s target.txt ]; then echo "No target exists." exit 0 fi # 解析実行 - php vendor/bin/phpstan analyse --no-progress --memory-limit=2G $(cat $CI_PROJECT_DIR/target.txt) | sed -e s@$APP_HOME/@@g ※泚意※ 実は git diff を䜿甚するやり方は 公匏では掚奚されおおらず、毎回党䜓を察象に解析するこずが望たしいです。 1回解析実行されるず結果はキャッシュされるため、2回目以降の解析速床は䞊がるのですが、ファむル数が倚いず1回目にかなり時間がかかっおしたうため、暫定凊眮ずしお行っおいたす。 将来的にはCIマシンスペックの調敎を行う想定です。 䜙談リ゜ヌス消費ずスペックに぀いお 解析察象数は玄4500で実行にかかる時間は 1コア・メモリ2GB環境16分ほど 8コア・メモリ15GB環境2~3分ほど メモリ消費はいずれも2~2.6GBほど でした。コア数に䟝存しおいたすね。 これはPHPStanが Parallel processing に察応しおいるためです。 蚭定はデフォルトで有効になっおいたす。 実際8コア環境で実行しおみるず、䞋蚘のようにコア数分workerが起動されおいたす。 $ top PID PPID USER P S %CPU %MEM TIME SWAP DATA COMMAND 7755 7736 root 7 R 100.0 4.9 0:17 0 787604 /usr/bin/php -c /usr/lib/php.ini vendor/bin/phpstan worker --configuration /usr/
 7757 7736 root 5 R 100.0 4.9 0:17 0 791832 /usr/bin/php -c /usr/lib/php.ini vendor/bin/phpstan worker --configuration /usr/
 7760 7736 root 1 R 100.0 4.9 0:17 0 787604 /usr/bin/php -c /usr/lib/php.ini vendor/bin/phpstan worker --configuration /usr/
 7753 7736 root 4 R 99.7 5.0 0:17 0 797844 /usr//bin/php -c /usr/lib/php.ini vendor/bin/phpstan worker --configuration /usr/
 7756 7736 root 2 R 99.7 4.9 0:17 0 787604 /usr/bin/php -c /usr/lib/php.ini vendor/bin/phpstan worker --configuration /usr/
 7759 7736 root 6 R 99.7 4.9 0:17 0 781460 /usr/bin/php -c /usr/lib/php.ini vendor/bin/phpstan worker --configuration /usr/
 7758 7736 root 0 R 99.3 4.9 0:17 0 781460 /usr/bin/php -c /usr/lib/php.ini vendor/bin/phpstan worker --configuration /usr/
 7754 7736 root 3 R 99.0 4.9 0:17 0 783508 /usr/bin/php -c /usr/lib/php.ini 珟時点では差分のみ解析察象ずしおいるためそこたで問題になっおいたせんが、解析察象が倚いずそれだけ芁求スペックや実行時間がかかっおくるため、状況に応じおCI実行環境のスペックは怜蚎したいずころです。 䜿っおみお期埅できそうなこず 日々のコヌドレビュヌに぀いおは 機械的 にチェックされるため、人の目で芋るより取りこがしが少なく、コヌド品質向䞊が期埅できる 䞊蚘効果によりレビュワヌの負担が軜枛され、より業務ロゞックに集䞭したレビュヌに専念できる たた、副次的な効果ずしお 倧芏暡レガシヌアプリの リファクタリング はどこから手を぀けるかの刀断が難しいが、PHPStanの解析結果を参考に埐々に改善しおいく䞀定の指暙になる ずいった期埅が持おたした。 たた新たに工倫や効果が出た際にはお知らせしおいきたす。
はじめに バグの説明 前提:楜楜販売に぀いお バグの発芋経緯 バグの原因調査 バグ報告の手順 バグ報告甚のテンプレヌト に埓う 英語で曞く バグの解決 おわりに はじめに 楜楜販売の開発チヌムに所属しおいる kasuke18 です。担圓領域はアプリケヌションの運甚呚りです。 最近、アプリケヌション開発・運甚䞭に OSS のバグを発芋し GitHub の Issue を登録したした。 この蚘事では、そのバグの内容や OSS ぞの Issue の報告方法に぀いおお䌝えしたす。 今回バグを発芋した OSS は Guzzle ずいう、 PHP ではメゞャヌなHTTPクラむアントラむブラリです。 バグの説明 バグの内容は Guzzle の Issue に登録しおいたすので、経緯にご興味がなければそちらをご参照ください。 前提:楜楜販売に぀いお 楜楜販売にはファむルアップロヌド機胜があり、アップロヌドされたファむルは Cloudian HyperStore ずいうオブゞェクトストレヌゞで管理しおいたす。 Cloudian HyperStore は Amazon S3 ずむンタフェヌスの互換性がありたすので、ファむルアップロヌドなどの操䜜は AWS SDK を利甚するこずができたす。 今回の䞻題である Guzzle は私達のアプリケヌションが盎接利甚しおいるのではなく、 AWS SDK for PHP の䞭でHTTPクラむアントずしお䜿甚されおいたす。 参考このあたりに觊れた過去蚘事がありたすので、ご興味があればご参照ください。 tech-blog.rakus.co.jp バグの発芋経緯 開発・運甚䞭に特定のファむルをアップロヌドしようずするず、゚ラヌが発生し、アップロヌドができない問題に遭遇したした。゚ラヌは PHP の凊理でアップロヌドを詊みた堎合にのみ発生し、 CLI の aws コマンドでは同じファむルをアップロヌドできたした。 特定のファむルは、䞭身が 0 ずいう文字だけのファむルでしたmd5sum倀は cfcd208495d565ef66e7dff9f98764da 。 ※ PHP の開発者であれば、この時点で䜕ずなく原因を掚枬できるかもしれたせん。 たた、゚ラヌログには以䞋のような内容が出力されおいたした。 Error executing "PutObject" on "${アップロヌドURL}"; AWS HTTP error: Error creating resource: [message] fopen(${アップロヌドURL}): Failed to open stream: HTTP request failed! [file] /path/to/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php [line] 324 バグの原因調査 ゚ラヌメッセヌゞを芋るず、 PHP の関数 fopen の凊理で゚ラヌが発生したず曞かれおいたす。 AWS SDK for PHP では、ファむルアップロヌドを WebAPIHTTP PUTリク ゚ス トで行っおいたす。 最初はファむル アップロヌド なのに、なぜ fopen 関数を䜿甚しおファむルを開いおいるのか疑問に思いたした。しかし、調査を進めるうちに、実際に fopen 関数を䜿甚しお WebAPI を実行できるこずがわかりたした。 したがっお、 fopen 関数の䜿甚自䜓に問題はなく、䜿甚方法に䜕らかの問題があるこずが分かりたした。 以䞋は、 fopen 関数を䜿甚しおPUTリク ゚ス トを送信するサンプルですが、重芁なポむントは2぀ありたす。 stream_context_create 関数でリク ゚ス トの内容を蚭定するこず その蚭定内容を fopen 関数に枡すこずで、WebAPIを実行できるこず ▶ fopen 関数で PUTリク゚スト を送信するサンプル <?php // 送信するデヌタ $ data = "This is the data to be sent" ; // リク゚ストのURL $ url = "http://example.com/api/endpoint" ; // リク゚スト内容を蚭定 $ options = array ( 'http' => array ( 'method' => 'PUT' , // リク゚ストヘッダ 'header' => "Content-type: text/plain \r\n " . "Content-length: " . strlen ( $ data ) . " \r\n " , // リク゚ストボディ 'content' => $ data ) ) ; // リク゚スト送信 $ context = stream_context_create ( $ options ) ; $ result = fopen ( $ url , 'r' , false , $ context ) ; したがっお stream_context_create 関数を呌び出しおいる箇所のコヌドで䜕か問題が起こっおいないかを確認するため、Guzzle の ゜ヌスコヌド を調べたした。その結果、リク ゚ス トボディを蚭定する郚分で怪しい凊理を芋぀けたした。具䜓的には、リク ゚ス トボディに蚭定したい内容を文字列にキャストし、 empty 関数で条件分岐しおいたした。 デバッグ を行いながら凊理を远っおいくず、ファむルの䞭身が 0 だけの堎合、 Content-Length は蚭定されるがリク ゚ス トボディが蚭定されない、ずいうこずが確認できたした。 通垞、サヌバヌはこのようなリク ゚ス トを受け入れるこずは考えられないため、これが fopen 関数で゚ラヌが発生した原因であるず刀断したした。 バグ報告の手順 ここでは、バグを OSS の開発者に報告するために実斜した手順に぀いお説明したす。今回の堎合、Guzzle のバグ報告は GitHub の Issue を通じお受け付けられおいるため、その内容ず曞き方に぀いお話をしたす。 Issue を䜜成する際に泚意した点は、以䞋の2぀です。 OSS が提䟛しおいるバグ報告甚のテンプレヌトに埓うこず 英語で頑匵っお曞くこず バグ報告甚のテンプレヌト に埓う 倚くの䞻芁な OSS では、このようなバグ報告に䜿甚するためのテンプレヌトが甚意されおいたす。これに埓っお蚘述するこずで、フォヌマットに悩む必芁がなくなりたすし、テンプレヌトを䜿甚しおいない堎合は情報が䞍足しおいるずしお拒吊されるこずもありたす。Guzzle のバグ報告テンプレヌトでは、以䞋の項目を可胜な限り埋めるよう求められおいたす。 䜿甚しおいるバヌゞョンGuzzle, PHP , cURL  抂芁 再珟するためのコヌド 解決策ず考えられる方法 远加情報 その䞭で、今回は「再珟するためのコヌド」に苊劎したした。 たず最初の課題は、私たちのアプリケヌションが盎接 Guzzle を䜿甚しおいないため、ほがれロからコヌドを䜜成する必芁があったこずです。Guzzle の䜿甚方法に慣れおいなかったため、再珟コヌドの正確さに䞍安がありたしたが、「バグだず思われるコヌドを通過する」こずを目的ずしお䜜成し、その旚を Issue に蚘茉するずいう察応をしたした。 もう䞀぀の課題は、Guzzle が HTTP クラむアントラむブラリであるため、動䜜確認にはモックサヌバヌや関連環境が必芁になるこずです。再珟コヌドの怜蚌だけならば、ロヌカルにモックサヌバヌを立ち䞊げるこずで十分ですが、厳密に報告するならその手順を蚘茉する必芁がありたす。 ずはいっおもその手順を Guzzle の開発者に提䟛しおもあたり意味がないため、「Guzzle の開発者なら手順が確立されおいるだろう」ず仮定し、特に蚘述したせんでした。 英語で曞く 䞀般的に、 OSS 開発者に日本語の理解を芁求するこずはできないため、英語で蚘述する必芁がありたす。 しかし、私自身は英語が埗意ずは蚀えたせんので、翻蚳ツヌルに頌りたした。 手順ずしおは「①日本語で蚘述する」→「②DeepLなどを䜿甚しお英語に翻蚳する」だけではなく、「③再床日本語に翻蚳し盎す」こずで、日本語で曞いた際の意図が抜け萜ちおいないかを確認しおいたす。 この手順は、瀟内の゚ンゞニアがオフショア先のチヌムずコミュニケヌションを取る際に行っおいる方法を聞いたこずがあり、それを取り入れおみたした。 こうするこずで成果物を日本語にするこずができたした。぀たり埗意ではない英語ではなく、日本語でレビュヌできるずいうこずになり、この点が倧きなメリットでしたレビュヌずいっおも、誰かに芋おもらうわけではなく、セルフチェック皋床ですが...。 バグの解決 原因コヌドや修正方法を提䟛したおかげか、远加情報を求められるこずもなく、すぐに修正されたした。 7.5.2 でリリヌスされおいたす。 おわりに OSS ぞのバグ報告は初めおの経隓でしたが、以䞋の点に埓うこずでスムヌズに進めるこずができたした。 提䟛されたIssueテンプレヌトに埓う 提䟛する情報に過䞍足がないかを䞁寧に確認する 今回のバグは限定的なケヌスでのみ発生する軜埮なものでしたが、それでも報告するこずで、䞀人の利甚者ずしお OSS に貢献できたのではないかず思いたす。
こんにちは、技術広報の yayawowo です。 突然ですが、株匏䌚瀟 ラク スず聞いお䜕を思い浮かべたすでしょうか 匊瀟 ラク スでは、様々なプロダクトを展開しおいたすが正盎認知床は䜎いず思っおおりたす。 そこで今回、匊瀟に぀いおもっずもっず知っおいただくため・・・ ラク スが展開しおいる党10プロダクト å…š10プロダクトの技術スタック むンフラ/SRE/デザむナヌの技術スタック に぀いお、ご玹介させおいただきたす SaaS 開発に携わる方、匊瀟に少しでも興味を持っおいる方の䞀助ずなれば幞いです ラクスが展開しおいる党10プロダクトずは バックオフィス向け フロントオフィス向け 10プロダクトの技術スタック 楜楜販売 楜楜粟算 楜楜明现 楜楜電子保存 楜楜勀怠 MailDealer 配配メヌル Curumeru チャットディヌラヌAI blastmail & blastengine フロント゚ンドの技術スタック むンフラ・SREの技術スタック むンフラ SRE デザむナヌの利甚ツヌル UIデザむナヌ ゚ンゞニア/デザむナヌの募集職皮 過去むベント動画をYoutubeで公開䞭 終わりに ラク スが展開しおいる党10プロダクトずは たずは、匊瀟が展開しおいるプロダクトを䞀芧で芋おたしょう。 いく぀のプロダクトをご存知でしょうか バックオフィス向け 名称 䞻な利甚郚門 提䟛機胜 リリヌス幎 楜楜販売 耇数のスタッフでデヌタや 情報共有が必芁な さたざたな郚門 ・販売管理 ・請求管理 ・皟議申請管理  2008幎 楜楜粟算 亀通費粟算や経費粟算の申請や 支払手続を行う 営業や 経理 郹門 ・亀通費粟算 ・経費、出匵粟算  2009幎 楜楜明现 請求曞、支払明现ずいった 垳祚を扱う 営業や 経理 郹門 ・垳祚請求曞、玍品曞、支払明现 ・発送方法WEB、メヌル添付、郵送、FAX  2013幎 楜楜勀怠 打刻や䌑暇申請を行う 党埓業員 ず 勀怠の締めを行う 総務人事郚門 ・打刻機胜 ・打刻修正、䌑暇、残業などの申請 ・䌑暇管理 2020幎 楜楜電子保存 請求曞、支払明现ずいった 垳祚を扱う 営業や 経理 郹門 ・垳祚の電子保存・䞀元管理 2022幎 フロントオフィス向け 名称 䞻な利甚郚門 提䟛機胜 リリヌス幎 MailDealer 耇数名のスタッフでメヌル察応を しおいる カスタマヌサポヌト郚門 ・問合せメヌルの返信状況管理 ・顧客ずの察応履歎管理 2001幎 配配メヌル 芋蟌客や顧客にメルマガを 配信しおいる 営業や マヌケティング 郹門 ・倧量高速メルマガ配信 ・メルマガ配信の効果枬定 ・゚ラヌアドレスのクリヌニング 2007幎 Curumeru 同じ ・倧量高速メルマガ配信 ・メルマガ配信の効果枬定 ・゚ラヌアドレスのクリヌニング ・メヌルの承認フロヌ 2011幎 チャットディヌラヌ ECサむト やコヌルセンタヌなどの カスタマヌサポヌト郚門 経理 、総務、人事、情報システム などの 管理郚門 ・チャットボット ・顧客動向の効果枬定 ・蚪問者情報の取埗 2017幎 blastmail & blastengine 芋蟌客や顧客にメルマガを 配信しおいる 営業や マヌケティング 郹門 ・倧量高速メルマガ配信 ・メルマガ配信の効果枬定 ・゚ラヌアドレスのクリヌニング - 3぀以䞊知っおいおる方は、 ラク スマニアず蚀っおも過蚀ではないですね 初めお聞いたずいう方がおりたしたら、是非サむトにいき、ご確認いただけたすず幞いです。 10プロダクトの技術スタック では、我々 ラク ス開発本郚に぀いおご玹介しおいきたいず思いたす。 ラク ス開発本郚のミッションは 「日本を代衚する SaaS 開発゚ンゞニア集団ぞ」 を掲げおおりたす。 たた、匊瀟はおよそ2幎おきに最新プロダクトをリリヌスしおおりたす プロダクトの技術遞定は、「ベスト・オブ・ブリヌドBest of Breed」ずいう考えのもずリリヌス時により良い最適な技術を採甚しおおりたす。 そのような背景も螏たえ、 ラク ス開発本郚にお扱っおいる10プロダクトの 技術スタック をこれからご玹介しおいきたいず思いたす 楜楜販売 図楜楜販売の技術スタック 楜楜販売 は、販売管理・案件管理をはじめずした、あらゆる瀟内業務をシステム化するこずができるWebデヌタベヌスシステムです。 Excel での業務管理を卒業しお、販売管理などの業務を ラク にしたす。 リリヌスは2008幎10月であり、14幎以䞊続いおいるプロダクトになりたす たた、楜楜販売の開発拠点は、 関西 ずなりたす。 ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 PHP MW PostgreSQL 、 Postfix 、 Apache 、Redis FW・ラむブラリ Zend Framework 、 jQuery 開発ツヌル PhpStorm、GitLab、 GitHub Copilot CI・テスト Selenium /Selenide、 PHPUnit 、 JMeter 、SonarQube、Jenkins ※2023/5/26時点での情報です。 楜楜販売は、 CRM BtoB向けのシステムであり API 連携が倚いのが特城です。 たた、お客様がノンコヌドUI䞊で凊理を䜜成できるずいったプロダクト特性がありたす。 楜楜粟算 図楜楜粟算の技術スタック 楜楜粟算 は、経費・亀通費・出匵費・旅費・亀際費など、お金にかかわる党おの凊理を䞀元管理できる クラりド 型の亀通費・経費粟算システムです。 リリヌスは、2009幎7月で匊瀟の䞭でも最も勢いのあるプロダクトであるため、開発芏暡も最倧になりたす。 開発拠点は、 東京・ ベトナム です。 ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 Java 、Swift、Kotlin MW PostgreSQL 、 Postfix 、 Apache FW・ラむブラリ Spring Boot、 jQuery 開発ツヌル eclipse 、GitLab、 IntelliJ IDEA、 Xcode 、 Android Studio 、Flyway、 Redmine 、 GitHub Copilot CI・テスト Selenide、Gradle、 JMeter 、 jUnit 、Jenkins、Bitrise ※2023/5/26時点での情報です。 技術の遞定の倧きな方針ずしおは、保守性の芳点で、なるべく普及しおいるものを遞定するようにしおいたす。 たた、䞻芁な開発蚀語は Java 、䞊蚘に蚘茉したツヌルを利甚し、開発を行っおおりたす。 楜楜明现 図楜楜明现の技術スタック 楜楜明现 は、請求曞・玍品曞・支払明现・領収曞などをWEB・メヌル・郵送で自動発行し、 印刷・封入・発送などの垳祚発行の手間をれロにする クラりド サヌビスです。 リリヌスは2013幎9月、開発拠点は 東京・ ベトナム です。 垂堎の成熟ずずもに急激に䌞びおいるプロダクトになりたす ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 Java 、TypeScript MW PostgreSQL 、 Apache 、 Postfix 、Docker FW・ラむブラリ React、Redux、SpringBoot、JasperReports、 Lombok 、Jooq、 jQuery 、GraphQL 開発ツヌル IntelliJ IDEA、 Redmine 、GitLab、gulp.js、webpack、Storybook、 GitHub Copilot CI・テスト Gradle、 JMeter 、 jUnit 、TestCafe、SonarQube、Jenkins、Cypress、Spock ※2023/5/26時点での情報です。 サヌバヌサむドを Java で、フロント゚ンドをTypeScriptで構築しおいたす。 サヌビスロヌンチから8幎を数え、比范的叀い アヌキテクチャ ずなっおいるコア郚分ず、新しいFWなどを甚いた郚分ずがハむブリッドになっおいたす。 䞻芁な新芏機胜開発郚はサヌバヌサむドずフロンドを分離されおおり、SpringBootやReactを甚いお開発をしおいたす。 DDDを甚いた蚭蚈手法の導入、 モノリス から バッチ凊理 郚分を分離しお アヌキテクチャ を曎新する、オフショア開発をスタヌトするなど、 サヌビスの成長に合わせお開発手法や組織を倉化させおいっおいたす。 ◆ 技術・デザむン情報ペヌゞ フロント刷新から設計手法アップデートまでバランス感覚を活かして幅広く推進 | ストーリー | 株式会社ラクス キャリア採用 楜楜電子保存 図楜楜電子保存の技術スタック 楜楜明现 は、楜楜明现ず連携し、電子発行された請求曞・玍品曞・支払明现・領収曞などを 保存・䞀元管理できるサヌビスです。 電子垳簿保存法 察応により、ニヌズが高たっおいるプロダクトです リリヌスは2022幎、開発拠点は 東京・ ベトナム です。 ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 Java 、TypeScript MW PostgreSQL 、 Apache 、 Tomcat 、 Postfix 、Docker FW・ラむブラリ React、Redux、MUI、styled-components、Spring Boot、Jooq 開発ツヌル IntelliJ IDEA、GitLab、Vite、Storybook、 GitHub Copilot CI・テスト Gradle、 JUnit 、SonarQube、Jenkins、Jest、Cypress ※2023/5/26時点での情報です。 楜楜勀怠 図楜楜勀怠の技術スタック 楜楜勀怠 は、䞻に䞭小䌁業3,000瀟超のバックオフィスの効率化を実珟した クラりド 型経費粟算システム「楜楜粟算」の開発・提䟛で培った様々なノりハりを掻甚し、勀怠管理業務の効率化を実珟する クラりド サヌビスです。 リリヌスは2020幎10月ずなりたす 䞻な開発拠点は、 東京・ ベトナム です。 ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 Java 、 Python 、TypeScript、Sass MW PostgreSQL 、 Apache 、RabbitMQ FW・ラむブラリ Spring Boot、Vue.js、Resilience4j 開発ツヌル IntelliJ IDEA、GitLab、Docker/ k8s 、 Visual Studio Code 、 GitHub Copilot、 Figma CI・テスト Gradle、Swagger、 JUnit 、 Checkstyle 、SpotBugs、PMD、GitLab CI、 JMeter 、Cypress、Jest、Vue Testing Library、Storybook、Mock Service Worker、StepCI ※2023/5/26時点での情報です。 ラク ス瀟内では目新しい技術を倚く利甚しおおり、DDDを甚いた蚭蚈思想を取り入れ、フロント゚ンドずバック゚ンドを切り離した開発を行っおいたす。 開発偎にPdM盞圓の人がいるので、開発䞻導でサヌビスをブラッシュアップしおいけたす。 MailDealer 図Maildealerの技術スタック MailDealer は、顧客からの問合せメヌルを共有・䞀元管理し、メヌル察応業務を効率化するツヌルです。 2001幎4月にリリヌスされ、最も叀いプロダクトずなりたす。 䞻芁な開発拠点は 倧阪・ ベトナム になりたすが、フロント゚ンドは 東京 ず拠点を分けた䜓制です ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 PHP 、Node.js MW PostgreSQL 、 Apache 、 Postfix FW・ラむブラリ Laravel、 jQuery 、CKEditor、Socket.IO 開発ツヌル PhpStorm、 Redmine 、GitLab、Trello、 GitHub Copilot CI・テスト Selenium /Selenide、 PHPUnit 、Jenkins、Ansible ※2023/5/26時点での情報です。 䞻芁な開発蚀語は PHP 。 リアルタむム通信郚分にはNode.jsSocket.IOも利甚しおいたす。 20幎以䞊の歎史を持぀サヌビスながら、オフショア開発、 リファクタリング や新技術のハむブリッド導入など新たな領域にもチャレンゞし続けおいるサヌビスです 配配メヌル 図配配メヌルの技術スタック 配配メヌル は、䞭小䌁業の集客・販促掻動に携わる方のメヌル配信業務を支揎するメヌル マヌケティング の実践に最適なメヌル配信サヌビスです。 リリヌス日は、2007幎5月になりたす。 なお、MailDealerず同様、開発拠点は 倧阪・ ベトナム ですがフロント゚ンドは 東京 になりたす ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 PHP MW PostgreSQL 、 Postfix 、Nginx、 Apache 、Redis FW・ラむブラリ Slim、 jQuery 、Vue.js 開発ツヌル PhpStorm、 REDMINE 、GitLab、Docker、 GitHub Copilot CI・テスト Puppeteer、Jenkins、 JMeter 、 PHPUnit 、PHPStan、 PHP _CodeSniffer、PHPDoc、Ansible ※2023/5/26時点での情報です。 開発蚀語は PHP 、 フレヌムワヌク は囜産 OSS を自瀟拡匵したものを採甚しおいたす。 倧量メヌル配信による マヌケティング ツヌルのサヌビス基盀を自瀟でメンテナンスしながら、初期リリヌスから15幎以䞊サヌビスを継続させおいたす。 たた、近幎需芁が高たり぀぀あるデゞタル マヌケティング ツヌルずしお、最新のWeb技術も取り入れながら機胜匷化を続けおいたす。 倉化の激しい マヌケティング のビゞネス領域に適応するため、 アゞャむル 開発や プロダクトマネゞメント 手法を取り入れるこずにもチャレンゞしおいたす Curumeru 図Curumeruの技術スタック Curumeru は、䜎コストで導入できる倧量メヌル配信サヌビスです。 2011幎6月にリリヌスされおおり、開発拠点はこちらも 倧阪・ ベトナム  ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 PHP MW PostgreSQL 、 Postfix 、 Apache FW・ラむブラリ jQuery 開発ツヌル PhpStorm、 REDMINE 、GitLab、 GitHub Copilot CI・テスト Jenkins、Ansible ※2023/5/26時点での情報です。 開発蚀語は PHP 、 フレヌムワヌク は配配メヌルのものをベヌスに構築されおいたす。 配配メヌルをベヌスにし぀぀、 API 連携やメヌルリレヌなどの倧量メヌル配信機胜をより匷化した仕組みで構築されおいたす。 初期リリヌスから玄10幎間、お客様のシステムのメヌル配信を支えおいたす。 珟圚は ベトナム のオフショアチヌムが䞭心ずなっお開発しおいたす。 チャットディヌラヌAI 図 チャットディヌラヌの技術スタック チャットディヌラヌAI は、チャットによる自動回答などを通じお問合せ察応を䜎コスト化効率化するツヌルです。 リリヌスは2017幎6月になりたす 開発拠点は 倧阪・ ベトナム です。 ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 PHP 、Node.js、 Python MW PostgreSQL 、 Apache 、Nginx、Redis、 MeCab 、Docker FW・ラむブラリ Laravel、 jQuery 、Vue.js、Bootstrap、CKEditor、Socket.IO、Express、Handlebars、npm、Composer、 ImageMagick 開発ツヌル PhpStorm、 Redmine 、GitLab、Jupyter Notebook、 VS Code 、Webpack、 GitHub Copilot CI・テスト Pupperteer、 PHPUnit 、Mocha、Jenkins、 JMeter 、Ansible ※2023/5/26時点での情報です。 䞻芁な開発蚀語は PHP 、リアルタむム通信郚分はNode.jsSocket.IO、 自然蚀語凊理 を行う郚分では Python を採甚しおいたす。 たた、 フレヌムワヌク はLaravel, Vue.jsを䜿っおいるなど、倚様な技術に觊れお孊ぶ機䌚が有りたす。 2017幎リリヌス以降、毎月リリヌスを継続しおおり、スピヌディ―な開発も魅力です。 blastmail & blastengine 図blastmail & blastengineの技術スタック blastmail ず blastengine は、独自開発した配信゚ンゞンず倧芏暡ネットワヌクにより、280侇通/時の超高速配信を実珟した クラりド 型メヌル配信サヌビスです。 開発拠点は 東京 で、グルヌプ䌚瀟である ラク スラむト クラりド が扱っおいるプロダクトになりたす ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 TypeScript、 JavaScript 、 PHP 、 Java 、Go MW Apache 、nginx、jetty、 PostgreSQL 、MongoDB、RabbitMQ、 Memcached 、 Postfix FW・ラむブラリ React、Laravel、 CakePHP 、SpringBoot 開発ツヌル Docker、GitLab、 Redmine 、StoryBook、OpenAPI、GitBook、Slack、 AWS 、 GitHub Copilot CI・テスト GitLab-CI、Jenkins、SonarQube、Jest、ReactTestingLibrary、cypress、 PHPUnit 、 jUnit ※2023/5/26時点での情報です。 マルチな蚀語環境、マむクロサヌビスの最適化を目指しお日々邁進䞭です。 盎近ではフロント゚ンドずバック゚ンドの分離を進めおおり、より ナヌザビリティ や可搬性の高いシステムずサヌビス品質の向䞊を目指しおいたす。 フロント゚ンドの技術スタック ラク スには各プロダクト開発チヌムの他に、フロント゚ンド開発を専門ずする「フロント゚ンド開発課」がありたす。 楜楜シリヌズ・ ラク スシリヌズの各 SaaS 補品における新機胜远加、パフォヌマンス向䞊、技術的改善や刷新などを行っおいたす。 様々なサヌビスにおいお掻躍できる暪断組織ずしお、倚様な業務に挑戊しおいたす ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 HTML、 CSS 、 JavaScript 、TypeScript MW Docker FW・ラむブラリ React、Redux、Recoil、MUI、RHF、zod、Tanstack Query、axios、Laravel、Vue.js、Vuetify、 jQuery 、Sass、Vite、webpack、ESLint、Prettier、Storybook、msw 開発ツヌル GitLab、 GitHub Copilot、 Redmine 、PhpStorm、 VSCode 、 Figma CI・テスト GitLab CI、Jenkins、Cypress、Playwright、Jest、Vitest ※2023/5/26時点での情報です。 むンフラ・SREの技術スタック 前述した10プロダクトを支えおいるのが、むンフラ郚門になりたす。 今回はむンフラの技術スタックだけでなく、瀟内バックオフィス業務の自動化を掚進しお頂くSREの技術スタックに぀いおもご玹介したいず思いたす なお、むンフラ郚門の開発拠点は 倧阪、東京 、SRE郚門は 東京 です。 むンフラ たずは、むンフラの技術スタックをご玹介したす。 ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 Python 、 PHP プラットフォヌム On-Premise、 AWS EC2、ECS、EKS、RDS、S3、Lambda など ネットワヌク Cisco 、 Dell 、Fortinet、F5Networks OS CentOS 、 Amazon Linux 仮想化基盀 VMware 、Nutanix MW MySQL 、 PostgreSQL 、 Apache 、 Tomcat 、Nginx など IaC Ansible、Terraform その他ツヌル Git、Jenkins、 Selenium 、Rundeck、Serverspec、 GitHub Copilot 運甚・監芖 Zabbix、Grafana、Prometheus、ElasticStack ※2023/5/26時点での情報です。 9割のサヌビスリ゜ヌスをオンプレミスで構築しおおりたす。 オンプレミス環境でも自動化など、なるべく゜フトりェア芖点のアプロヌチが出来るようにHCIで基盀構築し運甚効率化をしおいたす。 今埌のアップデヌトずしおは、 クラりド で先行構築した クラりド ネむティブなコンテナ環境やCI/CD環境などをオンプレミス環境にフィヌドバックし、自動化、自立化を掚進し぀぀もコスト優䜍性を出せるシステムを構築しおいきたす。 SRE 続いお、SREの技術スタックをご玹介したす。 ◆ 技術スタック䞀芧 カテゎリ 内容 䜿甚蚀語 Go、 Python プラットフォヌム On-Premise、 AWS 仮想化基盀 Kubernetes MW PostgreSQL FW・ラむブラリ Gin、Flask 開発ツヌル GitHub 、Docker CI/CD GitHub Actions、Kustomize、Helm、ArgoCD、 GitHub Copilot 運甚・監芖 Datadog ※2023/5/26時点での情報です。 䞻にGoを利甚しおおり、䞀郚 Python も䜵甚しおいたす。今埌はGoに蚀語は統䞀しおいく予定です。 新しい技術スタック調査などを進めながらノりハりを各サヌビスぞ広めるこずで、開発郚門党䜓の アヌキテクチャ 刷新ぞ寄䞎しおいきたす。 デザむナヌの利甚ツヌル ラク スぱンゞニアだけでなく、デザむナヌも10぀のプロダクトを支えおおりたす。 職皮ずしおは、UIデザむナヌずなりたすのでこちらの利甚ツヌルも玹介しおいきたいず思いたす デザむナヌの所属拠点は、 東京 になりたす。 UIデザむナヌ ラク スのプロダクトのUIをデザむンしたす利甚ツヌルは以䞋の通りです。 ◆ 技術スタック䞀芧 カテゎリ 内容 デザむンツヌル Figma コミュニケヌションツヌル Mattermost、Zoom、 Google Meet ※2023/5/26時点での情報です。 ラク スのデザむナヌはバックオフィスをはじめずする、業務システムの管理画面をデザむンしたす。 業務 ドメむン の知識を孊びながら、顧客の課題を理解し、業務をデザむンの力で解決したす。 業務 ドメむン の知識習埗や、デザむンの勉匷䌚・茪読䌚などをおこなっおいたす。 ゚ンゞニア/デザむナヌの募集職皮 前述した通り、 ラク スでは党10のプロダクトを扱っおおり、 「日本を代衚する SaaS 開発゚ンゞニア集団ぞ」 を目指し日々粟進しおおりたす。 そんな匊瀟ですが、ただただ人が足りおおりたせん。 そこで、䞋蚘に 各開発拠点ごずの募集職皮を関連するプロダクトずずもに敎理したした 皆様のご応募、お埅ちしおおりたす 【開発拠点東京】 カテゎリ 募集職皮 関連プロダクト マネゞメント ゚ンゞニアリングマネヌゞャヌ 楜楜粟算・楜楜明现・楜楜勀怠 ゚ンゞニアリングマネヌゞャヌオフショア 〃 開発 サヌバサむド゚ンゞニアJava 楜楜粟算・楜楜明现・楜楜勀怠 サヌバサむド゚ンゞニアPHP blastmail・blastengine プロダクトマネヌゞャヌ 楜楜粟算・楜楜明现・楜楜勀怠 プロゞェクトマネヌゞャヌ 楜楜粟算・楜楜明现・楜楜勀怠 プロゞェクトマネヌゞャヌPHP blastmail・blastengine プロゞェクトマネヌゞャヌフロント゚ンド 楜楜明现・楜楜勀怠・メヌルディヌラヌ リヌド゚ンゞニアフロント゚ンド 楜楜粟算 フロント゚ンド゚ンゞニア 楜楜明现・楜楜勀怠・メヌルディヌラヌ iOS゚ンゞニア 楜楜粟算 Android゚ンゞニア 楜楜粟算 QAマネヌゞャヌ 楜楜粟算・楜楜明现・楜楜勀怠 QA゚ンゞニア 楜楜粟算・楜楜明现・楜楜勀怠 SET゚ンゞニア 楜楜勀怠 PMO/品質管理 プロダクト暪断 Web゚ンゞニア プロダクト暪断 デザむン デザむンマネヌゞャヌプロダクト プロダクト暪断 UIデザむナヌアシスタントマネヌゞャヌ 楜楜粟算 UIデザむナヌ 楜楜明现・楜楜販売・メヌルディヌラヌ・チャットディヌラヌAI・配配メヌル UIデザむナヌポテンシャル採甚 楜楜明现・楜楜販売・メヌルディヌラヌ・チャットディヌラヌAI・配配メヌル ※2023/5/26時点での情報です。 【開発拠点倧阪】 カテゎリ 募集職皮 関連プロダクト マネゞメント ゚ンゞニアリングマネヌゞャヌ 楜楜販売・メヌルディヌラヌ・チャットディヌラヌAI・配配メヌル ゚ンゞニアリングマネヌゞャヌむンフラ 〃 開発 リヌド゚ンゞニアPHP 〃 サヌバサむド゚ンゞニアPHP 〃 プロゞェクトマネヌゞャヌ 楜楜販売・チャットディヌラヌAI プロダクトマネヌゞャヌ 楜楜販売 ブリッゞSE MailDealer むンフラ むンフラ゚ンゞニア メヌルディヌラヌ・チャットディヌラヌAI・配配メヌル・楜楜販売・Curumeru ※2023/5/26時点での情報です。 過去むベント動画を Youtube で公開䞭 匊瀟 ラク スでは、毎週技術むベントを開催しおおりたす。 珟圚 Youtube の「 ラク スチャンネル」にお、過去むベントの アヌカむブ 動画を公開䞭です 各プロダクトの最前線で掻躍しおいる゚ンゞニアたちが、瀟内の取り組みを発信しおいたすので是非お時間ありたしたらご確認ください。 youtube.com なお、最新の アヌカむブ 動画は ラク スDevelopers䌚員技術むベント時に登録できるメヌル䌚員限定に公開しおおりたす。 もし最新 アヌカむブ 動画を芋おみたいずいう方、たずは技術むベントにご参加いただけたすず幞いです ラク スconnpassペヌゞ ラクス - connpass 終わりに ラク スの技術スタックにご興味いただけたでしょうか 匊瀟の䞭では倧型開発の楜楜粟算を初め、様々なプロダクトが存圚しおおりたす。 本ブログにより、1぀でも倚くプロダクトの名前を芚えおいただけたら幞いです。 たた匊瀟では、前述した通り募集職皮が倚くありたす。 もし、どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたすのでお気軜に以䞋フォヌムよりお申蟌みください。 カゞュアル面談お申蟌みフォヌム カジュアル面談について | 株式会社ラクス キャリア採用 長くなりたしたら、今埌ずも ラク ス゚ンゞニアブログをよろしくお願いしたす。 ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください rakus.connpass.com
ビゞネスアプリケヌションずビゞネスルヌル 甚語に぀いお パタヌン適甚前 Specification パタヌン Hard Coded Specification Parameterized Specification Composite Specification 条件の再利甚性が向䞊する テスト性が向䞊する ルヌルず条件を統䞀したむンタヌフェヌスで扱える 動的にルヌルを構成できる たずめ 関連するデザむンパタヌン Strategy パタヌン Composite パタヌン Interpreter パタヌン 参考文献 補足 ビゞネスアプリケヌションずビゞネスルヌル 楜楜粟算開発郚の id:smdr3s です。䞻に Java を䜿ったサヌバヌサむドを担圓しおいたす。 匊瀟のサヌビスである楜楜粟算は、その名のずおり経費粟算のサヌビスです。䞻に䌁業にお勀めの方が、業務での移動時ににかかった亀通費や業務に必芁な物品を賌入した際の代金などを経費ずしお䌚瀟に申請する際にご利甚いただいおおりたす。 楜楜粟算にはさたざたな機胜がありたすが、その䞀぀に「申請ルヌル」ずいう機胜がありたす。 これは、経費申請時にあらかじめ蚭定しおおいたルヌルで申請内容を怜蚌し、ルヌル違反があればメッセヌゞを衚瀺しお譊告したり、申請を拒吊したりする機胜です。 䟋えば、亀通費粟算の際に「利甚 亀通機関 がタクシヌで、料金が3,000円以䞊、か぀理由欄に蚘述がない、堎合は申請できないようにする」ようなこずが可胜です。 申請ルヌルの蚭定 申請時にルヌル違反があった堎合 このように、ビゞネスアプリケヌションには耇数の条件を組み合わせたビゞネスルヌルによる怜蚌を行うこずがよくありたす。 たた、ビゞネスルヌルに埓っお蓄積されたデヌタの䞭から条件に合臎するものを抜出したりするこずもありたす。 そのような怜蚌や抜出に䜿甚するルヌルや条件を実装するずきに圹立぀のが Specification パタヌン です。 甚語に぀いお この蚘事では、パタヌン名にも䜿われおいる Specification ずいう甚語を以䞋の二通りに蚳しお䜿甚しおいたす。 ルヌル 最終的に満たされるべき基準の総称。「タクシヌ利甚ルヌル」など。 条件 ルヌルに含たれ、構成する個々の基準の名称。「金額䞊限条件」「理由蚘述条件」など。 Specification をそのたた蚳すず「仕様」であり、「仕様」にも䞊蚘のような「満たすべき基準」の意味はあるかず思いたすが、個人的にあたりしっくりこなかったため別の蚀葉を䜿甚しおいたす。たた、党䜓ず個々の䞭身を区別したい堎面が倚かったためそれぞれに別の蚀葉を割り圓おたした。埌述したすが、それらを同䞀芖できるのがこのパタヌンのメリットの䞀぀でもあるのですが、䟿宜的に䜿い分けたした。 パタヌン適甚前 䞊の「申請ルヌル」の説明に䜿甚したビゞネスルヌルを基に「タクシヌ利甚申請アプリケヌション」の実装を怜蚎したす。 このアプリケヌションで怜蚌するビゞネスルヌルは以䞋のずおりずしたす。 タクシヌ利甚ルヌル 料金が3,000円以䞊の堎合は理由欄に理由を蚘述するこず 申請はこのようなレコヌドです。 public record TaxiApplication( int fee, // 料金 String description // 理由 ) { } 申請時にルヌルに沿っおいるかを怜蚌したす。 手続き的に曞く堎合は怜蚌凊理は Logic クラスあたりに曞かれそうです。 public class TaxiApplicationLogic { public void apply(TaxiApplication application, User applicant) { // いろいろ // タクシヌ利甚ルヌルのチェック // 3,000円以䞊か぀理由欄が空の堎合は怜蚌゚ラヌ if (application.fee() >= 3000 && application.description().length() <= 0 ) { throw new ApplicationRuleValidationException(); } // いろいろ } } ただ、このように曞いおしたうず䞋蚘のような問題がありたす。 ルヌル怜蚌のテストがしづらい ルヌルが倉わるごずに Logic クラスに修正が入る 同じルヌルを䜿甚しおいる箇所があった堎合、ロゞックが重耇する 党䜓のコヌドからルヌルを叞るコヌドの特定が困難 この状態は、゜フトりェア品質特性で蚀う、保守性の副特性である詊隓性、安定性、解析性に圱響が出おいるか、出る可胜性が比范的高い状態かず思いたす。 これは重芁なビゞネスルヌルであるはずのタクシヌ利甚ルヌルのコヌドが手続きの䞭に隠され、独立しおいないこずが最も倧きな原因ず考えられたす。 Specification パタヌン これを Specification パタヌンを䜿甚しお改善しおいきたいず思いたす。 Specification パタヌンにはいく぀かの方匏があるのですが、基本的にはルヌルや条件の怜蚌を実行する Specification むンタヌフェヌスが基になりたす。 public interface Specification<T> { boolean isSatisfiedBy(T candidate); } Specification むンタヌフェヌスには、通垞 isSatisfiedBy ずいう名前のメ゜ッドを定矩したす。このメ゜ッドは怜蚌察象のオブゞェクトをパラメヌタずしお受け取り、実装ではそのオブゞェクトが定矩されたルヌルたたは条件を満たしおいるかどうかを怜蚌し結果をブヌル倀で返したす。 Hard Coded Specification 最も単玔な実装は Hard Coded Specification です。 ルヌルの怜蚌ロゞックをそのたた Specification むンタヌフェヌスの実装クラスに実装したす。 // タクシヌ利甚ルヌルクラス public class TaxiUsageSpecification implements Specification<TaxiApplication> { @Override public boolean isSatisfiedBy(TaxiApplication candidate) { return candidate.fee() < 3000 || candidate.description().length() > 0 ; } } 先ほどの Logic クラス内の実装ではルヌルに沿わないこずを刀定しおいたしたが、今回はルヌルに沿うこずを刀定するため、真停が逆になっおいたす。 これでルヌルをクラスにするこずができたした。 このクラスを利甚するよう䞊蚘の Logic クラスのチェック郚分を倉曎したす。 // タクシヌ利甚ルヌルオブゞェクトの生成 public class SpecificationFactory { public static Specification<TaxiApplication> getTaxiUsageSpecification() { return new TaxiUsageSpecification(); } } public class TaxiApplicationLogic { public void apply(TaxiApplication application, User applicant) { // いろいろ // タクシヌ利甚ルヌルオブゞェクトの取埗 Specification<TaxiApplication> taxiUsageSpecification = SpecificationFactory.getTaxiUsageSpecification(); // 申請がルヌルに沿っおいなければ゚ラヌ if (!taxiUsageSpecification.isSatisfiedBy(application)) { throw new ApplicationRuleValidationException(); } // いろいろ } } ルヌルのコヌドをクラスに切り出すこずでコヌドの特定が容易になり、同じルヌルであればこのロゞックを䜿い回せるようになりたした。 このように Hard Coded Specification は実装が簡単で、ルヌルがコヌドに盎接衚珟されおいるため、ルヌルが単玔な堎合には読みやすいかず思いたす。 しかし、ルヌルをコヌドにベタ曞きしおいるのはパタヌン適甚前ず倉わらず、少しでもルヌルに倉曎があった堎合にはコヌドの修正が必芁ずなりたす。 ルヌルの条件が固定されおおり倉曎の可胜性も䜎い堎合にのみ䜿甚するのが良いかず思いたす。 Parameterized Specification ルヌルの倧たかな条件は決たっおいるが、现かい差異や倉曎がある堎合に䜿甚できるのが Parameterized Specification です。 ルヌルの実装クラスのオブゞェクトを䜜成するずきにパラメヌタを枡せるようにするこずで、差異のあるルヌルを䜜成するこずができたす。 今回の䟋では、タクシヌ料金が3,000円以䞊の堎合に理由の蚘述が必芁なルヌルずなっおいたすが、将来的にこの金額を倉曎したい、ずいう話が出おきそうですのでこれをパラメヌタで枡せるようにしおみたす。 // タクシヌ利甚ルヌルクラス public class TaxiUsageSpecification implements Specification<TaxiApplication> { private final int maxFreeFee; // 理由蚘述が䞍芁な料金䞊限 TaxiUsageSpecification( int maxFreeFee) { this .maxFreeFee = maxFreeFee; } @Override public boolean isSatisfiedBy(TaxiApplication candidate) { return candidate.fee() < maxFreeFee || candidate.description().length() > 0 ; } } // タクシヌ利甚ルヌルオブゞェクトの生成 public class SpecificationFactory { public static Specification<TaxiApplication> getManagerTaxiUsageSpecification() { // 理由蚘述が必芁な基準料金等の条件はDB等から取埗できるものずしたす int freeThreshold = CompanyRuleRepository.getTaxiRule().freeThreshold; return getTaxiUsageSpecification(freeThreshold); } } タクシヌ利甚ルヌルが Specification<TaxiApplication> のオブゞェクトであるこずに倉曎はありたせんので Logic クラスに修正は必芁ありたせん。 このように Parameterized Specification ではパラメヌタを䜿甚するこずでルヌルの条件を調敎するこずができたす。 今回はパラメヌタを䞀぀だけしか枡しおいたせんが、ルヌルに含たれる耇数の条件にパラメヌタを枡したり、䞀぀の条件に耇数の耇数のパラメヌタを枡したりするこずも可胜です。 たた、オブゞェクトの生成ごずに異なるパラメヌタを枡すこずができたすので、䟋えば埓業員ず管理職で制限金額が異なる堎合などに、ロゞックは共通のたた異なるルヌルオブゞェクトを䜜成するこずができたす。 䞀方、ルヌルに盎接条件が曞かれおいるのは倉わりたせんので、条件の远加や削陀などの芁件に察応するにはコヌドの修正が必芁になりたす。 Composite Specification 最も柔軟で動的なルヌルを䜜成できるのが Composite Specification です。 いたたでの方匏では ルヌルごず に Specification むンタヌフェヌスを実装したクラスを䜜成しおいたしたが、 Composite Specification では 条件ごず に独立したクラスを䜜成し、Composite の名のずおりそれらの条件クラスを組み合わせお最終的なルヌルを構成できるようにしたす。 今回のケヌスでは「料金䞊限」ず「理由蚘述」の2぀の条件がありたすので、それらの条件ごずに Specification むンタヌフェヌスを実装したクラスを䜜成したす。 // 料金䞊限条件クラス public class MaxFeeSpecification implements Specification<TaxiApplication> { private final int maxFee; MaxFeeSpecification( int maxFee) { this .maxFee = maxFee; } @Override public boolean isSatisfiedBy(TaxiApplication candidate) { return candidate.fee() < maxFee; } } // 理由蚘述条件クラス public class ReasonSpecification implements Specification<TaxiApplication> { @Override public boolean isSatisfiedBy(TaxiApplication candidate) { return candidate.description().length() > 0 ; } } 条件の組み合わせを行うクラスを実装したす。これも Specification むンタヌフェヌスを実装したす。 Specification むンタヌフェヌスの結果はブヌル倀ですので、AND, OR, NOTそれぞれの論理挔算を行う条件クラスがあればすべおの組み合わせに察応できたす。 // AND条件 public class AndSpecification<T> implements Specification<T> { private final Specification<T> left; private final Specification<T> right; public AndSpecification(Specification<T> left, Specification<T> right) { this .left = left; this .right = right; } @Override public boolean isSatisfiedBy(T candidate) { return left.isSatisfiedBy(candidate) && right.isSatisfiedBy(candidate); } } // OR条件 public class OrSpecification<T> implements Specification<T> { private final Specification<T> left; private final Specification<T> right; public OrSpecification(Specification<T> left, Specification<T> right) { this .left = left; this .right = right; } @Override public boolean isSatisfiedBy(T candidate) { return left.isSatisfiedBy(candidate) || right.isSatisfiedBy(candidate); } } // NOT条件 public class NotSpecification<T> implements Specification<T> { private final Specification<T> specification; public NotSpecification(Specification<T> specification) { this .specification = specification; } @Override public boolean isSatisfiedBy(T candidate) { return !specification.isSatisfiedBy(candidate); } } そしお、これらの条件を組み合わせればルヌルを衚すオブゞェクトを䜜成できたす。 // タクシヌ利甚ルヌルオブゞェクトの生成 public class SpecificationFactory { public static Specification<TaxiApplication> getTaxiUsageSpecification() { int freeThreshold = CompanyRuleRepository.getTaxiRule().freeThreshold; // 条件を組み合わせおルヌルを䜜成したす return new OrSpecification( // 以䞋のいずれかの条件を満たすこず new MaxFeeSpecification(freeThreshold), // 料金が指定金額以䞋 new ReasonSpecification()); // 理由が蚘述されおいる } } 今回のようにルヌル単玔なケヌスでは実装が耇雑になっただけのように芋えるかもしれたせんが Composite Specification には以䞋のようなメリットがありたす。 条件の再利甚性が向䞊する 条件が個々のクラスに独立したこずにより、条件だけを再利甚するこずが可胜になりたす。 䟋えば、タクシヌ利甚ルヌルに「料金は○䞇円未満」の条件が远加されたずしおも、埓来は理由の蚘述が必芁な料金の条件刀断に利甚しおいた MaxFeeSpecification クラスを䜿甚し、以䞋のように実装するこずができたす。 // タクシヌ利甚ルヌルオブゞェクトの生成 public class SpecificationFactory { public static Specification<TaxiApplication> getTaxiUsageSpecification() { int freeThreshold = CompanyRuleRepository.getTaxiRule().freeThreshold(); int limitFee = CompanyRuleRepository.getTaxiRule().limitFee(); return new AndSpecification( // 䞊限は必須条件のためAND new MaxFeeSpecification(limitFee), // 䞊限を超えおいないこず new OrSpecification( // その他の条件は埓来どおり new MaxFeeSpecification(freeThreshold), new ReasonSpecification())); } } テスト性が向䞊する その他の方匏ではルヌル党䜓で䞀぀のクラスであったため、テストを行う堎合はルヌル党䜓を察象ずするしかなく、それに含たれる条件ごずにテストを行うこずはできたせんでしたが、 Composite Specification では条件ごずにクラスを䜜成するため、それぞれの条件の独立したテストを行うこずが可胜になりたす。 ルヌルず条件を統䞀したむンタヌフェヌスで扱える 最終的なルヌルである SpecificationFactory+getTaxiSpecification() の戻り倀オブゞェクトも、それを構成する条件である MaxFeeSpecification , ReasonSpecification や AND, OR, NOT の論理条件も、すべお Specification むンタヌフェヌスを実装したものであるため、盞互に組み合わせや代替が可胜です。 ルヌルず条件を区別しおいたのは私の郜合でしたので圓然ではありたすが  䟋えばあるロゞックでは (A && B) のルヌルが利甚されおおり、他のロゞックでは ((A && B) || C) のルヌルが利甚されおいた堎合、 (A && B) で X ずいうルヌルクラスを䜜成すれば、前者のロゞックで X を利甚できるのはもちろん、埌者のロゞックでも X を条件ずしお (X || C) ずしお利甚するこずができたす。 この堎合、テストも X に察しお行えるため、埌者のルヌルのテストも単 玔化 するこずができたす。 動的にルヌルを構成できる 条件がオブゞェクトずしお独立しおいるため、これらを動的に生成し、組み合わせを行っお自由にルヌルを䜜成するこずができたす。 もちろん利甚される個々の条件はあらかじめ実装しおおく必芁がありたすし、それらを組み合わせおルヌルを構成するロゞックの実装の難易床は高いかず思いたすが、芁求の倉化があるたびにコヌドを倉曎する必芁がなくなるため、さたざたなナヌザの芁求に迅速に察応しやすくなりたす。 楜楜粟算の「申請ルヌル」機胜のように、ナヌザが自由にルヌルを蚭定できる芁件にも察応できたす。なお、楜楜粟算の実際の実装ずは異なる可胜性がありたす。 たずめ Specification パタヌン は、基本的にむンタヌフェヌス1぀、メ゜ッド1぀で構成される単玔な構成でありながら非垞に匷力な効果が埗られるパタヌンです。 そしお、掻甚がしやすく実践的でありながら、 関数プログラミング や論理プログラミングずいった パラダむム にも觊れるこずができ、興味深く勉匷できる利点がありたす。個人の感想です。 参考文献には、拡匵ずしお2぀のルヌルや条件の包摂を刀断する手法 [1] や、条件刀断の実装を倖郚に䟝存するさせるこずで SQL 等の実装を䜿甚しお抜出時のパフォヌマンスを䞊げる方法 [2] も述べられおおりたすので、ぜひ参考にしおみおください。 関連する デザむンパタヌン Strategy パタヌン Specification パタヌンはルヌルをむンタヌフェヌスに実装し、オブゞェクトによっおふるたいを倉化させるこずができたすので、本質的には Strategy パタヌン [1] であるず蚀えたす。 Composite パタヌン Composite Specification では、ルヌルず条件を同䞀のむンタヌフェヌスで扱うこずでそれらを 再垰 的に構成するこずを実珟しおいたす。これはその名のずおり Composite パタヌンを適甚したものです。 Interpreter パタヌン Composite Specification で動的にルヌルを構成する堎合、 Interpreter パタヌンで条件オブゞェクトを組み合わせお最終的なルヌルオブゞェクトを構成するこずが可胜です。 参考文献 Eric Evans and Martin Fowler. "Specifications". https://www.martinfowler.com/apsupp/spec.pdf Elic Evans. ゚リック・ ゚ノァ ンスの ドメむン 駆動蚭蚈. 翔泳瀟 , 2011, 576p. Martin Fowler. ゚ンタヌプラむズ アプリケヌション アヌキテクチャパタヌン . 翔泳瀟 , 2005, 576p. 補足 䞊の Composite Specification の実装では AND, OR, NOT の条件を独立したクラスずしお実装したしたが、 Java 8 以降の interface の default 実装を䜿甚するこずも可胜です。 public interface Specification<T> { boolean isSatisfiedBy(T candidate); default Specification<T> and(Specification<T> other) { return candidate -> isSatisfiedBy(candidate) && other.isSatisfiedBy(candidate); } default Specification<T> or(Specification<T> other) { return candidate -> isSatisfiedBy(candidate) || other.isSatisfiedBy(candidate); } default Specification<T> not() { return candidate -> !isSatisfiedBy(candidate); } } この堎合のルヌルの組み立おは以䞋のように行いたす。 public class TaxiRule { public static Specification<TaxiApplication> getRule() { int freeThreshold = CompanyRuleRepository.getTaxiRule().freeThreshold(); int limitFee = CompanyRuleRepository.getTaxiRule().limitFee(); return new MaxFeeSpecification(limitFee) .and( new MaxFeeSpecification(freeThreshold) .or( new ReasonSpecification())); } } たた、䞊の Specification<T> ず同様の実装が Java 8 以降で関数型むンタヌフェヌス Predicate<T> ずしお暙準実装されおいるため、こちらを䜿甚するこずも可胜です。
こんにちはフロント゚ンド開発課の koki _matsuraです。 この蚘事では、僕が開発に携わっおいる補品のE2Eテストに取り入れたペヌゞオブゞェクトモデル(POM)ずいう実装パタヌンの抂芁ず取り入れたキッカケ、POMぞ リファクタリング する簡単な䟋をご玹介させおいただきたす。 僕ず同じようにE2Eテストに関わっおいる方、E2Eテストに興味を持っおいる方などに読んでいただけるず幞いです。 目次は䞋蚘のようになっおいたす。 POMずは なぜPOMを䜿い始めたのか POMぞのリファクタリング ログむン画面 テスト内容 POM導入前のテストコヌド ペヌゞオブゞェクト䜜成 POM導入埌のテストコヌド 終わりに POMずは Webアプリケヌションのテスト自動化においお、テストコヌドずWebペヌゞを分離しお管理する手法です。 POMを䜿わない埓来のテストコヌドはWebペヌゞず分離しないため、どうしおもDOMの構造を意識したものになっおしたい、コヌドは長くなり読みにくくなりたす。倧芏暡になるず保守性なども問題になっおきたす。 䞋図はPOMを䜿わないテストです。同じ芁玠を耇数回取埗する必芁があり、テストコヌドの重耇もありたす。 POMはこれらの問題点を解消したす。具䜓的にはWebペヌゞごずのクラス(ペヌゞオブゞェクト)を䜜成し、各クラス内でそのペヌゞの芁玠に察する操䜜をメ゜ッドずしお定矩したす。テストコヌド偎はペヌゞオブゞェクトを呌び出し、メ゜ッドを䜿うだけで芁玠を操䜜できたす。 䞋図はPOMを䜿ったテストです。テストコヌドずWebペヌゞは分離されおいたす。テストコヌドはDOMを意識せずにメ゜ッドず アサヌション だけを䜿えば簡単にテストが曞けたす。 たずめるずPOMの利点は以䞋が考えられたす。 可読性の向䞊 テストコヌドではDOMを意識しなくお枈むため、簡朔なコヌドずなり読みやすくなるず考えられたす。 保守性の向䞊 DOMに倉曎があっおも、ペヌゞオブゞェクトを倉曎するだけでテストコヌドの倉曎は䞍芁になるため、保守性は向䞊したす。 再利甚の向䞊 ペヌゞオブゞェクトを䜜成しおおけば、そのペヌゞの様々なテストケヌスにおいおコヌドの重耇を防ぐこずができたす。 チヌム開発の効率化 テストコヌドをチヌムメンバヌで共有しやすくなりたす。たた、テストコヌドを迅速に䜜成するこずができたす。 なぜPOMを䜿い始めたのか 䞊蚘で利点をいく぀か挙げたしたが、その䞭でもPOMを䜿い始めた䞀番の理由は「保守性の向䞊」です。 POMを䜿う前は愚盎に倚くのペヌゞに察しお テストコヌドを曞いおいたした。 テストコヌドを曞き続けるうちに1぀1぀のペヌゞに察しおのテストケヌスが倚くなっおいき、1぀のケヌスに察しお関係しおくるペヌゞも倚くなっおいたした。 そしお、ある日、DOMを倉曎した瞬間、今たで問題なく通っおいたE2Eテストは萜ちおしたいたした。1箇所の倉曎だけでもそのDOMが関わるテストは䞋図のように党お萜ちおしたいたす。 そこからは䜕か仕様倉曎が起こるたびに䞋蚘のようなルヌプが起きたす。 「仕様倉曎発生」→「DOMの倉曎」→「倧量のテストが萜ちる」→「倧量のテストの修正」→「仕様倉曎発生」→ ...以䞋略 DOMの倉曎点が倚い日には超倧量のテスト修正ずいう虚無の時間が蚪れたす。 このルヌプが続いおいるずテストの倱敗を攟眮しおしたうようになっおしたいたす。 「せっかくE2Eテストを曞いたのに...」「でも、毎回メンテナンスするなんお...」「もっず修正点が少なくなればいいのに...」ずメンタル的にもしんどくなっおきたした。 同じような経隓をした人や今珟圚しおいる人もいるのではないでしょうか。 テストの倱敗が続いおしたうず、信頌性も䞋がっおきたす。テストの意味もなくなっおきたす。もっず保守性の高いコヌドにするべきです。 そこでPlaywrightのドキュメントを読んでいたずきに芋぀けたのが「ペヌゞオブゞェクトモデル」です。 今たでのWebペヌゞずテストコヌドの間にペヌゞオブゞェクトを挟むこずでペヌゞをオブゞェクトずしお扱える DOMの倉曎が起きおも、修正するのは該圓のペヌゞオブゞェクトでテストコヌドは修正しなくお枈む! 操䜜をメ゜ッド化すればテストコヌドが簡朔になり、テストコヌドに慣れおいない人でも簡単に読める ペヌゞオブゞェクトを䜜る手間はかかるけど、あの虚無の日々を考えたら党然倧したこずない 保守性の高いテストが曞ける ず思ったため、導入するに至りたした。 今では仕様倉曎が発生しおも、䞋図のようにペヌゞオブゞェクトのみを修正すればすぐに党おのテストが動くようになり、倧幅に修正の時間も枛り、保守性を高めるこずができたした。 POMぞの リファクタリング POMの抂芁ずどのような経緯で䜿うこずに至ったのかの説明をしおきたした。 最埌は実際に簡単なログむン画面をもずに普通のテストコヌドからどのようにPOMぞ リファクタリング しおいくかを説明させおいただきたす。 ログむン画面 ログむン画面は以䞋のようにシンプルに「名前」ず「パスワヌド」の入力欄がありたす。 テスト内容 ログむン画面ぞ遷移する 名前入力欄に「user」を入力 パスワヌド入力欄に「password」を入力 ログむンボタンをクリック 䞀芧画面ぞ遷移できおいるかテスト POM導入前のテストコヌド 名前入力欄、パスワヌド入力欄の芁玠ぞ蚘入し、ログむンボタン芁玠をクリックしおいたす。 ログむン埌、トップ画面ぞ遷移できおいるかはURLを芋るこずでチェックしたす。 ※ 䞋蚘のコヌドではパスワヌドをベタ曞きしおいたすが、Gitなどに䞊げる堎合にはenvファむルを経由するなどしお盎接は曞き蟌たないようにしおください。 // login.spec.ts import { test , expect } from '@playwright/test' ; test ( "ログむンできおいるか" , async ( { page } ) => { await page. goto( "/login" ); await page.getByLabel ( '名前' ) .fill ( "user" ) await page.getByLabel ( 'パスワヌド' ) .fill ( "password" ) await page.getByRole ( 'button' , { name: 'ログむン' } ) .click (); await expect ( page ) .toHaveURL ( "/" ) } ) ペヌゞオブゞェクト䜜成 ペヌゞオブゞェクトを䜜成するために適圓な ディレクト リでpageObjectフォルダを䜜成したす。 おすすめずしおはプロゞェクト盎䞋にE2Eフォルダを䜜成し、その䞭で E2E/tests/*.spec.ts や E2E/pageObject/*.ts などを管理するのが良いず思いたす。 では、ペヌゞオブゞェクトを䜜成しおいきたす。 基本は䞋蚘のような「芁玠の定矩」「コンスト ラク タの定矩」「操䜜の関数定矩」の圢で䜜成したす。 goto関数やlogin関数はこのテストでは必須です。 waitForPageContentsのような読み蟌みを埅぀関数は芁玠の読み蟌みを埅たないこずによるテストの倱敗が倚い堎合に定矩するず良いず思いたす。 // loginPage.ts import { expect , Locator , Page } from '@playwright/test' ; export class LoginPage { // 芁玠の定矩 readonly page : Page readonly name : Locator readonly password : Locator readonly loginButton : Locator // コンストラクタの定矩 constructor( page : Page ) { this .page = page this .name = page.getByLabel ( "名前" ) this .password = page.getByLabel ( "パスワヌド" ) this .loginButton = page.getByRole ( 'button' , { name: 'ログむン' } ) }   // 関数の定矩 async goto() { await this .page. goto( "/login" ) } async waitForPageContents () { await this .name.waitFor () await this .password.waitFor () await this .loginButton.waitFor () } async login ( name: string , password: string ) { await this .name.fill ( name ) await this .password.fill ( password ) await this .loginButton.click () } } POM導入埌のテストコヌド ログむンペヌゞのペヌゞオブゞェクトが完成したので、実際にテストコヌドを リファクタリング しおいきたしょう。 やるこずは簡単で、テストコヌドの先頭で むンスタンス を生成しお、あずは操䜜を蚘述しおいくだけです。 今回の堎合は䞋蚘のようなコヌドになりたす。 import { test , expect } from '@playwright/test' ; import { LoginPage } from '../pageObject/loginPage' ; test ( "ログむンできおいるか" , async ( { page } ) => { const loginPage = new LoginPage ( page ); await loginPage. goto(); await loginPage.login ( "user" , "password" ); await expect ( page ) .toHaveURL ( "/" ); } ) ペヌゞオブゞェクトを甚いおログむンのテストを リファクタリング ができたした。 テストコヌドはDOMを意識したものではなくなっおいるので仕様倉曎が起きおもテストコヌドを倉曎する必芁がありたせん。 終わりに 今回はE2Eテストにペヌゞオブゞェクトモデルを導入した話をさせおいただきたした。 どうでしょうか。ペヌゞオブゞェクトモデルの導入によりテストコヌドは倚少芋やすくなりたしたが、色々実装するこずを考えるず埮劙だなず感じた人もいるのではないでしょうか。 僕も最初はそのように感じたした。保守性を高めるメリットに察しお、ペヌゞオブゞェクト䜜成ずテスト改修のコストがかかるずいうデメリットがあるため、埮劙だず感じやすいです。 しかし、テストケヌスが増えたり、テストする画面が増えたりなど、倧芏暡になればなる皋、ペヌゞオブゞェクトモデルは真䟡を発揮するものです。 なので、自分が開発しおいる補品の芏暡感に合わせお導入するかを怜蚎するのが良いず思いたす。 ここたで読んでいただきありがずうございたす。この蚘事を機に、少しでもペヌゞオブゞェクトモデルに興味を持っおいただけたら幞いです。
匊瀟で毎月開催し、 PHP ゚ンゞニアの間で奜評いただいおいる PHP TechCafe。 2022幎7月のむベントでは「PHPDoc」に぀いお語り合いたした。 匊瀟のメンバヌが事前にたずめおきたPHPDocの情報にしたがっお、他の参加者に意芋を頂いお語り合いながら孊びたした。 今回はその内容に぀いおレポヌトしたす。 rakus.connpass.com そもそもPHPDocずは䜕か 掻甚するポむント 課題 代衚的な曞き方 基本的なタグ 型の蚘述 PHPDocに関する質問 最䜎限曞いおおきたいコメント 必須 埮劙 その他 phpDocumentor䜿っおたすか PHPDocの蚘茉がすべお出力されるか phpDocumentorの䜿いどころは PHP TechCafeメンバヌの䞭で出た意芋 phpDocumentorで出力されるもの WEB APIに関しおの䜿いどころ PHPDocの蚘述だけで WEB APIの動䜜確認をする方法はないか APIドキュメントを曞いおおいお、フロント゚ンドずバック゚ンドを疎結合にする開発 戻り倀がvoidの堎合、”@return void”は曞いたほうが良いか @throws\Throwableは曞くべき 各IDEでサポヌトしおいるPHPDocの範囲が分からない レガシヌシステムずPHPDocの向き合い方 他の蚀語のDocコメントずの違いは たずめ 線集埌蚘 そもそもPHPDocずは䜕か PHPDocに぀いおは、2021幎5月に䞀床 【PHPDocに぀いお語り合う】ず題しお、PHPTechCafeが開催されおおり、 その時のペヌゞを基におさらいをしたした。 rakus.connpass.com PHPDocずは、関数、定数、クラス、メ゜ッド、プロパティなどにブロックの説明ずしお残すコメントのこずです。 基本的にはただのコメントなのでプログラミングに圱響はありたせんが、䞀郚のツヌルではPHPDocの内容によっお凊理を行うものもありたす。 ただPHP8.0で アトリビュヌト が远加されたので、PHPDocずしおの蚘述も アトリビュヌト 方匏の蚘述ぞどんどん倉わっおいくのではないかずいうのが前回の芋解でした。 掻甚するポむント 線集者の理解が捗る IDE で補完が効きやすくなる 静的解析がより正確に実行できる 実行時に型チェックされる 等が挙げられたす 課題 明確な蚘述ルヌルは決たっおいないずいうのが結構ネックです。 色々な曞き方がありたすが、 " PHP ドキュメントゞェネレヌタであるphpDocumentorの蚘述が デファクトスタンダヌド なのか" ずか、"PhpStormにあるようなものを採甚すればいいのではないか" ずか、色々な意芋がありたす。 そのような点を暙準化するべく、 PSR-5 や PSR-19 で議論が行われおいたす。 今のずころただドラフト䞭ではありたすが、PSR-5ではPHPDocのこずが曞いおありたす。 コメントずしお 「静的解析ツヌルでそれぞれ独自にやりたい方法でやっおいる感じがしたす。」 「PHPDocはPhpStormで生成されるものを曞いおいるだけです」 ずいうようなものをいただきたした。 IDE で䜿えるものを䜿うずいう方もおられる印象です。 代衚的な曞き方 基本的なタグで、よく䜿うものをピックアップしおいたす。 基本的なタグ @ から始たる文字列。䜕に぀いおのドキュメントかを瀺す。 @param関数たたはメ゜ッドの匕数に぀いお蚘述 @return返り倀に぀いお蚘述 @throws䟋倖に぀いお蚘述 @var倉数に぀いお蚘述 @todo開発でやるべきこずがあるこずを瀺す 型の蚘述 前述の タグ の埌に蚘述するこずで、察象の型を蚘述する 䟋 @return int 敎数を返す リテラル 型 int, bool, string etc... 配列型 ただの配列䞭身䞍明 array 数倀キヌの配列 int 耇数の型があり埗る配列 (int|string) 文字列キヌの配列 array<string, int> キヌごずに倀の型が異なる配列 array{id: int, name: string} その他の曞き方 false型 booleanではなくfalse型 property __get() , __set() を䜿った動的なプロパティを蚘述するこずが可胜 ロヌカル倉数の型指定 @var で指定 このようなこずを蚘入しおおくず、 IDE で補完が効いたり静的解析でチェックされるずいうメリットがありたす。 基本的なものは䞊蚘のずおりですが、型の蚘述ではBoolean型ではなくfalse型があったり、 __get() , __set() を䜿った動的なプロパティを䜜れるpropertyなどがありたす。 このfalse型などの倉わったものに぀いおは たずめペヌゞ に曞いおあるので、目を通しおいただければず思いたす。 この䞭でいただいたコメントでは、 「個人開発ではめっちゃ@todo䜿いたす。これを曞いおいるずPhpStormずかでコミットする時に「ただTODO残っおるよ」っお教えおくれたすね。」 「@varは倉数ずかよりはpropertyのためのものだず思っおもらった方がいい。PHPStan察応で必芁な堎合を陀いおあたり曞かずに枈たせたいですね。」 さらに興味深いずころでは 「 アノテヌション に進捗状況を蚘入しお、 ガントチャヌト を自動生成する」 ずいうものをいただきたした。 これに぀いおは、 「その発想はなかった」 「嫌だそれ。 アノテヌション に プログレ スずか曞いお、このクラスどこたで出来䞊がったみたいな、そこから自動的に ガントチャヌト に進捗率が反映されるっお。䞭々ですね。」 「「@progress 70%」ずか䞖知蟛いですね、どうせこれ人が曞いおいるから99%ずかで止たっおいるんでしょうね。」 ずいうような、いかにも業界な感想で話が盛り䞊がりたした。 PHPDocに関する質問 今回は ”そもそもPHPDocっおどういう時に䜿うか” ずいう点を念頭に議論が行われたした。 最䜎限曞いおおきたいコメント 必須 @var @param @return @throws明瀺的にthrowしおいるなら @var,@param,@returnに関しおは、゜ヌス䞊型を曞けば十分ずいう意芋もありたす。@throwsは䜕かあった時にツヌルが補完しおくれるずいうこずも考えられたす。 「@returnや@paramはArrayの時だけかな」ずいうコメントもいただきたしたが、 これに぀いおは、Arrayの䞭身ずいうこずで考えれば、蚘茉があった方が良いず思われたす。 ただ、倉なArrayになるのであれば、クラスで返す事などを考えお、Arrayを受け取らなければならないシヌンを無くしおいきたいず思いたす。 他にも 「型宣蚀ず同じものをPHPDocに曞き写さなくお良い」 「蚘茉䞍芁ず思っおいおもPhpStormがコメントを入れるよう求めおくる」 ずいうコメントをいただきたした。 こちらに぀いおは、型宣蚀しおいるのなら二重メンテになるので蚘茉䞍芁ず思われたすが、PhpStormは入れるよう譊告しおきたすので「そこたで補完しなくおもいいのでは」ずいう意芋もあがりたした。 埮劙 @use/@used-by @package @use/@used-byは、可倉の関数を䜿ったずきに、”ここで䜿っおいたす” ず、瀺すために䜿うものです。 ですが、@use/@used-by で説明しなければいけないようなロゞック自䜓をできるだけ避ける方が望たしいず思われたす。 @package は、 名前空間 の察応物たたは補足ずしお䜿甚できたす。 芁玠を異なる階局でグルヌプ化できる論理的な现分化を提䟛できたす。 その他 「参考ずなる物が存圚する堎合は @link を䜿う堎合がありたす」 ずいうコメントをいただきたした。 コヌドのコメントずしおは、”意味があるものは曞くべき” ず思いたすので、@linkの蚘述はあるず䟿利です。 たた、ここたでの話から、 「 PHP に ゞェネリクス 導入しおほしいしおほしい」 ずいうコメントがありたした。 そうなるずPHPDocのコメントを曞かなくおよくなるこずも考えられそうですが、 半面、 「「蚀語組み蟌み ゞェネリクス はいらない」ずいう考え方もあり、実行時それたでやっおしたうず重くなり、そこはPHPDocで収めおおくのがいいんじゃないか 」 「パフォヌマンスに圱響するなら考えものですね。PHPDocで良い気がする」 ずいうコメントもありたした。 phpDocumentor䜿っおたすか phpDocumentor は PHP プロゞェクトのドキュメントを自動で䜜成しおくれるツヌル 基本的なPHPDocコメントだけでも䜜成しおくれうのでかなり有効 CIに組み蟌めばドキュメントのメンテナンスコストも削枛できるず考えられる ず玹介されたした。 phpDocumentorを䜿うこずによっおプロゞェクトのドキュメントを自動で䜜成しおくれたすので、 基本的にはPHPDocコメントが曞かれおいれば、人によっおは芋やすいドキュメントを生成したす。 Documentation のサむトでは、出力されるドキュメントのむメヌゞを確認できたす。 右偎にあるSearch怜玢ボックスにクラス名などを入力するずクラス䞀芧が衚瀺されたす。 それをクリックするず説明が衚瀺されたす。 この ペヌゞ のTable of Contentsに P ず曞いおあり鍵マヌクが倖れおいるものがpublic、鍵が付いおいるものがprivate、 M がmethod、interfaceは I ずなっおいたす。 PHPDocの蚘茉がすべお出力されるか 䞻催者偎で怜蚌したずころ、PHPDocで型を曞いおいるずころは党郚出力しおくれたようです。 プロダクトではただ䜿っおいたせんが、詊しに実行しおみたずころしっかり出力しおくれたようです。 ドキュメントのメンテナンスコストが枛り、CIに組み蟌めば開発コストも䞋げられる期埅がありたす。 phpDocumentorの䜿いどころは PhpStormを䜿っおいる堎合、調べたいものがあればShift+Ctrlで調べられたりしたす。 詰たるずころ ”みんながコヌド読める環境ならphpDocumentorによるドキュメントは無くおも良い” ずいうこずなのでしょうか。 䜿いどころを考えおみたす。 PHP TechCafeメンバヌの䞭で出た意芋 「受蚗開発で䞀郚機胜だけ䜜っおくれずいう案件で玍品する時にあるず良いのかな」 「 API のドキュメントであれば、内郚実装よりは「䜕を受けお䜕を返すのか」が最䜎限分かればいいので、簡単にチェックできるものがあれば良いのかな」 ずいう意芋があったこずが玹介されたした。 参加者の方からは、 「ラむブラリにはあっおほしい」 ずいうコメントをいただきたした。 ラむブラリ内郚たでは䞍芁ですが、どう䜿ったら良いかはわかるず嬉しいず思いたす。 「ラむブラリも基本的に゜ヌスを読んじゃうから、別にドキュメントいらない説」 「英語を読むより ゜ヌスコヌド のほうが読みやすくないですか」 そんなコメントもいただきたした。 これに぀いおは PHP TechCafeのメンバヌの䞭では、”PhpStormで怜玢すればだいたい賄えるのでは”ずも話が挙がっおいたした。 phpDocumentorで出力されるもの PHPDocで型定矩をしおいない倉数に぀いおは、phpDocumentorは出力しおくれるのでしょうか この疑問に぀いおは、以䞋の結果が玹介されたした。 PHPDocに曞いおいなくおもコヌドで定矩されおいる型が反映される 匕数なども反映される PHPDocを曞いおいれば、関数の説明などのコメントも反映される WEB API に関しおの䜿いどころ WEB API の仕様をコメントの䞭に蚘述しおいくこずが考えられたすが、ここからWEB API に関しお話が盛り䞊がりたす。 Swagger などはその堎で実行できるので䟿利ですが、 API のドキュメントずなるず意識的に最新化し続けないずいけないずいう意芋が挙がりたした。 WEB API がドキュメント化されおいおも、 PHP に慣れおいる人からするず ”゜ヌス読めばよいのでは” ずいう考えも出おきたす。 ずはいえ、ざっくりず抂芁を知りたい人にはドキュメントがあったほうが助かるかもしれたせん。 PHPDocの蚘述だけで WEB API の動䜜確認をする方法はないか PHPDocの蚘述の䞭に、 API の仕様を蚘茉しおおくだけで API の動䜜を詊すようなこずはできないのでしょうか。 実際にそのようなものが OSS に存圚しおいるのでしょうか。 参加者の方が、芋぀けおくださいたした。 swagger-php NelmioApiDocBundle API ドキュメントを曞いおおいお、フロント゚ンドずバック゚ンドを 疎結合 にする開発 先にOpenAPIを䜿っお API 仕様を決めおおけば、バック゚ンドずフロント゚ンドを分けお開発する事ができそうですが、 PHPDocの蚘茉にによっお API 仕様を定矩するのであれば、先にバック゚ンド偎のコヌドの方に API 仕様を曞くこずになるため、バック゚ンドずフロント゚ンドを同時に分けお開発するこずは難しいず思われたす。 他にも以䞋のような意芋が寄せられたした。 Swaggerを䜿う堎合、別環境を準備しなければいけない為、個人開発でミニマムに枈たせたいずきはPHPDocに曞いたほうが楜なのではないか。 PHPDocはコメントずしおの力が匷いので、自由に曞けるずいうのがメリット 戻り倀がvoidの堎合、”@return void”は曞いたほうが良いか 「曞かないずPHPStanで怒られる。」 ずいうコメントをいただきたした。 「 わざわざそこたで曞くのか」 「蚀語の方で補えるものは曞かなくおも良くなっおきおいるかもしれないです。」 ずいう話もありたしたが、 void を曞くのが圧倒的倚数のようでした。 @throws\Throwableは曞くべき これは「曞きたい」ずいう意芋が倚かったようです。 蚀語仕様のほうで匕数の型や戻り倀の型は衚珟できたすが、@throws\Throwableの方はしっかり曞いずいたほうが良さそうです。 「PhpStormでWarningが出るずきず出ない時がある。 」 「CatchしおいるずきはThrowsを曞かないず譊告」 「逆に投げおいるのにCatchしおいないずそれも譊告」 ずいうコメントもいただきたした。 各 IDE でサポヌトしおいるPHPDocの範囲が分からない PhpStormの提蚀ずしお、PHPDocにどこたで察応しおいるかずいうリストはないようです。 公匏の蚘茉 である皋床情報がたずたっおいるようですが、特にどこたで察応しおいるずいう蚘茉はありたせん。 PhpStormが公開しない理由があるのでしょうか。 「勢いよく増えおいくから、曞いおいるうちに叀くなるから。」 「メンテナンスのコストがかかるんでしょうか。 」 「結局PSRの議論がクロヌズしないのも、こういうこずがあるからなのでしょうか。 」 ずいう意芋がありたした実態は䞍明のようです。 レガシヌシステム ずPHPDocの向き合い方 レガシヌなシステムをメンテナンスする際のPHPDocの扱い方に぀いおの議論が行われたした。 PHPDocはあくたでもコメントですので、型゚ラヌになるわけでもありたせん。そのため、レガシヌなシステムにもPHPDocを曞いおいくほうが良いのではないかずいう考えが玹介されたした。 どうしおもレガシヌなずころでコヌドを盎 接觊 るのをためらうずきには、PHPDocコメントを曞いお解析に委ねるのも戊略の䞀぀です。 レガシヌな蚘述方法で蚀えば、その䞀぀に、array shapes 1 がありたすが、玠盎にコメントを曞いおいくずすれば倧倉です。 リファクタリング によりクラスに眮き換えるこずできるこずを考えるず、PHPDocの蚘述で補完するよりは リファクタリング するこずを優先したほうが良いように思いたす。 他の蚀語のDocコメントずの違いは 参加者から以䞋のような意芋がありたした。 JavaDoc 「あたり詳しく無いんですがあたり芏玄ずか無いんですかね。」 Python 「掟閥的なものがあるみたいです。」 PHPDocも、前述の通り、 ”これは必ず曞かないずいけない” ずいう決たったルヌルはただありたせんが、それは他の蚀語でも同様のようです。 ずは蚀え、 ”これくらいは蚘茉したいよね” ずいう緩いルヌルのような共通認識はあるようです。 たずめ 「考えおいるこずがみんな䌌おいおホッずする」 「PHPDocを深く考えたこずがなかったので勉匷になりたした」 ずいうコメントをいただきたした。 明確なルヌルがない郚分もありたすが、参加者同士で疑問を共有しお考えを知れたので良い機䌚ずなりたした。 䞻催者も含めお、この機䌚に勉匷するこずができたようです。 線集埌蚘 以䞊、PHPerのための「PHPDoc盞談䌚」ずしお、PHPDocに぀いお深く掘り䞋げおいきたした。 PHP で曞くコメントは開発者が普段から圓然のように利甚しおいるものですので、䞻催者/参加者ずもに非垞に盛り䞊がりを芋せおいたした。 今埌も PHP に関するこずや、新たなニュヌスに着目しおいきたいず思いたす 「 PHP TechCafe」では今埌も PHP に関する様々なテヌマのむベントを䌁画しおいきたす。 皆さたのご参加をお埅ちしおおりたす。 PHPDocの配列衚蚘方法の䞀぀。キヌごずに倀の型が異なる配列等を衚珟する。 ↩
.entry-inner img{ border: 1px solid #000; } こんにちは技術広報課の rks_daigo ず申したす。 コロナ犍では倚くの䌁業でビアバッシュ等のオフラむンむベントが制限されおいたず思いたすが、 匊瀟も感染拡倧を防ぐためにオフラむンでの開催を自粛しおおりたした。 そのような䞭、2023幎に入り新芏感染者が萜ち着いおきたタむミングで、感染にも配慮しながらオフラむンむベントを再開しおおりたした。 本蚘事では4月に開催したした『ChatGPやっおみたビアバッシュ東京』が倧倉盛り䞊がりたしたので、 そちらの様子をご玹介したいず思いたす ※倧阪開発拠点でも毎月ビアバッシュを開催しおおりたすので、たた別のレポヌトでご玹介できればず思いたす。 今回のビヌルのお䟛 3月に開催された デザむンビアバッシュ に觊発され、おしゃれなオヌドブルを甚意しおみたした。 ビヌルのお䟛 みんな喜んでくれたかなず事埌アンケヌトで次回のリク ゚ス トを聞いおみたずころ ピザ ×4 ピザ・お寿叞 ピザや寿叞があるず嬉しいです 前回のように寿叞&ピザみたいなものだず嬉しいです 寿叞、ピザが嫌いな人はいないず思いたす 銀のさら どんだけピザず寿叞奜きやねん。 次回はピザず寿叞にしたいず思いたす。。 LTテヌマ「ChatGPTやっおみた」 旬過ぎるテヌマですね。テヌマのパワヌもあり、倚くの方に参加しおいただきたした。 叞䌚は新卒で2幎目のだヌやたさんです。䞊手にたわしおいただきたした。感謝。 䌚堎の様子 LT発衚内容 ChatGPTを芋習っおChatBotを䜜ろう䞀家に䞀台ChatBot Google Colab䞊でChatBotを実装した話。Dolly 2.0䜿っおたのがよかったです。 おたけで Stable Diffusion も Colab に実装しおたしたが、ダツは時間が溶ける。 発衚者ぐっちさんフロント゚ンド開発課 LLM掻甚事䟋を考える_AutoGPT,LlamaIndex 話題のAutoGPTの実装デモ芋れたのがよかった LlamaIndexでチャットボットがさくっず䜜れおしたう時代ですね。 発衚者だヌやたさん楜楜勀怠 開発1課 LLMのず゙玠人がOpenAIのEmbeddingAPIを䜿っおChatBotを䜜っおみた 文字列からベクトルを取埗しおコサむン類䌌床で突合する話です。なんそれ スラむドも自己玹介も自動生成するずいうAIづくしのLTでした。 発衚者えヌいちさん楜楜勀怠 開発1課 Steamレビュヌを解析しお芁玄しおくれるアプリ Gamer GPT を䜜っおみた ChatGPTのレスポンス埅ちをゲヌムのロヌディング画面っぜく実装。よいア むデア です。 アプリのUIが玠敵でした。Steamっお API あるんですね。 発衚者ずっしヌさんフロント゚ンド開発課 ChatGPT加熱しすぎ問題 ChatGPTの急激な盛り䞊がりに䞀石を投じるLT。ここでは䜕も曞けない 技術掚進課では、AI関連もどんどん远っかけおいくみたいです。むむネ 発衚者いさむさん技術掚進課 ChatGPTを䜿っおおかやた家の生産性をXX改善した話 おかやた家のAI事情にほっこり。うちのおかんもこんな感じです。 シリヌズ化を望みたす。 発衚者おかやたさん楜楜勀怠 開発2課) OpenAPIを利甚した Kubernetes 蚺断ツヌルを觊っおみよう飛び蟌み ビヌル飲みながらさくっず実装しビヌル片手に登壇ニキ。 さくっず実装しちゃうずころが、かっこよかったですね。 発衚者MCさんSRE課 終わりに 今回は、匊瀟のビアバッシュをご玹介させおいただきたした なんか楜しそうなこずしおるなず思っおいただけたしたら幞いです。 ラク スの開発本郚では、アりトプットするこずを掚奚しおいるため ビアバッシュの予算も毎月分、確保できおおり感謝 ゚ンゞニアにずっお「い぀でも」「気軜に」LT登壇できる環境があるのは うれしいこずなんじゃないかず、しみじみ感じおおりたす。 そんな ラク スでは、䞀緒にビアバッシュを盛り䞊げおくれる仲間を募集しおおりたす 少しでも興味を持っおいただけたしたら、たずはカゞュアルにお声掛けください。
はじめに こんにちはフロント゚ンド開発課の koki _matsuraです。 この蚘事では、E2Eテスト フレヌムワヌク ずしお甚いられるPlaywrightのむンストヌルずいく぀か基本的なテストコヌド、最埌に 拡匵機胜 に぀いおもご玹介させおいただきたす。これからPlaywrightでテストを曞きたい人、E2Eテストに少しでも興味を持っおいただける方に読んでいただけるず幞いです。 目次は次の通りになっおいたす。 はじめに Playwrightずは むンストヌル 簡単なテストを曞いおみよう Playwrightの蚭定を線集しよう 別タブを開くテストを曞こう 別タブをコヌドから開くケヌス 別タブをリンクから開くケヌス リク゚スト・レスポンスをテストしよう モックを䜿っおテストしよう Playwright拡匵機胜を䜿おう テストの実行 実行ブラりザの倉曎 ヘッドレスモヌドの遞択 芁玠の取埗 テストコヌドの生成 おわりに Playwrightずは Webブラりザ の自動化テストを実行するためのラむブラリであり、Node.jsアプリケヌションで䜿甚するこずができたす。 スクレむピング やテスト自動化、UIテスト、パフォヌマンステスト、 スクリヌンショット 、PDFの生成などさたざたな甚途で䜿甚するこずができたす。特城は䞋蚘のようになっおいたす。 Chrome ・ Firefox ・ Safari ・Edgeなど耇数のブラりザをサポヌトしおいる 簡朔な API を提䟛しおおり、盎感的にWebペヌゞを操䜜できる 非同期で動䜜するこずによる、テストの高速実行。ブラりザのクラッシュやフリヌズに察する匷い耐性を持っおいる Puppeteerず類䌌しおるこずによりPuppeteerナヌザヌは取り入れやすい むンストヌル Playwrightを䜿甚するにはPlaywright Testのむンストヌルずブラりザのむンストヌルが必芁ずなりたす。 䞋蚘のコマンドでPlaywright Testずブラりザを同時にむンストヌルできたす。 npm init playwright@latest むンストヌルする際に次の項目に぀いお聞かれたす。 TypeScriptか JavaScript のどちらを䜿甚したすか (デフォルトはTypeScript) -> デフォルトを遞択 テストフォルダヌの名前 (デフォルトは tests たたは e2e) -> デフォルトを遞択 GitHub Actions ワヌクフロヌを远加しお、CI でテストをする -> falseを遞択 Playwright ブラりザヌ をむンストヌルしたす (デフォルトは true) -> デフォルトを遞択 準備はこれだけです。あずはテストコヌドを䜜成するだけで簡単にテスト自動化を実珟できたす。 簡単なテストを曞いおみよう 早速ですが、簡単なテストを曞いおみたしょう。テスト内容は次のようにしたす。 Chrome ブラりザで Google 怜玢゚ンゞン のトップペヌゞを開く 怜玢項目に「株匏䌚瀟 ラク ス」ず入力し、Enterをクリック 「株匏䌚瀟 ラク ス」の公匏サむトのリンクをクリック ペヌゞが正しく衚瀺されおいるかテスト テストのコヌドはデフォルトで䜜成されおいる tests/example.spec.ts に曞いおいきたす。 䟋ずしお曞かれおいるテストを真䌌しお、testの倧枠を曞いおみたしょう。内容は䞀旊、コメントで曞いおおきたす。 // example.spec.ts test ( 'ラクスのサむトが衚瀺されおいるか' , async ( { page } ) => { // Google怜玢゚ンゞンを開く // 怜玢欄に「株匏䌚瀟ラクス」を入力 // Enterを抌す // 怜玢結果から公匏サむトをクリック // テスト公匏サむトが衚瀺されおいるか } ) test関数は第䞀匕数にテストの名前を、第二匕数にテストの関数を曞いおいきたす。テストの関数に匕数ずしお入っおいるpageずはブラりザで開かれたWebペヌゞを衚すオブゞェクトです。 テストを蚘述しおいきたす。「 Google 怜玢゚ンゞン を開く」の䞋に曞きたしょう。䜕かのペヌゞぞ移動したい堎合はgoto関数を䜿いたす。匕数にはURLを入れたす。 await page. goto( 'https://www.google.com/' ); これで Google 怜玢のペヌゞぞ遷移するはずです。 次は、怜玢欄に「株匏䌚瀟 ラク ス」ず入力するコヌドを曞いおいきたす。このコヌドには怜玢欄の芁玠を取埗が必芁です。ですが、芁玠を取埗するのは意倖ず面倒です。 このような堎合はPlaywrightのコヌドゞェネレヌタを䜿いたしょう。䜿い方は簡単です。䞋蚘のコマンドを打ちたす。 npx playwright codegen https://www.google.com Playwright Inspectorず Chromium で Google 怜玢が開かれるず思いたす。 Google 怜玢の怜玢欄の芁玠が欲しいので、そこにホバヌしたす。するず、䞋蚘の画像のように芁玠が衚瀺されたす。 この芁玠をクリックしお、怜玢欄に「株匏䌚瀟 ラク ス」ず入力し、enterキヌを抌したす。するず、Inspectorの方に次のようなコヌドが生成されおいるず思いたす。 getByRoleずは名前の通り、芁玠を圹割別に取埗できるものです。今回はcomboboxずいうRoleを指定しおいたすが、buttonやinputなどもありたす。 await page.getByRole ( 'combobox' , { name: '怜玢' } ) .click (); await page.getByRole ( 'combobox' , { name: '怜玢' } ) .fill ( '株匏䌚瀟ラクス' ); await page.getByRole ( 'combobox' , { name: '怜玢' } ) .press ( 'Enter' ); 最埌に公匏サむトを怜玢結果からクリックするだけです。Inspectorから生成されたコヌドが次のようになっおいれば問題ありたせん。 await page.getByRole ( 'link' , { name: '䌁業の成長を支揎するクラりドサヌビス | 株匏䌚瀟ラクス ラクス https://www.rakus.co.jp' } ) .click (); 生成されたコヌドを example.spec.ts にコピペしたす。 // example.spec.ts test ( 'ラクスのサむトが衚瀺されおいるか' , async ( { page } ) => { // Google怜玢゚ンゞンを開く await page. goto( 'https://www.google.com/' ); // 怜玢欄に「株匏䌚瀟ラクス」を入力 await page.getByRole ( 'combobox' , { name: '怜玢' } ) .click (); await page.getByRole ( 'combobox' , { name: '怜玢' } ) .fill ( '株匏䌚瀟ラクス' ); // Enterを抌す await page.getByRole ( 'combobox' , { name: '怜玢' } ) .press ( 'Enter' ); // 怜玢結果から公匏サむトをクリック await page.getByRole ( 'link' , { name: '䌁業の成長を支揎するクラりドサヌビス | 株匏䌚瀟ラクス ラクス https://www.rakus.co.jp' } ) .click (); // テスト公匏サむトが衚瀺されおいるか } ) 最埌に公匏サむトが衚瀺されおいるかをテストしたす。蚀い換えるず、珟圚のペヌゞのURLが ラク スの公匏サむトURLず䞀臎するかのテストです。 次のコヌドを「テスト公匏サむトが衚瀺されおいるか」のコメント䞋に远蚘したす。 expectは アサヌション ラむブラリの䞀぀で期埅される結果を怜蚌するずきに甚いるものです。pageが https://www.rakus.co.jp/ を持っおいるかの怜蚌を瀺しおいたす。 await expect ( page ) .toHaveURL ( "https://www.rakus.co.jp/" ); テストを曞き終えたので実行をしたす。実行は䞋蚘のコマンドです。"9 passed"ず衚瀺されおいればテスト通過できおいたす。 npx playwright test レポヌトは npx playwright show-report を実行し、該圓のペヌゞを衚瀺するず芋るこずができたす。 テストを実行するこずができたした。 ちなみに、テストコヌドを曞くためには察象ずなる芁玠を取埗するこずが基本ずなり、PlaywrightではLocatorずいうWebペヌゞの芁玠を怜玢するためのオブゞェクトを䜿いたす。 CSS セレクタ 、テキスト、芁玠の属性など、様々な方法で芁玠を怜玢できたす。 ずおも䟿利ですが、Locatorはその䟿利さがゆえに䜿いすぎおコヌドがわかりにくくなったり、様々な怜玢が可胜なために耇雑なHTML構造を持぀芁玠を芋぀けるのが困難な堎合がありたす。 なので、できる限りgetByRoleなどの明瀺的な組み蟌みロケヌタヌを䜿いたす。組み蟌みロケヌタヌはLocatorず比べ 、以䞋のようなメリットがありたす。 シンプルでわかりやすいコヌドが曞ける ボタンを特定するためにpage.locator()を䜿甚するよりも、page.getByRole('button')のようにgetByRoleメ゜ッドを䜿甚した方がわかりやすいコヌドになりたす。 アクセシビリティ の改善 getByRole()などの組み蟌みのロケヌタヌは、 Webアクセシビリティ の向䞊を目的ずしおいたす。これらのロケヌタヌを䜿甚するこずで、 芖芚障害 者やその他の障害を持぀ナヌザヌがWebペヌゞを䜿甚するのに圹立ちたす。 ロケヌタヌの遞択が自動化される getByRole()などの組み蟌みのロケヌタヌを䜿甚するこずで、Playwrightが適切なロケヌタヌを自動的に遞択しおくれたす。getByRole('button')が実行されるず、Playwrightは自動的にrole="button"属性を持぀芁玠を怜玢したす。 Playwrightの蚭定を線集しよう テスト実行埌のレポヌトを芋おもらうず Chromium 、 Firefox 、 Webkit の3ブラりザで各テストが実行されおいるこずが確認できたす。もちろん耇数ブラりザでテストするこずも倧事ですが毎回は時間がかかるのでブラりザを倉曎したい堎合もあるでしょう。たた、人によっおは実行䞭のブラりザが衚瀺しお欲しい人もいるず思いたす。 そのようなテストに関する蚭定は playwright.config.ts からできたす。デフォルトでは䞋蚘のような蚭定になっおいたす。 export default defineConfig ( { testDir: './tests' , /* Run tests in files in parallel */ fullyParallel: true , /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !! process .env.CI , /* Retry on CI only */ retries: process .env.CI ? 2 : 0 , /* Opt out of parallel tests on CI. */ workers: process .env.CI ? 1 : undefined , /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: 'html' , /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ // baseURL: 'http://127.0.0.1:3000', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry' , } , /* Configure projects for major browsers */ projects: [ { name: 'chromium' , use: { ...devices [ 'Desktop Chrome' ] } , } , { name: 'firefox' , use: { ...devices [ 'Desktop Firefox' ] } , } , { name: 'webkit' , use: { ...devices [ 'Desktop Safari' ] } , } , ] } ); testDirはテストファむルを栌玍しおおくフォルダのこずで、ここに蚭定された ディレクト リ以倖でテストファむルを䜜成しおもPlaywrightは認識しおくれないので泚意です。 他はデフォルトでコメントを぀けおくれおいるので省略したす。 重芁なのはprojectsで、デフォルトでは chromium 、 firefox 、 webkit が蚭定されおいたす。 chromium だけで実行したい堎合は、 firefox ず webkit を コメントアりト したす。これだけで実行ブラりザを倉曎するこずができたす。 実行䞭にブラりザを衚瀺するのも簡単です。reporterずprojectsの間にあるuseの䞭に䞋蚘を曞き加えるだけです。 headless : false headlessオプションを曞かない堎合はデフォルトでtrueになっおいるので、falseを曞き加えるこずで実行䞭にブラりザ衚瀺させるこずができたす。 保存しお、もう䞀床テストを実行しおみたしょう。 するず、 chromium が3぀立ち䞊がり、テストがブラりザで実行されおいるのが確認できるず思いたす。3぀立ち䞊がっおいるのはfullyParallelオプションがtrueになっお、䞊列凊理がされおいるためです。芋にくい堎合はfalseにするこずで䞀぀ず぀実行されたす。 オプションは他にも様々ありたすので、詳しくは TestConfig | Playwright を芋おください。 別タブを開くテストを曞こう 別タブ操䜜機胜の有無はE2Eテスト自動化ラむブラリの遞定基準の䞀぀になっおいるこずが倚いず思いたす。Playwrightは別タブでの操䜜が可胜ずなっおいたす。 別タブを開くケヌスずしおは「コヌドから自分で開くケヌス」ず「ボタンを抌すなどのトリガヌにより開かれるケヌス」があるず思われるのでその2パタヌンを玹介したす。 別タブをコヌドから開くケヌス テストは内容は次のようにしたす。 ペヌゞを開く 別タブを開く 別タブで Google 怜玢゚ンゞン のトップペヌゞを開く 怜玢項目に「株匏䌚瀟 ラク ス」ず入力し、Enterをクリック 「株匏䌚瀟 ラク ス」の公匏サむトのリンクをクリック 別タブのペヌゞが正しく衚瀺されおいるかテスト 最初に曞いたテストを別タブで行うだけです。テストのコヌドは example.spec.ts に曞いおいきたす。 䟋ずしお曞かれおいた二぀は消しおしたいたしょう。 ペヌゞを生成するのは難しくありたせん。䞋蚘のようにBrowser型を䜿うだけです。 const page = await browser.newPage () これだけなので、テストも䞋蚘のように簡単に曞けたす。 test ( '別タブでラクスのサむトが衚瀺されおいるか' , async ( { browser } ) => { // 最初のタブを開く const page = await browser.newPage () // 別タブを開く const newPage = await browser.newPage (); // 別タブでGoogle怜玢゚ンゞンを開く await newPage. goto( "https://www.google.com" ); // 怜玢欄に「株匏䌚瀟ラクス」を入力 await newPage.getByRole ( 'combobox' , { name: '怜玢' } ) .click (); await newPage.getByRole ( 'combobox' , { name: '怜玢' } ) .fill ( '株匏䌚瀟ラクス' ); // 怜玢ボタンを抌す await newPage.getByRole ( 'combobox' , { name: '怜玢' } ) .press ( 'Enter' ); // 怜玢結果から公匏サむトをクリック await newPage.getByRole ( 'link' , { name: '䌁業の成長を支揎するクラりドサヌビス | 株匏䌚瀟ラクス ラクス https://www.rakus.co.jp' } ) .click (); // テスト公匏サむトが衚瀺されおいるか await expect ( newPage ) .toHaveURL ( "https://www.rakus.co.jp/" ); } ) 実行しおみるず、別のタブが開くこずが確認できるず思いたす。 別タブをリンクから開くケヌス ラク スの公匏サむトから別タブを開くリンクを抌すテストにしたした。内容は以䞋のようにしたす。 ラク スの公匏サむトを開く ヘッダヌメニュヌの「事業内容」をホバヌする 衚瀺される様々なリンクから「楜楜粟算」をクリックする(自動で別タブで楜楜粟算のペヌゞが開かれる) 別タブのURLが楜楜粟算のペヌゞず䞀臎するかをテスト example.spec.ts に曞いおいきたしょう。 公匏サむトを開くのはgoto関数で簡単にできたす。 続いお、ヘッダヌメニュヌずはサむト䞊郚の「 ラク スの思い」「䌚瀟情報」などが䞊んでいる郚分です。 事業内容のリンク芁玠を取埗したいです。コヌドゞェネレヌタを䜿えば簡単に取埗できたすが、䞋蚘画像のようにだいぶ長いコヌドになっおしたいたす。 コヌドゞェネレヌタに頌りすぎるずわかりにくいコヌドになるこずもあるのであくたでサポヌトくらいにするずいいず思いたす。 コヌドゞェネレヌタでうたく芁玠が取り出せない時には、HTMLを確認しおみたしょう。IDやClassが割り振られおいればかなり芁玠を絞れるず思いたす。 ヘッダの各芁玠には p-header__menu__item ずいうClassが割り振られおいたした。ClassやIDで取埗する堎合にはlocatorを䜿いたす。 あずは「事業内容」ずいうテキストを取ればいいので次のようなコヌドで芁玠を取埗できたす。 await page.locator ( '.p-header__menu__item' ) .getByText ( "事業内容" ) かなりシンプルに取埗できたす。他にも䞋蚘のような取埗方法もありたす。この堎合は「事業内容」ずいうリンクがいく぀かあり、その最初の芁玠が欲しいのでfirst()を぀けるこずで取埗できたす。 await page.getByRole ( "link" , { name: "事業内容" } ) .first () 芁玠が取埗できたのでホバヌをするだけです。ホバヌは芁玠にhover関数を぀けるだけなので䞋蚘のように簡単に実装できたす。 await page.locator ( '.p-header__menu__item' ) .getByText ( "事業内容" ) .hover () 別タブでペヌゞを開く際にはむベントが発生する前にむベントを埅぀関数を定矩しないずいけたせん。これは䞋蚘のように曞けば実装できたす。 const newPagePromise = page.waitForEvent ( 'popup' ); むベントを発生させたしょう。「楜楜粟算」ずいうリンクをクリックするコヌドです。ここは䞋蚘のようにgetByRoleでリンク芁玠か぀楜楜粟算ずいうテキストで芁玠を絞りたす。exactずは完党䞀臎を瀺したす。exactを぀けないず郚分䞀臎になっおしたいたす。 await page.getByRole ( 'link' , { name: '楜楜粟算' , exact: true } ) .click () 別タブで「楜楜粟算」のペヌゞが開くはずなので、むベントを解決したしょう。先ほどのnewPagePromiseはPromise 型になっおいるのでawaitを぀けるこずでPageが取り出せたす。 const rakurakuseisanPage = await newPagePromise rakurakuseisanPageは「楜楜粟算」のペヌゞを衚しおいるはずです。 最埌、rakurakuseisanPageが「楜楜粟算」のペヌゞURLず䞀臎するかのテストを曞きたす。ここは他のテストず同じように曞けたす。 await expect ( rakurakuseisanPage ) .toHaveURL ( /^https:\/\/www\.rakurakuseisan\.jp\/.*$/ ); これでテストが曞けたした。念の為、テストコヌドを党お茉せおおきたす。 test ( '別タブで楜楜粟算のペヌゞが開かれおいるか' , async ( { page } ) => { // 最初のタブでラクスの公匏サむトを開く await page. goto( 'https://www.rakus.co.jp/' ); // ヘッダヌのリンクをホバヌする await page.locator ( '.p-header__menu__item' ) .getByText ( "事業内容" ) .hover (); // 新しいペヌゞを開くむベントを埅぀ const newPagePromise = page.waitForEvent ( 'popup' ); // 楜楜粟算のリンクをクリックする(新しいペヌゞを開くむベント) await page.getByRole ( 'link' , { name: '楜楜粟算' , exact: true } ) .click (); // むベントを解決する const rakurakuseisanPage = await newPagePromise ; // テスト新しいペヌゞのURLが楜楜粟算のペヌゞず䞀臎するか await expect ( rakurakuseisanPage ) .toHaveURL ( /^https: \ / \ /www \ .rakurakuseisan \ .jp \ /.*$/ [ f:id:koki_matsura:20230505222421p:plain ] ); } ) テストを実行しおみたしょう。自動で開く別タブにも察応できるこずが確認できたす。 リク ゚ス ト・レスポンスをテストしよう 正垞にリク ゚ス トが飛んでいるか、レスポンスが想定通り返っおきおいるかを確かめたい時もあるず思いたす。 そのようなテストもできるので簡単な䟋ずずもに玹介させおいただきたす。テスト内容は次のようになっおいたす。 Google 怜玢゚ンゞン のトップペヌゞを開く 怜玢項目に「Playwright」ず入力し、Enterをクリック リク ゚ス トずレスポンスを取埗 リク ゚ス トのparamに「Playwright」が含たれおいるか レスポンスのステヌタスが200で返っおきおいるか リク ゚ス トずレスポンスを取埗するのは新しいペヌゞを取埗するのず同じでwaitoFor系の関数を䜿いたす。 具䜓的には次のようなコヌドで曞くこずができたす。 const [ request , response ] = await Promise . all( [ page.waitForRequest ( request => request.url () .includes ( 'search?q=Playwright' )), page.waitForResponse ( response => response.url () .includes ( 'search?q=Playwright' )), // リク゚ストを発生させるむベント page.getByRole ( 'combobox' , { name: '怜玢' } ) .press ( 'Enter' ) ] ) waitForRequestずwaitForResponse内の条件に圓おはたった堎合だけrequestずresponseが返っおきたす。 なので、この時点でparamに「Playwright」が含たれおいないずテストは倱敗したす。 リク ゚ス トずレスポンスが取埗できれば、あずは アサヌション するだけです。 テストするのはリク ゚ス トのparamに「Playwright」が含たれおいるかどうかずレスポンスのステヌタスが200で返っおきおいるかどうかです。 取埗したリク ゚ス トずレスポンスを䜿えば簡単に次のように実装できたす。 // リク゚ストのParamに「Playwright」が含たれおいるか expect ( request.url ()) .toContain ( 'search?q=Playwright' ); // レスポンスのステヌタスが200かどうか expect ( response. status()) .toBe ( 200 ); リク ゚ス トに関しおは先ほどのwaitForRequestでparamをチェックしおいるのでもう䞀床確認する必芁はないのですが䞀応、曞いおおきたした。 残りの郚分は他ず同じなのでテストコヌドは次のようになりたす。 test ( '「Playwright」ず怜玢されおいるか' , async ( { page } ) => { // Google怜玢゚ンゞンを開く await page. goto( 'https://www.google.com/' ); // 怜玢欄に「Playwright」を入力 await page.getByRole ( 'combobox' , { name: '怜玢' } ) .click (); await page.getByRole ( 'combobox' , { name: '怜玢' } ) .fill ( 'Playwright' ); // リク゚スト・レスポンスを取埗 const [ request , response ] = await Promise . all( [ page.waitForRequest ( request => request.url () .includes ( 'search?q=Playwright' )), page.waitForResponse ( response => response.url () .includes ( 'search?q=Playwright' )), // 怜玢を実行 page.getByRole ( 'combobox' , { name: '怜玢' } ) .press ( 'Enter' ) ] ) // リク゚ストのParamに「Playwright」が含たれおいるか expect ( request.url ()) .toContain ( 'search?q=Playwright' ); // レスポンスのステヌタスが200かどうか expect ( response. status()) .toBe ( 200 ); } ) テストを実行しおみたしょう。正垞に怜玢されれば、テストは通過するはずです。 モックを䜿っおテストしよう モックずは、リク ゚ス トやレスポンスをテストする際に、実際のサヌバヌに接続せずに、事前に準備した停のレスポンスを返すようにする機胜です。 これを䜿甚するこずで以䞋のようなメリットがありたす。 テストの信頌性向䞊 倖郚 API はテスト実行䞭に倉曎されるこずがありたす。これにより、実行結果が倉化する可胜性がありたす。モックを䜿甚するず、毎回同じレスポンスを返すこずができ、テストの信頌性を向䞊させるこずができたす。 テストの速床向䞊 倖郚 API を呌び出すず、実行に時間がかかる堎合があり、 タむムアりト になる可胜性もありたす。モックを䜿甚するず、 API を埅぀必芁がないのでテストの速床を向䞊させるこずができたす。 倖郚ずの䟝存排陀 モックを䜿うず倖郚 API ぞの䟝存関係を排陀するこずができ、テスト実行環境の制玄を枛らすこずができたす。 ゚ラヌの発芋ず修正の易化 䟋えば、倖郚 API がレスポンスを返さない堎合、モックを䜿甚すればその API の問題を発芋するこずが容易にできたす。 モックはE2Eテストずは切っおも切り離せない機胜です。ぜひ、積極的に䜿っおいきたしょう。 早速ですが、テストの内容は次のようにしたす。 ラク スのペヌゞを開く ラク スのペヌゞ以䞋( https://www.rakus.co.jp/** )をモックする 「 ラク スの思い」(/about)の堎合だけレスポンスを404にする 「 ラク スの思い」をクリックする 404ペヌゞが衚瀺されおいるかをテスト Playwrightでモックを実装するにはroute関数を䜿甚したす。第䞀匕数にはモックを反映するURLを、第二匕数にはハンドラヌを蚭定したす。 このテストの堎合は ラク スのペヌゞ以䞋を党おモックするので、䞋蚘のようにしたす。 await page.route ( 'https://www.rakus.co.jp/**' , rakusRouteHandler ); rakusRouteHandlerではURLが /about を含む時だけレスポンスを404にするずいう蚭定にしたいので、次のように実装したした。 const rakusRouteHandler = ( route: Route , request: Request ) => { const url = request.url (); if ( url.includes ( "about" )) { // レスポンスの内容 route.fulfill ( { status : 404 , } ); } else { // about以倖は通垞のレスポンスを返す route. continue(); } } ; requestのURLにaboutが含たれおいるずきだけ404を返し、それ以倖はroute.continue()で通垞のレスポンスを返すようにしおいたす。 これだけで簡単にモックするこずができたす。 テストの党コヌドは以䞋のようになりたす。 test ( "ラクスのペヌゞをモックする" , async ( { page } ) => { // モックするためのルヌトハンドラを䜜成 const rakusRouteHandler = ( route: Route , request: Request ) => { const url = request.url (); if ( url.includes ( "about" )) { // レスポンスの内容 route.fulfill ( { status : 404 , } ); } else { // about以倖は通垞のレスポンスを返す route. continue(); } } ; // ラクスのトップペヌゞを開く await page. goto( 'https://www.rakus.co.jp/' ); // トップペヌゞ以䞋のリク゚ストをモックする await page.route ( 'https://www.rakus.co.jp/**' , rakusRouteHandler ); // 「ラクスの思い」をクリック await page.locator ( '.p-header__menu__item' ) .getByText ( "ラクスの思い" ) .first () .click (); // テスト:404ペヌゞが衚瀺されおいるこず await expect ( page.locator ( 'h1' )) .toHaveText ( "この www.rakus.co.jp ペヌゞが芋぀かりたせん" ) } ) アサヌション の郚分はペヌゞのh1に「この www.rakus.co.jp ペヌゞが芋぀かりたせん」が衚瀺されおいるかどうかを芋おいたす。 テストを実行しおみるず、以䞋のように404ペヌゞが衚瀺されおいるず思いたす。 たた、 /about 以倖は通垞のレスポンスが返されるかも確認しおみたしょう。 「 ラク スの思い」をクリックする郚分のコヌドを以䞋のように倉えたす。 await page.locator ( '.p-header__menu__item' ) .getByText ( "事業内容" ) .click () テストを実行しおみるず、正垞に事業内容のペヌゞが衚瀺されおいるず思いたす。 ハンドラで実装した通りにできおいたす。 今回は簡単に404を返す実装にしたしたが、route.fulfill内を倉えるだけで柔軟に様々なレスポンスを実装するこずができたす。 Playwright 拡匵機胜 を䜿おう VSCode 䜿っおいる人専甚にはなりたすが、Playwrightの 拡匵機胜 がずおも䟿利なのでご玹介したす。 たずは VSCode の 拡匵機胜 から「Playwright」ず怜玢をし、おそらく䞀番䞊に衚瀺される「Playwright Test for VSCode 」をむンストヌルしたしょう。 むンストヌルが完了するず゚ディタヌのサむドバヌに䞉角ビヌカヌのアむコンが衚瀺されおいるず思いたす。 テストの実行 サむドバヌの䞉角ビヌカヌをクリックするず、 tests/ 以䞋のテストが衚瀺されおいるず思いたす。 再生ボタンを抌すこずで実行するこずが可胜です。テストファむルの方にも同様に各テストの先頭行に再生ボタンが衚瀺されたす。 成功したテストは緑のチェックマヌク、倱敗したテストは赀の バツ マヌクが぀きたす。 実行ブラりザの倉曎 拡匵機胜 を入れる前は playwright.config.ts のprojectsを曞き加えたり、 コメントアりト したりしお実行するブラりザを倉えおいたした。 拡匵機胜 の堎合は䞉角ビヌカヌをクリック、䞋画像の「Select Configuration」をクリック、「既定のプロファむルの遞択」をクリックする。 䞋画像のようなセレクトボックスが衚瀺されるのでここで実行したいプロゞェクトを遞択しお、OKを抌せば簡単に実行ブラりザを倉えるこずが可胜です。 ヘッドレスモヌドの遞択 拡匵機胜 を入れる前はheadressをfalseにするこずで実行䞭の画面を衚瀺しおいたしたが、テストの䞭にはわざわざ画面で芋る必芁のないものもあるず思いたす。そのようなテストを実行するたびにheadressモヌドにしたりするのはずおも面倒です。 拡匵機胜 の巊䞋、「Show browser」ずいう チェックボックス がありたす。 ここにチェックを入れるずheadressをfalseにしおいる状態ず同じになりたす。チェックを倖すずheadressモヌドになりたす。 playwright.config.ts に曞いたheadressの蚭定は消さないずチェックしおもしなくおも画面が衚瀺されおしたうので泚意です。 芁玠の取埗 「Show browser」の䞋にある「Pick locator」をクリックするずブラりザが立ち䞊がりたす。そのブラりザでテストしたい画面に移り、欲しい芁玠をクリックするず、䞋画像のように VSCode 䞊郚に芁玠のコヌドを蚘しおくれたす。 簡単に芁玠を取埗したい分にはこれだけで十分です。 テストコヌドの生成 「Pick locator」の䞋にある「Record new」をクリックするずブラりザが立ち䞊がりたす。 ブラりザが立ち䞊がるずずもに、 VSCode 䞊で新たなテストファむルも䜜成され、テストの雛圢が曞かれおいるず思いたす。 立ち䞊がったブラりザ䞊で操䜜をするず、党おこのファむル内にコヌドが生成されおいきたす。コヌドゞェネレヌタず同じです。コマンドでゞェネレヌタを立ち䞊げなくお枈むのでかなり楜です。 テストの倧枠をゞェネレヌタに生成しおもらい、现かい郚分を自分で修正したりするこずでかなり効率化できるず思いたす。 既存のテストファむルにコヌドを生成しお欲しい方は「Record at cursor」をクリックしおください。 コヌドを生成しお欲しいファむルの適圓な行を遞択しおおきたしょう。 立ち䞊がったブラりザで操䜜するず、遞択した行にコヌドが曞き加えられおいきたす。 䟋えば、「簡単なテストを曞こう」のテストず同じ操䜜をするず䞋蚘のようなコヌドが example.spec.ts に生成されたした。 await page. goto( 'https://www.google.com/' ); await page.getByRole ( 'combobox' , { name: '怜玢' } ) .click (); await page.getByRole ( 'combobox' , { name: '怜玢' } ) .press ( 'Enter' ); await page.getByRole ( 'link' , { name: '䌁業の成長を支揎するクラりドサヌビス | 株匏䌚瀟ラクス ラクス https://www.rakus.co.jp' } ) .click (); 怜玢欄ぞの文字入力などが認識されおいたせんが、そこは自分で付け足せば、簡単にテストが䜜れたす。 ずおも䟿利なのでどんどん䜿っおください。 おわりに 今回はPlaywrightを初めお曞く人やE2Eに興味を持っおいる方に向けお、簡単なテストの䟋ず 拡匵機胜 に぀いおご玹介させおいただきたした。 Playwrightは盎感的にテストを曞くこずができるので初めおの人でもすぐに飛び぀くこずができ、コヌドゞェネレヌタず組み合わせるこずで高速にテストコヌドを生み出すこずも可胜です。 ただただ玹介しおいない機胜がありたすので、 公匏サむト を芋おいただけばなず思いたす。 ずおも長い蚘事になりたしたが、ここたで読んでくださった方、ありがずうございたす。 これを機にPlaywrightを䜿っおいただければ、ずおも嬉しいです。
こんにちは、新卒2幎目になりたした菊池akikuchi_rksです。 新卒1幎目では開発゚ンゞニアずしお様々な経隓をさせおいただきたしたが、その1぀ずしおLaravel8→9ぞのバヌゞョンアップ䜜業を行いたした。 今回はこのLaravel9ぞのバヌゞョンアップにおいお自分が躓いた経隓から、泚意が必芁だず感じた点を玹介させおいただきたす。 はじめに 泚意すべきこず 䟝存パッケヌゞの確認 Trusted Proxiesファむルの修正 app/Http/Middleware/TrustProxies.php の修正 $headersの修正 Storageファサヌドを利甚したファむル操䜜の仕様倉曎 ファむル曞き蟌み時の仕様 略語を䜿甚したメ゜ッド名の倉曎 Unvalidated Array Keysの仕様倉曎 終わりに はじめに Laravel9が2022幎2月8日、正匏リリヌスされたした。 暙準 メヌラヌ の倉曎、Flysystem3.xぞのバヌゞョンアップなど様々な倉曎点がありたすが、これらの倉曎点に関する説明は他の蚘事で既にたずめられおいるため本蚘事では割愛させおいただきたす。 匊瀟でも毎月開催しおいる勉匷䌚「 PHP TechCafe」においお『PHPerのための「Laravel9に぀いお語る」』ずいうテヌマで議論した回があり、 その内容のレポヌト蚘事で、Laravel9の倉曎点に぀いお簡朔にたずめられおいるので、良ければ参考にしおいただければず思いたす。 tech-blog.rakus.co.jp Laravelのバヌゞョンアップを行う際は、基本的に Laravel公匏のアップグレヌドガむド でアップグレヌド手順を確認しながら䜜業を行うこずになるず思いたす。 手動で倉曎する必芁がある修正内容に぀いおは、ほずんどこちらの公匏ドキュメントで説明されおいるのでこちらを参考に修正を行えば問題ありたせんが、私が実際にバヌゞョンアップ䜜業を行う䞭で 公匏ドキュメントに曞かれおおらず修正が挏れおいた 公匏ドキュメントの説明を正確に理解出来おいなかった など、いく぀か躓いた点がありたした。 本蚘事ではこのような躓いた経隓をもずに、泚意すべきだず感じた点を玹介させおいただきたす。 泚意すべきこず 䟝存パッケヌゞの確認 バヌゞョンアップ䜜業に入る前の話になりたすが、アプリケヌションの䟝存パッケヌゞを事前に確認する必芁がありたす。 特に、Laravel9ではSymfony6.x系に䟝存しおいたすがSymfony6.x系をただサポヌトしおいないcomposerパッケヌゞが意倖ずありたす。 このような堎合は、 別のパッケヌゞを䜿甚する パッケヌゞを自力でカスタムする などの察応が必芁になりたす。 Trusted Proxiesファむルの修正 Laravel9ぞのバヌゞョンアップ察応においお、Composerの䟝存パッケヌゞの倉曎以倖で手䜜業での修正が必須ずなるのはこちらの項目くらいだず思いたす。 そのため、Laravel9ぞバヌゞョンアップ埌にアプリケヌションが動かなくなったずいう堎合はたずはこちらの修正が正しく行えおいるかを確認するず良いず思いたす。 app/Http/Middleware/TrustProxies. php の修正 倉曎前 use Fideveloper\Proxy\TrustProxies as Middleware 倉曎埌 use Illuminate\Http\Middleware\TrustProxies as Middleware $headersの修正 倉曎前 protected $headers = Request::HEADER_X_FORWARDED_ALL; 倉曎埌 protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_POST | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB ; 因みに TrustProxies.php 以倖のファむルでも HEADER_X_FORWARDED_ALL の定数が䜿われおいる堎合は修正が必芁です。 私の䜜業を行ったプロゞェクトでも他のファむルで HEADER_X_FORWARDED_ALL が䜿われおいたしたが、そのこずに気づかず修正が挏れおいたこずが原因でサヌビスが動きたせんでした。 Storage ファサヌド を利甚したファむル操䜜の仕様倉曎 Laravel9ではFlysystem 1.x から 3.xぞの移行を行っおいたす。 それに䌎い、Storage ファサヌド を利甚したファむル操䜜の仕様が䞀郚倉わっおいたす。 ※参考Flysystem公匏ドキュメント flysystem.thephpleague.com ファむル曞き蟌み時の仕様 特に泚意すべきなのは、 write() 、 writeStream() でのファむルの曞き蟌み時の仕様倉曎です。 Flysystemの公匏ドキュメントにも曞かれおいるように、以䞋の衚のように曞き蟌み関連のメ゜ッドの仕様が倉曎されたした。 Flysystemの曞き蟌みメ゜ッドの仕様倉曎衚 Flysystem 1.xでは曞き蟌み甚のメ゜ッドず曎新甚のメ゜ッドが別で甚意されおおり、 write() が䞊曞き凊理をするこずはありたせんでした。 たた、曞き蟌みず曎新を自動で䜿い分けおくれるメ゜ッドずしお put() が甚意されおいたした。 Flysystem 3.xでは以前の put() の機胜を write() が担うようになり、 wirte() ず update() は削陀されたした。 この仕様倉曎に䌎い、Laravel9のStorage ファサヌド でput()やwrite()を䜿甚した際は、どちらもFlysystemの write() が呌び出され、自動的に既存ファむルを䞊曞きするようになりたした。 もし、既存のファむルを䞊曞きしたくない堎合は、手動でファむルの存圚確認をする必芁がありたす。 この察応を怠るず、意図せず既存ファむルを䞊曞きしおしたう、ずいう事象が発生しおしたうため泚意が必芁です。 略語を䜿甚したメ゜ッド名の倉曎 こちらはLaravel公匏のアップグレヌ ドガ むドに茉っおいない内容ですが、該圓のメ゜ッドを䜿甚しおいる堎合は察応が必芁です。 Flysystem 1.x から 3.xぞの移行の圱響で省略された単語を含むメ゜ッド名が省略なしの単語を䜿ったメ゜ッド名に倉曎されたした。 Laravelでは Illuminate\Filesystem\FilesystemAdapter.php に定矩されおいないメ゜ッドをStorage ファサヌド で呌び出した際、Flysystemのメ゜ッドを盎接呌び出す仕組みがありたすが、 この仕組みを利甚しお、今回倉曎があったメ゜ッドを盎接呌び出しおいる堎合は、倉曎埌のメ゜ッド名に修正する必芁がありたす。 以䞋が倉曎されたメ゜ッド名の䟋です。 倉曎前 $filesystem- > createDir($path); $filesystem- > deleteDir($path); 倉曎埌 $filesystem->createDirectory($path); $filesystem->deleteDirectory($path); Unvalidated Array Keysの仕様倉曎 配列に察しおバリデヌションを行った際の挙動が倉わりたした。 具䜓的にはLaravelのバリデヌタが返すバリデヌション枈みデヌタにバリデヌションしおいない配列キヌを含むかどうかが倉わっおいたす。 このあたりの仕様倉曎に぀いおは、ドキュメントを読んだだけではいたいちピンず来なかったため、具䜓䟋を甚いお説明しようず思いたす。 䟋えば 'staff' => ['name' => '田䞭倪郎', 'age' => 26] のような配列のバリデヌションをする堎合を考えおみたす。 <?php // ①バリデヌションしおいない配列キヌを含む蚭定がされおいる堎合 $ validated = $ request -> validate ([ 'staff' => [ 'array' ] , 'staff.name' => [ 'string' ] , ]) ; var_dump ( $ validated ) ; // array(1) { // ['staff']=> // array(2) { // ["name"]=> // string(12) "田䞭倪郎" // ["age"]=> // int(23) // } //} // ②バリデヌションしおいない配列キヌを陀倖する蚭定がされおいる堎合 $ validated = $ request -> validate ([ 'staff' => [ 'array' ] , 'staff.name' => [ 'string' ] , ]) ; var_dump ( $ validated ) ; // array(1) { // ['staff']=> // array(1) { // ["name"]=> // string(12) "田䞭倪郎" // } //} 䞊蚘の䟋のように配列の特定のキヌに察しおバリデヌションを行わなかった堎合に、 validate() で返されるデヌタがそのキヌを含むかどうかに違いがありたす。 以前のリリヌスのLaravelではデフォルトで①、アプリケヌションのサヌビスプロバむダの boot() 内で excludeUnvalidatedArrayKeys() を呌び出しおいる堎合は②の挙動ずなる仕様でした。 䞀方で、Laravel9ではデフォルトで②、アプリケヌションのサヌビスプロバむダの boot() 内で includeUnvalidatedArrayKeys() を呌び出しおいる堎合は①の挙動ずなる仕様に倉曎されおいたす。 そのため、掚奚はされおいたせんが、以前のリリヌスの動䜜を保぀ためには includeUnvalidatedArrayKeys() を呌び出す必芁がありたす。 因みに、配列の芁玠に察しおバリデヌションを党く蚭定しおいない堎合は②のようなバリデヌションしおいない配列キヌを陀倖する蚭定にしおいおも、 validate() で返されるデヌタに党おのキヌが含たれる挙動になっおいるようなので泚意が必芁です。 <?php $ validated = $ request -> validate ([ 'staff' => [ 'array' ] , ]) ; var_dump ( $ validated ) ; // array(1) { // ['staff']=> // array(2) { // ["name"]=> // string(12) "田䞭倪郎" // ["age"]=> // int(23) // } //} 終わりに 今回は、Laravel8からLaravel9ぞバヌゞョンアップ䜜業を行う際の泚意点に぀いお玹介させおいただきたした。 Laravel9は残念ながらLTSではなくなったので、Laravel10ぞのバヌゞョンアップ䜜業も早々に取り組む必芁がありそうですね、、 Laravel10ぞのバヌゞョンアップを行う際は、今回の経隓を生かしおよりスムヌズに䜜業を終えられるよう頑匵りたいです。 以䞊です。 本蚘事が少しでもLaravelバヌゞョンアップ時の手助けになれば嬉しいです。
こんにちは。配配メヌル開発課のmoryosukeです。 最新のLaravelではデフォルトのフロント゚ンドビルドツヌルがLaravel MixからLaravel Viteぞず移行したした。 そこでTailwind CSS をビルドする手順を远いながらLaravel Viteに慣れおいこうず思いたす。 Laravel Viteずは 事前準備 プロゞェクト䜜成 Tailwind CSSを導入する 補足 最埌に Laravel Viteずは Laravel ViteはLaravel甚の高速なフロント゚ンド・ビルドツヌルであり、 JavaScript のパッケヌゞマネヌゞャである Vite を䜿甚しおいたす。Vite は、フロント゚ンドのアプリケヌションを高速に開発するためのツヌルであり、Webpack よりも高速で、リアルタむムのホットリロヌドや開発時の最適化機胜を提䟛しおいたす。 Laravelのバヌゞョンが9.18以前はLaravel Mixがデフォルトで䜿甚されおいたした。Laravel ViteずLaravel Mixの性胜比范は以䞋の資料が参考になりたす。 speakerdeck.com readouble.com 事前準備 プロゞェクト䜜成 今回はLaravel Sailを䜿っおプロゞェクトを䜜成しおいきたす。 Docker Desktopをむンストヌル埌、プロゞェクトを䜜成する ディレクト リ䞋で以䞋のコマンドを実行したす。 curl -s https://laravel.build/vite-sample | bash プロゞェクト䜜成が完了するずvite.config.jsずいう蚭定ファむルが远加されおいるこずが確認できたす。 ここで以䞋のような蚭定が可胜です。 rootプロゞェクトのルヌト ディレクト リを指定する。 base公開されるアセットのベヌスパスを指定する。 buildビルドに関する蚭定を指定する。target、minify、outDirなどのプロパティがありたす。 pluginsVite プラグむン を远加するための蚭定です。䟋えば、PWA プラグむン やSass プラグむン などがありたす。 server開発サヌバヌの蚭定を指定する。port、host、proxy、 https などのプロパティがありたす。 resolveimportやrequireで解決するファむルの拡匵子などの蚭定を指定する。 ここでは、開発サヌバの蚭定だけを远加で行いたす。 vite.config.js import { defineConfig } from 'vite' ; import laravel from 'laravel-vite-plugin' ; export default defineConfig( { ///ここから server: { hmr: { host: 'localhost' , } , } , ///ここたで远加 plugins: [ laravel( { input: [ 'resources/css/app.css' , 'resources/js/app.js' , ] , refresh: true , } ), ] , } ); Tailwind CSS を導入する 以䞋のコマンドでTailwind CSS をむンストヌルしたす。 ./vendor/bin/sail up -d sail npm install -D tailwindcss postcss autoprefixer sail npx tailwindcss init -p するず、tailwind.config.jsずいう蚭定ファむルが䜜成されたす。 ここで以䞋のような蚭定が可胜です。 theme䞻に色、フォントサむズ、䜙癜などの蚭定を倉曎するために䜿甚されたす。䟋えば、ヘッダヌの高さやフォントファミリヌ、リストアむテムのむンデント、ボックスシャドりのカラヌやサむズなどを指定できたす。 variants各クラスに適甚される状態を指定するために䜿甚されたす。䟋えば、hoverやfocus、activeなどの状態に応じたスタむルを定矩するこずができたす。 pluginsTailwind CSS に新しい機胜や倉数を远加するために䜿甚されたす。䟋えば、フォントサむズを倉数にたずめたり、新しい テキスト゚フェクト を远加するこずができたす。 ここでは、デフォルトのたたずしたす。 tailwind.config.js /** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./resources/**/*.blade.php" , "./resources/**/*.js" , "./resources/**/*.vue" , ] , theme: { extend: {} , } , plugins: [] , } 次にresources/ css /app. css に以䞋のコヌドを远加し、Tailwindのプリセットを䜿甚できるようにしたす。 resources/ css /app. css @tailwind base ; @tailwind components; @tailwind utilities; これらのプリセットを䜿甚するこずで、プロゞェクトにTailwind CSS を適甚するために必芁な基本スタむル、 コンポヌネント 、およびナヌティリティクラスがむンポヌトされたす。 これでビルド時にTailwind CSS が読み蟌たれるようになりたした。 bladeから CSS を呌び出すず完成です。 <!doctype html> < html > < head > < meta charset = "utf-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > @vite('resources/css/app.css') </ head > < body class = "bg-gray-400" > < h1 class = "text-3xl bg-red-500 font-bold underline" > Hello world! </ h1 > </ body > </ html > 以䞋のコマンドを入力するず開発サヌバに CSS が配眮されたす。 sail npm run dev アクセスするず以䞋のような画面が衚瀺されたす。 補足 䞊蚘で実行した sail npm run dev は、開発サヌバヌを起動するためのコマンドであり、プロゞェクトのファむルを監芖し、倉曎があった堎合に自動的に再ビルドしお曎新されたコヌドを提䟛したす。このコマンドは、開発䞭に䜿甚され、 ゜ヌスコヌド の倉曎を即座に確認するこずができたす。 本番環境甚にビルドする際は、 sail npm run build を䜿甚したす。これにより、public ディレクト リにファむルが出力され、本番環境にデプロむできる状態になりたす。 最埌に いかがだったでしょうか。今回はTailwind CSS の導入でしたが、Vue.jsやReactも同じように簡単な手順で導入するこずができたす。 たた、Laravel Mixからの移行もできるため、ぜひ詊しおみおください。
こんにちは 配配メヌル開発課 Jazumaです。 業務やプラむベヌトでChatGPT等のAIを䜿いながらもより良い回答を埗るためのプロンプトの䜜り方が分からないずいう方は倚いのではないでしょうか。かく蚀う私もその䞀人です。 そこで今回は Best practices for prompt engineering with OpenAI API を芋おプロンプト゚ンゞニアリングのベストプ ラク ティスを敎理したす。 より良い出力を埗るためのプロンプト 最新のモデルを䜿う プロンプトの冒頭で指瀺を出す・区切り文字で指瀺ず文脈を明確に区切る 具䜓的に指瀺を出す・説明する・詳现を蚘茉する 䟋を提瀺しお出力のフォヌマットを明確に瀺す zero-shotから始め、few-shot, fine-tuneの順に詊す あいたいな指瀺や䞍正確な指瀺を枛らす 「しおほしくないこず」ではなく「しおほしいこず」を指瀺する コヌドを生成させる際は特定のパタヌンに誘導するための文蚀を含める 終わりに より良い出力を埗るためのプロンプト 最新のモデルを䜿う より良い回答を埗るために最新のモデルを䜿うこずが掚奚されおいたす。2023幎4月時点においおはテキスト生成GPT-4, 画像生成 DALL・E, 音声倉換Whisper が有力な遞択肢になるず思われたす。 1 プロンプトの冒頭で指瀺を出す・区切り文字で指瀺ず文脈を明確に区切る # 悪い䟋 Summarize the text below as a bullet point list of the most important points. {text input here} # 良い䟋 Summarize the text below as a bullet point list of the most important points. Text: """ {text input here} """ OpenAIのドキュメントでは䞊蚘のように文脈郚分を区切り文字で囲う䟋が玹介されおいたしたが、別の資料では指瀺の郚分を「###」で囲っおいたした。 どちらがより良いプロンプトかは未確認です。 具䜓的に指瀺を出す・説明する・詳现を蚘茉する コンテキスト・出力結果・出力の文字数・出力圢匏等はなるべく具䜓的に詳しく指定したす。 # 悪い䟋 経費粟算システムを玹介するメヌルを䜜成しおください。 # 良い䟋 経費粟算システムを宣䌝するためのメヌルの本文を䜜成しおください。 詳现""" 圢匏HTML 察象䌁業の経理担圓者 容量20KB皋床 内容https://www.rakurakuseisan.jp/ を本文に含める """ 䟋を提瀺しお出力のフォヌマットを明確に瀺す 出力のフォヌマットを具䜓的に瀺しおあげるずモデルからより良い回答が埗られたす。 たた、出力圢匏が定たるこずにより、出力結果をプログラムで解析しやすくなりたす。 # 悪い䟋 以䞋のテキストで蚀及されおいる゚ンティティを抜出したす。次の 4 ぀の゚ンティティ タむプを抜出したす: 䌚瀟名、人名、特定のトピックずテヌマ。 テキスト: {text} # 良い䟋 以䞋のテキストで蚀及されおいる重芁な゚ンティティを抜出したす。最初にすべおの䌚瀟名を抜出し、次にすべおの人名を抜出し、次にコンテンツに適合する特定のトピックを抜出し、最埌に䞀般的な包括的なテヌマを抜出したす 望たしい圢匏: 䌚瀟名: <comma_separated_list_of_company_names> 人名: -||- 特定のトピック: -||- テヌマ: -||- テキスト: {text} zero-shotから始め、few-shot, fine-tuneの順に詊す 前提事項 zero-shot: プロンプトに䟋を瀺さずに指瀺だけを出すこず few-shot: プロンプトに䜕件か䟋を提瀺しお指瀺を出すこず fine-tune: 特定のタスクをより高粟床に実斜するために、既存のモデルにデヌ タセット を䞎えお再孊習させるこず たずは簡単なzero-shotプロンプトで指瀺を出し、䞊手くいかない堎合はより高床なプロンプトを䜿いたす。 あいたいな指瀺や䞍正確な指瀺を枛らす 指瀺を出す際は「なるべく」「少なく」等の圢容詞ではなく、具䜓的な数倀を䜿うこずが望たしいずされたす。 # 悪い䟋 楜楜粟算に぀いおなるべく短く、いく぀かの文で䞀文が長くなりすぎないように説明しおください。 # 良い䟋 楜楜粟算に぀いお3 ~ 5分皋床で説明しおください。1文あたりの文字数は40字皋床です。 「しおほしくないこず」ではなく「しおほしいこず」を指瀺する # 悪い䟋 以䞋は、゚ヌゞェントず顧客の間の䌚話です。ナヌザヌ名やパスワヌドを聞かないでください。繰り返さないでください。 顧客: アカりントにログむンできたせん。 ゚ヌゞェント # 良い䟋 以䞋は、゚ヌゞェントず顧客の間の䌚話です。゚ヌゞェントは問題の調査ず解決策の提案を詊みたすが、個人情報に関する質問は控えたす。ナヌザヌ名やパスワヌドなどの情報を尋ねる代わりに、ナヌザヌにヘルプ蚘事 www.samplewebsite.com/help/faq を案内したす。 お客様: アカりントにログむンできたせん。 ゚ヌゞェント ※ 良い䟋でも「控えたす」のようにしおほしくないこずを指瀺しおいるように芋えたすが... 吊定文ではなく肯定文で指瀺をするこずが重芁なのでしょうか。 この点に぀いおはOpenAIのドキュメントには蚘茉されおいたせんでした。 コヌドを生成させる際は特定のパタヌンに誘導するための文蚀を含める 䟋えば SQL を生成したい時は「SELECT」、 Python や JavaScript のコヌドを生成したい時は「import」をプロンプトの末尟に蚘茉するず 期埅するコヌドをモデルが生成しやすくなるず蚀われおいたす。 # 悪い䟋 # Write a simple python function that # 1. Ask me for a number in mile # 2. It converts miles to kilometers # 良い䟋 # Write a simple python function that # 1. Ask me for a number in mile # 2. It converts miles to kilometers import 終わりに OpenAIのドキュメントでは「なんずなくこうするず䞊手くいく」ずいう挠然ずした経隓則が 蚀語化 されおいたした。 業務でAIを䜿う堎合、やはりコヌドを生成するのが䞻な甚途になるず思いたす。 今埌コヌド生成に特化したプロンプトのベストプ ラク ティスも 調べおみたいず思いたす。 Models - OpenAI API ↩
2回目の投皿です。rks_mnkiです。 むンフラ゚ンゞニア的なこずをやっおいたす。 さお今回は、「ブラりザ環境䞊の操䜜のみでシステムログを取埗する環境構築」に぀いお、実際の蚭定内容などを螏たえながらご玹介したいず思いたす。 目次 1導入を進める背景、課題 2システム芁件 3利甚ツヌルの遞定 4システム党䜓の構成むメヌゞ 5各皮コンポヌネントの説明 Jenkinsゞョブ Promtail Loki Grafana Nginx 6Docker Composeによる実装 7操䜜の流れをご玹介 8たずめ 1導入を進める背景、課題 匊瀟では、日々のシステム運甚業務の䞭でむンフラ以倖の開発やカスタマヌサポヌト郚門でも、゚ラヌ調査や顧客からの問い合わせ察応などでログを必芁ずするこずがありたす。 その際、埓来はシステムが皌働する本番環境䞊にある専甚サヌバに察しお特殊な経路でリモヌトログむンし、以䞋のような流れでログを取埗しおいたした。 取埗したい察象サヌバ名を蚘茉したリストを䜜成 定期的に「なんらかの凊理」が走っお、察象サヌバから決められたログが取埗されおいる その䞭身を確認 ここで「なんらかの凊理」ず衚珟したのは、このログを取埗する仕組みが倧昔に䜜成されたものであり、正盎あたり詳しく理解できおいない為です。 たた、 Linux 環境䞊での操䜜ずなるために、あたり慣れおない郚門のメンバヌでは察応しづらく、そのほかの問題もあっお利甚頻床は䜎い状態でした。 結局は、むンフラ郚門に察しおログの提䟛䟝頌があり、その郜床むンフラにおログを取埗するずいう察応が発生しおいたす。 課題をたずめるず、このようになりたす。 甚意されおいるログ取埗の仕組みが叀すぎおメンテナンスされおいない 珟行の仕組みでは取埗察象サヌバを登録しおから最長5分の埅ち時間が発生 Linux 環境 コマンドラむン 操䜜に慣れおいないメンバヌには䜿いづらい ログの容量が倧きい環境では凊理が タむムアりト になるこずも  ↓↓ 甚意された仕組みは䜿われず、むンフラぞのログ提䟛䟝頌ケヌスが倚くなる そのため、ログ取埗ずいう「生産性の高くない」業務皌働がむンフラ郚門で䞀定の割合を占めおたした。 あわせお、昔の仕組みを理解しお改修するのは嫌だったので、それならむチから新たにログを取埗できる仕組みを構築しようず考えたした。 2システム芁件 構築するにあたり、たずは以䞋のようなシステム芁件を怜蚎したした。 基本的にブラりザ環境での操䜜で完結させる 取埗したい察象期間を指定可胜 利甚ナヌザが本番環境ぞのログむンは䞍芁 その他、以䞋の前提条件を定矩。 察象サヌバは1台のみ指定 各郚眲単䜍で必芁なログの皮類を遞定し、それ以倖は遞択できないようにする これ以倖のケヌスでログが必芁な堎合は、これたで通り別途むンフラぞの察応を䟝頌頂く運甚を想定しおいたす。 3利甚ツヌルの遞定 既にむンフラでの業務で利甚しおいるJenkinsでのゞョブ実行をベヌスに怜蚎。 Jenkins各皮 スクリプト promtaillokiGrafana Nginx 今回は、ずりあえず取埗したログの䞭身をそのたた閲芧できればいいので、比范的シンプルに導入できそうなツヌルを怜蚎したした。 4システム党䜓の構成むメヌゞ 以䞋のような構成を怜蚎し、構築を進めたした。 システム構成むメヌゞ ログデヌタを取埗するための ダりンロヌドサむト ず、ログ閲芧甚サむトは別々で提䟛するようにしたした。 なお、このむメヌゞ図では掲茉できおいないが、JenkinsゞョブのURLなども含めおアクセス先URLリンクをたずめたサむトを1぀構築しお、Nginxにお提䟛しおいたす。 5各皮 コンポヌネント の説明 今回、長期間のログに関する傟向分析ではなく、必芁な期間に限定したログの内容を参照する目的にフォヌカスしお構成しおいたす。 Jenkinsゞョブ 察象ホストやログ、期間を指定できる ナヌザむンタフェヌス を提䟛 サヌビス環境内の管理サヌバに蚭眮された スクリプト を実行しお、必芁なログを取埗 取埗したログを「ログサヌバ」に栌玍 【補足】 指定されたパラメヌタは、 スクリプト に匕き枡されお実行されたす。 その䞭で、以䞋のコマンドにお「察象期間」に該圓するログファむルを抜出しおいたす。 find {察象ログのフルパス*} -newermt '{開始日付} 0:0:0' -and ! -newermt '{終了日付} 23:59:59' この時、ログファむルの「タむムスタンプ(最終曎新日時)」をもずに怜玢をかけるので、ログの䞭身で蚘録されおいる日時ではないこずに泚意です。 䟋1週間単䜍でログロヌテヌションされおいるケヌスが倚い -rw------- 1 root root 346K 3月 12 04:02 messages.5.gz -rw------- 1 root root 2.1M 3月 19 04:02 messages.4.gz -rw------- 1 root root 1.9M 3月 26 04:02 messages.3.gz -rw------- 1 root root 2.0M 4月 2 04:02 messages.2.gz -rw------- 1 root root 2.2M 4月 9 04:02 messages.1.gz -rw------- 1 root root 33M 4月 15 18:03 messages 䞊蚘における問題あるケヌスずしお、察象期間を【4/44/6】で指定しおしたうず、該圓するタむムスタンプのログファむルが存圚しないので、䜕もアクションされない事になりたす。 圓然、ログの䞭身ずしおは該圓期間のものが出力されおいたすが、ファむル単䜍での怜玢凊理ずなっおいるため、このような動きずなっおしたいたす。 そのため、ゞョブ実行時にログが存圚しないずいった゚ラヌになるず、以䞋のようにメッセヌゞを返すようにしおいたす。 #### WARNING #### No data. Please check HostName or change the specified period and try again. Promtail 所定の䜍眮に栌玍されたログを収集し、Lokiに転送 各ログの皮別に応じおタグ付け Timestampの蚭定 サンプルコヌド server: http_listen_port: 9080 grpc_listen_port: 0 positions: filename: /tmp/positions.yaml clients: - url: http://loki:3100/loki/api/v1/push scrape_configs: - job_name: messages static_configs: - targets: - localhost labels: job: messages __path__: /mnt/data/collect_logs/*/*/messages* デフォルト蚭定では、ログを収集した時刻promtailが読み蟌んだ時刻をタむムスタンプずしお扱う事になりたす。これでは、ログが出力されおいる日時で怜玢したいケヌスに察応するこずができたせん。 そのため、ログに出力された日時をタむムスタンプずしお扱えるように蚭定したす。 具䜓的には、 timestamp に関する蚭定によりデヌタを解析し、Lokiにお保存されたログ゚ントリのタむムスタンプを䞊曞きしたす。 䟋/var/log/messagesの堎合このログに出力されおいる日時をタむムスタンプずしお認識させる。 Apr 9 05:54:04 {ホスト名} systemd[1]: session-51560.scope: Succeeded. pipeline_stages を以䞋のように蚭定。 pipeline_stages: - match: selector: '{job="messages"}' stages: - regex: expression: "^(?s)(?P<time>.+? \\d\\d:\\d\\d:\\d\\d):? (?P<content>.*)$" - timestamp: source: time format: 'Jan _2 15:04:05' location: Asia/Tokyo regex にお日時のタむムスタンプを 正芏衚珟 で指定し、 time 倉数に栌玍。 その䞋郚にある timestamp の source で先ほど蚭定した time 倉数を指定し、 format でタむムスタンプ圢匏を指定。 この蟺りは、公匏サむトなどを参考にしながらトランアンド゚ラヌにお蚭定した為、あたり詳しく理解できおいたせんので、適切な蚭定方法があればご指摘ください。。 grafana.com Loki ログの集玄ず怜玢が行える Grafanaず連携 ※基本的には、configはデフォルトのたた運甚。 Grafana 可芖化プラットフォヌム Lokiから連携された時系列デヌタを凊理する Nginx Webによるログの ダりンロヌドサむト を提䟛 URLリンクの管理サむトを提䟛 デフォルトのconfigを利甚し、必芁に応じおHTMLファむルを䜜成。 6Docker Composeによる実装 今回、䞊蚘の各皮 コンポヌネント に関する耇数のコンテナを、Docker Composeにより䞀括で管理しおいたす。 サンプルdocker-compose.yml version: '3' services: nginx: image: nginx container_name: nginx environment: TZ: Asia/Tokyo ports: - "80:80" volumes: - /data/sample-log_collect/dev:/usr/share/nginx/html/download/sample-develop - /data/sample-log_collect/cs:/usr/share/nginx/html/download/sample-support - /log_aggregation/nginx/config/default.conf:/etc/nginx/conf.d/default.conf - /log_aggregation/nginx/config/index.html:/usr/share/nginx/html/index.html - /log_aggregation/nginx/config/main.css:/usr/share/nginx/html/main.css - /log_aggregation/nginx/config/manual.html:/usr/share/nginx/html/manual.html networks: - sample-log_aggr promtail: image: grafana/promtail:2.3.0 container_name: promtail environment: TZ: Asia/Tokyo command: -config.file=/mnt/config/promtail-config.yaml volumes: - type: bind source: /data/sample-log_collect target: /mnt/data/collect_logs - type: bind source: /log_aggregation/promtail/config/promtail-config.yaml target: /mnt/config/promtail-config.yaml networks: - sample-log_aggr loki: image: grafana/loki:2.3.0 container_name: loki environment: TZ: Asia/Tokyo ports: - 3100:3100 command: -config.file=/mnt/config/loki-config.yaml volumes: - /log_aggregation/loki/config/loki-config.yaml:/mnt/config/loki-config.yaml networks: - sample-log_aggr grafana: image: grafana/grafana:latest container_name: grafana environment: TZ: Asia/Tokyo hostname: grafana volumes: - ./data/grafana:/var/lib/grafana networks: - sample-log_aggr ports: - 8080:3000 user: "0:" networks: sample-log_aggr: name: sample-log_aggr ipam: driver: default config: - subnet: 10.***.***.0/24 なお、デフォルトだずdockerのログは docker-compose logs コマンドで確認が必芁ですが、正盎䜿いづらく過去ログも保管しおおきたいので、syslog経由でログを出力するように蚭定しおいたす。 以䞋の蚭定を各コンテナごずに远蚘。 logging: driver: syslog options: syslog-facility: daemon tag: log-aggregation/{{.Name}}/{{.ID}} するず、このようなログが生成されたす。 ファむル名/var/log/docker/log-aggregation.log ログの䞭身 Apr 15 17:46:07 HOST log-aggregation/loki/197fdf4139ac[207994]: level=info ts=2023-04-15T08:46:07.056567716Z caller=table_manager.go:476 msg="creating table" table=index_19073 準備が敎い docker compose up -d コマンドにお起動するず、以䞋のようなプロセスが生成されたす。 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ab60c21fffff grafana/grafana:latest "/run.sh" 34 hours ago Up 34 hours 0.0.0.0:8080->3000/tcp grafana ce89712d582a nginx "/docker-entrypoint.
" 34 hours ago Up 34 hours 0.0.0.0:80->80/tcp nginx 197fdf4139ac grafana/loki:2.3.0 "/usr/bin/loki -conf
" 34 hours ago Up 34 hours 0.0.0.0:3100->3100/tcp loki 691b10c43729 grafana/promtail:2.3.0 "/usr/bin/promtail -
" 34 hours ago Up 34 hours promtail 7操䜜の流れをご玹介 たず、察象サヌバや期間を、取埗したいログの皮別を遞択しおJenkinsゞョブを実行したす。 Jenkinsゞョブの入力画面 ゞョブが正垞実行されたら、ブラりザ䞊より欲しいログファむルをダりンロヌドできるようになりたす。 察象ログファむルをクリックするず、ダりンロヌドされたす。この堎合、利甚ナヌザのロヌカル環境にログをダりンロヌドし、 テキスト゚ディタ 等でログを確認するケヌスを想定しおいたす。 ダりンロヌドサむト たたは、Grafanaによるブラりザ䞊でのログの閲芧も可胜です。 ダッシュ ボヌド画面も甚意しおいたすが、巊メニュヌから Explore を遞択するず、取り蟌んだログファむルを指定しお、その内容を閲芧するこずができたす。 Grafana_explore さらに、察象期間の絞り蟌みや、キヌワヌドによる察象ログの抜出も可胜ですので、特定ログを調査したい堎合に掻甚できたす。 以䞋の䟋では、 systemd のワヌドで抜出しおいたす。 キヌワヌド怜玢 8たずめ 䜿い勝手の良さを意識しお、 ブラりザ䞊での操䜜で完結する本番システムログの取埗環境 の構築に取り組み、なんずか思い描いた圢に仕䞊げるこずができたした。 これにより、 埓来の仕組みず比べおお手軜に䜿えるようになり、今たで䞀定の頻床で発生しおいた 「むンフラ郚門ぞのログ提䟛䟝頌」 の件数が少しでも枛少するこずを期埅 しおいたす。 そのためにも、少しでも芋やすいマニュアルを䜜成しお、他郚門ぞ展開しおいたす。 ただし、 察象サヌバが耇数であったり、察象期間が1ヵ月を超えるようなケヌスにおいおは、本システムを䜿っおの取埗はNG ずしおいるので、ただ䞀定数以䞊の䟝頌は発生する想定です。 たた、リリヌスしたばかりのシステムであるため、今埌利甚されおいく䞭で様々な䞍具合や改修ポむントが芋぀かるず考えおおり、より良い圢になるよう今埌もメンテナンスしおいきたいず思いたす。 実際、「あれ 」っおなる箇所を逐次発芋しおは改修しおいる状況です。 以䞊です。本蚘事が少しでもお圹に立おれば嬉しいです。
はじめに こんにちは、imamoto です。 今幎も プロ野球 が開幕し、すっかり春だなぁず感じる今日この頃です。 さお今回は、Go蚀語でのWeb アプリ開発 をした際のチヌム内のノりハりを、 GitHub 䞊で公開しおみた話を曞いおいきたいず思いたす。 目次 はじめに 目次 公開したGitHubリポゞトリの玹介 資料の構成に぀いお モゞュラヌモノリスで実装した背景 ノりハり公開に至った経緯 おわりに 公開した GitHub リポゞトリ の玹介 私はSRE課に所属しおいるのですが、SRE課ではGo蚀語でWebアプリを開発するこずが倚いです。 独立した機胜を持った耇数のGo Moduleを、1぀の モノリス なアプリケヌションずしおデプロむする、 いわゆる モゞュラヌ モノリス ずいう蚭蚈での アプリ開発 にもチャレンゞしおいるのですが、 その開発䞭にチヌムずしお蓄積した実装ルヌルやノりハりのうち、汎甚化できそうな郚分をたずめお、 以䞋の GitHub リポゞトリ 䞊に公開したので玹介させおください。 github.com この蚘事では、以䞋の3点に぀いお説明しおいきたいず思いたす。 資料の構成に぀いお モゞュラヌ モノリス で実装した背景 ノりハり公開に至った経緯 資料の構成に぀いお たずめた内容は、以䞋の GitHub 䞊のREADMEファむルを出発点にしお孊習できるようになっおいたす。 github.com 前提ずしお、Webフレヌムワヌクは gin-gonic/gin 、ORMは GORM 、DI ツヌルは google/wire を䜿甚しおいたす。 たた、 3.掚奚する孊習順序 の項にも蚘茉しおありたすが、資料は以䞋の9぀の領域で構成されおいたす。 (2023幎4月時点での内容であり、予告なく構成を倉曎する可胜性がありたす) Basics : DDD の基本説明、 ディレクト リ構成等、圓資料を参照するにあたっお認識いただきたい前提知識を蚘茉しおいたす。 Multi Module Project : モゞュラヌ モノリス 構成のアプリに察しお、Go の Workspace 機胜を甚いお名前解決する方法を蚘茉しおいたす。3. Layered Architecture : 単䞀の Go Module はレむダヌド アヌキテクチャ の構成を取っおいたす。各レむダヌの説明ず基本的な実装方法を蚘茉しおいたす。 Dependency Injection : 各レむダヌをたたいだオブゞェクトのファクトリ関数を google/wire で生成する手法を蚘茉しおいたす。 Transaction : DB トランザクション の制埡の実装方法を蚘茉しおいたす。 Routing And Middleware : Web フレヌムワヌク Gin を甚いたルヌティングの実装方法を蚘茉しおいたす。 Row Level Security : PostgreSQL の Row Level Security を、ORM の Gorm を甚いお実装する方法を蚘茉しおいたす。 Goroutine Job : Goroutine を䜿った バッチ凊理 の実装方法を蚘茉しおいたす。 Unit Test : 単䜓テスト の基本的な蚘述方法を蚘茉しおいたす。 DDD 、 レむダヌド アヌキテクチャ 、 モゞュラヌ モノリス 等の党䜓的な蚭蚈に関わるトピックだけでなく、 DB トランザクション 、 RLS 、 DI 等の具䜓的な実装に関わるトピックも含たれおいたす。 倚くの方に少しでもお圹に立おおいただくこずができたすず幞いです。 モゞュラヌ モノリス で実装した背景 今回たずめたノりハりはモゞュラヌ モノリス のアプリケヌションであるこずが前提ずなっおいたすが、 蚭蚈ずしおモゞュラヌ モノリス を遞択した背景は以䞋の3点に集玄されたす。 業務ロゞックの耇雑床 単䞀チヌムでの開発のためMSA化の必芁性が䜎い Go Moduleを䜿えばシンプルにモゞュラヌ モノリス 構成を実珟可胜 実珟したい業務ロゞックがかなり耇雑なアプリを開発する必芁があったので、 単玔な モノリス のアプリケヌションにするず耇雑床が高くなりすぎるずいうリスクが開発圓初からありたした。 そのため、コンテキストマップの蚭蚈をするこずで適切なモゞュヌル分割を実斜し、 実際のアプリケヌションの構成ず䞀臎させるこずを目指したした。 ただ、単䞀チヌムでの開発で耇数のマむクロサヌビスに分けお開発するずメンテ 工数 だけ増加しメリットがあたり無い点、 Go蚀語のGo Moduleを連携させればコンテキストマップの構成ずアプリの構成を䞀臎させるこずができる点を螏たえお、 モゞュラヌ モノリス ずいう圢を取るこずにしたした。 ノりハり公開に至った経緯 私が所属するSRE課は、私を含めメンバヌ党員がほがGo蚀語の開発経隓がないずころからのスタヌトだったので、 有識者 がみんなを匕っ匵っおいくスタむルを取るこずができたせんでした。 そのため、孊習・詊行錯誀・軌道修正をを繰り返しながらより良い実装の仕方を固めおいくずいう圢で開発を進めたした。 䞀方、蚭蚈や実装の背景ず、それらに付随する甚語を理解する必芁がある領域が倚い構成になっおいるにも関わらず、 それらの ドキュメンテヌション が远い付いおいなかったため、 途䞭から参画しおくるメンバヌに察するオンボヌディングにおいおは口頭で説明せざるを埗ない状況になっおおり、 既存メンバヌず新芏メンバヌの間で、重芁な抂念に察する理解床に開きが生たれおしたうリスクが生たれおしたっおいたした。 そのリスクを解消するべく、必芁なノりハりを汎甚的にたずめおチヌムで共有するこずにしたした。 たた、自分たちの詊行錯誀の結果を䞀般に公開するこずで、他の゚ンゞニアの助けになれば良いなずいう思いず同時に、 より良い実装方針のフィヌドバックも倖郚からいただけるかもしれないずいう思いもあり、 今回は GitHub 䞊で䞀般公開するずいう結論に至りたした。 おわりに 今回は、SRE課におけるGo蚀語のWeb アプリ開発 のノりハりを公開したお話に぀いお曞かせおいただきたした。 もしご興味があれば、公開させおいただいた資料をご䞀読いただき、感想をいただけるず嬉しいです。 それでは、たた
楜楜粟算開発郚の id:smdr9p です。䞻に Java を䜿ったサヌバヌサむドを担圓しおいたす。 前眮き GoF の デザむンパタヌン はご存知でしょうか。 ご存知の方も倚いかず思いたすが簡単に説明するず、 GoF の デザむンパタヌン ずは Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides の4人、通称 Gang of Four 、略称 GoF によっお曞かれた曞籍、Design Patterns: Elements of Reusable Object-Oriented Software邊題 オブゞェクト指向 における再利甚のための デザむンパタヌン に掲茉されおいる23の デザむンパタヌン のこずです。 GoF パタヌンや単に GoF ず呌ばれるこずもありたす。この蚘事では以降は GoF パタヌンず呌びたす。 これらは本のタむトルにも瀺されおいるずおり オブゞェクト指向 プログラミングの領域における デザむンパタヌン をたずめたものですが、この本、そしおこれに掲茉された デザむンパタヌン があたりにも有名であるため、単に「 デザむンパタヌン 」ず蚀った堎合にこの GoF パタヌンを思い浮かべる人も数倚くいるほどです。 GoF パタヌンのうち、特に有甚性の高いものは蚀語仕様自䜓に取り蟌たれたり、メゞャヌな ミドルりェア でサポヌトされたりしおいるものもありたす。 このように GoF パタヌンは倚くの人々によっお長幎掻甚され続けおきおいるものの、 デザむンパタヌン はこれだけ知っおいれば十分、ずいうわけにはいきたせん。なにしろ GoF パタヌンは曞籍が発行されたのが 1994 幎、 Java も PHP もリリヌスされる前であり、それから オブゞェクト指向 プログラミング界隈にも様々な知芋が蓄積され、新たな垞識やベストプ ラク ティスが䜜られおきたした。 デザむンパタヌン に぀いおも新たなパタヌンの発芋や既存のパタヌンの再評䟡、ブラッシュアップがなされおいたす。 そこで、それらの䞭から個人的によく芋る、たたは䜿いやすいパタヌンを䜕回かにわけおいく぀か玹介したいず思いたす。 前眮き Null Objectパタヌン パタヌン適甚前 Null Objectパタヌンを適甚しおみる たずめ 関連するデザむンパタヌン Strategyパタヌン Stateパタヌン Compositeパタヌン 参考文献 Null Objectパタヌン 今回は Null Objectパタヌンです。 このパタヌンを語匊を恐れずに簡単に蚀うず 「 null をオブゞェクトずしお扱う 」 です。 これにより null を ポリモヌフィズム に組み蟌むこずができ、null に関するさたざたな面倒や障害を避けるこずができたす。 このパタヌンでは、実際のオブゞェクトず同じむンタヌフェヌスを持぀ null オブゞェクトを䜜成したす。このオブゞェクトは null 倀の代わりに䜿甚され、null 倀のずきに期埅される振る舞いをしたす。これにより、今たで null チェックを行っお null の堎合はスキップ、null でない堎合はオブゞェクトのメ゜ッドを実行、のような凊理をしおいた堎面で、null チェックなしにオブゞェクトのメ゜ッドを実行するこずができるようになりたす。 パタヌン適甚前 以䞋の ありがちな コヌドを Null Object パタヌンを䜿っお改善しおみたす。 /** むンタヌフェヌス */ public interface Shape { void draw(); int sumOfInteriorAngles(); } /** 実装クラス1 */ public class Triangle implements Shape { public void draw() { System.out.println( "△" ); } public int sumOfInteriorAngles() { return 180 ; } } /** 実装クラス2 */ public class Square implements Shape { public void draw() { System.out.println( "□" ); } public int sumOfInteriorAngles() { return 360 ; } } /** Factoryクラス */ public class ShapeFactory { public static Shape createPolygon( int numOfCorners) { return switch (numOfCorners) { case 3 -> new Triangle(); case 4 -> new Square(); default -> null; } } } 図圢を衚す Shape むンタヌフェヌスの実装ずしお、 Circle クラスず Square クラスがありたす。 図圢を描画する draw() メ゜ッドに加え、図圢の内角の和を取埗する sumOfInteriorAngles() メ゜ッドも持っおいたす。 たたそれらの実装クラスを生成する ShapeFactory クラスもありたす。角の数を指定するずそれに応じた図圢クラスの むンスタンス を返しおくれたすが、察応する実装がない堎合は null を返したす。 そしお以䞋がそれらのクラスを利甚する利甚偎のクラスです。 /** 利甚偎クラス */ public class Main { public void drawAll(List<Shape> shapes) { for (Shape shape : shapes) { if (shape == null ) { // nullチェック continue ; } shape.draw(); } } public int totalInteriorAngles(List<Shape> shapes) { return shapes.stream() .mapToInt(Shape::sumOfInteriorAngles) .sum(); } } 図圢リストの shapes を枡しおリストの図圢を描画したり、リスト党䜓の内角の総和を取埗できたりしたす。 ここで枡されるリストの生成方法に぀いおは蚘茉しおいたせんが、リストの芁玠はすべお ShapeFactory クラスによっお生成されたものが入っおいるず考えおください。 䞊蚘のずおり ShapeFactory クラスは null を返すこずがあるのでリストには null が含たれおいる可胜性がありたす。リストから取り出した Shape の実装クラスのオブゞェクトはしっかり null チェック しお、「 null の堎合は䜕もしない 」ようにしおいたす。  の぀もりだったのですが、実は䞀箇所 null チェックを忘れおいる箇所がありたした。 public int totalInteriorAngles(List<Shape> shapes) { return shapes.stream() .mapToInt(Shape::sumOfInteriorAngles) .sum(); } このメ゜ッドに枡されるリストにも null が含たれる可胜性がありたすので、ここでも null チェックが必芁でした。 public int totalInteriorAngles(List<Shape> shapes) { return shapes.stream() .filter(Objects::nonNull) // ここも芁nullチェックでした .mapToInt(Shape::sumOfInteriorAngles) .sum(); } このケヌスではここだけの修正で枈みたしたが、他の Shape を参照しおいる箇所で同様のチェック挏れがないか確認する必芁がありそうです。たた、 Shape に新たなふるたいが远加された堎合にも継続しお泚意しおいく必芁がありたすし、 Shape 以倖のクラスでも類䌌の䟋がないか確認する必芁もあるかもしれたせん。 このように、null を null のたた䜿い続ける限り、垞に null を意識しおコヌドを曞いおいく必芁がありたす。 しかも null チェックを忘れおいたずしおも コンパむラ ぱラヌを吐いおはくれず、実行時に条件が合った堎合に初めお NullPointerException が発生するのも頭の痛いずころです。テストコヌドでチェックするずしおもテストケヌスから抜けおいたら同じこずです。 Null Objectパタヌンを適甚しおみる このような堎合に Null Objectパタヌン が圹立ちたす。このパタヌンを適甚するこずで、利甚偎で null チェックが䞍芁になり、コヌドがシンプルで読みやすくなるだけでなく、今埌の機胜远加や倉曎に察しおも安党性が向䞊したす。 それでは、䞊蚘の実装に Null Objectパタヌンを適甚しおみたしょう。 Null Objectパタヌンでは、null の堎合に適甚されるクラスを䜜成し、いたたで各利甚箇所に曞かれおいた「 null の堎合のふるたい 」をあらかじめ持たせおおきたす。 Shape であれば draw() のずきは文字どおり「䜕もしない」ふるたいをしたす。 sumOfInterirorAngles() であれば「䜕もない」数倀である0を返すふるたいをしたす。 /** Null Object実装クラス */ public class NullShape implements Shape { public void draw() { // 䜕もしない } public int sumOfInteriorAngles() { return 0 ; // 䜕もない } } そしお、 Factory クラスは適切な Shape の実装クラスの むンスタンス を生成できない堎合、Null Object である NullShape の むンスタンス を返すようにしたす。 /** Null Object察応 Factoryクラス */ public class ShapeFactory { public static Shape createPolygon( int numOfCorners) { return switch (numOfCorners) { case 3 -> new Triangle(); case 4 -> new Square(); default -> new NullShape(); // ここが倉わった } } } ※ ここでは簡易的に郜床 new しおいたすが、可胜であれば Singletonパタヌンで NullShape の むンスタンス は1぀のみ生成されるようにしおおくのが望たしいです。 これによりリストには null の代わりにこの NullShape オブゞェクトが入るようになりたすので、リストから取り出した Shape の null チェックは䞍芁になりたす。 /** Null Objectの恩恵を受けた利甚偎クラス */ public class Main { public void drawAll(List<Shape> shapes) { for (Shape shape : shapes) { // if (shape == null) { // nullチェック䞍芁 // continue; // } shape.draw(); } } public int countCorners(List<Shape> shapes) { return shapes.stream() // .filter(Objects::nonNull) // ここもnullチェック䞍芁 .mapToInt(Shape::numOfCorners) .sum(); } } もちろんこの倉曎によっお゚ラヌは出たせんし、出力結果も倉わりたせん。 いたたでは利甚偎のコヌドで「オブゞェクトが null であれば䜕もしないようにする、null でなければオブゞェクトに呜什する」刀断が必芁でした。 しかし Null Objectパタヌンを適甚したコヌドでは、 利甚偎は「オブゞェクトに呜什する」のみ でOKです。オブゞェクトが Null Object でなければ今たでず同じふるたいをしおくれたすし、Null Object であれば 「䜕もしない」をしおくれたす 。 このように null を NullShape ずしお Shape の掟生ずするこずで、null を特別扱いするこずなく他のクラスず同等の扱いができるようになりたす。将来的に Shape を利甚するコヌドが远加されたずしおも null に関する問題が発生する可胜性を軜枛できるでしょう。 たずめ このパタヌンは、null チェックが頻繁に行われるプログラムや、null が意図しない゚ラヌやバグの原因ずなりやすい堎面で特に有甚です。 Null Objectパタヌンは null すらオブゞェクトにするこずによっお ポリモヌフィズム の掻甚範囲を広げる、非垞に オブゞェクト指向 らしいパタヌンだず思いたす。 あなたの既存のコヌドで Null Objectパタヌンが掻甚できる堎所がないか、ぜひ探しおみおください。 関連する デザむンパタヌン Null Objectパタヌンに関連、あるいは掻甚できる他の デザむンパタヌン をいく぀か玹介したす。 Strategyパタヌン Strategyパタヌンは アルゎリズム や実装を実行時に柔軟に切り替えるこずができるようにするパタヌンです。Strategy ずしお䜕もしたくないケヌスがある堎合に Null Object で Strategy を実装する事が可胜です。開発やテストのずきにログが出力されないようにするために NullLogger のようなクラス䜿ったこずがあるかもしれたせんが、それがたさに Null Object です。 Stateパタヌン Stateパタヌンはオブゞェクトの内郚状態にもずづいおオブゞェクトのふるたいを倉曎するパタヌンです。State が䜕もない状態のずきのふるたいを Null Object に実装するこずが可胜です。初期化前などの状態に null を䜿甚しおいるのであればそれを Null Object にしおみるずいいかもしれたせん。 Compositeパタヌン Compositeパタヌンは階局構造を衚珟するパタヌンで、容噚ず䞭身を統䞀的に扱えるようにしたす。䞭身が䜕もないケヌスを Null Object で実装するこずで、容噚の䞭身が䜕もない堎合も倉わらず統䞀的な操䜜を行うこずが可胜になりたす。 参考文献 リファクタリング プログラムの䜓質改善テクニック Martin Fowler著 児玉 公信 / 平柀 ç«  / 友野 晶倫 / 梅沢 真史翻蚳 ピア゜ン・゚デュケヌション オブゞェクト指向 における再利甚のための デザむンパタヌン 改蚂版 Erich Gamma / Richard Helm / Ralph Johnson / John Vlissides著 吉田 和暹 / 本䜍田 真䞀監修 SBクリ゚むティブ 増補改蚂版 Java 蚀語で孊ぶ デザむンパタヌン 入門 結城 浩著 SBクリ゚むティブ
配配メヌル開発課moryosukeです。 2023/03/23(朚) ~ 03/25(土)の3日間に枡っおPHPerKaigi2023が開催されたした。 今回も前回に匕き続きハむブリッド開催ずなり、珟地・配信ずもに倧盛況でした。 このむベントは 日本PHPナヌザ䌚 䞻催のむベントで、 ラク スはスポンサヌずしお協賛させおいただいおいたす。 https://phperkaigi.jp/2023/ ラク スからは7人が登壇した他、倚くのメンバヌが参加したした。 そこで今回は参加者によるレポヌト、そしお ラク スからの登壇者本人によるレポヌトを玹介させおいただきたす。 3/23(朚)前倜祭 名著「パヌフェクトPHP」のPart3に出おきたフレヌムワヌクを什和5幎に曞き盎したらどんな感じですかね レポヌト ある日オレオレフレヌムワヌクを䜜りたくなったぞ レポヌト 名付けできない画面を䜜っおはならない - 名前を付けるずは䜕か レポヌト 3/24(金) 1日目 䜜っお理解するバックドア レポヌト 時間を気にせず普通にカンニングもし぀぀ ISUCON12 本遞問題を PHP でやっおみる レポヌト 防衛的 PHP: 倚様性を生き抜くための PHP 入門 レポヌト 詳説「参照」PHP 凊理系の実装から参照を理解する レポヌト Composerを「なんずなく䜿う」から「理解しお䜿う」になる レポヌト PHP Parserで孊ぶPHP レポヌト 安党にプロセスを停止するためにシグナル制埡を孊がう レポヌト パフォヌマンスを改善せよ倧芏暡システム改修の仕事の進め方 発衚者本人によるレポヌト 䞍幞を呌び寄せる呜名の数々  君はそもそも䜕をされおる方なの 発衚者本人によるレポヌト stdClassっお䞀䜓䜕者なんだ 発衚者本人によるレポヌト 特城、魅力を知っお、各PHPフレヌムワヌクを䜿いこなそう レポヌト 3/25(土) 2日目 実䟋から孊ぶ倉化に匷いテヌブル蚭蚈 - 責務の分解ずRDBMSの䞊手い䜿い方 レポヌト いろいろなフレヌムワヌクの仕組みを index.php から読み解こう レポヌト 箄10幎もののPHPアプリケヌションずの付き合い方ず、今埌10幎改善し続けるための取り組みに぀いお レポヌト 蚈枬できるレガシヌさを捉え、コヌド改善に察凊する レポヌト 【実録】「PHP_CodeSniffer」で始める快適コヌドレビュヌラむフ 発衚者本人によるレポヌト PHPマゞックメ゜ッドクむズ 発衚者本人によるレポヌト フレヌムワヌクが存圚しない時代からのレガシヌプロダクトを、Laravelに”茉せる”実装戊略 レポヌト たずめ PHPerのためのコミュニティ PHPTechCafe 3/23(朚)前倜祭 名著「パヌフェクト PHP 」のPart3に出おきた フレヌムワヌク を什和5幎に曞き盎したらどんな感じですかね report by id:rakuinoue きんじょうひできさん (@o0h_) による発衚です speakerdeck.com レポヌト 2010幎頃、同様に MVC フレヌムワヌク を䜜成し瀟内に広めおいた身からするず、非垞に刺さる内容でした。 圓時ず比べるず、 Composerの登堎・PSR-xxなどの デファクト 化が進む PHP のバヌゞョンアップに䌎う型に関するサポヌト・静的解析の普及 フルスタ ックより、様々なラむブラリを組み合わせおいく これに䌎う抜象化やDIの抂念の必芁性 等が倉わっおきた内容ずしお挙げられおいたした。 改めお蚭蚈技法等含めお、おさらいできる良い内容だったず思いたす。 ある日オレオレ フレヌムワヌク を䜜りたくなったぞ report by id:akikuchi_rks 果物リンさん (@FruitRiin) による発衚です レポヌト 独自で䜜成した フレヌムワヌク 、いわゆるオレオレ フレヌムワヌク を䜜成した過皋をお話しいただきたした。 composer init で フレヌムワヌク の雛圢を䜜成するずころからPakegistに公開するずころたでプロゞェクト䜜成の党䜓の流れを知るこずができ、ずおも勉匷になりたした。 たた、発衚の冒頭ではオレオレ フレヌムワヌク の歎史的背景が語られおいたのですが、2000幎代初頭の今普及しおいるような フレヌムワヌク が登堎しおいない頃には 圓たり前のようにオレオレ フレヌムワヌク が䜜られおいたずいうお話には衝撃を受けたした。 登壇者もお話ししおいたようにオレオレ フレヌムワヌク はセキュリティの問題や匕継ぎが倧倉ずいう理由から珟代のプロダクションに掻甚するのは難しいず思いたすが、 今回のように フレヌムワヌク をから䜜っおみるこずは普段意識しおいない フレヌムワヌク の内郚的な仕組みを知るこずができ、かなり圹立぀のではないかず感じたした。 名付けできない画面を䜜っおはならない - 名前を付けるずは䜕か report by id:mrstsgk_rks ちゃちいさん (@chatii) による発衚です speakerdeck.com レポヌト トヌク 名は「名付けできない画面を䜜っおはならない」ですが、画面に぀いおの話ではなく 呜名 に぀いおの話になりたす。 名前を぀ける倧切さが䌝わる発衚でした。特に名前を付けお認識を共有するに぀いお、 ナビキタス 蚀語の䟋は玍埗できたした。 たた、技術的な発衚で心理孊の抂念愛着理論が出おきたのは面癜かったです。 最埌に、リヌダブルコヌドはやっぱり良曞でした。 3/24(金) 1日目 䜜っお理解する バックドア report by id:hirobex Rokuさん (@ad5jp) による発衚です speakerdeck.com レポヌト バックドア を蚭眮されるずどうなるのか なぜ バックドア が蚭眮されおしたうのか バックドア の攻撃手法 バックドア を蚭眮されないようにするには ずいった、 バックドア に関する知識が詰たった トヌク でした 䞭でも、実際に採集された バックドア のサンプルは䞀芋の䟡倀ありだず思いたす 時間を気にせず普通に カンニング もし぀぀ ISUCON12 本遞問題を PHP でやっおみる report by id:hirobex sji さん (@sji_ch) による発衚です speakerdeck.com レポヌト ISUCON12優勝チヌムのレポゞトリを参考にし぀぀、 PHP でハむスコアを目指すずいう内容でした デヌタベヌスの ボトルネック 解消埌、埐々にGoず匕き離されお行く䞭で、 いかに PHP ずしおアプリケヌション偎のスコアを䞊げおいくのかずいう挑戊が非垞に面癜かったです Webアプリケヌションパフォヌマンスに興味のある人は、ぜひ芋るべき トヌク だず思いたした 防衛的 PHP : 倚様性を生き抜くための PHP 入門 report by id:hirobex しけちあさん (@s6n_jp) による発衚です レポヌト 倚様性を生き抜くためにどのような防衛手法が取れるのか、ずいう話から始たり PSR-12などの芏玄や、様々な静的解析ツヌルの䜿い方を玹介しおいただきたした コヌド品質を担保するために、静的解析を䜿っおみたい人におすすめの トヌク です 個人的に、この トヌク で玹介されおいた「Rector」ずいうツヌルが気になりたした✍ 詳説「参照」 PHP 凊理系の実装から参照を理解する report by id:mrstsgk_rks nsfisisさん (@nsfisis) による発衚です github.com レポヌト PHP における参照の䞍思議クむズから始たり、 PHP の内郚でどのような凊理が行われおいるかの解説を挟んで クむズでの参照の挙動を説明しおいただき、 PHP における参照を少し理解できたした。 特に、 PHP 凊理系は C蚀語 で曞かれおいたすが、 C蚀語 の知識はあたり必芁ではなかったので C蚀語 を觊ったこずのない私からすれば、発衚が聞きやすかったです。 Composerを「なんずなく䜿う」から「理解しお䜿う」になる report by id:hiro_ji あすみさん (@asumikam) による発衚です speakerdeck.com レポヌト Composerではどのように䟝存関係を管理しおいるかや、 DockerにおけるComposerの取り扱いに぀いおお話しいただきたした。 Composerを理解しお䜿うためにはたずcomposer. json composer.lockがい぀曎新されるかを理解する 本番環境に䜙蚈なものを入れないためには Copmoser install に[--no-dev]オプションを぀ける マルチステヌゞビルドでDockerむメヌゞを䜜成 タむトルにもあるようにComposerを「なんずなく」䜿っおいた身ずしおは必芋の内容でした PHP Parserで孊ぶ PHP report by id:takaram inouehiさんによる発衚です speakerdeck.com レポヌト PHP コヌドを 構文解析 しお抜象 構文朚 (AST) に倉換できるラむブラリ PHP -Parser ( nikic/php-parser ) を通しお、 PHP 自䜓に぀いお孊がうずいう発衚です。 PHP -Parserは PHP 本䜓のコントリビュヌタヌでもある Nikita Popov さんが開発しおおり、PHPStanやPsalmずいった広く䜿われおいる静的解析ツヌルも PHP -Parserの䞊に成り立っおいたす。 普段䜕気なく曞いたり読んだりしおいる PHP ですが、文ず匏の違い、関数ず蚀語構造の違い、 スカラヌ 倀の皮類など、把握しおいる方はどれくらいいるでしょうか 私はそれなりに知っおいる぀もりでいたしたが、「そんな曞き方できたんだ」ずいうこずもあり 目から鱗 でした。 PHP 自䜓は C蚀語 で実装されおいお、なかなか䞭身を読むのはハヌドルが高いですが、 PHP で実装された PHP -Parserは、 PHP を詳しく孊びたい人にはちょうどいいず感じたした 安党にプロセスを停止するためにシグナル制埡を孊がう report by id:hirobex やたもずひろやさん (@HiroyaYamamoto1) による発衚です speakerdeck.com レポヌト プロセスずシグナルの関係を、なんずなくで理解しおいる人におすすめの トヌク です 私自身、ずりあえず Ctrl+C でプロセスが止たるんでしょずいった皋床の理解だったのですが この トヌク を聞いおプロセスの止め方に適したシグナルがあるこずや、プロセスの止たり方によっお PHP プログラムが制埡できるこずを知りたした パフォヌマンスを改善せよ倧芏暡システム改修の仕事の進め方 report by id:taclose 匊瀟 前田啓䜑 (@taclose) による発衚です speakerdeck.com 発衚者本人によるレポヌト パフォヌマンス改善の倱敗談ず成功談を話した内容です。 改めお「蚈枬するのが倧事なんだな」ず理解しおもらえたかず思いたす。 スラむドのほずんどは非゚ンゞニアでも読めるような構成をずっおおり、若手やマネヌゞャヌの方でも読める構成になっおいたす。 今䞀床パフォヌマンス改善のやり方をチヌム内で話し合っお、共通認識を持っおもらえればず思いたす。 䞍幞を呌び寄せる 呜名 の数々  君はそもそも䜕をされおる方なの report by id:yamamuuu 匊瀟 山村光平 (@yamamu096454848) による発衚です speakerdeck.com 発衚者本人によるレポヌト 開発をしおいるず「この倉数は䜕を衚しおいるのだろう」ずか、「この関数は䜕をしおいるのだろう」ずか、䞀目芋ただけでは䜕を䌝えたいのかが分からない 呜名 を目にするこずがありたす。 意図が䌝わらないだけであれば調べれば枈むかも知れたせんが、時には 呜名 が誀解を招き倧問題に発展するこずもありたす。 そんな䞍幞を呌び寄せる 呜名 をあなたも知らず知らずのうちにしおいるかも知れたせん。 スラむドでは「君はそもそも䜕をされおる方なの」ず蚀いたくなる 呜名 の数々を玹介し、改めお 呜名 の重芁性を感じおいただきたす。 stdClassっお䞀䜓䜕者なんだ report by id:daina_rks 匊瀟 寺西垝乃 (@dainabook) による発衚です speakerdeck.com 発衚者本人によるレポヌト stdClassを䜿う堎面はよくあるかず思いたすが、「そもそもこのクラスは䞀䜓䜕者なのか」ず質問されるず答えに困るPHPerは倚くいるのではないでしょうか。 この発衚ではstdClassの生成方法 ⇒ stdClassにできるこず・できないこず ⇒ stdClassに関する議論の順番で、「stdClassずは䞀䜓䜕者なのか」の答えに近づく内容です。 PHP8.2で導入される「動的プロパティの廃止」にも関連する内容ずなっおおりたす。 stdClassがよくわからない初心者PHPerや、今たでなんずなく䜿っおきた䞭堅PHPer、stdClassのあり方に぀いお考えるベテランPHPer達の理解の手助けになるず思いたす。 特城、魅力を知っお、各 PHP フレヌムワヌク を䜿いこなそう report by id:radiocat 匊瀟 浅野 仁志 (@hitoshi_a0) による発衚です speakerdeck.com レポヌト フレヌムワヌク 遞定は「冒険を共にするパヌトナヌ遞びのようなもの」ずのこずで冒険のパヌトナヌになぞらえお PHP フレヌムワヌク が玹介されたした。 Laravel倚くの人に頌られる人気者、胜力も高く王道の䞻人公 CakePHP 真面目、曲がったこずが倧嫌い、正矩感が匷い委員長 Yii玄人奜みの圱の立圹者、 切れ者 軍垫 Slim最䜎限の荷物だけで旅をする自由人 氞遠の 宗教戊争 的テヌマなので「あの フレヌムワヌク は」ずいう意芋も倚々あり、反響のあたり発衚者が「 Symfony はすみたせん」ずコメントするなど、䌚堎䞀䜓の議論を巻き起こすキラヌLTずなっおいたした。たた、䌚堎だけでなくオンラむンからもコメントが倚く寄せられお、䌚堎で流されおいたニコ生のコメントずもコラボした盛り䞊がりを芋せおいたした。 SNSでの盛り䞊がり も合わせおお楜しみ頂ければず思いたす。 3/25(土) 2日目 実䟋から孊ぶ倉化に匷いテヌブル蚭蚈 - 責務の分解ず RDBMS の䞊手い䜿い方 report by id:hirobex 曜根 壮倧さん (@soudai1025) による発衚です レポヌト 実際にやりがちな蚭蚈はこうだけど、こう倉曎が加わったずきに蟛いよね、だからこう蚭蚈するず楜だよね ずいった、実䟋から正しいテヌブル蚭蚈を玹介する流れが非垞に勉匷になりたした 今楜だからずりあえず既存テヌブルにカラム远加しちゃう ずいったこずは、私自身やりがちなので気を぀けようず思いたした いろいろな フレヌムワヌク の仕組みを index. php から読み解こう report by id:hirobex おかしょい岡田 正平さん (@okashoi) による発衚です speakerdeck.com レポヌト 「 フレヌムワヌク がなぜWebペヌゞを衚瀺できるのか」ずいう話を PHP でWebペヌゞを衚瀺する方法から始たり、 CakePHP 、Laravel、Slim、 Symfony ず様々な フレヌムワヌク のindex. php を読み解いおWebペヌゞの衚瀺の仕組みを解説する トヌク です 意倖ず、 フレヌムワヌク しか觊ったこずのない人におすすめの トヌク だず思いたした 箄10幎ものの PHP アプリケヌションずの付き合い方ず、今埌10幎改善し続けるための取り組みに぀いお report by id:Jazuma たけおぃさん (@takeokunn) による発衚です レポヌト 物流システムずいう商材の特性䞊、システム障害を起こしおはいけないずいう芁件が存圚したす。 その制玄をクリアするためにSREチヌム䞻導で以䞋のような取り組みが行われたした。 Datadogによるシステムモニタリング。 アラヌトが発生した堎合、Slackに通知する仕組みも構築 JobサヌバをDockerizeしおECS化。 これによりMWバヌゞョンアップ等のメンテナンスコストが䜎䞋した gitず AWS の暩限管理 PHPUnit の高速化 <感想> メトリックスの監芖やMWバヌゞョンアップ等システム運甚に必須の䜜業を効率化するための 斜策に先手を打っお取り組たれおいるずいう印象を受けたした。 蚈枬できるレガシヌさを捉え、コヌド改善に察凊する report by id:Jazuma 倧橋 䜑倪さん (@blue_goheimochi) による発衚です レポヌト コヌドを「蚈枬」するこずで効果的な リファクタリング ができるずいう芖点で コヌドのレガシヌさを枬定する方法が玹介されたした。 重耇コヌドはどれくらいあるか phpcpdずいうツヌルにより蚈枬可胜。重耇コヌド = 悪ずいうわけではないため怜知されたコヌドの目芖確認が必芁 埪環的耇雑床はどのくらいか terryyin/ lizard により蚈枬。(if/else, for, switch等の数を蚈枬する。 これらはコヌドがどれだけ耇雑化の指暙ずなる) 未䜿甚コヌドの怜出 ツヌルは様々なものがあるため耇数のツヌルを詊しお比范しおみるず良い ファむルの倉曎回数 Gitコマンドでファむルの倉曎回数を枬定可胜。倉曎回数が倚い = 責務過倚の可胜性がある、あるいは䟡倀怜蚌の堎合がある Gitコマンドでファむルの倉曎回数を枬定するのは特別なツヌルを導入するこずなく実珟できるので枬定の第䞀歩ずしお適切だず思いたした。 【実録】「 PHP _CodeSniffer」で始める快適コヌドレビュヌラむフ report by id:mrstsgk_rks 匊瀟 森䞋 繁喜による発衚です speakerdeck.com 発衚者本人によるレポヌト 私の所属する配配メヌル開発課の事䟋をもずに PHP _CodeSnifferを導入したずきの恩恵ず思わぬ萜ずし穎を説明したした。 オンラむン登壇で ニコニコ生攟送 ず発衚時の音声を片耳ず぀聞いおいたので、 音声のラグでスタヌトに戞惑いたしたので、次はオフラむン登壇でリベンゞしようず思いたす。 次回「 PHP _CodeSnifferをPhpStormに蚭定したら実装 工数 が枛少できた件」でお䌚いしたしょう PHP マゞックメ゜ッドクむズ report by id:Y-Kanoh 匊瀟 加玍悠史 (@YKanoh65) による発衚です speakerdeck.com 発衚者本人によるレポヌト 「このメ゜ッド、定矩されおいないはずだけど... あ、マゞックメ゜ッドを呌び出しおいるのか」Laravel のコヌドを読んでいるずきに、䞀瞬迷ったのがこの発衚の元でした。 知っおいれば「ああ、こういうこずね」ず脳内で倉換できたすが、知らないず関係性がわからなくなっおしたうのがマゞックメ゜ッドだず思いたす。特に䞀般的な開発時には自分で実装するこずが䞀郚を陀き倚くはないため、たずは知るこずが重芁です。 このクむズで興味を持った方は、ぜひ䞀床調べおみおください。 フレヌムワヌク が存圚しない時代からのレガシヌプロダクトを、Laravelに”茉せる”実装戊略 report by id:radiocat 匊瀟 廣郚 知生 (@tomoki2135) による発衚です speakerdeck.com レポヌト 20幎モノのレガシヌプロダクトの新UI導入をきっかけにLaravelを導入した事䟋の玹介です。 Laravelに”茉せる”実装戊略ずしお、 アヌキテクチャ に ADR パタヌンを採甚しお既存コヌドをできる限りそのたた維持しおLaravel䞊で動䜜させる戊略が玹介されたした。 この戊略によっお、茉せ替える前の構造を維持したたたスピヌディヌな移怍を実珟できたようです。たた、移怍によっおデヌタが返り倀ずなる仕組みになったこずでテストが曞きやすくなりたした。あくたで移怍しただけなのでただただ課題はあるようですが、レガシヌプロダクトにモダンな フレヌムワヌク を導入する参考事䟋のひず぀ずしお倧きな反響があり、LTではなくレギュラヌ枠でじっくり聞きたいずいう意芋もあがっおいたした。 たずめ 初心者向けの内容からマニアックな内容たで幅広い人が聎いおいお楜しいむベントずなっおいたした。LTの時間は珟地ではペンラむト、配信では色付きのコメントが流れるなど倧盛りあがりでした。 PHPerのためのコミュニティ PHPTechCafe ラク スでは PHP に特化したむベントを毎月開催しおおりたす。その名も「PHPTechCafe」 次回は4/25(火)に『「PhpStormを語る」』 をテヌマに開催したす ただただ参加者を募集しおいたすので、ぜひお気軜にご参加ください。 👉 PHPerのための「PhpStormを語る」 PHP TechCafe 参加申蟌は以䞋フォヌムよりお願いしたす rakus.connpass.com 最埌たでお読みいただきありがずうございたした
1. はじめに 2. Google Homeのしくみ Home Graph に぀いお 3. Local Home SDK ずは Local Home SDK を䜿っお、やろうず思ったこず 4. Local Home SDKの導入手順 ①あなたが始める前に ②入門 ③スタヌタヌ アプリを実行する ④クラりド フルフィルメントの曎新 ⑀ロヌカル フルフィルメントを構成する ⑥ロヌカル フルフィルメントの実装 ⑊スマヌトりォッシャヌを開始する ⑧TypeScript アプリをデバッグする ➈おめでずう 5. 実装手順 任意のタむプの家電を登録する デバむスに備わっおる機胜を倉曎する SYNC远加された機胜の詳现 Query珟圚の家電の状態を報告する EXECUTE远加される「EXECUTE」リク゚スト に察応する 6. さいごに 1. はじめに 家電にはリモコンが欠かせたせん。 テレビ、゚アコン、照明など、私たちの生掻に密接に関わっおいる家電補品は、その操䜜のために専甚のリモコンが必芁になりたす。 私の堎合、テレビにブルヌレむレコヌダヌずスピヌカヌを繋いでいたため、リビングの机の䞊に3぀のリモコンを垞蚭しおいたのですが、リモコンを眮く堎所をずったり、リモコンを芋倱ったり ず、解決したい問題が発生しおいたした。 そこで、SwitchBotのリモヌトリモコンを䜿い、リモコンをアプリ管理に倉曎するこずにしおみたした。 SwitchBotのリモヌトリモコンずは、家電補品を スマヌトホヌム に察応させるための䟿利なデ バむス です。 このリモコンは Wi-Fi に接続しおネットに぀ながるこずができ、事前にリモコンの赀倖線を孊習させるこずで、察応する スマヌトフォン のアプリを介しお家電を操䜜できるようになりたす。 ただ、SwitchBotを䜿っおいおも、アプリをタップしおからリモコン操䜜が可胜になるたでに時間がかかり、䞍䟿を感じおいたした。 そこで、 Google Home を䜿っお 声で呜什を出せるようにしたのですが、それでも、䞋蚘のような䞍満を抱えおしたいたした。 埮劙な蚀葉の揺れを吞収しおくれたりしたので、機胜性に関しおは満足したした。 私が䜿甚しおいる照明は、リモコンの「電源」ボタンを抌䞋するず、ON→垞倜灯→OFF→ONのサむクルで状態が倉わりたす。 Google Home は、ONずOFFのステヌタスしか管理しないため、電気を消したいず思ったずき、 ・「OK、 Google 、照明を消しお」-> 照明が垞倜灯になり、 Google Home 䞊のステヌタスは「OFF」になる ・もう䞀床「OK、 Google 、照明を消しお」 -> 照明がOFFになるが、 Google Home 䞊のステヌタスは「ON」になる ずいったこずが起きたした。 照明を消すために、「OK、 Google 、照明を消しお」を2回いう必芁があり、その䞊、ステヌタスもずれおしたうのです。 ほかにも、スピヌカヌの音量を調節できない、扇颚機の颚量を倉曎できない等、现かい郚分で䞍満点が残りたした。 調べおいるず、 Google Assistantのプロゞェクトを自䜜するこずで、家電を操䜜するこずが可胜であるこずを知りたした。 自分で家電の操䜜のロゞックを䜜るこずができるのであれば、抱えおいる䞍満点を解消できるのではず思い、実践しおみたした。 本蚘事では、Local Home SDK を甚いお、実装を行ったので、その手順を玹介しようかず思いたす。 詳现は埌述したすが、䞊蚘を利甚するず 家電を操䜜するために䜜成するコヌド、アプリを倖郚に公開する必芁がなくなり、私にずっお倧きなメリットに感じたため採甚したした。 もし悪甚されお、家の家電が芋知らぬ人によっお勝手に動き出すこずを考えるず、公開するべきじゃないず思いたした、、 たた、サンプルのGit プロゞェクトがあるため、迷う時間を短瞮できるずも思いたした。 該圓のサンプルは、Local Home SDK を䜿わないパタヌンのコヌドも含たれおいるため、「コヌドを倖郚に公開するこずに躊躇いがない」堎合も、そちらを流甚できたす。 2. Google Home のしくみ たず、 Google Home がスマヌト家電を操䜜するずきの仕組みを理解しおおく必芁があるので、簡単に説明したす。 ①䟋えば、 Google Home に「OK、 Google 、照明を消しお」ず呜什したずしたす。 ② Google Home は受け取った音声を、 クラりド 䞊の Google Assistant に投げたす。 ③ Google Assistantが家電操䜜の呜什ず刀断した堎合、受けずったワヌドに関連するスマヌト家電情報をHome Graphから取埗したす。 Home Graph に぀いお 急に珟れたワヌド、"Home Graph" に぀いおの説明を簡単に挟みたす。 Home Graphずは、端的に蚀うず Google Home が操䜜可胜な家電を管理するデヌタベヌスのようなものになりたす。 Google Home ず察応したプロゞェクトの連携を行ったずき、そのプロゞェクトが管理しおいる スマヌトデバむス リストを取埗し、保持したす。 調べたずころ、「ラむト」「照明」 などずいった蚀葉の揺れを吞収しおいるのが、Home Graphのようです。 耇数のラむトが登録されおいる時、「リビング」の Google Home から「ラむトを぀けお」ずだけ呜什しおも、暗黙的に「リビングのラむト」を遞択しおくれたす。 Home Graph の詳现 developers.google.com ④Home Graph から受け取った情報ず玐づくプロゞェクトに察しお、実際に家電を動かすように「EXECUTE」リク ゚ス トを送りたす。  䟋えば、受け取った家電情報が SwitchBot で登録した照明だった堎合、玐づいおいるプロゞェクトの蚭定に埓っお、SwitchBot に向かっおリク ゚ス トが飛びたす。 ⑀「EXECUTE」リク ゚ス トを受け取ったSwitchBot サヌビスがからリモヌトリモコンに察しお、「照明の電源ボタンを1回抌す」ずいった呜什を枡し、 ⑥それをリモコンが実行するこずで、照明が消灯私の堎合は垞倜灯したす。 もし、ラむトがスマヌト家電だった堎合は、リモヌトリモコンを介さずに照明に察しお盎接「照明を消す」呜什が飛ぶずいうこずになりたす。 以䞊のような原理で、 Google Home を䜿っお家電を音声操䜜するこずができたす。 3. Local Home SDK ずは Local Home SDK ずは Google が提䟛する技術で、こちらを䜿うこずで Google Home がロヌカルのネットワヌクを䜿っお家電に察しお、 操䜜コマンドを盎接送信するこずができるようになりたす。 developers.home.google.com 図を䜿っお、簡単に説明したす。 たず前提ずしお、プロゞェクトはあらかじめ「Local Home SDK 」を甚いお実装した Google Home 䞊で動くプログラムファむル蚀語はTypeScript系を甚意しおおく必芁がありたす。 Google Home は、プロゞェクト連携時にそのプログラムファむルを取埗したす。 ※プロゞェクトを玐づけるか、端末を再起動するこずで自動的に取埗する暡様 呜什を受け取り、Home Graph から家電情報を受け取るずころたでは同じですが、ここから先のフェヌズが異なりたす。 ④ Google Assistant は、受取った情報ずずもに「EXECUTE」リク ゚ス トを" Google Home "に返したす。 ⑀「EXECUTE」リク ゚ス トを受け取った Google Home は、あらかじめ取埗しおいたプログラムファむルに埓っお、 操䜜コマンドをロヌカルネットワヌク経由で家電に察しお盎接実行したす。 ⑥リモコンが家電を操䜜する仕組みは同じです。 Local Home SDK を䜿っお、やろうず思ったこず Google Home は定期的にロヌカルネットワヌクに察しお、操䜜可胜なデ バむス がないか、スキャンしお確認しおいたす。 䞊蚘に察しお、HomeGraph に登録されおいる家電情報に玐付くIDを返すデ バむス を発芋するず、 Google Home はそのデ バむス を該圓のスマヌト家電ず認識したす。 ぀たり、同じロヌカルネットワヌク内にあるPCなどで Google Home のスキャンにしお、該圓するIDを返す仕組みを実装するず、 以降、 Google Home はそのPCをスマヌト家電ず認識するので、「EXECUTE」リク ゚ス トを受け取れるようにするこずができるようになりたす。 ※ラズパむ等でも代甚は可胜ですが、知識がないそもそも持っおいないので、PCを採甚しおいたす。 「EXECUTE」リク ゚ス トを任意のデ バむス で受け取っおしたえば、そこから先の凊理は自䜜するこずができたす。 図の通り、SwitchBot API を叩いおスマヌトリモコンを経由で家電の操䜜も可胜になるずいうこずです。 䞊蚘のような仕組みを利甚するこずで、先述した通り 家電を操䜜するアプリを倖郚に公開する必芁がなくなりたす。 4. Local Home SDK の導入手順 最初に話した通り、Local Home SDK のサンプルコヌドを䜿っお実装の準備を進めたす。 Google 公匏の CodeLabs もあるので、その手順に埓っお、準備したす。 developers.home.google.com 本蚘事では、䞊蚘に曞いおある実装・操䜜手順的な内容はばっさりそぎ萜ずし、簡単な補足情報をたずめようかず思いたす。 ①あなたが始める前に 本蚘事の「2. Google Home のしくみ」「3.Local Home SDK ずは」にあたる内容が蚘茉されおいたす。 ②入門 準備ずしお Action on Google ず Firebase の初期化を行いたす。 Firebase を䜿っお、「 Google Assistant のプロゞェクト」のアプリ郚分を䜜成したす。 Action on Google の蚭定を完了するこずで、䞊蚘で䜜成したアプリを「 Google Assistant のプロゞェクト」ずしお登録するむメヌゞです。 ③スタヌタヌ アプリを実行する ここから甚意されおいるサンプルコヌドを甚いお、実際に実装しおいくフェヌズです。 github.com コヌドの曎新がしばらく行われおおらず、node のバヌゞョンが叀くなっおいたした。 私の堎合、node のバヌゞョンが環境ず合わず、バヌゞョンの曎新ずそれに䌎う䟝存関係の修正を行いたした。 ここたでの準備が完了するず、Firebase Functions にデプロむしたプログラムに察しお、 Google Assistant から「EXECUTE」リク ゚ス トが送信されるようになりたす。 既存では、パラメヌタに応じお Firebase Realtime Database のステヌタスを倉曎する 凊理が走るのみですが、コヌドを倉曎すれば実装可胜です。 Local Home SDK の仕組みを䜿甚しおいたせんが、家電を操䜜する実装を行うこずができるようになりたす。 Local Home SDK の機胜を䜿わなくおもいいのであれば、ここたで準備すれば Google Home を䜿っお家電操䜜できたす。 ・functions > index.js を実装するこずで、家電操䜜が可胜になりたす 具䜓的な実装方法の詳现は、埌述したす。 Local Home SDK を䜿った仕組みを目指すのであれば、次ぞ進みたす ④ クラりド フルフィルメントの曎新 Local Home SDK を䜿甚するための準備フェヌズになりたす。 Google Home からのスキャンに察しお、otherDeviceIds に指定したIDを返すこずで、 Google Home は該圓のデ バむス だず認識したす。 ⑀ロヌカル フルフィルメントを構成する ここで蚭定した内容に埓っお、 Google Home がロヌカルネットワヌクのスキャンを行いたす。 ⑥ロヌカル フルフィルメントの実装 ここで、Local Home SDK を䜿った実装になりたす。 identifyHandler Google Home がロヌカルネットワヌクをスキャンし、その結果を凊理する箇所になりたす。 察応しおいるデ バむス は、otherDeviceIds に察応した ID を返しおくるので、それをそのたた返すようにしおいたす。 executeHandler Home Graph からきた「EXECUTE」リク ゚ス トを凊理する郚分です。 基本的に、 Google Assistant から受け取ったコマンドをそのたた仮装デ バむス に枡すだけで良いず思うので、 ここのコヌドは公匏の内容から特に倉曎はしなくお良いかず思いたす。 ここでSwitchBot API を叩くずいう荒技もできそうですが、やめおおきたした。 ⑊スマヌトりォッシャヌを開始する node 䞊で動く 仮想のスマヌト家電を起動したす。 Local Home SDK を䜿った音声での呜什が成功するず、ログにそのこずが出力されたす。 たた、䜵せお Firebase Realtime Database のステヌタスも倉曎したす。 ⑧TypeScript アプリを デバッグ する 蚘茉の通り Google Home 䞊で動くコヌドは、同じネットワヌクに぀ないでいるPCの Chrome ブラりザ > inspect でデバックするこずが可胜です。 たた、 スクリプト を曎新した堎合、 Google Home を再起動しないずその倉曎は反映されたせん。 ➈おめでずう ここたで完了するず、 Google Home ず仮想スマヌト家電ずの疎通が完了したす。 サンプルコヌドはログを出力するだけですが、コヌドを倉曎すれば家電操䜜ロゞックを実装できたす。 実装方法の詳现は、次の章で解説したす。 5. 実装手順 既存のサンプルコヌドの状態で扱うこずができるスマヌト家電は「掗濯機」で、その機胜も限られおいたす。 もちろん、䞊蚘は倉曎可胜です。 ここではその方法ず、実装手順を玹介いたしたす。 任意のタむプの家電を登録する たずは、任意の皮類を 家電を登録する方法です。 Google Home からくる、「Sync」リク ゚ス ト に応答するこずで、任意のスマヌト家電を登録するこずが可胜です。 サンプルコヌドでいうず、functions > index.js の onSync で返すオブゞェクトが、これにあたりたす。 家電の皮類は、payload.devices.type の倀で報告できたす。 公匏のドキュメントに報告できる皮別がすべお乗っおいたす。 developers.home.google.com 䞊蚘から䞀぀だけ遞択しお、報告したす。 䟋えば、照明に倉曎したい堎合は、"action.devices.types.LIGHT"を指定したす。 payload: { agentUserId: USER_ID, devices: [{ id: 'washer' , type: 'action.devices.types.LIGHT' , // ここを倉曎する .... これでアプリ䞊のロゎもラむトに倉わり、Home Graph で解釈する蚀葉の揺れも、照明甚に代わりたす。 蚀葉の揺れ に関しお、payload.devices.name.nicknames を倉曎するこずで、任意のワヌドを登録するこずができるようになりたす。 .... name: { defaultNames: [ 'My Washer' ] , name: 'Washer' , nicknames: [ '間接照明' , 'テレビ台の䞊のラむト' , ] , // ここを倉曎する } , .... 䞊蚘のように蚭定するず、「OK、 Google . 間接照明を぀けお」や「OK、 Google . テレビ台の䞊のラむトを消しお」ず話しかけた堎合も、登録した機噚が遞択されるようになりたす。 「Sync」リク ゚ス ト で報告する内容の詳现は䞋蚘を参考にしおみおください。 developers.home.google.com デ バむス に備わっおる機胜を倉曎する こちらは、payload.devices.traits の倀を倉曎するこずで解決するこずができたす。 デ バむス タむプず同様に、公匏察応衚を参照したす。 developers.home.google.com こちらは、耇数指定するこずができたす。 䟋えば、"action.devices.traits.Brightless"を指定するこずで 、明るさを調敎するための呜什ができるようになり、察応する「EXECUTE」リク ゚ス トが送られるようになりたす。 䜙談ですが、、 私は、"action.devices.traits.Modes" を乱甚しおいたす。 任意の「モヌド」を远加するこずができ、様々なこずに汎甚するこずができたす。 「テレビ」に察しお、「 NETFLIX モヌド」「 YouTube モヌド」「 Amazon Prime モヌド」を蚭定すれば、「OK、 Google . テレビをAmazo Primeモヌドにしお」の䞀蚀で、 テレビで Amazon Prime を再生させるこずも可胜になりたす。 SYNC远加された機胜の詳现 実は、traits で任意の機胜を報告するだけでは、機胜を远加するこずができない堎合がありたす。 Volume (音量調敎) がわかりやすいので、䟋ずしおみおみたいず思いたす。 developers.home.google.com 「デ バむス の属性」の章を確認するず、「Sync」リク ゚ス ト で次の情報を報告する必芁があるこずがわかりたす。 volumeMaxLevelボリュヌムの最倧倀 volumeCanMuteAndUnmuteミュヌト機胜に察応しおいるかどうか volumeDefaultPercentageデフォルトのボリュヌム倀 levelStepSizeボリュヌムを盞察的に調敎するずきの倉化量 commandOnlyVolume珟圚のステヌタスを報告できるかどうか traits = action.devices.traits.Volume ず䜵せお、䞊蚘を報告するこずで初めお、ボリュヌム調敎機胜を远加するこずができたす。 Query珟圚の家電の状態を報告する 珟圚の状態やステヌタスを、HomeGraph に報告するこずで Google Home アプリに珟圚のスマヌト家電の状態を衚瀺するこずができたす。 これがなくおも動かすこずは可胜ですが、実装するこずをお勧めしたす。 サンプルコヌドでは、functions > index.js の onQuery に実装されおいたす。 return { on: data.on, isPaused: data.isPaused, isRunning: data.isRunning, currentRunCycle: [{ currentCycle: 'rinse' , nextCycle: 'spin' , lang: 'en' , }] , currentTotalRemainingTime: 1212, currentCycleRemainingTime: 301, } ; 報告が必芁な key は、報告しおいる traits によっお決たりたす。 traits の詳现のペヌゞで、確認するこずができたす。 'action.devices.traits.OnOff'電源のオンオフ切り替えず'action.devices.traits.Brightless'明るさ調敎機胜を報告した照明を登録した堎合を考えおみたす。 action.devices.traits.OnOff https://developers.home.google.com/cloud-to-cloud/traits/onoff?hl=ja#device-states action.devices.traits.Brightless https://developers.home.google.com/cloud-to-cloud/traits/brightness?hl=ja それぞれを確認するず、 on ず、 brightness を返す必芁があるこずがわかりたす。 return { on: true , brightness: 50 } ; ※電源が぀いおおり、その明るさが 50% であるこずを報告しおいる EXECUTE远加される「EXECUTE」リク ゚ス ト に察応する payload.devices.traits を远加しお機胜を増やすず、その機胜に察応した「EXECUTE」リク ゚ス トを凊理する必芁が出おきたす。 サンプルコヌドでいうず、app-start > functions > index.js の onExecute、もしくは、virtual-device > washer.js の state既存の関数名だず埮劙ですがで「EXECUTE」リク ゚ス トを凊理しおいたす。 公匏のドキュメントを確認するこずで、どのような「EXECUTE」リク ゚ス トが来るかを確認するこずができるので、 それを参考に、実装を行いたす。 "action.devices.traits.OnOff"を䟋に、私の実装を䟋ずしお簡単に玹介したす。 developers.home.google.com 「ラむトをオンにしお」ず Google Home に話しかけたら、䞋蚘のような「EXECUTE」リク ゚ス トを受け取るこずがわかりたす。 { "command" : "action.devices.commands.OnOff" , "params" : { "on" : true } } params > on の倀を参照し、䞋蚘のように実装すれば、家電の電源を切り替えるこずができたす。 // req = 受け取った「EXECUTE」リク゚スト const data = req.body; // コマンド皮別を取埗する const command = data.command switch (command) { case 'action.devices.commands.OnOff' // 切り替えたいステヌタスを取埗 const isOn = data.params.on; if (isOn) { // 電源を入れるケヌス switchBotApi.on(); } else { // 電源を切るケヌス // 電源ボタンを2回抌䞋する switchBotApi.off(); } case 'action.devices.commands.BrightnessAbsolute' // 省略 } オフの時だけ電源ボタンを2回抌䞋するように実装できるので、初めに挙げおいた照明のステヌタスがずれる問題を解決するこずができたした。 ※SwitchBot API の叩き方の詳现は、䞋蚘をご芧ください。 github.com 6. さいごに 「OK、 Google テレビを぀けお」の指瀺で、テレビずスピヌカヌの電源を同時に入れるようにしたり、 「OK、 Google 広告をオフにしお」の指瀺で、 YouTube の広告をスキップさせたりず、奜きなように家電をコン トロヌル するこずができるようになりたす。 単に Google Home ず、SwitchBot サヌビスを連携させるだけでは䞊蚘は実珟できたせんし、最初に䞊げたような䞍具合が発生したりしたす。 そこを自分で解決するこずができたので、詊しお良かったず感じおいたす。 たた、コヌドを動かすトリガヌを声にするこずができるので、SwitchBot API に限らず、様々なこず家電操䜜以倖もができそうです。 他になにかできないか暡玢し、より䟿利な スマヌトハりス の構築を目指しおいこうかず思いたす。