TECH PLAY

BASE株式会社

BASE株式会社 の技術ブログ

587

こんにちは。BASE株式会社 Design Groupに所属しているイシグロです。 普段は主にマークアップを担当しています。 今回、ブログ初投稿ということで、ネットショップ作成サービス「BASE」でショップを運営するにあたり、ショップのデザインに大きく関わる「HTML編集App」と「デザインテーマ」についてお伝えできればと思います。 主に下記の方にお役に立てる情報かと思います。 「BASE」でネットショップ開設を検討していて、ショップのデザイン部分が気になる方 すでに「BASE」でネットショップを開設していて、ショップのデザインをもっと工夫したいという方 「BASE」で開設されたネットショップのページを、HTMLやCSSを用いてオリジナルのデザインを作成される方 オリジナルデザインのネットショップが作りたい!そんなショップオーナーのための「HTML編集App」 せっかくネットショップを作るなら素敵なデザインがいい。そう思ってらっしゃるショップオーナー様は大勢いらっしゃると思います。 でも「BASE」をはじめとするネットショップ作成サービスだと予め用意されたデザインを選ぶだけだったり、 パーツを組み合わせるだけであまり自由にデザインを変更できない。そういうイメージありませんか? まずはこちらのショップ様を御覧ください。 TAWARA HONEY SELECTION ( http://www.honey-selection.com/ )様 こちらは実際に「BASE」をご利用頂いているショップ様で、デザインは完全オリジナルとなっています。 冒頭のアニメーションが可愛いので是非リンクをクリックして実際のショップを御覧いただきたいです。 ※こちらのデザインはBASEオフィシャルパートナーのLANDMARK様が制作されたものです。( https://thebase.in/andbase ) 「BASE」ではネットショップの基本的な運営をするための基本機能とは別に、「 BASE Apps 」という形で様々な追加機能を提供しています。 初心者の方でも簡単に運営できるよう手助けをするようなAppsが多い中、「HTML編集App」はちょっと初心者の方には手を出しづらいAppかもしれません。 HTML編集画面 こちらはショップページのHTML編集をする画面です。Web制作のご経験がある方はお分かりになるかと思いますが、その名の通り「HTML編集App」は独自のHTML、CSS、Javascriptなどを用いてショップ毎にオリジナルデザインのネットショップを作成することを可能にするAppです。 上記のキャプチャ画像は「BASE」の管理画面の「デザイン編集」から「HTML編集」の画面に切り替わった状態のものです。 ここで直接編集することもできますし、お好みのエディタで記述したソースを貼り付けることで反映することも可能です。 「BASE Template」という仕組みでショップの様々な情報を表示 HTML編集エリアには {PageTitle} などの見慣れない記述があるかと思いますが、こちらが「BASE」独自の「 BASE Template 」という仕組みです。 基本的にはHTMLの中にこのBASE Templateのタグを組み込み、ショップや商品の情報などを含むページを構成するパーツをページの必要な箇所で出力します。 タグのには2種類あり、タグ単体で情報を出力する 変数 と、エリアを指定する ブロック があります。 変数 には商品名やショップ名などのいわゆるテキストを単純に表示する小さなものから、お問い合わせフォーム一式をHTMLとしてまとめて出力する大きいものまで様々です。 タグ 説明 {ItemId} 商品のID {ItemTitle} 商品の名前 {ItemPrice} 商品の価格 {ItemProperPrice} 商品のセール価格に対する通常価格 {ItemDiscountRate} 商品の割引率 {ItemStock} 商品の在庫数 {ItemDetail} 商品の説明 ※一部抜粋 ブロック は「ここからここまでは商品詳細ページ」といったエリアを限定する if文 に相当するものと、「登録されてる商品の数だけ繰り返す」といった繰り返しの for文 に相当するものがあります。 タグ 説明 {block:Items} 商品一覧における商品のループ {block:HasItems} 商品がある {block:NoItems} 商品がない {block:HasItemProperPrice} 通常価格がある {block:NoItemProperPrice} 通常価格がない {block:HasItemStock} 商品の在庫がある {block:NoItemStock} 商品の在庫がない ※一部抜粋 これらを駆使し、1ソースの中にショップのすべてのページの構造を記述します。 6~13ページ分(※)のソースを1ソースに記述するのですが、短いテーマで500行、長いテーマで2500行ぐらいになります。 (※BlogAppやカテゴリAppを使うとショップのページ数が増えます) 1ソースで!? とお思いになられるかもしれませんが、AboutページやContactページに表示するコンテンツ部分は、予め用意されたタグ一つで表示できるのでそれ自体は1行で完結します。 ヘッダーやフッターなどのショップ全体で共通なものは1箇所に記述すれば使い回せるので、あとは該当ページをどういうページレイアウトにしたいのかによって、レイアウト用のHTMLタグが必要になるだけです。 (※ 1ソースの全体構成の例 ) CSS、JavaScript、画像ファイルなどはファイルアップローダーを使って外部読み込み HTMLとBASE Templateタグについてご説明してきましたが、Webサイトの構成に欠かせないのがCSS、JavaScriptや様々な画像ファイルです。 CSSやJavaScriptまで1ソースで記述してしまうと更に行数も増え管理が大変です。 そのため「BASE」では外部ファイルとして読み込むファイルはファイルアップローダーをご用意しています。 BASE Developers ファイルアップローダー (※ファイルアップローダーはBASE Developersからショップアカウントでログインすることで使えます) アップローダーでサーバーにアップロードされたファイルは上記 https://example.com/sample.css のように独自のURLが発行されますので、それをソース内でファルパスとして記述することで読み込むことが可能です。 (※例としてexample.comとして改変しているので、本来はもっと長いURLになります。) ここまで分かればテーマが作れる!? 先はまだまだ長く険しいテーマ作成 Web制作のスキルがある方にとっては、ここまで分かればテーマ作れそうと思われるかもしれません。 しかし大変なのはここからで、対応しなければならないAppsの数だけ様々なケースを想定してチェックしなければなりません。 テーマ チェックリスト チェックリストにあるとおり、在庫がある場合、在庫がない場合、商品名が長い場合、短い場合、商品画像が少ない場合、多い場合など様々なケースの組み合わせの表示チェックが必要になります。 また、「英語・外貨対応App」や「販売期間設定App」などもご利用になる場合はさらに大変です。 英語表示になると文字数が増えるので往々にしてデザインが崩れたり、販売期間設定の場合、販売開始前、販売期間中、販売終了後の表示確認もあります。 他にも「BlogApp」、「セールApp」、「カテゴリApp」など、ショップの表示に関わるAppsが多くあり、 大規模ショップで高機能になればなるほどあらゆる想定をしたチェックが必要になります。 また1ソースが故に、必然的にモバイル表示も考慮に入れたレスポンシブデザインにする必要があります。 (※デザイン編集の設定で、モバイル表示のときはBASEのデフォルトテーマを表示するという設定もあります。) BASE Templateを使いこなし作り上げられた「デザインテーマ」 この「HTML編集App」は誰でもご利用いただくことが可能ですが、さすがにHTMLやCSSの知識がないと使いこなすことはすこし難しいかもしれません。 さらに前述の通り何通りものチェックが必要になります。 しかし、ご自身で「HTML編集App」でカスタマイズをせずとも、実は同じBASE Templateの仕組みで制作されたテーマを購入することができます。 BASEデザインマーケット( https://design.thebase.in/ ) ここで販売されているテーマは外部のデザイナーの方々が独自にテーマを作成し、前述のあらゆるケースを想定したBASE社内の審査を経ている完成されたデザインテーマです。 販売金額はテーマ制作者が自由に設定することができ、5,000円から上は1万円を超えるものまで様々。 テーマがショップオーナー様に購入されると、規約に則った配分でテーマ制作者の方に報酬として支払われます。 現在販売されているテーマは40種類以上あり、テーマによっては特定の利用ケースを想定したユニークなものもあります。 例えばこちらの LPshoot はランディングページのようなデザインになっており、商品数がごく少数の場合に適したデザインとなっています。 BASE デザインテーマ購入ページ( https://design.thebase.in/detail/34 ) その他にも大量の商品を扱うことに適しているテーマや、柔らかいデザインで和の雰囲気の商品を扱うことに向いているテーマなど、単純にレイアウトが違うというよりも、様々なジャンルのショップに適したテイストのテーマが作られています。 また、各テーマには「デザインオプション」と呼ばれるテーマ独自の設定項目が用意されていて、直接HTMLを編集しなくても、バナーの表示、特定のエリアのレイアウト変更、独自に作成したページコンテンツの表示なども可能となっています。 このデザインオプションでショップ独自の設定を適応することで、高機能なテーマだと、同じテーマでも全く違うテーマのような魅せ方をすることも可能です。 実際各テーマの購入ページには、そのテーマを利用しているショップ様のページへのリンクがありますので、ぜひいろいろなテーマ、およびショップ様をご覧になってください。 各テーマ、各ショップ様ともに創意工夫にあふれていて、見ていて飽きないかと思います。 デザインテーマのソースをHTML編集Appでカスタマイズして独自テーマに拡張 私が個人的にショップオーナー様にオススメしたいのは、「好みのテーマを購入」し「HTML編集Appでちょっとだけカスタマイズ」です。 あくまでHTMLなどWeb制作に関するスキルをある程度持ち合わせていることが条件ですが、前述の様々なチェックやBASEの審査をクリアしているデザインテーマを元にすれば、ある程度は安心してご自分の好みにカスタマイズすることができるのではないでしょうか? (※一度HTMLを編集すると新機能追加などテーマの自動更新がされなくなります。カスタマイズはあくまで自己責任でお願いします。) 購入したデザインテーマは「HTML編集App」で修正することが可能です。ここの色だけ変えたい、画像サイズを修正したい、このエリアにバナー画像を挿入したい、などちょっとした修正ならば、不具合を起こす可能性もゼロからつくるよりもかなり低くなります。 素敵なデザインのショップがたくさん増えることを願って 「HTML編集App」および「デザインテーマ」にご興味をお持ち頂けましたでしょうか? ご興味のあるショップオーナー様はぜひ「HTML編集App」を触ってみてください。 失敗しても元々のテーマを再度選択すればもとに戻りますのでご安心を。 また、デザインテーマは購入する前にご自分のショップに適用した状態を確認できます。 「BASE」にログインした状態でテーマ購入ボタンの横にある「プレビュー」ボタンを押してください。 プレビュー状態でも様々なデザインオプションを変更したりすることで購入後のイメージができるかと思います。 お気に召しましたら是非ご購入を。 Web制作のご経験のあるクリエイターの方は是非テーマを作成して販売してみませんか? テーマ作成にはショップ開設が必要ですが、ショップ開設は無料ですし、ご心配でしたら「 シークレットECApp 」を使えば作成中のテーマを見られる心配もありません。 ご自分のデザインスキルを活かして副収入を得たいという方、是非どうぞ!
こんにちは!この度、6/29(土)に開催された PHPカンファレンス福岡2019 にて、BASEがスポンサーとして協賛&2名のメンバーが登壇いたしました!今回は川島( @nazonohito51 )・めもりー( @m3m0r7 )・東口( @hgsgtk )・田中( @tenkoma )の4名より参加レポートをお届けします! 会場レポート みなさん、こんにちは!基盤チームのめもりー ( @m3m0r7 ) です!今回、私は参加者として、PHP カンファレンス福岡に参加してきました! BASE では、カンファレンスへ登壇や参加といったメンバーのコミュニティ貢献活動を積極的に支援しており、今回PHPカンファレンス福岡も業務として参加してきました これが決まったのは、実は先週だったこともあり、ホテルや飛行機などの予約が大変でしたがそれでも無事参加することができました。 ということで会場レポをお送りしたいと思います。 会場レポ 今回弊社はブロンズスポンサーとしてスポンサードさせていただいており、かわいい旗がずらりとしている中に弊社が! 弊社デザイナーがめちゃめちゃかわいく仕上げてくれました!ありがとうございます。 まだ、PHPカンファレンス福岡でしか配布していない BASE BANK のステッカーです! 弊社はブロンズスポンサーとはまた別に、2名のエンジニアが登壇させていただいておりました。 下記に詳しく記載します! 一方、セッションの裏では… セッションの裏では、GMOペパボさんが開催していた、「マネクラからの挑戦状」があり、これは参加しなくては…!ということで参加してきました。 〜 が ? に文字化けしてる! 具体的には2つに分かれて、一つが脆弱性を見つけていくもの、もう一つが既存のコードを短くしていくもので、通称「コードゴルフ」と呼ばれているものです。 私はコードゴルフの方をやっていました。 もともとのコードは下記でした。 詳しくは ペパボさんの GitHub リポジトリ を御覧ください。 それを下記のようにしていきました… 追い打ちをかけるようにスコアを更新しまくっていました。 時間が限られていたのでコードがだいぶ雑ですが、最初の4,855,534 スコアから 75,371 スコアまで減らして、無事優勝しました! そして 10 万円分のクーポンをもらってしまいました。本当にいいんですか?ありがとうございます。 コードゴルフ一位は めもりーさんで、10万円クーポンをお渡ししました。 おめでとうございます!  #hall_lo #phpcofuk #mclolipop pic.twitter.com/ARuYGO4n8k — すねこすり (@sunecosuri) June 29, 2019 ということで、セッションの内容も楽しかったですが、合間の時間も楽しく、とても有意義な1日でした。 ありがとうございました! 余談ですが、アフターハックとしてもっと短くできないかと思い、また桁数を1つ減らす形でスコアを更新して最終的に 7,159 となりました。 @tenkoma さんのコードと組み合わせるともう少し短くなりそうです。 <?php array_multisort ( $ v =$ _GET , $ a = SORT_DESC, $ b = SORT_STRING, array_keys ( $ v ) , $ a , $ b , $ v )?> <!DOCTYPE html> < style > body , html { height : 100 vh; margin : 0 ; background-color : #fff ; color : #465560 ; font-family : Arial , Verdana , Meiryo , sans-serif ; font-feature-settings : "pkna" ; letter-spacing :. 04em ; font-size : 1rem ; text-rendering : optimizeLegibility ; -webkit- font -smoothing: antialiased } body { font-size : 1rem } * { box-sizing : border-box ; background-repeat : no-repeat ; padding : 0 ; margin : 0 } table { width : 100 %; height : 100 % } html { box-sizing : border-box ; -webkit- text-size-adjust : 100 % } td { text-align : center ; height : 50 %; width : 5 % } h1 { font-weight : 400 ; margin : 0 }</ style >< table border = "0" cellspacing = "0" >< tr >< td bgcolor = "#147ecc" >   < td >   < td style = "width:80%" >< table >< tr >< td style = "height:10%;" >   < tr >< td style = "height:80%" >< img src = "https://raw.githubusercontent.com/pepabo/lolipop-mc-codegolf-challenge/master/mc.png" width = "100%" />< br >< h1 > <? = strrev ( array_values ( $ v )[ 2 ] ?? '' )?> </ h1 >< tr >< td style = "height:10%" >   </ table >< td >   < td bgcolor = "#147ecc" >   マネクラからの挑戦状参加レポート by 田中( @tenkoma ) BASE Product Dev Division 基盤グループの田中です。午前中セッションを聴講して、午後はマネクラからの挑戦状(PHPアプリケーション脆弱性修正チャレンジ)に参加していました。 ルールについては pepabo/lolipop-mc-vuln-challenge をご覧ください。 用意されたWebページに脆弱性があるのでそれを直す、という問題が5つ用意されていました。時間内に5問解けたので11,000円分のクーポンをいただきました!(最速で解けた場合豪華なクーポンがあったのですが、残念ながら2位でした) めもりーさんが優勝された コードゴルフ も面白そうだったので、翌日 株式会社Fusic で開催された (非公式)PHP Conference Fukuoka 2019 After Hack!! のネタにしたいな、と思いました。楽しむためにはオンラインで動いているチェッカーが必要なので、イベントを開催された GMOペパボ株式会社 の方にお願いしたところ、翌日も動作してもらえることになりました。 マネクラからの挑戦状で使われたチェックサービスを明日も動かしてもらえることになったので、アフターハックでハックしていきましょう!! #phpconfuk #hall_lo https://t.co/kkkEKB9yY1 — Koji Tanaka (@tenkoma) 2019年6月29日 会場で書き換えて、東京に戻ってからも書き換えた結果、PNG画像ファイルを含めて60315というスコアになりました。コードゴルフなのでかなりダーティなコードですが以下のようになります。 <!DOCTYPEhtml> < table cellspacing = 0 >< tr >< td bgcolor = #147ecc >< td >< td style = width:80% >< table >< tr >< td style = height:10% >< tr >< td style = height:80% >< img src = m width = 100% >< h1 > <?php foreach ( $ _GET as$ k =>$ v ){ $ t [] = [ $ k , $ v ] ; } usort ( $ t , function ( $ a , $ b ){ $ i =$ a [ 1 ] !=$ b [ 1 ] ? 1 : 0 ; return strcmp ( $ b [ $ i ] , $ a [ $ i ]) ; }) ; echo $ t [ 2 ] ? strrev ( $ t [ 2 ][ 1 ]) : '' ?> < tr >< td style = height:10% ></ table >< td >< td bgcolor = #147ecc >< style > body{height:100vh;font-family:Helvetica;letter-spacing:.04em}table{height:100%}*{border:none;padding:0;margin:0;font-weight:400;color:#465560;text-align:center}td{height:50%;width:5%} 見やすくフォーマットされたコードはこちら https://gist.github.com/tenkoma/416cdf36a51c9610e0a7d353102a43ce 実はチェッカーは、リダイレクトをチェックしてなかったため、「コンテナ内の /var/www/html 内にWebサイトを表示するのに必要な全てのコード、およびファイルを設置してください」というレギュレーションを無視すれば以下のコードもチェッカーをパスします。(スコア: 80) <? = header ( 'Location://phpconfuk-codegolf-php.lolipop.io?' . getenv ( QUERY_STRING )) ; 「マネクラからの挑戦状」、ゲームを楽しみながらマネージドクラウドの使い方を覚えるというナイスな企画で、楽しく参加できました。 登壇スライド 今回登壇した、東口( @hgsgtk )・川島( @nazonohito51 )の発表内容について発表者自身より紹介します。 ユニットテストの現場の問題を原則に立ち返って考える by 東口和暉 BASE BANK株式会社 Dev Divisionでソフトウェアエンジニアをやっている東口( @hgsgtk )です。 これまでのPHP系のカンファレンスにて、いろいろユニットテストについて話してきたのですが、今回もユニットテストの話です。 今回の内容は、ユニットテストについて現場で起きる問題や悩みがちな意思決定について、問題を整理した上で取りうる戦略とその戦略の良し悪しを様々な文献をもとに説明するものです。各々の現場で異なりうる意思決定の判断材料を提供することを試みました。 駆け足で話してしまったのですが、Ask the Speakerにて、現場でテストを書いてる聴講者の方々に「参考になった」と言っていただけたので、ある程度この発表が目指したいものは実現できたかなと思います。 今年は、今後も CakeFest や Go Conference Summer in Fukuoka 、 PyCon JP 2019 等で、ユニットテストについて話す機会を頂いているので、引き続きユニットテストをはじめとしたソフトウェア開発に関する造形を深めるべく精進していきます。 PHPStanでCustomRuleを作る by 川島慧 BASE Product Dev Division 基盤グループの川島( @nazonohito51 )です。今回はPHPStanを使って独自の静的検査を行うことが出来るというお話をさせていただきました。 PHPStanにはCustomRuleという独自の検査を作るための機能が備わっているのですが、READMEにほぼ記述はなく、かなり手探りの作業を要求されます。今回は私が dependency-analyzer という静的解析ライブラリを作った経験から、そのあたりの知見をコミュニティに還元すれば喜ぶ人がいるんじゃないかな?という思いで発表させていただきました。なるべく「こんなに簡単にCustomRule書けるんだよ」と簡単さを押して資料を作りましたが、ありがたいことに意外と簡単にかけそうだぞという感想もいただいて、発表の目指したいところは達成できたかと思います。 同時に気になったのが「静的解析って何ですか?」という質問でした。色々お話させていただいた感触としては、おそらく「PHPStan/Phanというツールの存在はなんとなく知っているが、具体的にそれらがどういうものなのかはみんなハッキリとは認識していない」ぐらいなのがコミュニティの実情なのかなという感触を得ました。 @tadsan さんとも懇親会の場でお話しましたが、やはりみんなあまり知らなそうだという認識とのことです。 https://twitter.com/suzuki/status/1144873913790259201 PHPstan + CustomRule によるコードクオリティの維持については、既にアプリケーションエンジニアの範疇を超えて来ている気もするなー。 これができるなら、そういう役割のおちんぎんがプラスされても良い世界な気がする。 #phpconfuk — suzuki (@suzuki) June 29, 2019 なるほど。たしかにコードクオリティを維持する仕組みづくりは、事業へのコミットしながら同時に手を出すのは難しい領域かもしれません。これらを踏まえて、大多数の人が興味を持ちづらい領域の話だったかな〜と思いました。次回はより多くの人が興味を持ってくれそうな話をしたいと思います! まとめ 台風が直前に出現するなど困難が現れる中、トラブルなく素晴らしいカンファレンスを運営していただいた、実行委員長の松村様( @tsubakimoto_s )をはじめ実行スタッフの皆様、本当にありがとうございます。 また、登壇者の皆様、スポンサー企業各位、聴講者の皆様方にこの場を借りて御礼申し上げます。 引き続き、PHPコミュニティに積極的な貢献を続けていきたいと思います。
はじめに BASEでは、開発者様向け機能として BASE Template と BASE API を提供しています。 BASE TemplateではBASEショップが使えるHTMLテンプレートの開発を、BASE APIではショップの商品情報や注文などをWEB API経由でアクセスしアプリケーション開発を行うことができます。 今回はその2つの機能のドキュメントサイトをリニューアルしましたのでお知らせ致します。 なぜリニューアルする必要があったのか 以前のドキュメントサイトは、以下のようにGitHub上にドキュメントとしてMarkdownファイルを配置しているだけでした。 template-docs baseinc/api-docs 機能としては最低限満たしてはおりましたが、デザイン性は乏しく必要な情報へのアクセスも難しいという問題がありました。 加えて、ドキュメントに新しいAPIレスポンスについての情報を加えようとするとGitHubのPull Requestを経由せざるを得ず弊社エンジニアやデザイナー同士の仕様定義についてのやりとりも見えてしまうという問題も存在しておりました。 これらの問題を解決しつつ開発者の皆様に使いやすいドキュメントにリニューアルしていく運びとなりました。 どのようなツールを利用するか 社外向け開発ドキュメントをホストするサービスやツールは数多くあります。 弊社で選定する際に重要視したのは下記です。 既にあるMarkdown ドキュメントを大幅に変更する必要がない ある程度デザインを自由に変更することができる 独自ドメインを割り当てることができる なるべく新しいSaaSなどを利用したくない 検索機能を開発せずに利用できる もともとドキュメントはmarkdownで書かれていますので、例えばSphinxなどをドキュメントツールとして選定してしまうとrst形式に書き直す必要があります。 今回のリニューアルではドキュメント自体を変更することまでは考えておりませんでしたので作業工数的な考えからも現在のドキュメント資産自体はなるべくそのまま利用できることが重要な条件でした。 検索機能についても同様で、検索機能は必要ではありますが一から開発していくことは望ましくありません。 デザインに関してははBASEのブランドガイドラインに沿ったサイトを構築するのが望ましく、一定のカスタマイズが可能である必要があります。 独自ドメインは大抵のドキュメントツールや静的サイトのホスティングでサポートしています。 ですが、別途SaaSなどを契約することでアカウント管理の煩雑さを増やすことは避けたいという考えもありました。ドキュメントをメンテナンスする社内メンバーは多くいるためそれらの人に改めてアカウント権限を付与する作業が必要となってしまうためです。 Docusaurus + GitHub Pages 上項のような条件のもと、GitBookやHugo、Swagger-UI、API Blueprintなどを試していたところ Docusaurusというツールに出会いました。 https://docusaurus.io/ DocusaurusはFacebook社が公開しているOSS向けReact製のドキュメント作成ツールです。 React NativeやRedux、textlintのような OSSドキュメント に利用されています。 Docusaurusはmarkdown形式のドキュメントを扱うため、一部の変更は加える必要はありましたがBASEの既存ドキュメントからの移行は問題なくできるようでした。 デザインは柔軟に変更でき、ローカルでの開発も容易でしたのでデザイナー自らがデザイン修正を行うことができました。 Docusaurusでドキュメントを作ることができたのでそれをホストする環境についての選定をしましたが、ここは順当にGitHub Pagesを選定しました。 独自ドメインを扱うことも可能ですし、弊社ではGitHubを元々利用しているため公開フローのために特別なアカウントを必要としないことが選定理由です。 現状問題はほとんどありませんが、ステージング環境のような物が存在しないのでローカルで検証したサイトを複数人で確認し辛い事に少し不安があるなと感じています。 既存ドキュメントの移行作業 ツールの選定が終わったので、あとは既存ドキュメントを移行していきます。 docusaurus のセットアップ docusaurus-init というツールを利用すると最低限必要な初期ファイルを用意してくれます。 基本的なドキュメント部分は設定ファイルとmarkdownの変更で対応できますが、例えばトップページを変更したい、となった場合はある程度 React の知識が必要になってきます。 リニューアルタイミングで新しい機能が追加される予定だったこともあり、今回はエンジニアがデザインの組み込み込みで構築を担当し、デザイナーを中心にドキュメントの追加、修正、構成の見直しを行いました。 移行作業 既存の markdown のドキュメントからの移行は、ヘッダー情報を付加するのみで行うことができました。 いままではコンテンツのみが書かれていた markdown にこのようなヘッダーを追加します。 --- id: add title: items/add --- # POST /1/items/add 商品情報を登録 id は、ドキュメント上で自身が存在するディレクトリを含めたユニークキーとなります。例えばこのファイルは docs/api/items/add.md に配置されているので、実際の id は api/items/add となります。 あとはこれをすべて markdown に追加していき、sidebar.json へ構成を記述すれば完成です。 "docs": { "BASE API": [ "api/index", { "type": "subcategory", "label": "OAuth", "ids": [ "api/oauth/authorize", "api/oauth/access_token", "api/oauth/refresh_token" ] }, { "type": "subcategory", "label": "Item", "ids": [ "api/items/index", "api/items/search", "api/items/detail", "api/items/add", ... 検索 Docusaurusはそのままでは検索を利用する事ができません。 ですが、 Docsearch と連携させることで検索機能を使うことができます。 Docsearchはalgolia製の検索を提供してくれているサービスで、OSS向けでは無料で利用することができます。 利用する際はDocsearchのサイトから、利用申請を送る必要があります。 送った後数日で、このサイトの管理者かどうか?といった質問がメールで送られてくるので管理者である旨を返信するとAPI keyなどが送られてきます。 下記のようにconfigが配置されていれば検索が可能になっているのでDocusaurusのsiteconfig.jsonに設定を書き加えることで検索機能が有効になります。 https://github.com/algolia/docsearch-configs/blob/master/configs/thebase.json 検索のレスポンスが驚くほど速いのでDocusaurusを利用しなくとも、Docsearch(algolia)を利用する価値はあると感じました。 GitHub Pageへのデプロイ GitHub PagesへのデプロイはCircleCI 経由でやっています master branchへのcommitを検知すると、デプロイ jobを実行しGitHub Pagesへのデプロイを行っています。 これらの 手順 もDocsaurusのドキュメントに詳細に書いてあるので手厚いなと感じました。 これによりエンジニアでなくともGitHubのアカウントさえあれば手軽にドキュメントのメンテナンスが行えるようになっています。 ドキュメント上で一部機能の確認が行えるようになりました。 ここからは新機能のお知らせとなりますが、昨今のBASE TemplateはBASE Appの拡充に伴い様々な条件を想定し開発をしていただく必要があります。 しかし、現状のエディタ機能では色々パターンを想定し開発していただくのには不便であることは開発チームとしても課題として受け止めておりました。 そこで、今後のシステムの拡張の先駆けとして、テンプレートのサンドボックス機能を一部実装いたしました。 サンドボックスは BASE Template に関するドキュメントの 対応ページ で確認することができます。 この機能はテンプレートを作成するにあたって、複雑化するタグの動作イメージをつかんでもらおう、という目的で実装されました。 タグによっては BASE Apps (拡張機能) の有無や、商品に設定されている項目や時間によって動作が異なることがあるため、 動作を確認するためには実際に Apps をインストール、設定、アンインストールしてまたインストールというような労力をかけていただく必要がありました。 サンドボックスではこれを解決するため、Apps の設定を簡略化したものをその場で設定できる機能を搭載しています。 この機能は現在一部のタグのみをサポートしていますが、徐々に対応範囲を広げていく予定です。 最後に 今回はBASE TemplateとBASE APIのドキュメントサイトの更新とドキュメントへの機能追加についてお知らせさせていただきました。 開発者の皆様がBASEを使ってHTMLテンプレートやアプリケーション開発をして頂く際の一助としてお使い頂ければと思います。 ご不便な点や間違いなどを見つけられた際には開発チームに メール にてお知らせ頂ければ幸いです。
こんにちは、BASE株式会社 ランニング部部長の元木です。 日々、社員に運動不足解消を促す傍ら、Owners Marketingというチームでバックエンドエンジニアをしています。 さて、弊社ではソースコードを変更した際に必ずメンバー間でコードレビューを行ない、OKが出たコードだけをデプロイすることになっております。 今ではほとんどの開発現場でコードレビューを取り入れていると思いますが、読者の中には 「レビューのコメントって、どう書いたらいいのか分からない」 「こんな事を言って嫌な顔をされたり、喧嘩にならないか心配」 などと、苦手意識を持っている人もいるのではないでしょうか? そこで、今回は私がコードレビューの際に気をつけているコメントの書き方をご紹介したいと思います。 気を付けているポイントとレビューコメントの書き方の例 私は、レビューで指摘事項をコメントする際のポイントは 「いかに分かりやすく、納得感のあるコメントを書けるか」 だと考えております。 そのために、コメントは以下の順に書くようにしています。 どのように修正してほしいか なぜ、そのように修正してほしいのか エビデンス それでは、以下仮のPHPコードを例に順を追ってご説明します。 <?php /** * 引数 $phone_number が電話番号であることをチェックする。 * ただし、厳密なチェックはせず、'-'を除いた後の桁数と数字だけの文字列であることのみチェックする。 * * @param string $phone_number 電話番号 * @return bool 引数 $phone_number が電話番号ならば true。 */ function is_phone_number ( string $ phone_number ) : bool { $ phone_number = str_replace ( '-' , '' , $ phone_number ) ; $ length = strlen ( $ phone_number ) ; if ( $ length < 10 || $ length > 11 ) { return false ; } return is_numeric ( $ phone_number ) ; } このコードは実装者の意図通りに動くでしょうか? 結論を言うと、このコードにはバグがあります。それをコメントで指摘してあげましょう。 まずは悪い例から。 こんなコメントをする人はまずいないと思いますが、下手をすれば喧嘩になるかもしれません。 では、次はどうでしょうか? 間違ったことは書いていません。 なぜか、を同時に書くと親切かなとおもいます。 分かりやすくなりました。 エビデンスを示すのは、親切心のためだけではありません。勘違いなどにより、間違った指摘をしてしまうのを防ぐ目的もあります。 しかし、これを読んだレビュイーは 「じゃあ、どうすればいいの?」 と悩むかもしれません。 特にレビュイーが新人プログラマーだった場合は、そうなりやすいです。 そこで、「どのように修正してほしいか」も追記します。 これならレビュイーも悩む必要がなくなりますね。 最後に、修正方法を先頭に移動します。 最初の一文だけ読めば結論がわかるようになりました。 日本語の文章としてはちょっと違和感があるかもしれませんが、こちらの方が読み手に優しい文章だと思います。 それに、熟練のプログラマーなら結論だけで 「あ、そうか」 と気づいてくれるかもしれません。 もちろん、すべてのコメントをこのように書けるとは限りません。 問題があることは分かったけど修正方法が思いつかないこともありますし、エビデンスを示すのが難しい指摘事項などもあるからです。 そういった場合は無理せず、書けることだけをコメントするとよいと思いました。 他のレビュアーが補足してくれるかもしれませんし、大抵の場合、レビュイーはコメントをもらえるだけで十分にありがたいと思ってくれるはずです。 コードレビューはみんなの資産 コードレビューは、ぶっきらぼうなコメントですと殺伐としたり、そうなるのが嫌で億劫になりがちです。 HRTのマインドセットをお互いに持ち、コメントの書き方を工夫することで、レビューしやすい/されやすい文化が育まれ、良いコードと良いチームへ繋がっていくと思います。
こんにちは、Design Groupに所属している森( @ mrkzk )です! 年末に初めてアドベントカレンダーでテックブログデビューを果たしたのですが、新しく入社された方に「あのブログを通して、エンジニアと他部署の距離の近さ、社員同士の仲の良さが見えてよかったです」というお声をいただきまして嬉しい限りです! と、前置きはこのくらいにしておいて、実は最近 ブランドプロジェクト が始まり、ブランドポリスに就任しました! ブランドポリスって何?という部分と、ブランドポリスとして実際にやっていることのお話をしたいと思います。 ブランドプロジェクトの目的って?ブランドポリスって? ブランドプロジェクトの目的は、プロダクトを通じて実現したい未来のために、メンバーが共有すべき考え方を明確にし、それに対してメンバー全員の意識を合わせることです。 私たちが「BASE」というプロダクトによって伝えたいメッセージや体験をユーザーをはじめとするステークホルダーに届けるためには、まず情報のアウトラインを整え、そこから情報の信頼性を高めていくことが重要だと考えました。 例えば、メンバーのひとりひとりが認識しているBASEのミッションが同じであっても、アウトプットの方法が異なると、情報を受ける側のBASEに対する認識は変わってしまいます。 それはロゴの見せ方であったり、外部の方向けの資料のデザインからも伝わるものなので、体裁が整っていないと、その情報を受け取った方は「これって「BASE」の公式情報なのかな?」と不安になってしまうのではないでしょうか。。。 「これは「BASE」が発信しているオフィシャルの情報だから安心できる!」 そう思っていただくために、外部向けの資料やドキュメントはもちろん、オフィス内でしか利用しないものまで、その全てをプロダクトと捉え、メンバーみんなで自信を持って提供できるような体制とデザインを整えていきたい!そんな思いから始動しました。 そして、そのための施策を実行し、「BASE」のブランドを保持するため「ブランド毀損してませんか~~」とBASEが発信するクリエイティブを取り締まり、会社全体で自信を持って提供できるようデザインと意識を統一していこうね!と呼びかけることが私、ブランドポリスの役割です! それで具体的には何をするの?? BASEでは、営業資料など外部の方にお渡しするものはもちろん、社内利用のみであるオフィス販売のラベルも含んで全てをプロダクトとして扱う方針です。 こちらを考慮して施策を挙げてみると・・・ ブランドガイドラインの作成 カラーガイド フォントの統一 ロゴの調整、追加 スライド資料の作成 既存営業資料のクリーンナップ テンプレートの新規作成 ブランドガイドラインの社内研修 請求書、明細書、送付状デザインの統一 営業提案時のチラシや採用パンフレットのデザイン 「SHIBUYABASE」「OIOI BASE」などのポップアップのポスターやサイネージ、ポスターデータなどのテンプレ作成 ブランド毀損に該当していそうなSNSのカバーやアイコンの修正 社内クリエイティブのデザイン(オフィスコンビニのQRコードラベルなど社内販売のパネル、SNSの投稿写真に写り込んでもおかしくないものは全て) 名刺のリニューアル 管理画面のグラフィック刷新 などなど、ここにないものも含めとにかく大量・・! デザイナー3人がかりで徐々に倒していきましたが、この中で最も力を入れていた(つまり苦労した) ①ブランドガイドライン ②スライド資料 ③研修 の3つを簡単に取り上げていきたいと思います。 ①ブランドガイドライン BASEにはブランドガイドラインというものがほとんどない状態だったのでそこからのスタート・・・! ブランドガイドラインになくてはならない基本的な ⅰ.ロゴ ⅱ.カラー iii. フォントの3つガイドを作成しました。 ロゴ BASEのロゴはデザイナーが使用するにも難しいバランスで作られていました。今回、全体的にセーフティスペースを広げることで非デザイナーでも、置くだけで他の要素とのバランスも綺麗に取れるロゴに微調整してあります。 また、サービスのマルチカラーロゴは色が淡いので背景が複雑であったり写真の上に配置する際に視認性が低く、悩みのタネでしたが、これを機にステッカー風の白ふち付きロゴを新たに追加しました。可愛い! 他にも、デザイナーのみ使用OKとしたWebページフッター用の白抜きロゴなども用意しました。 カラー サービスのマルチカラーはBASEそのものを象徴する色であり、管理画面に使用されているカラーはテキストを強調するための色。これらの同じプロダクトに使用されているカラーでもそれぞれ用途が違うことなどもお話ししています。 フォント デザイナーのチームでは「BASE」のクリエイティブをつくる際にAXISという有料フォントを使用しているのですが、全社で使っていくには難しいので、よく似たニュートラルで「BASE」のイメージにぴったりな源の角ゴシックというフォントを採用しました。 ②スライド資料 BASEが社外に共有している資料は、サービス概要の紹介資料、会社紹介資料、その他「&BASE」などのプロジェクト紹介資料などがあるのですが、こちらカスタマーサクセスやMarket Developmentなどビジネス部門の方々が各自思い思いに作成してくださったものなので トンマナが揃っていない ロゴに枠線が付いているなどブランド毀損にあたる 使用PCがWindowsだったりMacだったり、使用ソフトがKeynoteだったりPowerPointだったりバラバラなので互換性が低く崩れている など改善点がいくつもありました。 使用PCがWindowsだったりMacだったり、使用ソフトがKeynoteだったりPowerPointだったりとバラバラなので互換性が低く崩れている 特に重たかったこちらの課題は、それぞれのソフトで同じ資料を作ることで解決するべく、クリーンナップを行いました。 資料の作成ツールは、下記の3つがあり Keynote(for Mac) PowerPoint(for Win)(稀にトリッキーなppt for Mac) Googleスライド 資料の種類は大きく3つ コーポレート サービス 登壇用スライド そしてスライドのサイズも標準、ワイドのそれぞれテンプレートを用意すると既存資料だけでも18個・・・!!!頑張るぞ!! と、こちらがクリーンナップした資料のビフォーアフターの一部です。(Keynoteバージョン) このようにサービスカラーのフッター・ヘッダー、 confidentialをマスターに追加して固定してあります。 そして、既存資料以外にも、誰でも新たに資料を作成、スライドを追加しやすいよう、それぞれサービスに合ったテンプレートを作ることにしました。 ここでご紹介したいのが Keynoteのテーマ作成 !!!!テンプレのテーマ作成がすごい! カスタムテーマと言って、ヘッダー、フッター、ページ番号、テキストプレースホルダー など、それぞれスライドを作成してテーマで保存すると、ローカルに落としてテンプレートを引き出せるので簡単に資料作成ができちゃうんです。 (この下に実際に動かしているGifがあります) ちょうどこのタイミングでカンファレンスなどで登壇の機会が多いエンジニアさんからこのようなご要望ありました。 このように社内でいただいたご要望に応えることもポリスの役割なので、エンジニアさん用の「BASE」感控えめの登壇資料テンプレも作成することに。 エンジニアさんの登壇資料ということで、プロフィールページを追加し、TwitterやGitHubアカウントを入れられるプレースホルダーを作成。 このようにプロフィール画像もダブルクリックでカンタンきれいに設定できちゃうんです。 (Keynoteのテーマ作成、本当に便利なのでぜひ使ってみてください!) 上記が良い例ですが、Slackに#brand_design_checkというチャンネルを設けており、いつでも「資料用のアイコンが欲しい」、「サービスカラーの可変グラフが欲しい」などのリクエストを受け付けるための環境も整えています。 ③研修 もちろん、デザインガイドラインを作り終えておしまい!ではなく、これらのガイドラインを会社の皆さんにも知っていただく必要があるので、研修を実施しました。 研修は、PRの田中(@yokotie)と一緒になって実施しました。田中には、PR視点でパブリックリレーションズとは何か?や、ブランドを保持することの意味などを話してもらい、デザイナー側では今後全社で使っていくフォントをインストールしてもらったり、今回作成したこれらのガイドラインや資料の周知、新しいロゴの使い方やスライドの追加方法、素材の紹介、質疑応答などを行いました。 チームごとに開催したので、1回60分の研修を計13回ほど行いました。BASEのメンバー全員が対象なので当然!CEOの鶴岡ら役員にも受けてもらいました! 研修と言っても終始和やかな雰囲気で、笑顔が絶えない会ばかりでした!正直はじめは照れるなあ、と思っていたのですが、でも、相談しやすいポジションでありたい!という思いから欠かさなかった「この度ブランドポリスに就任しました、森です!」の挨拶も、会を重ねるともはや照れる気持ちもどこかへいきました!さいなら! 途中雑談も交えつつ、最後までしっかりコミュニケーションを取りながらすべての研修を終えることができました。 無事、全研修が終了した日にはこれまで頑張ってきたメンバーと最高のお寿司ランチをきめました!!赤しゃりサイコー!(白目) 最後に 今回ガイドラインやテンプレートといったルールを決めたことで、メンバーから「フォントをわざわざインストールするのが面倒」、「何でもかんでもチェックしてもらわなきゃいけないのは苦痛」などマイナスの声をもらうこともあるかもしれないな、と懸念していましたが、 「確かにこれは「BASE」っぽい、これは「BASE」っぽくないがなんとなくわかるようになった」 「提案資料がすごく見やすくなった」 「迷わず簡単に資料を作れるようになるのは嬉しい!」 など本当にプラスのお声ばかりいただきました。研修中も、みなさんしっかり目を見て、表情や相槌でリアクションを取ってくれたり、受講者なのにウケを取りにいってくださる方もいらっしゃったりと、全体的にワイワイ賑やかな雰囲気で進んでいたので私も特に緊張することなく、とってもやりやすかったです。はぁ〜〜めっちゃいい会社じゃん、、と好きが溢れ落ちましたぁ。 そもそもこのブランドガイドラインはガチガチにルールで縛るものではなく、社員のみなさんが何かを作る際に”迷うことなく、サクッと時間をかけず簡単に、それなのに「BASE」らしさのあるものを制作して対外的にもアピールできちゃう!”ことが目的だったのでとても嬉しい感想でした。 今回の施策はロゴの簡単な改善や資料のクリーンナップなど、マイナスをゼロにするものが中心でしたが、今後は「BASE」への信頼を向上させるようなプラスを作る発信のサポートをしていきたいと思っていますのでどうぞよろしくお願いします!
こんにちは、CommerceDevというチームでエンジニアをやっています島田です。 このチームは、Eコマースプラットフォーム「BASE」のサービスの根幹を作る事をミッションとし、ショップオーナーの管理画面や決済機能の改善に取り組んでいます。チームができる前は決済チームのエンジニアリングマネージャー(以下EM)をやっていたのですが、いまはEMを移譲しエンジニアとして働いています。 今回はマネジャーを移譲した理由を含め僕がBASEに入社してからのチーム変化を書きたいと思います。 EMになるまで 僕が入社した当時、社内にエンジニアは10名程度でした。現在は約50名のエンジニア組織になりました。 エンジニア以外の社員も増え、それに伴ってかつて問題ではなかったことが問題になったり、これから問題になるだろう課題も抱えるようになっていきました。人が増えると組織としてやることが増えますが、エンジニアも例外ではありません。細かい事の積み重ねにより関心事が増えるとエンジニアが本当にやりたい事に集中してコミットできなくなり、結果としてパフォーマンスを十分に発揮できないという悪循環に陥ってしまいます。 それを解決するためにエンジニアとしてどういった振る舞いをするのが良いのか考えた時、今はマネージャーになりエンジニアがエンジニアとしてちゃんと力を発揮できる環境を作ったほうが良いのではないかと思いました。 EMとして考え実施してきたこと どういった制度や環境があればエンジニアが事業に一番コミットできるかを考えていました。 自分の背景がエンジニアなので、エンジニアとしてここはこうしたほうが良いと思うことを検討し、関係各所と連携して進めました。実現するためにはエンジニアだけでなく人事や労務など別の部署にも協力をお願いすることが多いので、関係各所との関係性を構築しておくのも大事だと感じました。 ここからは、EMとして考えて実施してきたことをいくつか挙げてみたいと思います。 採用 ビジネスとプロダクトと開発の課題調整 エンジニアの提供価値に対しての適切な評価 エンジニアの生産性向上・スキル向上に寄り添う 採用 組織の規模が小さかったときは各エンジニアが全体を見ることもできたのですが、組織が大きくなるにしたがって並行で進行するプロジェクトが増えたためそれが難しくなっていきました。 当初は1人のエンジニアが開発を複数かけ持ちすることもあったのですが、やはり関心事が増えると一つのことに集中しにくくなり結果的にあまり生産性がよくありませんでした。また、エンジニアが他社との折衝やテストの段取り、カスタマーサポートチームへの共有といった開発自体以外にも工数が取らていることは課題だなと思いました。 そこで、開発時の役割を細分化しエンジニアは開発に専念できるよう、工程管理などは開発ディレクターを立てることにしました。すでに社内にもいましたがエンジニアの数とのバランスが取れていなかったのと、今後さらにエンジニアが増えたときにもっと必要になると思い、組織や会社の状況を考察しながら、どういった人材が必要か検討し人事などと協力し採用を進めました。 開発現場の意見やプロダクトの成長から、今後どういった組織にすべきか、どういった人材が何人必要なのか、人事と協力しながら解決していきました。 ビジネスとプロダクトと開発の課題調整 BASEの機能開発の基点とには、プロダクトマネージャーやBusiness部門(事業開発、カスタマーサクセス、カスタマーサポート、マーケティングなど)の企画・依頼以外に、エンジニアからの課題発見や機能提案があります。 この時に、「この機能を開発してもらいたい」「こっちのほうが優先順位が高いのでは?」とグループの目標や視点の違いによって、組織の課題認識にズレが生じる場合があります。 そこでEMは全体を理解し、その時・その後も最適になるようにうまく調整する必要があると思います。 あるときにはプロダクトマネージャーやBusiness部門からの開発案件を優先し、またあるときには開発側として重要だと思うことの優先度を上げる。そのためにEMがそれぞれが納得感を得られるように調整し目標咀嚼して伝え協力的な職場をつくることに取り組みました。 時々、開発現場からの意見や課題はプロダクトマネージャーやBusiness部門とは別の観点を優先していることもあります。ですが、その課題の解決を疎かにしてしまうとふとした時に事業やプロダクトの成長の足かせになってしまいます。事業とプロダクトの長期的なビジョンをEM自身が理解納得したうえで、エンジニア個人の短期・中期・長期的な成長・変化を想像しつつ、実現するためにどういった環境にすべきか考えていきました。 エンジニアの提供価値に対しての適切な評価 EMの役割として一番重要だと思います。どんな成果物を作ったかという点に偏りがちですが、それ以外にもたくさん評価すべき点があります。例えば次のようなことも評価対象にしていました。 テックブログの投稿、カンファレンスへの登壇 技術力の向上は良いプロダクト作りへつながり、良いサービスを提供できるようなると考えています。私たちが使っているOSSやコミュニティへの貢献もできます。また、社内の別のエンジニアに対しても良い刺激になります。 レビュー時の指摘が的確、コメントが優しい 的確なレビューはそのままコードのクオリティ向上に繋がりますし、優しいコメントはレビューを依頼しやすい空気感がうまれ、心理的安全性に繋がります。また、レビューは教育的要素があるので技術の底上げにも繋がります。 自分以外の人でも分かるようにドキュメントをまとめた ドキュメントは大事な資産だと思います。開発の経緯や使い方などをきちんとドキュメントに落とし込んでおいてもらえると誰かに作業を依頼するときにも調査などの時間を削れますしミスも少なくなります。また、自分でも半年くらいすると記憶が曖昧になるので、そういったときにも役立ちます。 メンバーの普段の活動を通じてどういった価値を提供しているかをしっかり見続けて、適切に伝えていくことが大切だと思います。メンバーとの1on1や上長とのミーティング時の他、普段からピアボーナスのUniposを使ってメンバーの良かったことを伝えていました。 エンジニアの生産性向上・スキル向上に寄り添う 性能の良いPCや自分にあった椅子を推奨 技術書の購入補助 カンファレンスやテックイベントへの出席・登壇を推奨 このあたりの制度や文化はすでにベースがあったので僕の方では大きなことはしていません。もしこれから検討する場合は総務や労務の方と一緒に進めていったと思います。 組織がどう変わっていったか 組織構築の一環として採用を強化しことによりメンバーが増えました。メンバーが増えたことによってノウハウも増えましたし、メンバーが自主的に行っていた勉強会やイベント登壇などに賛同する人も増えました。 各メンバーが会社や社外に提供してくれた価値をきちんとポジティブ評価することによって流れが加速し、新しいことへ挑戦するモチベーションと技術の向上のにつながりました。 EMはメンバーが活躍できるフィールドを作り、そしてメンバーを集め、活躍できるようにフォローし、適切に評価することが大事だと思いました。 EMとエンジニア文化 EMはメンバーの評価や組織作りを通じて会社のエンジニア文化を作ることができます。良い文化ができると良いエンジニアが集まってきます。 エンジニア文化は一夜ではできないし1人で作ることは難しいです。メンバーの協力がなくては実現できないので、メンバーやEM仲間にも協力してもらいながら少しづつ積み重ねていくと良いと思いました。 一方でエンジニア文化は定期的に見直すと良いと思いました。時間がたつとその時の最適解が今の最適解ではないことが多いです。また、グループごとに培った良い文化を交換留学のように取り入れあうのも良いです。そのためにはEMはローテションさせ、定期的に客観的な視点で見直しを行うのが良いと思いました。 EMの先のキャリア 社内にはEMの先の事例がないことにも気づきました。 「プログラムを書くのは好きだけどマネージャーになってからコードを書く時間が減ってしまった。」という言葉も良く聞きます。 エンジニアからEMになった後に再びエンジニアになるというのは、正直なところネガティブな印象があるかもしれません。ただその印象を少しでも変えられたら、エンジニアのキャリアパスを広げられるのではと思っていたので、自ら実行することにしました。あわせてEMが居なくなってしまうと組織のバランスが崩れてしまうので権限委譲も合わせて行いました。 エンジニアに戻ってみて感じたこと プロダクトは日々成長していたので、再びエンジニアとして途中から開発に合流することは不安でした。 それを救ってくれたのが意外にも自分でやってきたことで、たとえばドキュメントやログをちゃんと残すことや、他の社員へのノウハウの共有を評価項目としていたおかげで調べたり聞けばなんとかなる環境ができていました。 エンジニアのためにやってきたことが正しいことだったのか、自分がその立場になることで結果検証できたのがよかったです。 おわりに 当時はEMになろうとは思っていませんでした。ただ結果的に自分のやってきたことを振り返ってみると、CTO藤川の記事にもある、 「事業、プロダクトに貢献しながら、チームのエンジニアの活躍にコミットすることで、メンバーの評価を上げる仕事」 になっていたなと思います。 (参考: エンジニアとしてワクワクし続けるためのエンジニアリングマネージャという役割分担 ) エンジニアの働きやすさというのは組織の変化や個人のライフスタイルの変化によっても変わってきますので、その時々で課題を感じた人がEMの役割を担い自分が働きやすい環境に改善していける文化があると良いのではないかと思います。 BASEではEMによるエンジニアのためのエンジニア組織の改善を日々行っています。エンジニア、EMの仲間を募集中です!もしこの記事を読んでご興味を持った方はぜひご連絡下さい。 open.talentio.com
こんにちは。 BASE BANK株式会社 でバックエンドエンジニアをやっている東口( @hgsgtk )です。 先日開催された Go Conference Tokyo 2019 Spring にて、「 Design considerations for container-based Go applications 」というタイトルで20分トークのお時間をいただきました。このエントリでは、 発表内容をどう作ったか ということについて紹介してみようと思います。 発表内容 実際に発表したスライドはこちらです。私が去年から取り組んできたサービス開発で得た実践知見を、なるべく忠実に投影した発表内容にしました。 Go・コンテナの組み合わせで開発・運用している・したい方が多いのか、当日は立ち見の方が出るくらい多くの方に参加していただき、大変感謝です。 今回は、トーク準備にあたって、どのように発表内容・構成を作っていったかについてご紹介します。 発表構成を考えるにあたって トークするにあたって、至極当たり前のことなので恐縮ですが、「トークを聞きに来る人の期待に応える時間にしたい」という風に思います。この発想を重視して、次のような流れで発表内容・構成を考えました。 「誰に役立ってほしいか」というありたい姿を整理する 期待チェックリストを作る 期待に応えるための構成・ストーリーを作る 1. 「誰にどう役立ってほしいか」というありたい姿を整理する 「自分が共有する内容はこういう人に役立つはず」というトークのありたい姿を考えます。実際、このトークでは次のように定義していました。 誰に:Go、コンテナでのアプリケーションを本番導入しようとしている方 どう役立つ:「これでいいのか?」という不安を少しでも解消して一歩進める内容にしたい 2. 期待チェックリストを作る 実際に話を聞きにきてもらう「 聴講者の期待 」・場を与えてくれる「 カンファレンスの期待 」の2点について考えて整理しました。 聴講者の期待 自分がトークする20分の時間、聞いてくださる方々の時間をお借りすることになります。全ての人の期待にしっかり応えられるかわかりませんが、なるべく多くの方にとって有意義な時間にしたいです。そのため、「 プロポーザル概要を読んで何を思うか 」について新鮮な目で見直しました。 今回のプロポーザル概要はこちらです。この概要を読んで「どんな事を話してくれそう」と期待するかをリストアップしてみます。 Go言語でのアプリケーション開発で、特にコンテナを前提とする場合の設計考慮点について話します。 例えば、Go言語でAPIを開発する場合、コンテナとして動かすことを前提とするケースが多いと感じます。コンテナベースで動かすことを前提とした場合、コンテナイメージ作成・アプリケーション監視において、考慮すべき点が出てくるでしょう。このトークでは、Go言語での実装にまで踏み込んだ上で、コンテナベースアプリケーションにおける設計の考慮点について話します。 カンファレンスの期待 トーク時間をいただくにあたって、プロポーザル審査の時間をかけていただき採択いただいています。そのため、「カンファレンスとしてどういうことが期待されているのか」について改めて見直しました。実際、公開されてる Call For Proposal のSelection Criteriaを読み直しました。 結果的に、ありたいトークの姿・聴講者の期待・カンファレンスの期待を総合的に見て、次の期待チェックリストになりました。 Goの話が聞ける 知識ではなく実践の話が聞ける 業務導入の参考にしたい方のために業務での実践の話が聞ける コンテナ使う場合に抑えておくと良い設計ポイントがつかめる その設計ポイントを実現するためのGoの実装例が聞ける 3. 期待に応えるための構成・ストーリーを作る ここまで期待を定義した上で、構成・ストーリーを考えていきます。特に今回のトークタイトルだと、「抽象的な概念の話」なのか「具体的な実践の話」なのかどちらなのかわかりずらいだろうと感じたので、 トークの課題・背景共有 を入れる方式にしました。 トークの課題・背景共有 前述したようなこのトークで伝えたい内容を定義します。「こういう話するんだな」という認識の統一を図る意図です。例を挙げると、「このトークで持ち帰ってほしいこと」とか「このトークで話すこと」といったタイトルのスライドのことですね。 また、実例系の話の場合、誰がどのような現場で実践したのかという前提があると参考にしやすいと思っています。そのため、Goへの習熟度・アプリケーション規模などの背景を抑えるための自己紹介・会社紹介を入れました。 プレゼンの準備 事前の練習 恥ずかしながらこれまで何度かカンファレンスで話させていただいていますが、脳内シミュレーションのみを行っていて、事前の社内プレゼン練習はしていませんでした(社内で話すほうが緊張するといった理由で避けていたり・・・)。今回は、1週間前に同僚に練習を見てもらってフィードバックをもらい、内容をブラッシュアップしました。 練習することで、よりわかりやすい構成や見えにくいスライドの改善など、より伝わりやすい表現を模索するきっかけに繋がりました。 道具の導入 プレゼン自体に向き合ってみようということで、ずっと二の足を踏んでいたlogicoolの Spotlight を導入しました。 www.logicool.co.jp 遠隔でスライドを操作したり、ポインタで画面を拡大したりするものです。Spotlight自身がタイマー機能を持っていて適宜バイブレーションで残り時間を伝えてくれたり便利です。一番、大きい点としてPC操作から離れられる点でした。PCから離れて壇上中央寄りに立つことで、聴講者の方々の視線・顔が見えるので、 伝える ことに意識を向けようとする効果がありました。 発表を終えて 実際、全員の参加者の方の期待に添えた内容を伝えられたかは分かりませんが、Twitter上では次のような反応をいただけてひとまず安心しています。 コンテナアプリケーション設計方針、具体的なノウハウが詰まっててとてもためになった #gocon #gocon_a — nosukeru (@ey_nosukeru) May 18, 2019 基本が忠実に押さえられてて、最初の一歩にちょうどいい感じのトークでした。 #gocon_a #gocon — チェシャ猫 (@y_taka_23) May 18, 2019 なかなか個人でここまで気にした開発運用はできないのでこういう場か業務でしか得られない知識だ #gocon #gocon_a — むさしん (@musaprg) May 18, 2019 Design considerations for container-based Go applicationsを聞いてる。 @hgsgtk さんの発表慣れがすごい #gocon #gocon_a — po3rin (@po3rin) May 18, 2019 昨年の Go Conference 2018 Spring に聴講者として参加してから、セッション登壇する(できるくらいGo力を上げる)ことがひとつの目標だったので、今回その目標を達成できてよかったです。 また、スピーカー特典でGopherくんの人形もらえて嬉しかったです。社内のデスクに飾ってます。 Gopher君かわいい ただし、Go力はまだまだ足りないので、レベルアップしてまた次のカンファレンスでお会いできるように精進します。 Next Go Conference 2019年7月13日(土)に Go Conference'19 in Fukuoka が開催されます。 fukuoka.gocon.jp 私も 「 Cost-effective Go unit test thinking and practices 」というタイトルで同じく20分お時間頂いています。ユニットテストの基礎的な考え方・Go特有のアプローチ・実践例について紹介します。ぜひ、福岡でお会いしましょう!
こんにちは、BASEの次世代管理画面プロジェクトでデザインを担当している小山です。 ネットショップ作成サービス「BASE」は2019年2月に、商品管理ページをリニューアルしました。 今回は商品管理ページをリニューアルして、再検討が必要になってしまった機能にどう向き合ってきたかをお伝えできればと思います。 「次世代管理画面プロジェクト」がどのようなコンセプトのプロジェクトであるかは、過去のアドベントカレンダーで早川が書いた記事がありますので、そちらをご覧ください。 devblog.thebase.in 次世代商品管理ページリリース まずは2月にリニューアルされた商品管理ページの Before / After を紹介します。 リニューアルのポイント 今回のリニューアルでは、主に以下の点を変更しました。 スマートフォンファーストなデザイン 新機能(商品の複製、一括削除、一括公開/非公開設定)を追加 検索・絞り込みの強化 商品登録の整理 コンポーネント刷新 リリース後の反応 今回の商品管理ページのリニューアルはインパクトの大きいリリースとなり、リリース後は良い反応から悪い反応まで様々なフィードバックをいただきました。 5年以上続いているサービスのUIをリニューアルしたので、「使いにくくなった」「前の方がよかった」という声はある程度覚悟していましたが、今回のリニューアルで最も多くフィードバックを頂いたのは、ページャーと並び替え機能でした。 リニューアルでページャーと並び替え機能に加えた変更 BASEのサービスが成長するにつれショップの規模も大きくなり、登録商品数は増加傾向にあります。 リニューアル前は登録商品数が多くても100件程度を想定して無限スクロールを採用していました。しかし、登録商品数が100件を超えるショップが多くなり、無限スクロールでは、全体数の把握のしにくさや該当商品へのたどり着きにくさ、商品編集後のページ保持が困難であることなど、不便な状況が多くなってきました。この問題を解決するため、今回のリニューアルではページャーを採用しました。 次に、商品の並び替えについてです。 リニューアル前は、リストの一番上にある商品を一番下に移動する場合、ドラッグで並び替える方法しかなく、商品数が多いショップの場合、複数回のドラッグ操作が必要でした。そのため、数値を入力して並び替えができる機能を追加し、移動距離の多い並び替えを簡単にできるようにしました。 フィードバックの例 ページャーと並び替え機能をリニューアルしたことで、実際にユーザーから頂いたフィードバックの例としては下記のようなものがありました。 「並び替えを終了する」ボタンがページの一番下まで行かないと押せないのがめんどくさい 20個区切りでページが分かれてるのが大変、せめて100個とか選べるようにしてほしい ドラッグで並び替えたいのに移動先が次のページになってしまって移動できなくなった 数値で並び替えができるけど、毎回移動先の順番を確認するためにページを行ったり来たりするのが大変 ページごとに区切られたせいで全体の並びが確認できず使いにくい 前の管理画面に戻してほしい(せめてページ分けではなく無限スクロールにしてほしい) フィードバックを元にどう改善していくか これらのフィードバックを受けて、旧デザインの商品管理に戻すという判断はしませんでした。次世代管理画面プロジェクトは「これからの5年を支える」という目的で進めてきたので、ユーザーの声から新デザインの問題点を整理して、旧デザインのよかったところを新デザインに追加していくことで、前に進みながらUI/UXを改善していく方針をとりました。 まず、並び替え機能に関しては、小さな改善を段階的にリリースをすることで、すばやく改善をすることにしました。はじめに、1ページあたりの商品数を増やし、「並び替えを終了する」ボタンを見直しました。 また、特に要望の多かった「ドラッグで並び替えたいのに移動先が次のページになってしまって移動できない」という問題は、並び替え機能とページャーの両方に関係しています。そのため、プロダクトマネージャーやエンジニアと一緒に議論し、まずはPC側の開発を優先して素早いリリースを目指しました。 PC並び替え機能リニューアルリリース ユーザーさんから頂いたフィードバックを元に以下の改善を加えました。 並び替え専用ページを作成 商品管理ページはページャーのまま、並び替え専用ページは無限スクロールを採用 並び替え終了ボタンを下の方に配置しセンター表示にすることで見慣れたレイアウトに変更 また、画面下部に固定配置させることでボタンのコンポーネントを変更させずに目立たせた 1ページあたりの表示商品数を増やせるグリッド表示の切り替えを追加 表示切り替えを追加したのでドラッグで並び替えと数値で並び替えを1画面内でできるように変更 並び替え専用のページを作成しページ遷移をさせることで不要な情報はすべて非表示に まとめ 長年使われてきたデザインをリニューアルすると、使い慣れたユーザーからはネガティブなフィードバックがくることがあります。その際に、旧デザインに戻すのではなく、フィードバックと旧デザインを元に、新デザインをより使いやすく改善していくことが重要です。 その場合、新デザインの改善は細かくリリースして、なるべく早くユーザーに価値を届けていくことが大切だと感じました。 「次世代管理画面プロジェクト」では、これからもユーザーの声を聞きながら「これからの5年を支える管理画面」を目指して開発を進めて行きます。今後はユーザーインタビューやユーザーテストの実施なども予定しています。 最後に、BASEではUXデザイナーを募集しています。 この記事を読んで興味が出たという方は以下よりご連絡ください。 open.talentio.com
こんにちは。SREチームの山根( @fumikony )です。 このブログでも東口( @hgsgtk )が何度か紹介している即時資金調達できる金融サービス「 YELL BANK(エールバンク) 」のインフラまわりに関わっています。 今回は、YELL BANKのデプロイメントパイプラインを構築したときの工夫などを紹介します。 インフラ構成 インフラ構成図 まず大まかなインフラ構成について説明します。上の図は構成図です。 YELL BANKではGo言語でAPIサーバを開発しており、ビルドしたコンテナをECSのFargateモードを使って動かしています。 コンテナレジストリにはAWSのECRを使っています。 また複数AWSアカウント構成をとっていて、本番・ステージング・開発の各環境ごとに個別のAWSアカウントを用意しています。 今回のデプロイ機構ではこれらの環境のうち本番環境(prd)およびステージング環境(stg)を対象としました。 GitリポジトリにはGitHub、CIにはCircleCIを使っています。 デプロイ ECSデプロイツールには kayac/ecspresso を採用しました。 GitHub上のmasterブランチへのマージをトリガーとして、CircleCI内からecspressoを実行することでECSへのデプロイを実現しています。 以下、このデプロイ機構について説明していきます。 ecspressoについて ecspressoはGo言語製のECSデプロイツールです。 今回ecspressoを採用した理由は主に2つあります。 1つは、 aws ecs describe-task-definition で出力されるjsonを、そのままecspressoで使うことができるという点です。これによって、まずECSのマネジメントコンソール上で試行錯誤してタスク定義を作り、それをそのままecspressoで使うという事ができます。これはECSの経験が浅い身としてはとても便利でした。 もう1つはテンプレート機能の存在です。これは、タスク定義のjson内に {{ env `FOO` `bar` }} という記述があると、その部分を環境変数 FOO で置き換えるというものです。 bar は FOO がなかった場合のデフォルト値です。また、 {{ must_env `FOO` }} という記述の場合は FOO が無いとエラーになります。 この機能を使って、タスク定義内部で以下のように記述しました。 taskdef.json { " taskDefinition ": { " containerDefinitions ": [ { " name ": " example ", " image ": " {{must_env `AWS_ACCOUNT_ID`}}.dkr.ecr.ap-northeast-1.amazonaws.com/basebank/example:{{env `D_TAG` `latest`}} ", これによって2つのことが実現できました。 環境変数 D_TAG によって、dockerイメージのタグをデプロイ実行時に指定します(省略時は latest )。 環境変数 AWS_ACCOUNT_ID によって環境ごとの差を吸収します。こうすることで、prdとstgのタスク定義を一括で管理できます。 なお、これらの機能はecspressoの README で説明されているので、あわせて参照いただければと思います。 CircleCI設定 いきなりですが、今回作成した .circleci/config.yml です。縦に長いですがご容赦ください。 .circleci/config.yml # https://circleci.com/orbs/registry/orb/circleci/slack # https://circleci.com/docs/2.0/env-vars/#using-bash_env-to-set-environment-variables version : 2.1 orbs : slack : circleci/slack@2.0.0 commands : install_awscli : steps : - run : | sudo apt-get install python-pip sudo pip install awscli setenv_docker_tag : steps : - run : echo "export DOCKER_TAG=${CIRCLE_SHA1:0:8}" >> $BASH_ENV setenv_stg : steps : - run : echo "export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX" >> $BASH_ENV - run : echo "export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_STG" >> $BASH_ENV - run : echo "export ECR_ENDPOINT='yyyyyyyyyyyy.dkr.ecr.ap-northeast-1.amazonaws.com'" >> $BASH_ENV setenv_prd : steps : - run : echo "export AWS_ACCESS_KEY_ID=YYYYYYYYYYYYYYYYYYYY" >> $BASH_ENV - run : echo "export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_PRD" >> $BASH_ENV - run : echo "export ECR_ENDPOINT='zzzzzzzzzzzz.dkr.ecr.ap-northeast-1.amazonaws.com'" >> $BASH_ENV jobs : test : docker : - image : circleci/golang steps : - checkout # (略) build : ## (B) docker : - image : circleci/golang steps : - slack/notify : message : "begin build" - checkout - setup_remote_docker - install_awscli - run : name : docker build command : | make build - setenv_docker_tag - setenv_stg - run : name : stg docker tag & docker push command : | $(aws ecr get-login --no-include-email --region ap-northeast-1) docker tag "basebank/example" "${ECR_ENDPOINT}/basebank/example:latest" docker push "${ECR_ENDPOINT}/basebank/example:latest" docker tag "basebank/example" "${ECR_ENDPOINT}/basebank/example:${DOCKER_TAG}" docker push "${ECR_ENDPOINT}/basebank/example:${DOCKER_TAG}" - setenv_prd - run : name : prd docker tag & docker push command : | $(aws ecr get-login --no-include-email --region ap-northeast-1) docker tag "basebank/example" "${ECR_ENDPOINT}/basebank/example:latest" docker push "${ECR_ENDPOINT}/basebank/example:latest" docker tag "basebank/example" "${ECR_ENDPOINT}/basebank/example:${DOCKER_TAG}" docker push "${ECR_ENDPOINT}/basebank/example:${DOCKER_TAG}" deploy-stg : ## (C) docker : - image : circleci/golang steps : - slack/notify : message : "begin deploy-stg" - checkout - setup_remote_docker - install_awscli - setenv_docker_tag - setenv_stg - deploy : name : deploy-stg command : | make deploy-stg D_TAG=$DOCKER_TAG - slack/status deploy-prd : ## (C) docker : - image : circleci/golang steps : - slack/notify : message : "begin deploy-prd" - checkout - setup_remote_docker - install_awscli - setenv_docker_tag - setenv_prd - deploy : name : deploy-prd command : | make deploy-prd D_TAG=$DOCKER_TAG - slack/status workflows : ## (A) version : 2 test-build-deploy : jobs : - test - build : requires : - test filters : branches : only : master - deploy-stg : requires : - build filters : branches : only : master - slack/approval-notification : message : 'prdにデプロイするにはApproveが必要です' mentions : '<!here>' requires : - deploy-stg filters : branches : only : master - approve-deploy-prd : type : approval requires : - deploy-stg filters : branches : only : master - deploy-prd : requires : - approve-deploy-prd filters : branches : only : master 以下、工夫したポイントを解説していきます。 (A): workflows デプロイの流れが test-build-deploy というワークフローに定義されています。 GitHubのmasterブランチにfeatureブランチがマージされると、以下のような流れでデプロイが進んでいきます。 テスト ビルド stgへのデプロイ Manual Approval prdへのデプロイ Manual Approvalというのは CircleCIの機能 で、ワークフローの次のjobに行く前に手動による承認を要求するというものです。 これをワークフローに挟み込んでおくことで、stgでの確認を終えるまでprdへのデプロイを待たせることができます。 また、ワークフロー内に slack/approval-notification というものがありますが、これは CircleCIのSlack Orb を利用したもので、以下のようなSlack通知を簡単に出すことができます。( @ が重なっているのは、Orbが @here に対応していないところに強引に入れたため) Slack Orbによる通知 (B): build このjobでは、docker build、docker tag、docker pushを行っています。 この際、stgで動作確認したイメージそのものをprdにもデプロイしたいので、同一job内でstgとprd両方のECRに対してdocker pushしています。 また、dockerのtagとしては、gitのコミットハッシュの先頭8桁を使うようにしました。こうしておくことで、どのコミットからビルドされたイメージなのかわかります。 (C): deploy-stg, deploy-prd 各環境へのデプロイを実行するjobです。 具体的なデプロイコマンドはMakefileにラップして、例えばstgであれば make deploy-stg D_TAG=$DOCKER_TAG のようにしています。この D_TAG というのはecspressoに渡すための環境変数です。 Makefileのターゲットとしては以下のようになっています。 deploy-stg: bin/ecspresso AWS_ACCOUNT_ID=yyyyyyyyyyyy \ ./bin/ecspresso deploy --config=config/stg.yml deploy-prd: bin/ecspresso AWS_ACCOUNT_ID=zzzzzzzzzzzz \ ./bin/ecspresso deploy --config=config/prd.yml Makefileにラップしておくことで、いざというときには手元からもデプロイしやすくなっています。 おわりに CircleCIとecspressoを用いて、ECSへのデプロイメントパイプラインを構築しました。 しばらく使ってみるうちにいくつか気になるところも出てきたので、引き続き改良していこうと思っています。 また、今回ひととおりのECSデプロイを組んでみて、ECS自体にも慣れることができました。 次の機会があればCodePipelineによるBlueGreenデプロイメントを使うパターンなども試してみて、今回作ったものとの比較できればと考えています。そのときにはまた本ブログで紹介しますので、お楽しみに。
こんにちは! この度、3/29(金)から3/31(日)に開催された PHPer Kaigi 2019 にて、BASEがゴールドスポンサーとして協賛&3名のメンバーが登壇いたしましたので、今回のそのレポートを書いていきたいと思います! 会場レポート 今年の会場も去年と同じく 練馬区立区民・産業プラザ Coconeriホール にて開催されました。入り口ではロールアップバナーが出迎えてくれます。 アイキャッチ画像にもありますとおり、本当にたくさんPHPerたちが集まっていました。「同窓会のようなカンファレンスにしたい」という実行委員長の言葉もあって、PHPerたちが楽しみながら互いに交流を深める仕掛けがたくさんあり、あちこちで盛んな交流が行われていました! トークの採択を通して選ばれた登壇者による発表ももちろん、アンカンファレンスによる突発的な発表、IRT(Interactive Round Table)による相談会(こちらも突発的なものがありました!)など、「主催者側がコントロールしてない突発的なイベントが発生してしまう」ほど練度の高いエンジニアが集まり、思う存分技術談義が楽しめるような圧倒的空間でした!(もちろん楽しいですよ!)同時にすごいエンジニアたちがこれだけ集まるのだからと、PHP界隈の盛り上がりを感じずにはいられません。 そんなPHPer Kaigiに、今回弊社はゴールドスポンサーとして協賛させていただき、3名のエンジニアが登壇いたしました! 登壇スライド 「質」の良いユニットテストを書くためのプラクティス by 東口和暉 BASE BANK株式会社 Dev Divisionでソフトウェアエンジニアをやっている東口( @hgsgtk )です。 私は、ユニットテストに関心が強く、最近のカンファレンスではユニットテスト関連の話をしているのですが、今回もユニットテストの話です。 以前、 PHPカンファレンス2018 にて、 PHPバージョンアップと決済リプレイスを支えたユニットテスト というトークで、 テストの量 を増やしていった過程を話しました。今回のトークは、 テストの質 に焦点を当てたものになります。 仕事の現場で発せられる「テストの質」という言葉について「その本質・意味はなんなんだ」というなにやら壮大なテーマをモヤモヤ考えていました。途中のいくつかのカンファレンス・勉強会・ブログでのアウトプットを通じて少しずつ考えを整理していって、30分で話せる内容にまとめました。 それなりに壮大なテーマを発表したので少し反響が不安だったのですが、聴講者の方から「わかりやすかった」などの良い反応を頂いたり、はてぶやTwitterでもたくさん拡散していただいて、トーク採択から3ヶ月間、考え抜いてまとめたものが多くの人に役立つものになったことに安堵しています。また、会場で公開収録されていた PHPの現場 28. ファミコンで理解する DI(ytake) でもトークを紹介していただいてとてもありがたい限りでした。 特にアウトプットしてよかったと感じているもう一つの要素として、会場内での質問やAsk the Speakerによって多くの議論ができたことが挙げられます。せっかくなのでその際の内容を共有します。 質問・Ask the Speakerでの議論 質問:それでもprivateメソッドに対してテストしたいと思った時どうするか 「privateメソッドに対してもテストしたい時があり、テストしないということにもやもやを感じる」という疑問がありました。これについてその後のAsk the speakerにて議論なども踏まえて、3つの観点でまとめます。 1. private methodを切り出す選択肢 「privateメソッドをテストしたい」と思った時点で、そのメソッドは責務を持っていることが考えられます。そのため、「privateメソッドをテストしたい」と思った時点で別クラスへ切り出すなど設計の検討をする必要があるかもしれません。 2. どの視点を前提とするか 「privateメソッドをテストしない」という主張の根底には、オブジェクト指向という視点が前提にあり、手続き型的に考えると可視性はprivate修飾子で明示した上で、privateメソッド内の手続きはテストしたいという考え方もあるというフィードバックをいただきました。 たしかに、プログラム開発をどういう視点でみるかによってここの考え方は変わるポイントだなと感じたと共に、「プロジェクトとして何を大事にするか」によって判断が変わる可能性がありますね。 3. 変更の頻度をどこまで気にするか 「privateメソッドをテストしない」という主張の根拠として、privateメソッド自体の不安定さをあげました。しかし、テストを書いている以上、「しっかり落ちてほしい変更」もありますよね。この点に関して、落ちてほしい変更というものがある中で、どういう変更を「変更の頻度が高い」と捉えるかについての質問がありました。 オブジェクト思考の考え方の延長線上として、テスト対象をブラックボックスと捉えた上で、外部への振る舞いをテストで保証し、その振る舞いの内部で行われている処理詳細についてはテストでは検証しないという考え方が前提にあると解釈しています。 その解釈を前提とした場合、変更には「外部に対する振る舞いを変えるもの」と、「そうではないもの」という2種類が存在します。前者の変更はシステム全体の欠陥になりうるため「しっかり落ちてほしい」反面、後者の変更は「内部の処理詳細」の変更に対して落ちることになるので、「落ちてほしくない」ものと捉えられると思います。 つまり、privateメソッドの実装は、「内部の処理詳細」を担っているケースが多いため、「privateメソッドは極力テストしない」というふうに説明させていただきました。 どこまでモックするか 「不安を軽減するためのテスト」と考えると、AWS S3など外部サービスをモックせずに直接テスト対象に含めて不安を軽減したいという気持ちがあるという考え方をフィードバックとしてもらいました。これは、 PHPの現場 28. ファミコンで理解する DI(ytake) でも話題に上がっていましたが、「どこまでをテスト対象とみなすのか」・「何をテストしたいのか」といったテストに対する要件から、テストの不安定さ・速度の低下といったデメリットなど様々な考慮事項を踏まえて、総合的に判断しないといけない部分で難しいポイントですね。 まだまだ、言語化できていない領域がたくさんあるので、これからも精進して継続してアウトプットしていこうと思います。 PhpStormでコードを理解する技術 by 田中孝治 BASE Product Division で技術基盤の整備を担当している田中 ( @tenkoma ) です。 今年初めくらいにアプリケーション開発をより容易にするため、ユニットテストをPhpStormから実行できるようにしましたが、PhpStormを使ってコードを理解するために様々な機能を使ってきたと思い、そのノウハウをまとめて発表しました。 今回の発表ではIDEでコードを理解するための技法を4つに分類したのが成果かな、と思っています。 単方向依存を実現する静的解析ライブラリのご紹介 by 川島慧 田中と同じくBASE Product Divisionで技術基盤を担当している川島( @nazonohito51 )と申します。 今回は自作していた静的解析ライブラリのご紹介をさせていただきました(BASEのプロダクトではまだ使ってませんが、機会を見て導入していきたいと考えています)。元々15分相当の内容を5分に凝縮しているため「マシンガントーク」とか「いつ息継ぎしてるんだ」とか色々言われました(笑) シンタックスの強化やPhpStormの影響で近年のPHPソフトウェアは静的構造を持つようになってきた時代であることを背景に、どうすれば設計に意識を持ってもらえるか、どうすれば設計者の意図を表明できるか、ということを考え続けた結果生まれたライブラリです。PHPという言語がサポートしてくれない領域を静的解析による力技でカバーしようとしているのですが「そうだよこれこれ、これが欲しかったんだよ」と、ありがたいことに会場内の沢山の人に興味を持ってもらえて、何人かの方の参加レポートでも取り上げていただけました。引き続き機能を拡張して、開発チーム全員が同じ設計指針を共有して開発できる環境づくりを支えるライブラリにしていきたい所存ですのでよろしくお願いいたします。 まとめ 3日間開催というおそらく開催期間という意味で国内最大のPHP系カンファレンスにもかかわらず、トラブルもなく大変実りある時間を過ごすことができました。大量のCFPへのトーク応募が殺到する中、3名もの登壇者を送り出すことのできた弊社としましても、今回のカンファレンスを大変意義深く感じております。実行委員長の長谷川様( @tomzoh )をはじめ実行スタッフの皆様方、登壇者の皆様、スポンサー企業各位、もちろん聴講者の皆様方にこの場を借りて御礼申し上げます。
こんにちは、 BASE BANK株式会社 でソフトウェアエンジニアをやっている東口( @hgsgtk )です。 さて、Eコマースプラットフォーム「BASE」は、2019年3月29日(金)から3/31(日)に開催される「 PHPer Kaigi 2019 」にゴールドスポンサーとして協賛します。 PHPer Kaigiへは昨年に引き続き今年もスポンサーをします。昨年のようすは こちら をぜひご覧ください。 今年のPHPer Kaigiは、 PHPerチャレンジ という企画など盛りだくさんの内容で、参加するエンジニア一同とても楽しみにしています。 また、BASEから3名のメンバーが登壇予定です。 3/29(金)17:55~ Track A レギュラートーク 30分「 「質」の良いユニットテストを書くためのプラクティス 」  スピーカー:東口 和暉( @hgsgtk ) 3/31(日)11:25~ Track B レギュラートーク 15分「 PhpStormでコードを理解する技術 」  スピーカー:田中 孝治( @tenkoma ) 3/31(日)16:05~ Track A LT「 単方向依存を実現する静的解析ライブラリのご紹介 」  スピーカー:川島 慧( @nazonohito51 ) 当日ご参加される方は、ぜひ登壇を聞きにいらしてください! #BASE_PHP_Yatteiki
出典: https://unsplash.com/photos/36Vbwo1OiZU BASEでData Strategyチームのマネージャーをしている鈴木僚です。 Data Strategyチームのミッションは、データを使ってプロダクトを成長させ、戦略的に事業を推進させることです。 EC事業では、オーナーズ(ショップオーナー)・購入者・社内メンバーの3者からなる膨大なデータが日々蓄積されています。Data Strategyチーム(以下、DSチーム)では、その3者に対して、より良い意思決定ができるよう機械学習を活用したソリューションを提供しています。例えば、直近ではオーナーズがより簡単にショップ運営ができたり、ショップと購入者のマッチングをより適切なものにしていくことに取り組んでおります。また、安心して購入者の方々にショッピングを楽しんでいただけるように商品の品質の自動チェックも始めております。 中長期的には、プロダクトだけでなく経営戦略、事業戦略など会社全体でデータを使った意思決定ができるようにすることを目指しています。 チーム設立から1年が過ぎ、組織としてのアウトプットも安定してきたため、今回はチームビルディングをどう進めてきたか、時系列順に共有したいと思います。 目次: Phase 0 チームを作る前にすべき事 Phase 1 チーム発足、ミニマムスタートを最速で Phase 2 レコメンドモデル(ショップ教えるくん)リリース Phase 3 学習モデル作成とパーソナライズ Phase 4 マイクロサービスアーキテクチャと本格稼働 Phase 5 属性情報を取得 Phase 6 BASE BANK Phase 0:チームを作る前にすべき事 まだ、自分一人しかいない状態。 周りのチームはもりもりビジネスを進めているので、焦りを感じます。この焦りをうち消すためにも、事業のゴールに対して現状・課題・理想をなるべく早く掌握する事がキーとなります。 *1 *2 Phase 0 チーム発足前 このフェーズで実施したのは以下の通りです。事業規模にもよりますが、心理的に2週間位で終わらせたいです。 このフェーズでやるべきこと: 現状のシステムを把握する(何がどこにあって、何をしている?) 組織のビジョンと、ゆるいロードマップを作る ビジョンに賛同してくれる人材の募集 チームメンバーの募集 チーム方針を決定したら、その方針に賛同してもらえそうなエンジニアを社内外から集めることになるかと思います。 データ戦略を司るチームを立ち上げるポイントとしては、以下の経験者がなるべく初期の段階で揃うことかと思ってます。 ビジネスプランナー 機械学習エンジニア データアナリスト また、マネージャーに求められる役割としては、このあたりが重要かと考えてます。 ビジネスモデルとコストマネジメントはマネージャーが受け持つ 集中出来る環境:外部からの突発タスクはなるべくマネージャーが拾う 相談を自由にできる雰囲気づくり(メンバーからの相談を求めるだけではなく、相談しやすいチームメンバーの環境構築にもマネージャーの力量がかかってます。) 良い道具、良い開発環境、実力の発揮できる時間の提供 前処理がされた、質の良いデータの準備 得意なことは得意な人に任せる、任せられる雰囲気づくり 成長の機会の提供:論文・資料・勉強会・学会、input出来る機会は全力で応援する・すべき Phase 1 : DSチーム発足、速度優先でミニマムスタート 社内のBI環境を構築したメンバーが加わり、過去の施策内容にグッと迫る事ができるようになりました。 Phase 1 チーム発足時の状態 準備運動なしに全力疾走すると足がつるのと同じように、ビジネス案件を実施する前に、必要最低限の環境を揃えます。とはいえ、組織として社内的信用は無なので、組織イメージが社内で固まる前にアピアランスを上げる努力が必要となります。すなわち、 本番にデプロイできる何かを作る 。どのような業務であっても過去に頓挫したタスクが存在するので、これらの中から優先して探します。なぜなら、以下のような事が事前に分かっているからです。 既にニーズの検証は行なっている 期待される効果もわかる なぜ止まったかもわかる 検討した結果、DSチームの最初のタスクは、アプリ内における おすすめショップのリコメンド に決定しました。前提の共有ですが、アプリとは、ネットショップ作成サービス「BASE」で開設された70万のショップがすべて集まるショッピングアプリです。それまでアプリ内の「おすすめショップ」は、ショップのキュレーションを担当する社内のメンバーがマンパワーでピックアップしていました。 ニーズ キュレーターによるレコメンドはキュレーターのセンスに左右される 担当キュレーターが休むと、レコメンドが止まる 期待される効果 CTRが上がる→CVRも上がる→GMVに繋がる なぜ止まったか 分析まで行ったが、実装する機械学習エンジニアがいなかった このフェーズでやるべきこと: ミニマムスタート 必須の環境作り 前処理とログ取得がきちんとできる環境を作る 効果測定ができる環境を構築する 基本的な開発環境が整う チームのアピアランスを上げる 本番にデプロイできる何かを復活させる これで、アウトプットを生み出す状況が整いました。 Phase 2:レコメンドモデル(ショップ教えるくん)リリース 既存の仕組みが存在する場合、担当チームとの意識合わせと共感が成功に結びつきます。 キュレーターが所属しているチームとレコメンドの目的や背景、そしてチームが持つ価値観の共有と共感した上で、既存のオペレーション内容と効果測定基準をヒアリングし、数値目標を定義しました。 Phase 2 レコメンドモデルのリリース この段階から徐々にキュレーターの業務内容に影響してきます。具体的には、冒頭に触れた3者向けのコンテンツ育成やブランディング等、より人と人とのコミュニケーションが重要となる業務が中心となっていき、全体を俯瞰する業務になってきます。一方、機械学習が活躍する分野の一つとしてパーソナライズがあり、その部分についてはDSチームが担当することとなりました。言うなればセンスと数字の分業と考えています。 実際、今後このような形で人間と機械(ロジック)がそれぞれ得意なタスクに分かれて業務が進行していくかと思います。とはいえ、一方で今まで人が担当していた部分なのでロジックを擬人化してみました。 擬人化したレコメンドモデル その時の紹介文がこちら: ショッピングアプリBASEのおすすめのショップ枠で修行させていただくことになった、『ショップ教えるくん』です!全アプリユーザーのお気に入り、フォロー、購入データから、あなたが好きそうなショップを考えて選びます! まだ選んだショップをフォローしてくれて嬉しい!というポジティブな感情しかないので、選んだのに無視された、、などのネガティブな感情には対応できてませんし、24時間に1回しか勤務できませんが頑張るのでこれからよろしくお願いします。 結局、 ショップおすすめ君 とか おすすめショップ君 とか名前をちゃんと覚えてもらえませんでしたが、ひとまず社内で何をやっているのかは周知できました。 このフェーズでやるべきこと: 本番環境の環境構築 最初は計算結果をバッチでDBに格納する DB・サーバーサイド・アプリケーションチームとの連携をしっかりと取る 実装と効果検証 導入した結果、タップ率は従来に比べ4倍以上に向上しました。 Phase 3:学習モデル作成とパーソナライズ 成功事案ができると、チーム的には、組織の仕組み チョットワカル の段階に入ったともいえます。ですが、急に前が開ける段階が来るまでは、類似手法で改善できる箇所を探しつつ、バッチ処理とサバイバルコードからの脱却を目指します。 また、それまでサービスドメインに適応した基礎データ、例えば単語辞書を作成していなかったので、このタイミングで整備するようにしました。 devblog.thebase.in 伸ばすとどこか歪むので見つける、治す この頃からBatch処理におけるデータ転送量やDBへの負荷が高すぎて本番系に悪影響が出始めるようになってしまいました。また、似たような処理を行うインスタンスも増えてきました。 ここでメンバーが増えたので、バッチ処理を学習済モデルを用いてAPIで必要な時に都度計算する方式に置き換えてDBへの負荷を減らし、あわせておすすめ商品、関連商品など、複数のサジェストの実施できる環境を構築し始めました。 Phase 3 学習モデル作成とパーソナライズ パーソナライズの開始 学習モデルの特性として、よりセグメント化されたデータの方が精度が良くなります。セグメントも含めて最初から推定する方法もありますがあまり精度は良くありません。それよりは一人一人におすすめ出来るパーソナライズという目的があるのであれば、各ユーザー様に直接確認するのが一番早い、ということで、アプリユーザーに対してチュートリアルの際に性別と興味のあるジャンルを伺うように変更しました。ありがたいことに、相当数の方に答えていただいているため、パーソナライズの基礎を構築することができました。 このフェーズでやるべき事: コードが本番に出た時に、問題が起こりそう、もしくは発生している時に、成果物自体が何を目指していたかを復習する 成果物は会社の利益になるか、数字で説明しようと思ったらできるようにしておく。即座に数字にする必要はない。逆に数字目標だけおうと、必ずサバイバルコードができて、後で倍苦労する サバイバルコードを廃止し、学習済モデルを使用する形に変更する レコメンドのロジック改善(学習モデルもパーソナライズ化) 効果測定結果の理論的な説明 このあたりで改めて機械学習チームにおける環境構築の経験と測定結果の正当性がきちんと把握できるメンバーが不足している事が改めて感じられたので、募集内容の変更を行いました。このように特にチームの規模が小さい段階ではチームの状況に応じて募集要項をこまめに変更することは重要だと考えていますし、実際に募集要項をこまめに変更している会社も多いように感じます。 Phase 4:マイクロサービスアーキテクチャ化と安定稼働 さらに新しいメンバーが増え、AWSのサーバレス環境へ完全移行しました。 Phase 4 マイクロサービスアーキテクチャと本格稼働 また、Terraformを用いてインフラの構築、変更管理を安全にかつ効率的に行える仕組みを導入しました。Terraformは比較的最近リリースされたAWSコンポーネントにも対応しているため、新しい機能を追加する際もほぼほぼ問題ない状態です。 *3 また完全移行したことによって、DS AWSと呼んでいる独自環境が誕生し、本番系環境とは基本APIを介してデータをやりとりするようになりました。このあたりはチームメンバーの氏原の記事が詳しいです。 devblog.thebase.in それに伴い、データ周りも分析やモデル作成用途のものはDS AWSに保管するように変更し、大量データがあっても自分たちで負荷コントロールできるようになりました。 そこで、本番系では躊躇していた画像データの分析を開始し、関連商品のサジェストに画像とテキストの組み合わせたモデルを使用するようになりました。こちらによる回遊性は非常に効果が高かったです。 自分たちの責任で環境を何度も再構成できるということの恩恵に、発表されたばかりの論文やロジックの検証も手軽にできるようになりました。実際の例として、こちらの記事にあるようなモジュールをいち早く本番運用に適用することができました。 devblog.thebase.in このフェーズでやる事: サーバレスへの完全移行 インフラの整備 本番環境と分離I αやβのモジュールを採用する勇気 Phase 5:テキストや画像の属性の取得 パーソナライズが進んでくると、改めてクラスタリングを行いたくなってきます。そのためには属性情報が重要になってくるため、再び社内外からヒアリングを行います。 そして、いくつか肝となる属性が見えてきました。ハンドメイドと量産品の違い、商品の品質など、従来の画像やテキスト分析だけでは難しい属性です。そう行った情報を元に、ロードマップの先を伸ばす施策を考えるようになりました。企画と未来は尽きてしまってからでは事業的にもモチベーション的にもリカバリーが難しいので、随時更新・修正するフェーズを設けることによってハンドリングしています。 このフェーズでやる事: 属性用の学習モデルの作成 信用モデルに必要なパラメータの収集開始 企画と未来は尽きる前に補充する Phase 6:BASE BANKと機械学習 属性情報を作成している段階で、ショップ単位で、月次決算を試算したいという話が出てきました。また、このタイミングで、データ分析を得意とするメンバーがチームに加わり、それにあわせて100%子会社のBASE BANK株式会社が本格的にサービスを立ち上げるという話が進行し、即効薬を求められるようになりました。 Phase 6 BASE BANK 例えば定番?のDCF法(割引キャッシュフロー法)などを試してみました。 shikakutorunara.tokyo 他にも試した手法の一つをチームメンバーの岡が記事にしています。 devblog.thebase.in ここで作られたロジックは、BASE BANKが提供している、即時に資金調達ができる金融サービス 「YELL BANK(エールバンク)」 の調達可能金額の算出に現在用いています。 まとめ 今回は、駆け足でDSチームの1年間を振り返ってみました。チームが大きくなるにつれ、より多くのメンバーやビジネスシーンが関わり、スケール感が増してくるのを感じることができました。今現在も新たなPhaseが進行中です。 BASEでは一緒にネットショップ作成サービスを開発・改善するエンジニアを募集してます。 機械学習チームでは、様々なデータや技術を使ってECならではの開発を続けています。 ご興味のある方はぜひ遊びにきてください!! binc.jp *1 : この段階でチーム方針の資料を作成することになるかと思うのですが、その資料にバズワードや図を取り込むと読み手・書き手共に不幸の始まりになるので、なるべく具体的にかつ自分の言葉で説明できる事が望ましいです。(例えば人工知能・AI、光り輝く脳の図とか) *2 : 以前の職場では、うっかり資料にバズワードが蔓延してしまい、エンジニアを含めチームが何を作ったら成果と言えるのか理解できなくて、頭を抱える状況が生まれてしまいました。 *3 : 実際に待ったのはFargate導入の際、実装されるのを少し待った位です。
出典: https://unsplash.com/photos/JKUTrJ4vK00 BASE BANK株式会社 でソフトウェアエンジニアをやっている東口( @hgsgtk )です。即時に資金調達ができる金融サービス「 YELL BANK(エールバンク) 」というプロダクトを開発・運用しています。 さて、日々、ユーザーに使っていただくサービスを運営していく中で、「サービスを安定的に提供できているか」という観点において、 監視する技法 について関心があります。 そんな折、『 入門 監視――モダンなモニタリングのためのデザインパターン 』という書籍が最近発売され、世間的にも監視について、関心が高まっているかと思います。 今回は、この書籍の中から、実際に業務で実践していた「 Health エンドポイントパターン 」について、 実践例 と 書籍の内容の深掘り を含めて紹介しようと思います。 また、 Mackerel Meetup #13 Tokyo というイベントでも今回の内容を発表いたしましたので、こちらも合わせてご参照ください。 Health エンドポイントパターンとは アプリケーションの健全性を伝えるアプリケーション内のHTTPエンドポイントを作る パターンです。 カナリアエンドポイント(canary endpoint)・ステータスエンドポイント(status endpoint)とも呼ばれ、特に名前がついていることを知らずに使っている方も多いのではないでしょうか。(筆者もその一人でした。) このエンドポイントでは、最低限「HTTPリクエストを受けてレスポンスを返せるか」という情報のみを返すこともできれば、デプロイされたバージョンや依存関係のあるDBなどのサブコンポーネントのステータスといった情報までをレスポンスに含めることもできます。 使用用途としては、次のようなケースがあげられます。 Mackerel など監視SaaSからの 外形監視 ALBなど ロードバランサのヘルスチェック アプリケーション 起動確認のデバッグ 実際に、実践する場合、アプリケーションの状態を伝えるHTTPエンドポイントを作成します。例えば、 /healthcheck や /ping などと言った名前になるでしょうか。 そのエンドポイントは、 ヘルスチェックに成功すればHTTPステータスコード200 を、 失敗した場合は200以外(特に503) を返すという実装になります。 BASE BANKでの実践例 BASE BANKでは、2つのエンドポイントを用途別に用意する方法をとっていて、それぞれ外形監視の対象としています。 ひとつが、 コンテナ単体の生存確認 を主目的とした、 /health 、もう一つが、 依存しているDB・Redisなどへの接続までを確認対象に含める 、 /health/deep です。 なお、この実践例は、 「 Mackerel Meetup #13 Tokyo 」で 山根 ( @fumikony ) より発表した、『 BASEにおけるMackerel利用上の工夫と困りごとのご紹介 』内でも事例として言及しております。 Mackerel 等の監視SaaSとの組み合わせという点では、合わせてこちらを一読いただけるとより良いかなと思います。 単体の生存確認: /health Go言語で実際に実装する場合は、例えば次のようなHTTP Handlerになります。 // HTTPステータスをフィールドに含むレスポンスフォーマット type SimpleResponse struct { Status int `json:"status"` Message string `json:"message,omitempty"` Detail string `json:"string,omitempty"` } // 200レスポンスが返却される func SimpleHealthCheck(w http.ResponseWriter, r *http.Request) { rs := SimpleResponse{ Status: http.StatusOK, } respondJson(w, rs, http.StatusOK) } // JSON形式でレスポンスを返却する func respondJson(w http.ResponseWriter, body interface {}, status int ) { w.Header().Set( "Content-Type" , "application/json; charset=utf-8" ) w.WriteHeader(status) if err := json.NewEncoder(w).Encode(body); err != nil { fmt.Fprintf(os.Stderr, "failed to encode response by error '%#v'" , err) w.WriteHeader(http.StatusInternalServerError) return } } これを、 /simple/.health_check に対してルーティング設定した場合は次のようなレスポンスとなります。 -> % curl -i http://localhost:8080/simple/.health_check HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Mon, 04 Mar 2019 13:24:23 GMT Content-Length: 15 {"status":200} これは、ロードバランサからの外形監視などの際に利用しています。 依存サービス込みの動作確認: /health/deep 次に、DBやRedisなど依存している外部サービスに接続できているかどうかを確認対象に含めるエンドポイントです。 func SimpleDeepHealthCheck(w http.ResponseWriter, r *http.Request) { _, err := NewMySQL(config.DB) if err != nil { // DBへのコネクションにてエラーが発生した場合は503レスポンス rs := SimpleResponse{ Status: http.StatusServiceUnavailable, Message: "failed to get connection database" , Detail: err.Error(), } respondJson(w, rs, rs.Status) return } rs := SimpleResponse{ Status: http.StatusOK, Message: "success to connect server" , } respondJson(w, rs, rs.Status) } これを、 /simple/.health_check/deep に対してルーティング設定した場合次のようなレスポンスが返却されます。 -> % curl -i http://localhost:8080/simple/.health_check/deep HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Mon, 04 Mar 2019 13:33:22 GMT Content-Length: 53 {"status":200,"message":"success to connect server"} 例えば、データベースに対する接続が失敗した場合は、次のような503レスポンスが返却され、アプリケーションの健康状態について知ることができます。 -> % curl -i http://localhost:8080/simple/.health_check/deep HTTP/1.1 503 Service Unavailable Content-Type: application/json; charset=utf-8 Date: Mon, 04 Mar 2019 13:35:38 GMT Content-Length: 106 {"status":503,"message":"failed to get connection database","string":"sql: connection is already closed"} このパターンのエンドポイントは、 Mackerel からの外形監視で主に利用しています。 利点 外形監視に利用できる APIの通信ができるかといった外形監視は特にアプリケーションを運用していると最低限関心をもつところだと思います。このパターンでは、ステータスコードで状態を判別できるため、外形監視に使いやすいかと思います。 デバッグに有効 起動したアプリケーションが正しくHTTPリクエストを処理する事ができるかを知る上で、重宝しています。 さらに、依存関係のあるDBなどのサービスへのコネクションが取れるかについても最低限確認できるため、起動確認に有用です。 余談:コンテナベースアプリケーションとの親和性 運用している YELL BANK というサービスは、以前公開した『 ECS(Fargate)でコンテナアプリケーションを動かすための設定情報の扱い方 』という記事でも紹介した通り、コンテナ上で動作することを前提としたアプリケーションとして機能提供しています。 コンテナ内で動かすアプリケーションにおいても、外形監視は重要と感じていますが、実際このパターンはコンテナベースアプリケーションにおいてはどのように考えられるでしょうか。 コンテナベースアプリケーション設計として、「Health エンドポイントパターン」をどう評価できるかを考えるにあたり、 redhat が公開している『 Principles of container-based application design 』 から参考になる原則を一つ見てみましょう。 それが、「 HIGH OBSERVABILITY PRINCIPLE (HOP) 高観測可能性の原則 」 という設計原則です。 これは、コンテナ内部をブラックボックスのように扱う設計前提を持った上で、自身のアプリケーションの活動状況や準備状況など、様々な状態チェックについてAPIを提供するという設計について言及しています。 自身の健康状態を伝える「Health エンドポイントパターン」も、観測度を上げる上で有用なパターンと言えそうですね。 ドラフト段階の共通レスポンスフォーマットについて さて、「Health エンドポイントパターン」について、パターンと実践について見たところで、少し話を深掘りして『 Health Check Response Format for HTTP APIs 』という議論中の共通レスポンスフォーマットについて見ていきたいと思います。 これは、『 入門 監視――モダンなモニタリングのためのデザインパターン 』の「付録C」という章で言及されているものです。 どういったレスポンスを返すべきか、議論中のこのフォーマットについて少し深掘りしてみます。 Health Check Response Format for HTTP APIs このフォーマットは、大きく以下の3つの特徴を持ちます。 JSONフォーマット を利用する media-typeは、 application/health+json とする 必須フィールドである status と いくつかのオプショナルなフィールドを含む 必須フィールド: status status には「次のどれかの値を設定する」とされています。 pass : healthy status code: 2xx-3xx range (MUST) その他、下記の選択肢も可能 Node's Terminus をサポートするための ok JavaのSpringBootのための up fail : unhealthy status code: 4xx-5xx range (MUST) その他、下記の選択肢も可能 Node's Terminus をサポートするための error JavaのSpringBootのための down warn : healthy, with some concerns status code: 2xx-3xx range (MUST) warningレベルのタイプが設定できるのは一つ面白いところかなと思いました。 その他フォーマット一覧 必須とされている status 以外にも次のフィールドがオプショナルな項目として提示されています。 status version (optional) - サービスの公開バージョン releaseId (optional) notes (optional) - 健康状態に関する記述 output (optional) - 生のエラー出力、 statusが pass のときは省略すべき details (optional) - 依存しているサービスも含めた詳細情報、 The Details Object というオブジェクトで定義 links (optional) - より詳細情報を得るための外部URLなど serviceId (optional) - アプリケーションスコープなユニーク識別子 description (optional) - 人間に優しい説明 The Details Object 下流の依存関係やRedisなどのアプリケーションから見たサブコンポーネントの状態を伝えるためのオブジェクトとして提示されています。公式の例では、以下のようにcassandraやcpu・memory状態などアプリケーションが依存するものについての健康状態を伝える例を示しています。 " details ": { " cassandra:responseTime ": [ { " componentId ": " dfd6cf2b-1b6e-4412-a0b8-f6f7797a60d2 ", " componentType ": " datastore ", " observedValue ": 250 , " observedUnit ": " ms ", " status ": " pass ", " time ": " 2018-01-17T03:36:48Z ", " output ": "" } ] , " cassandra:connections ": [ { " componentId ": " dfd6cf2b-1b6e-4412-a0b8-f6f7797a60d2 ", " type ": " datastore ", " observedValue ": 75 , " status ": " warn ", " time ": " 2018-01-17T03:36:48Z ", " output ": "", " links ": { " self ": " http://api.example.com/dbnode/dfd6cf2b/health " } } ] , " uptime ": [ { " componentType ": " system ", " observedValue ": 1209600.245 , " observedUnit ": " s ", " status ": " pass ", " time ": " 2018-01-17T03:36:48Z " } ] , } , inadarei.github.io Health Check Response Format for HTTP APIs から学ぶこと これは、現時点では、ドラフト版なので正式に守るべき標準・制約というわけではありません。しかし、実際に「Health エンドパターン」を実践するにあたって、詳細な点について迷いが生まれた際にこのように議論している場所があると知ると、参考になるかと思います。 最後に 私は、PHPやGo言語でのアプリケーション開発がメインのサーバーサイドエンジニアですが、そのような視点でも、『 入門 監視――モダンなモニタリングのためのデザインパターン 』は非常に勉強になります。 迷われている方はぜひお手にとって見てはいかがでしょうか。 また、 BASE株式会社 は、サービスの継続的な提供を守り・発展させていきたいそんな方を募集中です。ご興味があればぜひお気軽に遊びにいらしてください。 binc.jp
サーバサイドエンジニアの宮村です。 カートの負荷試験について、第3弾の記事です。 最初の記事 でも触れましたが、今回の負荷試験実施にあたり、外部サービスを模擬するモックサービスを作成しました。 外部サービスへ接続する負荷試験を行うには 今回、負荷試験の対象としたのは、BASEのカートシステムです。 カートシステムには決済時に外部サービスを利用する箇所があり、通常の開発時には、外部サービスより提供されている検証環境へ接続しています。 一般的に提供されている検証環境は、本番環境ほどの性能ではなかったり、他の利用者と共用しているというものではないでしょうか。そのため、利用者の都合で自由に高負荷をかけることは難しいと言えます。 負荷試験のような高負荷をかけることが可能か否か、また可能な場合、自由に実施してよいか、事前申請が必要かなどを確認し、それなりの準備を行う必要があります。 また利用が可能だったとして、外部サービス要因でパフォーマンス影響が出る懸念、送信するリクエストの制約など、外部サービスの提供する環境を使用する場合に考慮しなければならない点がいくつかあることがわかってきました。 外部サービスへ接続しない 一方で、提供されている検証環境を使用せずに負荷試験を実施することについて検討します。 提供されている検証環境と同等の動作をするモックサービスを用意し、接続先を変更する 提供されている検証環境へ接続する処理を、外部接続せずに処理が完了するように変更する いっそのことすべてを本番環境で行う 本番環境との差異を小さくするという点において、3を除けば、プログラムの変更が少なくなる1の方法が有利と言えそうです。 稼働中のサービスで3を行うのは、リスクが高い上に、検証等の準備を含めるとコストが低いとは言えません。 調査を行ったところ、用意するモックサービスは、 BASEのサービスからのリクエストに対して 処理可能な形式のレスポンスを 適切な時間をかけて返してくれれば十分 という見通しを持つことができました。 これであればモックサービスを準備することが有力な選択肢になるだろうということになり、検討を始めました。 モックサービスとしてSwaggerを検討する さて、モックサービスをどのように準備するかということになり、調査を開始しました。 たとえば Swagger は、決まったレスポンスを返すモックサーバとして動作してくれるようです。作成したAPI定義がドキュメントとして残るなら、それも良さそうに思えます。 ただし、「適切な時間をかけて返す」という部分が解決できないようで、採用を見送ることにしました。 ここでふと、 sleep(1); したいだけであれば、PHPで書いてしまえばよいのでは?と思い直し、PHPで作ってみることにしました。 PHPなら普段から書いていますので、キャッチアップのコストは不要です。 FastRouteで行為に高速なモックサービスを実装する 簡単なPHPで書けるだろうと高を括っていたため、特にウェブアプリケーションフレームワークは使用せずに実装をはじめました。 今回用意したいモックサービスのエンドポイントが8つほどあります。 いくつか似たものはあるものの、バリエーションのあるURIであったため、ルーティングがあるといいなと思いました。 そこで FastRoute を使うことにしました。これでルールの一定しないエンドポイントでも、仮にエンドポイントを増やす場合にも拡張が容易になります。ずいぶん楽になりました。 <? $ dispatcher = FastRoute\simpleDispatcher ( function ( FastRoute\RouteCollector $ r ) { $ r -> addRoute ( 'GET' , '/users' , 'get_all_users_handler' ) ; // {id} must be a number (\d+) $ r -> addRoute ( 'GET' , '/user/{id:\d+}' , 'get_user_handler' ) ; // The /{title} suffix is optional $ r -> addRoute ( 'GET' , '/articles/{id:\d+}[/{title}]' , 'get_article_handler' ) ; }) ; こんな感じで簡単に書けました。(サンプルより引用) あとは、事前に調査しておいた資料をもとに、エンドポイントごとのレスポンスと応答時間を設定していきました。これは地道な作業です。 一通り書き上がったところで開発環境の接続先を変更し、疎通確認を行います。HTTPリクエストヘッダを使用している箇所などのいくつかの修正を行い、ついに注文が完了できるようになりました。 これで、設置してcomposer installするだけで使えるモックサービスの完成です。 実戦投入 負荷試験実施の際には、AWSのEC2に設置し、期待通りのレスポンスを返しているかを確認しながら使いました。 試験中、何度か期待通りのレスポンスが出ないことが検知されることがありましたが、Apacheの設定値の調整などを行うことで期待通りの役割を果たしてくれました。 これはモックサーバの設定を見直していたときのやり取りでした。 モックサービスなので、実在するクレジットカード番号を使う必要もなければ、メールアドレスの重複を気にする必要もありません。 シンプルなテストシナリオを繰り返し実行することができ、便利に使用することができました。 まとめ 提供されている検証環境を使わずに自前でモックサービスを作成、使用することも、負荷試験時の選択肢としてアリだと思いました。 モックサービスを自由にできることで、アプリケーションやテストシナリオをシンプルにできる点も良いと感じました。 今後、他の外部サービス連携にかかわる部分の負荷試験を行う際も、同じ要領でモックサービスを活用することができそうです。 最後に これまで3回にわたり、負荷試験関連のトピックを紹介させていただきました。興味がある方は、過去の記事も参照いただけると嬉しいです。 devblog.thebase.in devblog.thebase.in パフォーマンスに関する改善に終わりはなく、また別の課題に向けて取り組んでいる最中です。 BASEでは、カートのパフォーマンスアップに興味がある方をお待ちしております! open.talentio.com
フロントエンドエンジニアの松原( @simezi9 )です。BASEでは現在 ショップ向けの管理画面をリニューアルするプロジェクトが進んでいて 、UI/UXの更新と同時に創業当時から継ぎ足して作ってきたフロントエンドの技術スタックを一新しようとしています。この記事では、具体的にそのフロントエンドの更新でどのようなことに取り組んでいるのかをいくつかご紹介したいと思います。 Vue + TypeScriptを利用したMPA(multi page application)化 HTMLの構築をPHP(サーバーサイド)からJS(クライアントサイド)へ移行する 従来の「BASE」の画面ではPHPでHTMLの構築を行っていましたが、HTMLの構築をすべてPHPのコードから分離させて、Vueによるクライアントサイドでのレンダリングにしています。また管理画面の特性上(1ページあたりの閲覧時間が長く相対的にローディングの時間が短くなる)、サーバーサイドレンダリングなどは特に行っていません。 クライアントサイドでのRoutingの導入 Routingに関しては管理画面の機能を大きな単位でいくつかに分割して機能間のRoutingはCakePHPで行い、機能内ではSPAのようにクライアントサイドで細かくRoutingを行っていく構成になっています。フロントエンドのRoutingはVue Routerを利用しています。 大雑把に責務を整理すると以下のようになります。 PHPサーバの役割 大きな機能単位でのRouting RestAPIの提供 Javascript(Vue.js)の役割 機能内でのRouting 画面の描画 RestAPIの構築とAPI Blueprintによるカタログの作成 データの取得・操作は基本的に全てAPI経由で行えるように必要なだけのAPIを用意しています。作成したAPIはAPI Blueprintを利用してカタログ化されていてサーバサイドのエンジニアとフロントエンドのエンジニアが疎結合に作業を進めていけるようになっています。 フロント側でも基本的にAPIの構成と1エンドポイントに対して1ファイルで対応するようにinfra層を構築しています なぜVue+TSか もともとBASEではHTML/CSS/JSによるフロントの構築をすべてデザイナーが担っていてフロントエンドエンジニアというポジションはありませんでした。この次世代管理画面プロジェクトでのフレームワーク選定もデザイナー陣主導で行われました。そのなかでRiot.jsやReactなども試した上で、Vue.jsがもっとも技術導入がスムーズに出来そうだという結論となりVueを採用しました。 また、プロジェクトのサブテーマとして「次の5年を支える」というものがあり、TSが提供する型システムによる安定性がプロダクトのライフサイクルをサポートしてくれることを期待してTSを導入しています。 開発していて実際どうか? 現行のVue2.xとTSの組み合わせはReactなどと比べると劣る面があることは否めない(props周りなど、型が失われてしまう場所が多い)ですが、API通信などのVueが絡まない部分でのTSの型システムのサポートは非常に強力ですし、Vueの次期メジャーバージョンであるVue3.0では コアがTSに移行し、サポートの強化も表明されており 今後に向けた選択肢としてVue.js + TSの組み合わせは有力だと思っています。 Vue.js + TSで最も問題になるのは、公式のドキュメントがJSで書かれていることであり、 TSの書き方と若干サンプルコードが異なる という点です。これに関してはVue.jsに馴染みのあるメンバーがいれば大した問題にはなりませんが、全員がVueを初めて触るような場合には、いきなりTSを導入することには慎重になったほうがいいかもしれません(TSとJSはファイル単位で共存できるので後から追加することは難しくない)。 Storeをどうしているか Vue.jsではデータを一元管理するためのライブラリとしてVuexを使うのが一般的ですが、現状でのVuexはTSとの相性があまりよくなく、せっかくAPIレスポンスの型を定義したのにいざVueコンポーネントで取り出そうとすると型情報が失われてしまいます。そこでTSを活かすためにあえてVuexを採用せず、 GlobalEventBus のような構造を拡張した独自のStoreを使っています。この独自実装に関してはそのメリット・デメリットは以下のように現状では一長一短に感じています メリット TSの型をVueコンポーネント内部で利用して堅牢なコードを書ける シンプルな実装で可読性が高い デメリット 最低限の機能しか持たず、Vue.jsのエコシステムの流れからは外れる Vue.js devtools のVuexサポートが利用できない 後者のdevtoolsが使えない点に関しては、 公式の実装 を参考にして、storeの内部状態のダンプなど最低限のデバッグは可能にしています。 AtomicDesignに基づいた共通UIライブラリの構築 次世代管理画面プロジェクトと並行して社内のサービスで共通して利用するためのUIコンポーネントライブラリを構築しています。現在BASEでは Atomic Designを採用したデザインシステムの構築を進めており 、そのSketch上のデザインシステムと対応する形でStorybookを利用してコンポーネントライブラリを作っています。 storybook-addon-vue-info や @storybook/addon-knobs を利用して、メンバーがStorybookを見るだけでアプリを構築していけるように整備を進めています。 ブランチ単位での自動デプロイ このライブラリのリポジトリではブランチを切ってPRを作るたびにブランチ単位でStorybookがビルドされるようになっており、デザイナーとエンジニアの確認が簡単に行えるようになっています。 自前でUIライブラリを実装していく上での工夫・苦労 最初にコンポーネントを全部用意しようと考えない 一番小さいレイヤ(Atoms)のコンポーネントから作る コンポーネントだけを作ろうとせず、 実際に使いながらライブラリを育てる 特にformを構成するコンポーネントなど SketchのデータとStorybookのデータを一致させることにこだわりすぎない 見た目だけではわからないデザインの意図を拾ってStorybookに反映することを心がける 汎用的なコンポーネントを作るのは見た目の単純さに反して考慮することが多く、一発で作ろうとしてもなかなか作りきれません。有名なVueのUIコンポーネントライブラリの一つとしてVuetifyがありますが、その実装を見ても buttonのtsファイルが170行 、 inputで300行 あります。実際自分でコンポーネントを作っても、「あの機能がない」、「このカスタムができない」と問題が続々と出てきては一個ずつ対処する繰り返しになります。その状態で複雑なコンポーネントを用意しても、品質が上がらずコンポーネントの修正の足かせになりがちなので、小さなコンポーネントから我慢して作っていくことが必要だと感じました。 最後に BASEの次世代フロントエンド環境はまだ開発がはじまったばかりで、実際にはまだまだ課題が山積みです。次世代の管理画面も、UIコンポーネントライブラリも、自分の力で構築していってみたいというエンジニアを募集しているので、興味がありましたらぜひ一声かけていただければと思います。 open.talentio.com
こんにちは、BASE BANKでエンジニアをしている東口( @hgsgtk )です。 さていきなり本題ですが、2019年1月26日(土)に PHPカンファレンス仙台2019 が開催され、ネットショップ作成サービス「BASE」は、シルバースポンサーとして協賛しました。 大変盛り上がった最高のカンファレンスだったのですが、BASEからは、私と田中( @tenkoma )がセッションスピーカーとして登壇しましたので、それぞれの発表内容についてレポートいたします。 phpcon-sendai.net 発表資料 テストを書くのがつらくならないテスト駆動開発のアプローチ 私、東口( @hgsgtk )は、午前の最初の登壇で30分の発表をしました。 「テストがつらい」状況の様々な要因のうち、「テストを書くのが億劫」なことや「テストを書くのが難しいコードになる」といった要因にフォーカスを当て、それらに対してテスト駆動開発のアプローチを活用することで解決できないかという内容です。 ライブコーディング中の様子 当日は、ライブコーディングにてテスト駆動開発の流れを説明しました。 懇親会や後日Twitterなどで、感想や質問をいただけたのが大変ありがたかったです。 当日頂いた質問 テストを書くことに慣れてないと実際にやり始めるのに一苦労しそう 「テストを先に書く」という点について、テストを書くのに慣れていないと確かに難しいと思います。そのため、まずはテストを書くことに慣れるというのは前提として必要だろうという話をしました。 こちらについては、以前 PHPカンファレンス大阪2018 にて、 テストを書いたことがないエンジニアがテストを書けるようになるまでやったこと という発表しましたので、こちらの資料を参考にしていただくと良いかもしれません。 PhpStormとPHPUnitを連携してユニットテスト作成を楽にする 田中( @tenkoma )より、午後2つ目の登壇で30分の発表をしました。 PHPStormとPHPUnitを連携することでユニットテスト作成・実行を効率的に進めるというテーマで発表です。 発表中の様子 田中の個人ブログにて当日の発表の様子をレポートしておりますので、こちらも併せてご覧ください。 tenkoma.hatenablog.com 最後に PHPカンファレンス仙台2019 は今年初開催でしたが、良い意味で「初開催とは思えない」ほどしっかり運営されていて、とても楽しいイベントでした。 運営の皆様、素晴らしいカンファレンスをありがとうございました! 次はPHPerKaigi2019 次のカンファレンスは、3月29日〜3月31日に PHPerKaigi 2019 が開催されます。 BASEからは今回仙台で登壇した田中・東口が同じく登壇します。 田中からは、「 PhpStormでコードを理解する技術 」(レギュラートーク 15分)というテーマで発表します。 fortee.jp 東口からは、「 「質」の良いユニットテストを書くためのプラクティス 」(レギュラートーク 30分)というテーマを発表いたします。 fortee.jp また、ネットショップ作成サービス「BASE」は、ゴールドスポンサーとして協賛しています。 BASE株式会社 さま( @BASEec )から ゴールドプラン のお申込頂きました!ありがとうございます! https://t.co/Ezqw0Z0SiW #phperkaigi — PHPerKaigi 2019 @3/29-31 (@phperkaigi) February 1, 2019 ぜひ、皆さんPHPerKaigi 2019でお会いしましょう!
先週に引き続き、BASEでサーバサイドエンジニアをしている宮村です。 先日、負荷試験の取り組みについて紹介させていただきましたが、今回はその際に使用した Apache JMeter の活用について紹介させていただきたいと思います。 JMeterは高機能なツールなので使いこなすと強力ですが、少し複雑な機能のテストを行おうというとき、ややとっつきにくい部分もあるのではないかと思います(私はそうでした)。具体的な使い方をいくつか知っておくだけで、ぐっと便利に使えるようになると思いますので、これから負荷試験を行おうという方に少しでも参考になれば幸いです。 選定理由 負荷試験を行うツールはいくつかありますが、今回は下記の条件が満たせるものを探していました。 セッション管理できること ページ遷移を伴うシナリオが作成できること シナリオでレスポンスの値を取得して使えること 攻撃サーバがスケールすること 習熟コストが高すぎないこと これが満たされていれば、どれでもいいかな〜と思っていたので、以前少し使ったことがあったJMeterでできそうだと見えてきた時点でJMeterで進めることに決めました。 他に見たものを少しだけ紹介します。 Apache Bench:導入及び使用がとても簡単ですが、複雑なシナリオを扱うことができないため、カートの負荷試験には不向きであると判断しました。 Locust:JMeterと機能的には類似しているとのことで良さそうにも思いましたが、私個人にとってPythonでシナリオを書けることがあまりメリットにならないこともあり、選択しませんでした。 シナリオ作成 下記の手順で、シナリオを準備していきます。 テストケースの作成 作業PCへのJMeterの導入 記録コントローラでテストシナリオのベースを作成 実現したいテストシナリオへ改修 1. テストケースの作成 どのような高負荷状態を作りたいかを決めます。〇〇のページに、単位時間あたり〇〇のアクセスを、〇〇の時間発生させる、というようなものになるかなと思います。 これはツールによらない工程ですが、これがなければシナリオは作れません。今回は、過去の高負荷状態を再現できるようにケースを作成しました。 例)商品Aを1個、クレジットカードで購入するユーザが1分間に100人のペースで5分間来る、等(※数字はイメージです。) 2. 作業PCへのJMeterの導入 公式ページに従い、インストールを行います。 必要に応じてJavaのインストールを併せて行います。 (この工程の情報はWeb上にたくさんありますので、詳細は割愛させていただきます) 3. 記録コントローラでテストシナリオのベースを作成 シナリオ作成には「記録コントローラ」を使用しました。 JMeterをプロキシとして動作させ、ブラウザのプロキシ設定をJMeterに向けることで、ブラウザでの操作をJMeterで記録する機能です。 これを使えば記録したシナリオをそのまま使用できるはずでしたが、いくつかのパラメータが欠けていたので補ったり、不要なシナリオを削除したりといった作業が必要でした。 ただ、この修正の工程が必要であったとしても、記録コントローラを使うメリットは大きいと感じましたのでおすすめです。 4. テストシナリオの改修 1で決めたテストケースを実現できるよう、各種の設定値を書き加えたり変更したりします。 今回は、たとえば商品IDなどのいくつかのパラメータは変数として定義するなど、必要に応じて記録されたシナリオに改修を加えていきました。 ここで、便利だったエレメントを以下に紹介します。 便利だったエレメント8選 ユーザ定義変数 手元の環境でシナリオを作成し、試験環境にで実行するということをしたので、urlなど環境固有の値を簡単に切り替える必要があり使用しました。 HTTP認証マネージャ basic認証をかけた環境で試験をするのに使用しました。 HTTPクッキーマネージャ セッションを利用するので使用しました。 異なるユーザの購入を想定したので、「繰り返しごとにクッキーを破棄する」設定にしました アサーション 各リクエストで、レスポンスコードは問題ないが、期待するレスポンスが返らない場合にテストを失敗させるため使用しました。 具体的には、正しく次の画面に遷移した場合と、エラーで同じ画面にとどまっているにもかかわらずレスポンスコードは正常な場合を区別したい場合に使用しました。 HTMLリンクパーサ 正規表現抽出 前の画面で生成した値を、後続のリクエストのパラメータとして使う場合に使用しました。 はじめは後述のHTMLリンクパーサを使っていたのですが、JMeterサーバを複数台構成にして、リモート実行した際に正常に動作しないことがあったため、正規表現抽出に切り替えました。 統計レポート シナリオ実行の様子を眺めるのに使いました。 JMeterには様々な高機能なリスナがあり便利なのですが、リクエスト数を増やした場合に、リスナの処理が重くなってしまうそうです。それを避けるため、これとシンプルデータライタの2つだけを実際の試験実行時には使用しました。 シンプルデータライタ シナリオ失敗の具体的な状況を調査するため、結果はすべてCSVファイルに書き出しました。 リクエスト失敗の原因調査等、必要に応じてExcelで調査しました。 完成したシナリオの例 実行 シナリオ実行 AWS上のWindowsサーバ1台にJMeterを設置し、少ないリクエスト数から徐々に負荷をかけていきました。 最初は、シナリオや設定値の妥当性の確認も兼ねて、1リクエストから実行していきます。 リクエスト数を増やす過程で、JMeterサーバがボトルネックかな?というタイミングでリモート(Linuxサーバ2台)で実行するように変更しました。 socket write error, failed to respond, closed connection というエラーが、シンプルデータライタで取得したログに出力されたタイミングがそれです。 結果の記録 どういうシナリオを流したか、結果はどうだったかをスプレッドシートに都度記録しました。「実験ノート」をとる要領で、下記のような内容を都度記録しておきました。これが後に結果レポートになっていきます。 リクエストの種類 成功数、失敗数 シナリオ完了までの時間 成功はしているが遅延している、を検知 実行時刻 各種ログを後から調査するため まとめ フォームの入力やセッションを利用し、複数画面の遷移を伴う機能であるカート機能の負荷試験を、JMeterを使うことで実施できました。 ツールの選定には、試験でどういった機能が必要かをまず明確にするのが重要でした。 シナリオが資産として残っているので、今後も改善しながら負荷対策に役立てていく予定です。 最後に 本番相当の環境でのパフォーマンス改善に興味のある方、これからもさらなる改善を行っていくことになると思いますので、ぜひご連絡ください! open.talentio.com
BASEでサーバサイドエンジニアをしている宮村です。 つい最近まで、主にEコマースプラットフォーム「BASE」の決済領域の開発をしていました。決済領域は、いかなる場合でも安定稼働が求められる領域です。いかなる場合でもというのは、BASEが対応する各種決済方法やクーポン、 ショップコイン など機能の組み合わせという意味でもそうですが、アクセス集中による高負荷に対しても、同様に安定が求められます。 前者に対しては、弊社東口から ユニットテストの取り組み を以前紹介させていただきました。今回は、後者への取り組みとして、負荷試験の取り組みを紹介させていただきたいと思います。 動機 「BASE」は「Eコマースプラットフォーム」ですので、主として提供している機能の一つに、「カート」の機能があります。主として提供しているということは、サービス開始当時から、この機能を提供させていただいているということでもあります。 リリースした頃のBASE おかげさまで多くのショップ様、購入者様にご利用いただけるようになり、その性能面について把握、改善することがこれまで以上に求められる場面が出てきました。 改善するためには、改善したことが評価できなくてはいけません。購入に関する定量的な指標をおいて、計測することにしました。 準備 環境 前提として本番相当のものを用意することにしました。いくつかの懸念があったのですが、下記のようにクリアすることができました。 1. コスト面の課題 使うときだけ簡単に試験環境を立ち上げられる仕組みを作ったり、関連している諸サービスのうち今回のシナリオで必要なものだけを本番相当にするなど、コストを抑える工夫をしました。 2. 外部サービスとの連携 カートシステムでは、外部の決済サービス等との連携を行っています。負荷試験といっても、外部サービスへの過負荷は望ましくありません。(サービスによっては許可されない場合もあります。)今回は内部の性能試験にフォーカスしたかったこともあり、外部サービスを模したモックサービスを構築してそこに接続するようにしました。 また、試験中の状況の把握や、発生した異常の解析のため、監視サービス等も、本番同様のものを導入しました。 ツール 試験ツールには、諸条件を考慮して Apache JMeter を使用しました。 セッション管理やページ遷移を伴うシナリオが必要だったこと、負荷テストサーバーのスケールが容易にできること、メンバーの経験などを考慮してツールの選定を行いました。(JMeterの活用については、別の記事で述べられればと思います。) 結果として、機能や習熟の不足などによる大きな問題もなく、試験を行うことができました。 シナリオ カートに商品を投入してから、購入者情報の入力、購入完了までの数画面を遷移するものとしました。カート内は購入者情報など入力される値も多いのですが、JMeterの「記録コントローラ」を使用することで比較的手をかけずにシナリオを作ることができました。 実施 役割分担 今回の負荷試験は、主として3名のエンジニア(アプリケーションエンジニア2名、SRE1名)で進めました。 シナリオ構築やモックサービスの構築、シナリオ実行、レポーティングなど、主にアプリケーションに関する部分をアプリケーションエンジニアが担当し、環境構築などの部分を、SREが担当しました。 それぞれがやるべきことに集中できたことで、環境構築の工夫やモックサービスの構築などプラスアルファの部分にも力を割くことができたことはとても良かったように思います。 さて実行 シナリオを実行してみると、いくつかの課題が発生しました。 モックサーバがボトルネックになっていた! これは元々、様子を見ながら調整する予定でした。LBとappサーバのログを確認し、接続数を増やして安定しました。 SREのメンバーがここをサッと見てボトルネックを特定してくれました 購入ではないところがボトルネックになっていた! 当初のシナリオでは、まず商品画面にアクセスして、カートに商品を投入するということをやっていたのですが、商品画面に使っている外部サービスが開発用のスケールのものでした。今回のシナリオでは不要なアクセスだったため、本当に必要な画面遷移に絞ることで解決しました。 New Relicで、遅くなっている処理を特定しました 想定したところと違うボトルネックが発覚した! DBがボトルネックになるかな?と想定していたところ、Apacheがボトルネックになっているような挙動を見せました。どちらも本番相当の環境であるため、当初想定していた負荷の強度をクリアしていたこともあり、このあたりが限界であると結論づけました。いくつかの設定を変更して追加の試験を行い、即座に反映できるような変更点は見つけられませんでしたが、次の改善への取り掛かりとして知見が得られました。 Mackerelで監視 DBエンジニアの 植木 に教えてもらったRDSのPerformance Insightsがとても便利でした 実施中の様子 Slackで実況しながら、わいわいやりました。 負荷を増やしていきながら、エラーなく処理を完了している様子や、謎のエラーが発生していることを随時報告するようにしました。隣の島のリードエンジニアがさっくりと原因を指摘してくれたり、SREのメンバーがインフラを調整してくれたり、次々に現れる課題が攻略されていくさまに感動と感謝でいっぱいになりました。 結果 負荷試験を実施すると決めてから2ヶ月程度で結果を出すところまで行うことができ、定量的なレポートを社内に共有できました。 また、並行して進めていた改修についても、前向きな効果がありそうだという結果も得ることができました。 トラブル以外では決済領域が目立つことは少ないのですが、前向きな成果を共有できたことは、チームにとっても良かったなと思いました。 まとめ 負荷試験を実施することで、システムの性能について定量的な指標を得ることができました。 性能に関する改善を行うにあたり、その効果が見込めることを改修前に示すことができました。高負荷状態は常に発生するものではないので(残念ながら)、同等の環境で再現させることで、その効果や副作用がないことを確認したうえでリリースの判断をすることができました。 高負荷状態を再現させる環境を手に入れたことで、安心してサービスを成長させていく土台ができたかなと思います。他の箇所で高負荷に起因する課題が発生した場合にも、知見と環境を活用して対応していけるものと期待しています。 最後に 本記事では、BASEで実施した負荷試験の取り組みについて紹介させていただきました。負荷試験に取り組むにあたり、特定のツールの使い方以上の実践的な情報がまだ少ないなと感じるところもあり、一つの実践例として本記事が少しでも参考にしていただければ幸いです。 また、本文では簡単な紹介になってしまいましたが、JMeterの活用やモックサーバの構築については今後別の記事で紹介できればと思います。 BASEでは60万ショップの決済を支えるエンジニアを募集しています。支えるだけでなく、より良い決済システムにしていく挑戦をやっていきますので、興味のある方はぜひ下記よりご連絡ください! open.talentio.com
あけましておめでとうございます。 BASE BANK株式会社 でソフトウェアエンジニアをやっている東口( @hgsgtk )です。 2018年末から年明けにかけて、EKSが東京リージョンに来たりAWSからのリリースが賑わいを見せていますが、その中から、 AWS Fargate の次の新機能を実際のプロダクトに適用しました。 AWS Fargate プラットフォームバージョン 1.3 でシークレットのサポートを追加 これを期に、コンテナアプリケーションにおける設定情報を扱う考え方・それを実現するためのAWSのサービス構成と得られた利点についてまとめてみようと思います。 目次 設定情報の扱いに対する要件 コンテナベースの設計思想・原則 ECS(Fargate)を用いる場合の設定情報の扱い方 設定情報の扱いに対する要件 開発背景 BASE BANK社では、即時に資金調達ができる金融サービス「 YELL BANK(エールバンク) 」というプロダクトを開発しています。 以前本ブログに投稿した「 GoのAPI開発現場におけるユニットテストTips 」 や「 Goを運用アプリケーションに導入する際のレイヤ構造模索の旅路 | Go Conference 2018 Autumn 発表レポート 」の通り、Go言語でアプリケーションを開発しており、docker buildしたイメージから作成したコンテナをECS(Fargate)上で動かすことで機能を提供しています。 設定情報とは 本記事内での「設定情報」は、データベース、Memcached、他バックエンドサービスなどのリソースハンドルのための 認証情報 を指します。これらは、本番・ステージング・開発・QAなど環境ごとにそれぞれ異なる値を持つ属性があります。 コンテナアプリケーションの設計として、設定情報をどう取り扱っていくか次に考えていきます。 コンテナベースの設計思想・原則 コンテナベースで動かすアプリケーションでの設計思想について次の2点の資料がよく参照されます。 Beyond the Twelve-Factor App Principles of container-based application design (Redhat) この2つの資料からコンテナベースアプリケーションにおける設定情報の扱い方について見ていきます。 Beyond the Twelve-Factor App 2012年に、モダンなクラウドアプリケーションのベストプラクティス「 The Twelve-Factor App 」をHerokuの中の人が書きました。Beyond the Twelve-Factor Appは、2016年に Pivotal 社が、オリジナルのガイドラインのアップデート・ガイドラインの追加したものです。 クラウド環境を活用したクラウドネイティブアプリケーションの新たなベストプラクティスをガイドラインとしてまとめてくださっています。次のURLから実際にPDFをダウンロードすることができます。 content.pivotal.io また、次のスライドが大変わかりやすくガイドラインについてまとめてくださっているので、そちらもご参照いただくと良いかと思います。 Chapter 5 Configuration, Credentials and Code この資料内で、特に設定情報については、 Chapter 5 Configuration, Credentials and Code という章で言及されています。ピックアップすると大きく次の内容です。 設定や認証情報は コードから分離 すべき 環境は無限に増えていくため、環境(dev, prd...etc)ごとに設定をグルーピングすべきではない。 設定をコードから分離する一番の方法は 環境変数 への格納である。 設定情報とコードを分離することを求めており、分離できているかどうかの指標として、 今すぐにでもコードをオープンソース化できるか を上げています。 次にもう一つredhatが公開している設計原則について見てみましょう。 Principles of container-based application design (Redhat) redhatが公開しているホワイトペーパーで、コンテナベース・アプリケーションの設計原則についてまとめています。 次のURLにて日本語版の資料をダウンロードすることができます。 www.redhat.com IMAGE IMMUTABILITY PRINCIPLE (IIP) イメージ不変性の原則 いくつかの原則を説明している中で設定情報についての扱いに関連のあるものとしてこちらの原則があります。 コンテナ化アプリケーションは不変であるため、ビルドされた後、異なる環境間で変化することは想定されていません。つまり、環境ごとにコンテナの作成や修正を行うのではなく、ランタイムデータの保存に外部手段を利用し、外部化した設定を環境によって使い分けます。 上記の記述により、yamlファイルなどでアプリケーション内で設定情報を分けてそれぞれビルドする方法ではなく、ビルドするアプリケーション内に環境によって異なる情報は入れず、外部に保存した設定情報を使用することが推奨されています。 2つの思想・原則から方針を見出す これまで見てきた2つの資料から、 コードから設定情報を分離し、環境変数から外部設定した設定情報を注入する 構成としていきます。 ECS(Fargate)を用いる場合の設定情報の扱い方 設計方針が決まったところで実際に AWS 、特に ECS(Amazon Elastic Container Service) を利用した場合の設定情報の扱い方についてです。 概要構成 概要構成は次のようなものになります。 概要構成 以下、 AWS Fargate プラットフォームバージョン 1.3 でシークレットのサポートを追加 で発表された機能を利用するため、プラットフォームバージョンは 1.3以上 を前提とします。 アプリケーション 環境変数から設定情報を取得する実装とします。例えば、Go言語の場合はosパッケージを利用して次のようなコードを書くことになるでしょう。 dbHost := os.Getenv( "DB_HOST" ) ビルドしたアプリケーションのコンテナイメージは、 ECR(Amazon Elastic Container Registry) や Docker Hub といったコンテナレジストリサービスにpushします。 設定情報の保存 設定情報は、 SSM(Systems Manager) Parameter Store に保管していきます。 SSMでは、パラメータを階層的に管理する事が可能です。 docs.aws.amazon.com 具体的には、 /stage1/stage2/stage3 といった形で階層を掘っていく形になります。 この際、DBのパスワードなど暗号化して保存したい場合は、 KMS(Key Management Store) を用いて暗号化キーを作成し、そのキーを持って暗号化します。 SSMに設定する情報を暗号化する際は登録時に暗号化オプションを付け、KMSキーを指定します。 aws ssm put-parameter --name /goecssample/database/sample/master/password --type "SecureString" --value "password" --key-id "< KeyId >" --description "データベースのmasterユーザーパスワード" --region ap-northeast-1 具体的には、typeを SecureString とし、key-idに作成したKMSキーを設定するだけです。 コンテナから設定情報を利用 SSMに保存した設定情報を、コンテナに挿入するためには タスク実行ロール に対してSSMのパラメータ取得・KMSキーでの復号を許可する必要があります。 具体的には、タスク実行ロールに対して以下のようなポリシーを追加します。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": [ " ssm:GetParameters ", " kms:Decrypt " ] , " Resource ": [ " arn:aws:ssm:region:aws_account_id:parameter/parameter_name ", " arn:aws:kms:region:aws_account_id:key:key_id " ] } ] } タスク定義 ECSのプラットフォームバージョン1.3.0より前、Fargateを利用している場合、System MangerのParameter Storeなどから設定情報をコンテナに注入するには、自前でdocker-entrypoint.shなどからSSMに対してAPIアクセスして取得する必要がありました。 しかし、今回のサポートによって、タスク定義内のコンテナ定義に設定することによって、コンテナ起動時に自動でコンテナに対して設定を注入することができるようになりました。 具体的には、コンテナ定義の環境変数に、環境変数名・SSMのパラメータ名を指定するだけです。 コンテナ定義/環境変数設定 1.3より前は、次のようなentrypoint.shなどを書いて対応していました。 #!/usr/bin/env bash set -e export DB_HOST=$(aws ssm get-parameters --name /prd/database/host --query "Parameters[0].Value" --region ap-northeast-1 --output text) exec "$@" 1.3へのアップデートによって、自前での実装が不要になり、かなりシンプルになりました。 その他 その他、より詳細の説明は、AWS公式の次のドキュメントを参照してみてください。 docs.aws.amazon.com この構成にして得られた利点 コードから設定情報を分離できた コードから設定情報を分離したことによって、全アプリケーションエンジニアがすべての設定情報を参照できる状況は避けることができました。 加えて、設定情報は、 AWS Systems Manager Parameter Store に設定されています。 本番・ステージングなどでアカウント自体が分かれている場合は、そもそもアカウントを発行されている人のみに閲覧を絞ることができ、加えてIAMの設定等で誰のアクセスを許可するかを制御することが可能になりました。 設定の量が増えても階層的に扱える AWS Systems Manager Parameter Store では、階層的にパラメータを登録することが可能なため、情報を階層的に扱いたいモチベーションもある程度満たしてくれました。 シークレットのサポートによって得られた嬉しいこと AWS Fargate プラットフォームバージョン 1.3 でシークレットのサポートを追加 によって嬉しかった点も記載します。 コンテナ起動時の複雑性が軽減された 当初、デプロイ時の複雑性を増していたdocker-entrypointでの自前実装が不要になり、アプリケーションの複雑性が減りました。 イメージサイズが小さくなった 副次的な効果として、AWSのAPIに対するアクセスが不要になったため、実行イメージに含めていた python と aws-cli が不要になりました。 その効果によって、 約40MB程度だったイメージサイズが約10MBまで小さくなりました。 まとめ そもそも、コンテナアプリケーションをどう扱うべきなのかという観点から、実際にAWS Fargateを利用した場合についての説明をさせていただきました。 当初扱いづらさがあった部分もアップデートによって日々使い勝手がよくなってきている印象を覚えています。 現在、ECSなどでアプリケーションを構成しようとしている・または検討している方にとって、一つの参考になれば幸いです。
この記事は「BASE Advent Calendar 2018」25日目の記事です。 devblog.thebase.in こんにちは。BASEでFrontend Groupに所属している 三佐和 です。主にネットショップ作成サービス「BASE」のフロントエンドを担当しています。 先日デザイングループのマネージャー早川が 「BASE」の管理画面リニューアルプロジェクトのこれまでとこれから で話しているように、現在BASEでは本格的にフロントエンドをVue.jsで置き換えるプロジェクトが進行しています。 これまでのBASEのフロントエンドは、主にマークアッパーを含むデザイナーが中心になってjQueryでゴリゴリと実装していました。 Frontend Groupが発足したものの、まだまだこれからで、しばらくはデザイナーと協力してサービスを作っていくスタンスで開発を進めています。 そのため、モダンなフロントエンドの考え方や新しく導入されたシステムについて、デザイナーの方へ伝えたり、慣れてもらうことの重要性が高まっていました。 しかし、当初はこんな声もありました。 そこで、Frontend Groupとして、主にデザイナー向けにVue.js勉強会を開催することにしました。 また、少し前に流行した短期集中型エクササイズ・Billy's Boot Campから、この勉強会のタイトルを「Vue Boot Camp」と名付けました! このブログでは、それを開催する過程で伝えたかったことや考えていたこと、準備したことを紹介していけたらと思います。 対象を考える BASEの場合は主に以下の3種類のロールが「デザイナー」と呼ばれています。 いわゆるマークアッパーで、jQueryを使ったフロントエンドコーディングができる UIデザインができて、HTMLとCSSでそれを表現できる UIデザイン、ビジュアルデザインの専門で実装はほとんどしない このうち今回対象にしたのは、上の2つで、前提としてある程度HTMLとCSSのことは分かっている、ということをラインとしています。 これらの条件に当てはまる人は一旦Vue.jsにはまったく触ったことがない人、と仮定しています。 覚えてもらいたい・知ってもらいたいこと 対象を絞ったので、次に覚えてもらいたいことを考えていきます。 「デザイナー」と呼ばれる方にフロントエンドで責任をもってもらいたい部分は、主に以下の2つだと考えました。 大まかなシステムが構成されている上での、デザイン当て、マークアップ、インタラクションデザイン 自社開発のコンポーネントのメンテナンス これらを実現する為にVue.jsやモダンフロントエンドに関する知識の中でも、この要素は伝えたい!というのが Web Componentsという考え方 BASEで利用している基本的なフロントエンド構成 自社開発のコンポーネントを実際に利用した開発を体感してもらう css-moduleを使ったスタイリング フロントエンドにおける簡単なCRUD操作 これらであるとして題材を考えることにしました。 題材を考える 前半はVue.jsのチュートリアルをなぞりつつ、BASEの新しいフロントエンドやWeb Componentsな考え方に触れてもらう、というところまではすぐに決まりました。 後半は、なにか一つアプリを作る体験をしてもらいたいと考えていました。 これらを満たせるアプリを考えたときに、JavaScript界隈ではおなじみ(?)の TodoMVC というものを紹介してもらいました。 これをベースに考えていくと上記のような要素が満たせそうだったので、これをアレンジしたTodoアプリを今回の題材にすることにしました。 これに対し、実際にどのようなアレンジをしていったかというと... 自社コンポーネントを使った開発 BASEではBBQという名のUI実装時に使用されるコンポーネントのライブラリがあり、例えばVue.jsのサンプルでは以下のようなコードになっていますが、 < ul class = "todo-list" > < li v- for = "todo in filteredTodos" class = "todo" :key= "todo.id" : class = "{ completed: todo.completed, editing: todo == editedTodo }" > < div class = "view" > < input class = "toggle" type = "checkbox" v-model= "todo.completed" > < label @dblclick= "editTodo(todo)" > {{ todo.title }} </ label > < button class = "destroy" @click= "removeTodo(todo)" ></ button > </ div > //... </ li > </ ul > このようなリストに含まれるチェックボックスや削除ボタンのコンポーネントをBBQを使って書くと以下のように書くことができます。 < ul : class = "$style.todo" > < li : class = "$style.todo_list" > < bbq-checkbox : class = "$style.todo_checkbox" > < template slot= "text" > {{ item.text }} </ template > </ bbq-checkbox > < bbq-icon- button : class = "$style.destroy" icon= "crossCircle" noBorder @click= "removeItem" ></ bbq-icon- button > </ li > </ ul > このような変更を全体的に行うことで、それぞれをBBQを使って実装することを体験してもらうことができます。 css-moduleを使ったスタイリング またcss-moduleを使った実装に置き換えて .vue ファイル内にスタイルを書くことで、そのコンポーネントの中でしか影響を与えないCSSを作ることができます。 < div : class = "$style.hoge" > {{ message }} </ div > < style lang = "scss" module> // スタイルを書く .hoge { //... } </ style > 事前に準備したこと テンプレートプロジェクトの作成 デザイナーの人にwebpackの設定をしてもらいたいわけではないので、BASEで実際に使用している構成と近い形になるよう、事前に以下のような設定を行ったプロジェクトを準備しました。参加者は git clone と yarn install を行うだけで、すぐに Vue.jsでの開発が始められます。 一般的なwebpackの設定などは割愛しつつ、特に重要なポイントのみ列挙します。 必要なパッケージをインストール yarn add -D webpack webpack-cli webpack-dev-server yarn add vue yarn add -D typescript ts-loader vue-class-component yarn add -D vue-loader vue-style-loader vue-template-compiler yarn add -D css-loader sass-loader postcss-loader webpackを設定 TypeScript、シングルファイルコンポーネント、css-moduleが使えるよう設定します。 module: { rules: [ { test: /\.tsx?$/ , use : { loader: 'ts-loader' , options: { appendTsSuffixTo: [ /\.vue$/ ] , } } } , { test: /\.vue$/ , loader: 'vue-loader' , options: { loaders: { 'scss' : 'vue-style-loader' , 'sass' : 'vue-style-loader' } } , exclude: /node_modules/ } , { test: /\.[s]?css$/ , use: [ 'vue-style-loader' , { loader: 'css-loader' , options: { modules: true } } , { loader: 'postcss-loader' } , { loader: 'sass-loader' } ] , exclude: /node_modules/ } ] } シングルファイルコンポーネント用の型定義を追加 拡張子が .vue となっているSFCのファイルをimportするときに、記述されているコードをTypeScriptとして認識できるようにする必要があります。このために以下のような型定義ファイルを作成します。 declare module '*.vue' { import Vue from 'vue' export default Vue } ドキュメントの用意 Vue.jsの公式ドキュメントとは別にBASEの構成で表現するための対応の説明と、順を追って TodoListを作成していくドキュメントを用意をしました。 全体の進行をこれにあわせることで当日参加していない方でも、このドキュメントを上から追っていくとだいたい理解できるようになっています! 当日の様子 そんなこんなで迎えた勉強会当日 Vue.jsを独学で勉強し始めたメンバーやバックエンドエンジニアなど、デザイナー以外もたくさん参加してくれました! 反省と感想 開発環境作りやドキュメントを作りながら、どのような順序でチュートリアルを進め、どのような説明をどのタイミングで伝えたらVue.js初学者にとって分かりやすい勉強会になるかを考えて準備を進めてきました。 実際にVue Boot Camp当日を迎えてみると、進行していくことに精一杯で、参加メンバーの進捗具合など見れない部分が多かったのですが、Frontend Groupのメンバーがフォローに回ってくれたり、Vue Boot Camp専用のSlackチャンネルの中で、参加メンバー同士で参考となるリンクや追加の課題を共有し合ったり、とサポートしてくれたおかげで会を円滑に進めることができました。 参加者の感想のコーナー 楽しかったです!追加の課題なんかも丁度良い難易度に感じました。 第二回目があれば是非参加したいと思います。 題材がちょうど良かったです。 ある程度人集まってしたので色々フォローしてもらったり解説してもらったりすごく有意義でした。 業務でそれなりに使ってる方だったのでまあまあ自信もって臨みましたが、改めてこうやってステップバイステップでやっていく中で、結構基本的なところで理解できてなかった点が色々と発見できたので非常に良い機会でした! このような声をもらうことができたので、第二回目も開催できたら、と思います。 また、今回の記事がBASEアドベントカレンダーの最終日ということで、今までに公開された記事の一覧をご紹介します! 日付 タイトル 12/1(土) エンジニアとしてワクワクし続けるためのエンジニアリングマネージャという役割分担 12/2(日) 君は GitHub の Suggested change を知っているか? 12/3(月) 新任エンジニアリングマネージャ(私自身)を支えてくれた本と言葉 12/4(火) GoのAPI開発現場におけるユニットテストTips 12/5(水) BASE で使っているPHPフレームワークにプルリクエストを送ろうとしたら、先を越された話 12/6(木) 分位点回帰を使って、「その回帰予測どれぐらい外れるの?」を説明する 12/7(金) Abstractを用いたデザイン管理システムを導入して1年経ったお話 12/8(土) 「BASE」の管理画面リニューアルプロジェクトのこれまでとこれから 12/9(日) SQLアンチパターンとBtreeインデックスの関連性 12/10(月) 初めてでも実践できる、挫折しないテックブログ運営~半年間更新0→30本公開しました~ 12/11(火) BASE株式会社を6年間経営して感じた学び 12/12(水) BASEがもっと好きになる。鶴岡さん観察日記 12/13(木) テストを書くモチベーションを上げるための、カバレッジレポート活用方法 12/14(金) デザイナーの私が初めてプロダクトのコードをコミットしてみた! 12/15(土) 日本のパパに、育休のススメ~私の育休体験記~ 12/16(日) デザイン表現が広がる、Lottieアニメーション 12/17(月) グロースハックとディレクションとAndroid開発を経験した1年の振り返り 12/18(火) Data Strategy GroupのAPI開発の挫折とその後 12/19(水) 国内2019年のFinTechトレンド予想(融資・資金調達・ファイナンス領域編) 12/20(木) クラスタリングで時系列予測はできる? 〜Twitterの株価を予測してみた〜 12/21(金) 「Sketchを用いたデザインシステム」を作ってチームでのデザイン作業を効率化した話 12/22(土) ボドゲ最強説 ~BASEボードゲーム部のご紹介~ 12/23(日) BASEのプロダクトマネージャーが大切にしている3つのこと 12/24(月) Goによる静的解析入門 それではみなさん、良いお年を!