TECH PLAY

BASE株式会社

BASE株式会社 の技術ブログ

576

Service Dev所属、サーバサイドエンジニアの宮村です。 現在私は、Service Devのチームに所属し、ネットショップ作成サービス「BASE」及びショッピングアプリ「BASE」の機能開発を担当しています。 BASEでは最近、機能開発の際に設計レビューを行うようにしています。その取り組みについて紹介したいと思います。 開発チームについて BASEの開発チームは、メンバーが増えるに従って専門化する形でチームを分割してきました。 現在、サービスの機能開発を主に担当しているService Dev Sectionは、バックエンドが担当領域を分担して2Group、フロントエンド、ネイティブアプリを担当するそれぞれ1Groupの計4つのGroupから成り、Service Devのエンジニアはいずれかのチームに所属する形となっています。 (組織図について興味を持たれた方は、こちらの 会社説明資料 をご確認いただければと思います。) 機能開発の際はそれらの職能別のGroupを横断する形でプロジェクトチームを編成し、プロジェクトチームが主体となって機能開発を行っていきます。チームのメンバー構成はプロジェクトの特性や規模により様々ですが、多くの場合、同じグループから1〜2名がプロジェクトにアサインされることとなります。 設計レビューを始めたわけ 機能の増加、開発メンバーの増加、並行するプロジェクトの増加により、新しく課題が見えてきました。エンジニアに対して多くのプロジェクトが立ち上がったことで顕著に現れたものもありました。 サーバサイドの領域を専門にするエンジニアが自分以外にプロジェクト内にはいない・少ない状態になるため、機能の品質が個人に依存しがちな状況になってしまっていた。早い段階で多くの目で見ることで、機能の品質を担保したい。 チームのコードレビューのプロセスは取り入れていたが、コードレビューの段階で指摘を受けると手戻りが大きいので、早い段階で既存のシステムに詳しいチームメンバーによるレビューを取り入れ、手戻りを少なくしたい。 コードレビュー時に初めてコードを渡されても仕様把握が難しいので、チームメンバー側が事前に新機能を把握しておきたい。 以前からコードレビューは必須としており、チームで品質を担保することを重視してきていましたが、設計段階でレビューを行うことで改善できることもあるのではないかと思い、設計レビューを始めてみることにしました。 設計レビューの実践 いつやるのか 設計レビューのタイミングは、プロジェクトにエンジニアが参加し、テーブル設計、画面設計がある程度できた頃、実装に入る前を目安としました。これまでの実績では、開発チームのキックオフから数日〜数週間の間に行われています。 どうやるのか プロジェクトの担当エンジニアが、レビュー用のドキュメントを作成します。それをもとに、チームメンバーに説明しフィードバックを受ける形でレビュー会を開催します。対面もしくはオンラインミーティングで、同期的に行うこととしており、所要時間は機能によりますが、30分から2時間程度としています。長くなる場合は、複数回に分けて実施することもあります。 ドキュメントとして必ず用意するようにしているのは、以下の内容です。 データベース設計 一度動き出すと変更のコストが大きいので、ER図を必ず用意して確認するようにしています。 アプリケーションのスケーラビリティ クリティカルな処理への影響 決済などお金に関わる箇所を中心に、不具合が発生すると影響が大きい部分は特に注視します。 その他、画面設計やシーケンス図など、機能を理解するための資料を必要に応じて用意します。 設計レビューを運用してみて 最初にやってみてうまくいかなかったこと 仕様理解のために画面イメージから説明を進めていたところ、機能の仕様やUIへのフィードバックが盛り上がってしまい、時間がかかりすぎてしまいました。サービスに対する思いが各々にあることはとても良いと思いますが、効率の面からはバランスを取る必要があります。 それらの部分は、プロジェクトチームでディレクターやデザイナーも含めて検討されたものであり、一番その機能を考えているのはプロジェクトチームのメンバーということは間違いないでしょう。これらの点についてはプロジェクトチームでの決定を尊重し、設計レビューでは実現方法にフォーカスしてレビューするようにしました。 機能の仕様やUIについては明らかに問題があると考えられる場合のみフィードバックすることにして、再度仕切り直すことにしました。 良い点 進め方は未だ改善を繰り返していますが、総合するとポジティブな面が多いと感じています。いくつかを箇条書きで挙げてみます。 ドキュメントを起こして他の人のレビューを受けるというプロセス自体で、設計が整理される効果がある 担当エンジニアが責任を持って設計するので大筋では問題ないことが多いが、やはりいくつかの有効な指摘がある レビュアが現在担当しているリリース前の機能との整合などを検討できるといったメリットもある レビューを受ける側のメリットとして、まだ実装を始める前なので指摘を受け入れて修正しやすい コードレビューの時点では、当然ですがコードはある程度書き終わっているので、その時点でこの変更は…という躊躇も生まれますが、それがないのは個人的にとても大きいと感じています。 もちろん、このレビューは開発を始める前のプロジェクトチームを含めて新機能に対する理解が深くはないタイミングで行われるので、すべてがここでレビューを受けたとおりには進みませんし、すべての問題を軌道修正できるわけでもありません。ただ、レビューを行ったほうが、開発起因での手戻りや課題が早い時点で発生するようになったというような気はします。 課題や注意点 準備段階に関しては、レビューのフォーマットが各人に任せるのではなく統一したほうがレビューする側がやりやすいのではないかということで検討しています。ただ、プロジェクトの特性などもあるので型を決めて守るというのが最善ではない気がしており、試行錯誤しているところです。 また、レビューまでにどのくらい詰めるか、という点も個人の感覚に頼るところが多いかもしれません。レビューを受けても大きな変更は必要ないだろうという程度には詰める必要がありますが、詰め切るのに時間をかけすぎても機能の提供に時間がかかってしまいます。 やりたいことは Move Fast にプロダクトを改善することなので、それを念頭に置いてよりプロセスの方も良い形に改善していきたいと思います。 設計レビュー後のプロセス 設計が承認されると、それをもとに見積もりを行い、各チームの開発に進んでいきます。この時点でプロジェクトのスケジュール、人員計画の見直しを行うようにしています。とりあえず始めてみて、遅れそうになったところ調整を行うのではなく、この段階で相談できるようになったことも、プロジェクト管理の観点からはポジティブな面と言えるかもしれません。(もちろん、開発開始後でも、必要があれば柔軟に対応していきます。) まとめ メンバーの増加、プロジェクトの増加という状況の中、サービス品質と開発スピードを維持するために、設計レビューを取り入れました。 最初は所属Group内で試験的に行っていましたが、最近では別チームも含め、ほぼすべてのPJを対象にレビューを行っています。また、チーム内でのレビュー後にマネージャやCTOといった意思決定者も交えたレビューを実施するようにもなり、少しずつ役割を広げて運用されています。 より良い開発が行えるよう、私たちも日々試行錯誤しながらやっているのですが、同じような課題を抱える方の取り組みの第一歩として、少しでも参考になれば幸いです。
アバター
BASE株式会社 Product Dev Division 基盤グループ Engineerの田中 ( @tenkoma )です。 ある出来事がきっかけで2要素認証にYubiKeyを購入して使ってみたので紹介します。 フィッシングに引っかからない自信を無くした話 1ヶ月半前の土曜夕方に、外出先で以下のツイートを見ました。 GitHub Japanさんからフィッシングらしきメールが来てたのでみなさんもお気を付けください pic.twitter.com/CsmkObwUS9 — Eiji Kitamura / えーじ (@agektmr) June 13, 2020 ちょうど数時間前に同じメール文面を見たような気がしたのと、同じく数時間前にPCでGitHub.comにログインしていたので、 「これはマズいかもしれない、引っかかったか?」と焦りました。 その場ではパスワード変更だけしました。急いで帰宅して、状況を調べました。その結果— GitHub またはGitHub Japanを騙るメールは見当たらなかった ブラウザの履歴に偽サイトにアクセスした履歴は無かった GitHub.com のSecurity logに自分の部屋とモバイル回線以外のIPからログインされたり操作されたログは無かった ので、フィッシングにひっかかったというのがほぼ思い違いであることがわかりました。(一安心) もしかすると、上記ツイート以外の注意ツイートを見たことを、メールで受信したと思い込んだのかもしれません。 この経験をしたことで、「上記のようなメールを受信したら、冷静にフィッシングかもと疑うこと無く、偽サイトにワンタイムパスワードごと渡してしまうかもしれない、入力情報を中継されたら、ログインされてしまうかもしれない」と思いました。 YubiKeyを購入して、普段の2段階認証にはそれを使う いままで、GitHubログインするときは、ID/パスワード入力には1Passwordを、 2段階認証(2FA)では、Authyを使った時間同期式のワンタイムパスワード(TOTP)を入力していました。 しかし両方とも人間が入力する情報なので、フィッシングで偽サイトにアクセスした場合に、両方を入力してしまうことができます。 (1Password ならURLも保存しておけば、ブラウザ拡張の補完候補で絞り込まれるので、偽サイトにアクセスしたとき、「候補に表示されない」ことで気づける可能性はあります) YubiKeyなどのキーデバイスを使うと、2FAではサーバー側のホスト名なども含め認証に必要なデータを生成します。 よって本物のGitHubログインにつかう認証データを、人間のミスで渡してしまうことはありません。 僕が購入したのは、YubiKey 5Ciです。 Amazon | Yubico - YubiKey 5Ci - USB-C / Lightning 認証セキュリティキー | Yubico | USBメモリ・フラッシュドライブ 通販 ワンタイムパスワードトークンYubiKey |(株)ソフト技研 MacBook Pro, iPhone X, Pixel 4で使いたかったので、USB Type-C, Lightning端子が付いている5Ciにしました。 GitHub.com の2FAにYubiKeyを設定すると、ログインはどうなる? 使い始める前は、「TOTPより面倒くさくなるのでは、端末毎に設定が必要とかだとつらいな」と思っていましたが、むしろ簡単になりました。 設定は、ページにアクセス後、YubiKeyをさして金属部分を触るだけなので省略します。 (日付をみると、GitHubフィッシングが話題になってすぐYubiKeyを買って設定したことが分かります) GitHub.com に設定したデバイスキー一覧 ログインで、ID/パスワードを入力して送信すると、次のように表示されます。 ID/パスワード送信後は、まずセキュリティキーを使った2要素認証をうながされる キーデバイスを設定すると優先してそれで認証するように促されるんですね。 「Use security key」をクリックして、YubiKeyを差し込み金属部分を触ると、ワンタイムパスワードが送信され、ログインが完了します。 僕の場合、Authyを使ったときより簡単になりました。 Authyの場合、 Authyを起動し GitHubのエントリを検索して表示し(設定が15個くらいある) クリップボードにコピーするか6桁の数字を覚え 貼り付けるか入力して送信 という感じなので、検索しなくてよいので楽です。 また、MacのChromeで有効にすると、他のデバイスでの設定は不要です。 FirefoxやSafariでも使えますし、Pixel 4(Chrome)やiPhone X(Mobile Safari)でもYubiKeyでの2FAが出来ました。 他にどんなサービスで使える? YubiKeyが使えるか試したところ、以下のサービスでは使えることが分かりました G Suite GitLab Twitter Facebook Sentry AWSマネジメントコンソール(rootアカウント、IAMともに) AWS 以外ではTOTPとキーデバイスの両方を同時に設定できるので、YubiKeyを紛失したときのリカバリーとしてTOTPも有効にしています。 個人でAWSのrootアカウントを持っているのですが(全然使えていませんが…)、現時点ではTOTPかキーデバイスの片方しか設定出来ず、YubiKeyを紛失したときのリカバリができないため、rootアカウントには設定していません。 まだ買ってないけど、TOTPのかわりに使える方法ってある? YubiKeyを使い始めてから知ったのですが、最近のMacではTouch IDが使えます。 2段階認証が、Touch IDを指で押さえるだけになるので、オススメです。 またPixel 4の顔認証もキーデバイスとして使えました。 iPhone XのFace IDは使えませんでした。 まとめ YubiKeyを使った2段階認証は、お金はかかるけど、フィッシングでの不正ログイン対策になります ログイン操作も、時間同期式のワンタイムパスワード(TOTP)より簡単になりました YubiKey紛失時のリカバリがかなり面倒なので、AWSマネジメントコンソールのrootアカウントは複数の2FAを設定出来るようになって欲しい YubiKey持ってない場合でも、MacのTouch IDやAndroidの顔認証が使える可能性はあります YubiKey、小さいので、財布とかに入れるとすぐに無くしてしまいそうです。 いまのところ、IDカードホルダーに付けているのですが、リモートワークだと常時付けてないので、別のネックレスのようなものか、リストバンドに付けられるといいかもしれない、と思っています。よい案があれば @tenkoma まで教えてください。
アバター
こんにちは。BASE BANK株式会社 Dev Division にて、 Software Developer をしている東口( @hgsgtk )です。 先日開催された July Tech Festa 2020 にて、「 少人数でのアジャイル開発への取り組み実例 (一歩目の踏みだし方) 」という表題で、発表させていただきました。 https://speakerdeck.com/hgsgtk/a-first-step-to-agile-movement 今回はその発表内容について、その思考過程で出会った書籍などを詳説として加えつつ、ブログとして書き下していきます。 発表資料 今回の発表資料は、Speakerdeck に公開しています。 発表内容を通じて解決したいことは、 率直に書くと、 数ヶ月前の自分が教えてほしかったこと です。数ヶ月前の自分は次のような状況でした。 漠然とチーム開発に課題を持っていている その課題に対して、アジャイル関連の施策が、有効な気がしているが、一歩踏み出せていない この資料は、そんな状況を目前としている方々のなにかの役に立てば、と思いまとめたものです。 また、アジャイルと一口に言っても様々な要素が絡んできますが、当該資料は、「チーム環境」に焦点を当てたものです。「 An Agile Way: アジャイルの「ライトウィング」と「レフトウィング」 」の整理では、 アジャイルのレフトウィング (協働でゴールに向かう「チーム環境」)の範囲をスコープとしています。 まずは現状を見る その状況において、私が出会って解決の糸口となったのは、「 みんなでアジャイル ―― 変化に対応できる顧客中心組織のつくりかた 」という書籍です。 www.oreilly.co.jp その中で、次のようなフレーズがありました。 成功するアジャイルの適用は、常に厳しく正直に現状を見ることから始まる。 何がうまくいっていて、何がうまくいっていないのか。アジャイルを今の仕事 のやり方をちょっと変えるだけのことと思っているなら、アジャイルから得られ るメリットもちょっとだけになるだろう。今のやり方を選んだ元になっている現 2章 自分たちの北極星を見つける そして、章の名前「2章 自分たちの北極星を見つける」にある通り、自分たちが大事にしたい・目指したい目標を、言語化することから始めています。 そこからアジャイルとの親和性を考える 自分たちの現状の課題・目指す方向性を言語化出来ると、アジャイル開発の考え方・取り組み方法との対応を考えることができます。 Manifesto for Agile Software Development に示されているアジャイル開発宣言や、「 アジャイルな見積りと計画づくり 価値あるソフトウェアを育てる概念と技法 」にて説明のあるような基本的な仕事の進め方、から、その実践の有無を考察しました。 アジャイルプラクティスを漸進的に導入する すべてのプラクティスを一気に導入することは、手一杯になりますし、一気に生まれた新しい手段・HOWを理解しようとすることに、関心が持っていかれる重力が生まれるでしょう。そのため、優先度にそって、少しずつプラクティスを拡大していくような変遷を、結果的にたどっています。 具体的には、 1. チーム自身の検査と適応 → 2. プロダクトに対する検査と適応 というフェーズをたどりました。 ここで取り組み始めたのは、まずチーム自身の検査と適応のリズムを作ることです。 1週間の スプリント(イテレーション) を設定、最初に計画( スプリント計画 )し、スプリント終了後に、自分たちチームの取り組みについて振り返る レトロスペクティブ を行う 見積もりに、相対的な大きさによって図る ストーリーポイント を利用 現在の状況を可視化するために カンバン管理 を行う カンバン管理は、かつてから Asana を使っていたのですが、うまく管理できていませんでした。今回の取り組みでは、 アジャイルの境界を開発チーム内とした ので、開発作業との親和性を考え、 GitHub Project を利用しました。 それ以外には、日々のコミュニケーションの機会であるデイリースタンディングは、以前から行ってました。 そして、その後、チームが作り出す成果・プロダクトの作り方に対してプラクティスを適用していきました。 プロダクトへのフィードバックループがより頻繁に回るように、スプリントごとの成果物に対する振り返り( スプリントレビュー )を行う フィードバックをもらうために、リリース計画を行う際の前提の考え方を変える( バーティカルスライス でのデリバリーへ) 不確実性を段階的に低減させていく意図 この変遷になった背景には、主に2つの理由を考えていました。 1つ目は、まずは具体的なプラクティスではなく、目標に目を向け、その方法の WHY に着目し、自身の取り組み・振る舞いに対する検査と適応のリズムを作り出すのを優先するという意図。 2つ目は、「 アジャイルな見積りと計画づくり 価値あるソフトウェアを育てる概念と技法 」にて紹介されている、開発プロジェクトの不確実性の考え方「 Alexander Lauferの不確実性理論 」です。この概念では、プロダクトにおける不確実性を次の2つに整理しています。 目標の不確実性 (end uncertainty) (開発PJに対応させると、)何を開発するのか、スコープ・プロダクトの性質 方法の不確実性 (means uncertainty) (開発PJに対応させると、)どうやって開発するのか、技術・スキル・連携方法 すべてのことを一気に片付けようとすると混乱が生まれがちです。そのため、まずは、チームの連携方法や動き方、についての方法の不確実性を低減させ、その後「どういうプロダクトを作るのか」という目標の不確実性を低減させるような取り組みを続ける、フェーズ分けとなりました。 バーティカルスライスでのデリバリーを前提とする 「プロダクトに対する検査と適応」を考えると、その具体的な施策は、プロダクト成果物に対するレビューを行うスプリントレビューが、一つ考えられます。これは、そもそも、イテレーションで生まれる成果物(スクラムの言葉では「インクリメント」でしょうか)に対して、フィードバックが得られるような計画をしていることが前提にあります。その前提において重要なことが、 バーティカルスライスでのデリバリー でしょう。 これは、「 More Effective Agile “ソフトウェアリーダー”になるための28の道標 」という書籍では、より効果的にアジャイルの価値を引き出すための一つの基本原則としても紹介されています。 短いスプリントがうまくいくには、動く機能を少しずつ頻繁にデリバリーする能力をチームが養わなければならない。こうした活動をサポートするために用いられる設計アプローチはバーティカルスライスと呼ばれる。バーティカルスライスは、増分的に機能または価値をデリバリーするために各アーキテクチャ層で変更を行う、というものである。 9.4 基本原則:バーティカルスライスでのデリバリー つまり、「XxxAPIを実装します」・「テーブルの設計をします」といったレイヤごとの 作業ではなく て、「ユーザーとして自身のメールアドレスを変更できる」といったように、 一つのフルスタックの機能 を指します。 実際に、プロダクトに対する検査と適応のループを回そうとすると、この考え方が必要になってくるため、リリース計画自体もこの考え方を前提にリプランニングをしました。 取り組みを始めてから 実際にこのような取り組みに踏み切ったのは、COVID-19の流行がはじまった今年の春からの話です。しかし、1weekのスプリントを通して、チーム開発についてのフィードバックループが、以前よりも早く回っていることを感じます。 具体的に目に見えるような差で言うと、JTF2020から2月弱前の2020年6月4日に、コネヒトマルシェというイベントで「 小さなチームが始めたアジャイル開発 」という発表をしました。目指す方向性は変わっていませんが、その中のチームの取り組み・実装方法は改善され、変容を遂げています。 チームやその周りを取り巻く状況は日々変わっていきますが、その不確実性の高い外部要因に対しても、スプリント単位での適応の議論ができているように感じています。 さいごに:July Tech Festa 2020 への謝辞 July Tech Festa 2020 とは、2020年7月25日(土)に開催された、カンファレンスです。今回、600名強?の参加申込みがあったとのことした。 techfesta.connpass.com ITに関わる全ての人の知的好奇心を満たすお祭りを作りたい。 その思いからJuly Tech Festaは生まれました。 興味のある技術に触れ、普段会えない人の話を聞き、 参加したエンジニアがスキルやキャリアについて考えるきっかけになれば。 そんな場を作ろうと今年も July Tech Festa 2020 を開催します。 個人的な話で恐縮ですが、自分が社会人エンジニアになってから初めてカンファレンス参加したのが、July Tech Festa でした。たしか July Tech Festa 2016 だったと思います。その際、「外の世界は想像以上に先へ進んでいる...!」と衝撃を受け、今回のカンファレンステーマであるように「 Extend Your Engineering Life! 」したことを、強い記憶として思っています。今回、そんなJuly Tech Festaのスピーカーとしてプロポーザルを採択いただいたのは、感慨深い想いでした。 今回、初のオンラインでのカンファレンスのなか、運営スタッフの方々には、この場を借りて感謝申し上げます。ありがとうございました。
アバター
CTOの川口です。 今回はアプリケーションのエラートラッキングツールについてです。 これまでの経緯 BASEでは主にPHPアプリケーションのエラートラッキングにRaygunを利用していました。 https://raygun.com/ これを採用したのは3年以上前で、当時BASEではPHP5.3を利用していたために利用できるツールは限られておりRaygunはPHP5.3でも動いたため採用されたようです。 今では7.3を利用していたのでこの条件は気にする必要はありませんが、積極的に変更する理由もなく使っていました。 当初はPHPのエラートラッキングにのみ利用していましたが最近はfrontendのエラートラッキングにも利用しています。 ここが辛いよRaygun まず料金が結構高めです。 APMやRealUserMonitoringなどの利用はしておらずエラートラッキングのみ使っています。 https://raygun.com/platform/crash-reporting APMはPHPに対応していませんし元々Newrelicを利用しています。 small business プランを利用しており、$249/month です。 https://raygun.com/platform/crash-reporting#pricing これは非常に高額というほどでもありません。 ですが、更にこの上のプランになると$899と一気に値段があがります。これは一気に高額になります。 これのしきい値がエラーイベントの件数になっており、月間の件数を超えてしまうとプランを変更する必要があります。 25万エラーを超えて100万エラーまで受け付けてくれるのはありがたいですが、結果的には30万イベント程度で済むであろう事が想定されコストパフォーマンスが悪くなります。 さらにRaygunはあまりPHPのサポートに積極的でなく、UTF-8以外を含むと問題が出たりします。 https://github.com/MindscapeHQ/raygun4php/pull/69 https://github.com/MindscapeHQ/raygun4php/pull/69#issuecomment-514351759 https://github.com/MindscapeHQ/raygun4php/issues/94 PRに対する反応も鈍いため弊社ではforkしてパッチを当てて運用していました。 WEB UIもあまり良いものでなく全体的に遅く、日付範囲でのサマリなどがし辛いと感じていました。 GitHubへのissue連携も古いAPIなどを利用しているようで、Raygunへ渡す権限があまりに強くこのあたりも問題です。 別のエラートラッキングツールに変更も話題には登っていましたが、ずるずると先延ばしていました。 エラー量増加に依るトラッキングの停止 現在のプランでは250,000 error events/monthを処理することが出来ます。 基本的にこの数を超えることはないのですが、ミドルウェアの変更などで想定外のエラーが出たりするとアクセス量が多いサービスの場合エラーイベントが一時的に大量に発生します。 ある時、これが複数回起きてしまいlimitを超えてしまいました。 完全にトラッキングが止まったわけではありませんが、エラートラッキングツールとして常用出来ません。 当然プランを上げれば動作するわけなのですが、3.5倍近い値段を払ってまで?という気持ちもありこのタイミングで乗換を検討しました。 Raygunのようなサービスでは過去のデータはそこまで重要度は高くありません。 まだ修正出来ていないエラーが有る場合別のトラッキングツールに乗り換えたところで発生することはわかっているので改めて収集すればいいので問題にはなりません。 料金も安く、機能的に優れているものに乗り換える方がメリットになると考えました。もちろん安いからと言って機能が十分でなければraygunでもいいですし別の高額なツールでも問題はありません。 乗り換え先 同様のエラートラッキングツールはいくつかあり Bugsnag Rollbar newrelic Airbrake などがあります。 今回は弊社で利用したことがあるメンバーもいたので、Sentryにすることにしました。 値段もRaygunより安価ですし、機能も豊富そうに見えます。 仮に特定の月にエラーが大量に発生しても、その量に応じて追加課金になるので今回のような事態になっても毎月のプランまで変える必要がなくて安心感があります。 https://sentry.io/pricing/ https://docs.sentry.io/accounts/pricing/#faq 14日はトライアルもできるので一時的な乗り換えに使って不満があればRaygunに戻る事もできます。 SDKも用意されています。弊社で使っているCakePHPを完全にサポートされているわけではないですがRaygunを利用しているコードに少し修正を加えるだけで動きそう、ということで移行をはじめました。 https://sentry.io/for/php/ 移行の実装は数時間で完了しました。 ここがすごいよSentry Sentryのエラートラッキング自体はraygunと別に変わりはありませんが、圧倒的に多機能である事がわかりました。 WEB UIを見てみると、動作も速く情報量が非常に多くあります。 Raygunの場合、環境毎にアプリケーションを登録しapi keyを差し替える必要がありますがSentryの場合はenvironmentを指定することで一つのアプリケーションとして登録することが出来ます。 特に便利だと感じたのはエラー時のスコープにある変数がSentry上で確認できるので、どのような変数によってエラーが起きるのかの調査が捗ります。 下記のような事象は「Undefined index: id」というエラーが発生した場合の表示です。 $favorites に特定indexのみないのかそもそも空を参照していたか、というのが判断可能であり、さらにitem_idも空配列ということがわかるのでなぜこのようなエラーが発生したかの調査にとても有用です。 error PHPのコードも一部表示されるので出先でちょっとした調査くらいならできそうです。 とはいえ勝手にSentryにコードがアップロードされているのでは?ということでセキュリティ的にちょっと心配になるのも事実です。 Spike Protectionという機能がデフォルトでオンになっており、一時的に大量にイベントが発生した場合などにイベントを破棄してくれるようです。 DB障害などがあると全てのアクセスでエラーイベントが発生し情報の精度は下がりつつイベント回数を消費してしまい課金額が上がってしまいがちですがこれはそれを回避してくれそうです。 https://docs.sentry.io/accounts/quotas/?_ga=2.25032318.591036687.1594604704-646375577.1594038001#spike-protection docs.sentry.io ここがつらいよSentry トライアルしている状態なので明確な不満があるわけではまだありません。 通知も細かく設定できるのですが、ここはちょっと慣れていないと大変だなという印象です。 RaygunはとりあえずSlack通知くらいだったらwebhookのurlを渡せばよかったのですが、どういう条件で通知するかというのを登録しないといけないので慣れるまでは戸惑いがありました。 他には「Allow Shared Issues」という機能がありカジュアルにエラーのURLを公開出来てしまうのは危険なのでオフにしました。 多機能であるがゆえに、どこを見ればいいか迷ってしまうなとは感じています。あまりにシンプルだったRaygunからの移行なため余計にそう思ってしまうのかもしれません。 おわりに まだトライアル段階なので使いこなせているというほどではないですが、SentryはRaygunよりも優れているツールだと感じました。 もちろんエラーは通知さえできればいいというものではなく解消していき狼少年にならないようにアプリケーションを改善していくことが重要ですが、どのような場合にエラーが出ているのかの調査がわかりやすく改善もしやすいです。 どのデプロイによってどのようなエラーが引き起こされたか、などを観測していきアプリケーションの改善に役立てていきたいと思います。
アバター
フロントエンドチームの右京です。 Vue.js 3 が 八月上旬にリリース予定 ということで、BASE でもバージョンアップに向けて少しづつアクションを始めています。 Vue.js 3 では多くの機能が追加され開発の幅が広がりますが、一方で削除や非推奨となる機能も多く頭を悩まされている方もいるのではないでしょうか、BASE もそうです。 この記事では ESLint とその Vue.js 向けプラグインの eslint-plugin-vue を利用した、deprecated となる機能へのアプローチを紹介します。 なぜ eslint-plugin-vue か ESLint には Vue.js の SFC のためのプラグインとして eslint-plugin-vue が開発されていて、BASE でもこれを利用しています。 このプラグインには vue/no-deprecated- で始まるルールがいくつかあります。これは非推奨になった機能を使用しているかどうかを検出するためのルールです。 これまでは Vue.js 2.6 で非推奨になった slot と scope に関する以下のルールのみでした。 vue/no-deprecated-slot-attribute vue/no-deprecated-scope-attribute vue/no-deprecated-slot-scope-attribute しかし、最近リリースされ開発の勧められている v7.0.0-alpha.x で多数のルールの追加が行われています。 例えば BASE の場合、Vue.js 3 の移行で特に課題だったのが filter の廃止です。 金額の変換に多くの filter を使用していたため、範囲も広く置き換え方法を模索していたところでした。 eslint-plugin-vue では、これを vue/no-deprecated-filter ルールを適用することで検出することできます。 このほかにも多数のルールが現在進行形で追加されています。 ルールの一覧は 7.0.0-alpha.x タグの docs や、@ota-meshi さんによる日本語での解説から参照できます。 https://github.com/vuejs/eslint-plugin-vue/tree/v7.0.0-alpha.9/docs/rules https://qiita.com/ota-meshi/items/ff0d70ef326657249727 BASE では多数あるルールの中でも、特に効果の大きそうな <template> に関するルールを中心に追加していくことにしました。 <script> 部分には vue-class-component を使用していることもあり、一旦優先するべきところではないと判断しています。 Monorepo と GitHub Actions を利用した別ラインでの継続的な改修 現行の Vue.js 2.x での開発ももちろん行われているため、突然 ESLint のルールを変更するのはハードルが高く感じ、しばらくの間は既存のルールを共存させることにしました。 これを実現するため、 yarn workspace で Monorepo として 7.0.0-alpha.x をインストールし、普段使用しているものとは別のルールを適用できるようにしています。 . ├── packages │ └── eslint-for-vue3 │ ├── node_modules │ │ └── eslint-plugin-vue // 7.0.0.alpha-x │ ├── .eslintrc.js // Vue 3 に向けた設定 │ └── package.json ├── node_modules | ... │ ├── eslint │ └── eslint-plugin-vue // 普段使っているバージョン ├── src // lint する対象 ├── .eslintrc.js // 普段使っている設定 ├── package.json └── yarn.lock eslint-for-vue3 の package.json で 7.0.0-alpha.x を dependencies に追加します。そして、この Monorepo のコンテキストで ESLint を実行する scripts を設定しています。 { " name ": " @base/eslint-for-vue3 ", " private ": true , " dependencies ": { " eslint-plugin-vue ": " 7.0.0-alpha.9 " } , " scripts ": { " lint ": " eslint -c ./.eslintrc.js --ext .vue ../../src " } } .eslintrc.js には普段使用しているルールに加えて、 vue/no-deprecated-* のルールを追加しています。 module.exports = { extends : "@baseinc/eslint-config-base" , rules: { 'vue/no-deprecated-slot-attribute' : 2, 'vue/no-deprecated-scope-attribute' : 2, 'vue/no-deprecated-slot-scope-attribute' : 2, 'vue/no-deprecated-filter' : 2, 'vue/no-deprecated-v-bind-sync' : 2, 'vue/no-deprecated-v-on-number-modifiers' : 2, 'vue/no-deprecated-events-api' : 2, 'vue/no-deprecated-functional-template' : 2, 'vue/no-deprecated-html-element-is' : 2, 'vue/no-deprecated-vue-config-keycodes' : 2, 'vue/no-deprecated-dollar-listeners-api' : 2, 'vue/no-deprecated-v-on-native-modifier' : 2, 'vue/no-deprecated-dollar-scopedslots-api' : 2, } } この状態で以下のコマンドで、普段使っているものとは別のルールを適用した ESLint を実行できます。 $ yarn workspace @base/eslint-for-vue3 run lint 対応が終了したらこの .eslintrc.js を普段使うものに昇格させ、Monorepo を削除してしまえばあとの片付けも簡単です。 GitHub Actions でデイリービルドを構築し、モチベーションを高める フロントエンドチームでは毎日十四時ごろからスタンドアップミーティングを行っており、これに合せて ESLint を実行するような GitHub Action を設定しています。日々進捗を確認する機会を設けることで、Vue.js 3 へのモチベーションも高めるようにしています。 name: lint for Vue.js 3 on: schedule: - cron: 0 5 * * * jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: node-version: '12.x' - uses: actions/cache@v1 with: path: node_modules key: ${{ runner.os }}-lintvue3-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-lintvue3- - run: yarn install --pure-lockfile --ignore-optional --network-concurrency 1 - run: yarn workspace @web/eslint-for-vue3 run lint - if: failure() env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} run: | curl \ -X POST\ --data-urlencode "payload=\ {\ \"text\": \":bomb: Vue.js 3 マデアト: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID} \",\ }"\ ${SLACK_WEBHOOK} 以上です。 まとめ ESLint を利用した比較的気軽に導入できる Vue.js 3 への対応方法を紹介しました。 もちろんこのエラーがなくなったからといって Vue.js 3 への対応が終了するわけではありませんが、対応のとっかかりなどになれば幸いです。 ちなみにですが、特に Vue.js の比率の高いリポジトリにこれを実行した結果は以下でした。 ✖ 500 problems (500 errors)
アバター
こんにちは!デザイナーの渡邊です。 今年の5月に入社し、UIデザイン業務などを担当しています。リモート下でチームメンバーとなかなか直接会えない状況ですが、毎日楽しくお仕事させていただいております! そんなリモート中でも、活発に新たな知見を得たり情報交換をしていこうと、BASEでは『BDI NIGHT』という勉強会を行っています。 今回は『BDI NIGHT』ロゴの制作過程についてお話します! そもそも『BDI NIGHT』とは? 2018年の秋頃から活動している、BASEのデザイナーがやりたいことを持ち寄って、デザインに関する幅広い知見をみんなで楽しく学ぶことを目的とした任意参加の社内勉強会です。 デザイナーだけでなく誰でも参加することができ、時々PMやエンジニアが覗きにきてくれることも! 『BDI』は「BASE Design Inspiration」の略。Inspirationの名の通り新たなひらめきにつながる新しいトピックを取り上げることも多くあります。 『NIGHT』がつく理由は主に夜に開催されること、また仕事よりちょっとリラックスモードで、お酒やお菓子などを片手に気軽に参加してほしいなという想いからついたそうです。 今までに行ったBDIの例だと Figma講座 フォントかるた webレイアウトトレース アプリトレース 内製UIコンポーネントライブラリ「bbq」のロゴを作る Instagramのデザイナードキュメンタリーを見る 開発ブログの微妙なとこ洗い出し カスタマージャーニーワークショップ などなど....勉強だけでなくコミュニケーションの場としても活用しています。 『BDI NIGHT』のロゴをつくろう! BDI NIGHTのお題としてこの勉強会のロゴを作ることに。ロゴ決定までの全3回を振り返っていきます! 1.BDIを知る・分析する DAY1では新入社員の私が参加するということで、改めてBDIについての概要を教えていただきました。 その後、BDIをどう思っているか、どんな場にしたいかを明確にするためにmiroを使ってブレストを行いました。 ざっくりとですが「自由度の高さ」や「わいわい感」「敷居の低さ」などに関わるキーワードが多めの印象でした。 「なるほど、堅苦しさや過度なアカデミック感を出すと温度感がズレてしまうかも...?」などの見当がつき、BDI初参加の私にとって大いに参考になるありがたい時間でした。 2.デザイン制作 第1回の後半〜第2回はみんなで作業タイム。 zoomを繋ぎ、雑談しながら資料探しやラフ作業などを進めていきました。 個人的にですが人と話ながら作業をするとかなり手が進みます!特にラフなどの精密さよりも量や勢いが必要な作業は特に...。オフィスなら何気なく隣の人とお話したりできますが、リモート下だとこういったコミュニケーションも少なくなっていたので、久しぶりの感覚でとっても楽しかったです。 私のデザインの進め方 デザインの進め方は人それぞれですが、一例として私の進め方を紹介します! とりあえず資料をpinterestで集め 「なんかいい感じなの作りたい...」ぐらいのゆるい感覚でロゴを眺め観察します 「BDI」と短いアルファベットなので、文字そのものにユーモアな図案が加わってるものorグラフィック主体のロゴじゃないと持たなそうだな....など考えながら見当をつけてピンしていきます BDIのらしさを演出するアプローチを複数考えながらラフを書く ラフを出す際は似たような案が並ばないよう、がっつり見た目が変わることを意識します。アプローチから全然違う考え方にするとアウトプットがばらけて良い感じに! インパクトある象徴的なグラフィックをメインにしたい→ひらめきの象徴の電球を使いたい、それだけだと情報量すくないので、手を入れたり背景に星空いれたり... 勉強会であることをアイコン化したい→知見を得る....インストールアイコンとかを落とし込む?先進感・シンプル・ラボっぽさ 勉強会なんだけども、敷居を低くしたいという意志を汲みたい→BARとかお酒みたいな夜の楽しいプライベートな雰囲気 ラフを書きながらもpinterestに戻って、どうやったら想像してる図案がうまいこと収まるのか、参考資料を集めたりを繰り返します。 ラフはipadで書いてます。 気に入った案をブラッシュアップしながら、オリジナリティを担保する 資料をいっぱい見ながら書いていると、資料にデザインが似てくることがかなりあります。他のデザインと差別化できるオリジナリティを加え、影響を受けていると思われる資料からはリスペクト精神を持って意識的に離していきます。 トレスやレイアウトの一致などのトラブルが起こらないよう、パーツは01で手書きで書き起こしたりします。 イラストレーターで整え、仕上げ加工などする Aiを使ってガッツリ詰めていきます。基本的にはモノクロで制作→コントラストがあってちゃんと視認できるかチェック→着彩の順に進めています。 打ち文字をそのまま使うことはせず、基本的にはアウトライン化してバランスを見ながら調整します。 3. お披露目&投票タイム 最終回でメンバーの案をお披露目!各案にコンセプトを添えて、自身の作品を紹介していきました。1つのお題でも製作者によって全然解釈が違い、個性的なロゴが集まりました。 各自コンセプトを発表した後、1人3票で好きなロゴに投票する形で決定しました。 最終的に投票で私の案が選ばれました...!ありがとうございます...! 採用されたロゴ 結果、こちらの案が採用されました!BASEの象徴ティピからひらめきを外に向けて発信するイメージの図案です。グランジの加工を施し、ティピ×夜=ナイトキャンプな雰囲気に仕上げました。 グランジ加工はwebにおいてはあまり相性が良くなく、サイズによっては潰れてしまうこともあります。 グランジは私の好みで付けた点でもあるので、どんな環境でも快適に使ってもらえるようにグランジ無しverと横組verも用意しました。 また、slackのコミュニケーションのために小さくても視認性をある程度保った絵文字verも用意しました。割と好評でうれしかったです! まとめ 普段UIデザインの仕事がメインの中、他のメンバーのグラフィックデザインを見れた事が新鮮でとっても楽しかったです。発想も1人1人全然違い、自分では考えつかないような素敵な案が沢山出ていました。 UI/UXと違ってロジカルには解決しづらいグラフィックデザイン領域ですが、こういった解釈の広がりを見ると明確な答えがないからこその面白さを改めて実感します。 柔軟な発想力を持って、これからも色々なデザインにチャレンジしていきたいと思います!次のBDI NIGHTが待ち遠しい...!
アバター
こんにちは。BASE BANK株式会社 Dev Division にて、 Software Developer をしている東口( @hgsgtk )です。私のいる開発チームでは、アジャイル開発の考え方・取り組みを取り入れています。アジャイル開発の導入については、「 小さなチームが始めたアジャイル開発 」という資料を公開しています。 今回は、アジャイル開発において、重要な振り返りについて、 Mad Glad Sad(喜、怒、哀) というレトロスペクティブ(振り返り)のワークを紹介したいと思います。 TL;DR Mad Glad Sad(喜、怒、哀)は、感情データを集めるためのワーク イテレーションで起きた、喜んだり、怒ったり、哀しかったりした時間やイベント、を書き出していくイベント 素直な感情ベースでイベントを振り返ることで、 "理性のフィルター"で見つからない潜在的課題をチームが見つける きっかけになる Mad Glad Sad(喜、怒、哀)とは レトロスペクティブのワークの一つです。感情データを集めるために使用する取り組みです。このワークは、「 アジャイルレトロスペクティブズ 強いチームを育てる「ふりかえり」の手引き 」で、データを収集するアクティビティとして紹介されてます。 このワークでは、イテレーションで起きた、喜んだり、怒ったり、哀しかったりした時間やイベント、を書き出していきます。書き出されたそれらのイベントを深堀りしていきながら、グルーピングしていきます。 「 アジャイルマニフェスト 」では、 プロセスやツールよりも個人との対話に価値を置いている ことを宣言しています。 また、「 More Effetive Agile ソフトウェアリーダーになるための28の道標 」では、 ソフトウェアチームのEQ(Emotional Intelligence、感情知性)向上の重要性 を示しています。 自分の感情の状態と他者の感情の状態によく注意し、感情をうまくコントロールし、他者との良好な関係を築くことは、技術職メンバーにとってプラスに働く可能性がある。 チーム開発において、自己・他己の感情に向き合うことは、個人との対話に価値を置くアジャイル開発の価値をより引き出すために重要と言えます。 Mad Glad Sad(喜、怒、哀)は、そんな自己・他己の感情に向き合うきっかけとなります。 オンラインワークにmiroを用いる 2020年7月8日現在、WFH(Work From Home)での業務のため、オンラインでのレトロスペクティブを行っています。オンラインでのコラボレーションツールとして、 miro を使用しています。 miroには、テンプレートがいくつか用意されていますが、その中に「 Retrospective Mad/Sad/Glad 」というテンプレートがあります。miroで同じく実施してみる場合、こちらのテンプレートを使うと手軽に始められそうです。 miro.com 実際に実施したワーク 実際に、本ワークを実施した際のmiroのボードです。 (中身はお見せできないのですべてxxxxになっています。「実際にどういう話があったの?」と気になった方は、お気軽にカジュアル面談などでお話しましょう...!) open.talentio.com 書き出しやすいように、Mad Glad Sadは、次にように翻訳していきました。 Mad: イラッとしちゃったこと Sad: 内省したこと Glad: 楽しかったこと 書き出されたイベントは、それぞれ深堀りしていくなかで、チームにとっての「やっていったほうがいいこと」が見つかってくるので、それらは"Action Item"とつなげています。これは、「 アジャイルレトロスペクティブズ 強いチームを育てる「ふりかえり」の手引き 」で紹介されている深堀り質問例のひとつ 次に行うべきステップは何か? に対する議論の結果をカードとして言語化しています。 どういう効果があったか 言語化しきれていない生の感情データが浮き彫りになる よく用いられる振り返り手法としては、KPT(Keep Problem Try)がありますが、人によっては個人的な課題を、あげることをためらってしまうことがあるかと思います。たとえば、「個人的にはこの作業はやらないといけないことがわかっているが、ちょっとしんどい」や「他チームとの調整において、ちょっともやっとした」といったものが例で挙げられます。 こういった課題は、論理的に言語化しきれていないものだったりするので、チームのProblemとして上げづらいこともあるでしょう。 感情ベースのデータ収集であることがワークとして明確なMad Glad Sadは、こういった発生イベントを明らかにしてくれます。 深堀りしていく中でチームとして取り組むべき潜在的課題が見えてくる 浮き彫りになったイベントに対する感情データに対して、深堀りしていくなかで、チームとしての潜在的課題が見つかってきます。 たとえば、「アルゴリズム設計の心理的負荷が、チームで背負いきれていない」、といった課題がワークを通じて発見されました。 KPTを重ねてきた中では明らかになっていなかった課題だったため、感情データに着目するこのワークが、潜在化された課題を見つけるきっかけになりました。 最後に チームの取り組みを振り返るワークの一つして、まだ試していなければ試してみてはいかがでしょうか。なにか新しい自分たちが見つかるかもしれません。
アバター
こんにちは。BASE BANK株式会社 Dev Division にて、 Software Developer をしている東口( @hgsgtk )です。Stay Homeで仕事していく中で、ちょっとした面倒事を解消するような小ネタが溜まってきたので、一つお届けします。 TL;DR リポジトリ作成時には、毎回CIの設定・ .editorconfig ・ .gitignore の配置、最低限のHello Worldコードの作成など、定形作業が存在する 自分たち用のボイラープロジェクトを作成するCLIを用意するのも一つの手だが、気軽にサクッと出来る方法として、GitHubのTemplate Repositoryがある Goプロジェクト作成時に実際に活用しているTemplate Repositoryをご紹介する 背景 BASE BANKでは、「 YELL BANK(エールバンク) 」というサービスの開発・運営を中心に、Goを用いてアプリケーション開発を行っています。 よくある面倒事として、新規にGoプロジェクトを作成する際に毎回作業するようなCI (Contenious Integration) の設定などがあります。 これは、Go言語に限った話ではありませんが、新規リポジトリを作成すると毎回脳死してコピペを行いがちなものがあります。 今回は、そんな面倒事をGitHubのTemplate Projectを用いてちょっとだけ省力化するお話です。 GitHubのTemplate Repositoryとは Template Repositoryとは、「 テンプレートリポジトリを作成する 」で説明のある通り、既存のリポジトリをテンプレートにして同じディレクトリ構造・ブランチ・ファイルで新しいリポジトリを生成できるようになる機能です。 既存のリポジトリをテンプレートにして、自分や他の人が同じディレクトリ構造、ブランチ、およびファイルで新しいリポジトリを生成できるようにすることができます。 help.github.com 始め方は、非常にかんたんで、リポジトリの Settings にて、 Template repository にチェックを入れるだけです。 こうして、チェックを入れると、新規リポジトリ作成時に、次のようにテンプレートが選択できるようになります。 実際にテンプレートを選択すると、Template Repositoryの内容をコピーした形で新規リポジトリを作成できます。この機能を用いて、自分たちの定形作業をTemplate Repositoryに入れておくと、面倒事を少し解消することができます。 以下、具体的にどういう内容を入れているか、実際に活用しているGoプロジェクト用のTemplate Repositoryをご紹介します。 どういうことをしているか BASE BANK Devでは、Goアプリケーションの新規リポジトリを作成することが多いのですが、次の内容をTemplate Repositoryに入れています。 CircleCIの設定 GitHub Actionの設定 Hello WorldなGoコード( go.mod ・ go.sum と一緒に) $ tree -L 2 -la . ├── .circleci │   └── config.yml ├── .editorconfig ├── .github │   ├── PULL_REQUEST_TEMPLATE.md │   └── workflows ├── .gitignore ├── .golangci.yml ├── README.md └── app ├── Dockerfile ├── Makefile ├── go.mod ├── go.sum └── main.go CircleCIの設定 GoコードにおけるCircleCIの自動Lint・テストは、次世代型イメージのcimg/goを使用した設定をしています。毎回コピペするのも面倒なので、レポジトリ作成時に生まれてくれると面倒事をさばく人生の時間が減って少しだけ幸せです。 version : 2.1 jobs : test-app : environment : TZ : "Asia/Tokyo" GO111MODULE : "on" docker : - image : cimg/go:1.14.4 environment : GOCACHE : "/tmp/go/cache" TEST_RESULTS : /tmp/test-results steps : - checkout - run : mkdir -p $TEST_RESULTS - restore_cache : key : gopkg-{{ checksum "app/go.sum" }} - run : name : mod download command : | cd app go mod download - save_cache : key : gopkg-{{ checksum "app/go.sum" }} paths : - /home/circleci/go/pkg/mod - restore_cache : keys : - build-cache-{{ .Branch }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }} - run : name : install-gotools command : | cd app go get github.com/fzipp/gocyclo - run : name : build command : | cd app mkdir -p $GOCACHE go build -v - run : name : test command : | cd app gotestsum --junitfile ${TEST_RESULTS}/unit-tests.xml -- -p 6 -race -cover ./... - run : name : calcurate-cyclomatic-complexities command : | cd app gocyclo -avg $(find . -name "*.go" | grep -v _test) - save_cache : key : build-cache-{{ .Branch }}-{{ .Environment.CIRCLE_BUILD_NUM }} paths : - /tmp/go/cache - store_artifacts : path : /tmp/test-results - store_test_results : path : /tmp/test-results workflows : version : 2 test : jobs : - test-app この設定内容自体については、同僚の @budougumi0617 さんが「 [Go]次世代イメージcimg/goとcircleci/go Orbsを使った2020年版CircleCIの環境構築 」で解説しているのでそちらをご覧になってみてください。 budougumi0617.github.io GitHub Actionの設定 .github ディレクトリ以下も、おまじないのように作るものが多い場所の一つでしょう。たとえば、 PULL_REQUEST_TEMPLATE.md などは初手で作ることが多いです。それに加えて、GitHub Actionの設定もある程度共有できるものが多くなるため、それらもTemplate Repositoryという形で共有しています。 ReviewDogによるgolangci-lint実行 GoコードのLintにgolangci-lintを用いているのですが、その指摘内容をGitHubのコメントとして反映するため、ReviewDogを用いています。 具体的には、 reviewdog/action-golangci-lint を活用しています。 github.com 実際に行っているのは、公式の解説どおりですが、以下のような設定を配置しています。 name : reviewdog on : [ pull_request ] jobs : golangci-lint : name : runner / golangci-lint runs-on : ubuntu-latest steps : - name : Check out code into the Go module directory uses : actions/checkout@v1 - name : golangci-lint uses : reviewdog/action-golangci-lint@v1 with : github_token : ${{ secrets.GITHUB_TOKEN }} golangci_lint_flags : "--config=.golangci.yml ./..." golangci-lint自体の設定もTemplate Repositoryに同梱しているため、レポジトリを作成すれば即座にgolangci-lintのチェック下に置かれます。 Hello WorldなGoコード Go Modulesを用いる前提で Hello World コードを用意しています。主にAPIサービスを作る際に、 app/ ディレクトリ以下にアプリケーションコードを置くことが多いため、 app/ 以下にmain.goを配置します。配置しているコードは、Go公式ブログの「 Using Go Modules 」に例示されているコードを微修正して置いています。 package main import ( "fmt" "rsc.io/quote" ) var ( revision = "default" ) func main() { fmt.Println(hello()) } func hello() string { return quote.Hello() + "by " + revision } また、テンプレ的に毎回用意するようなDockerfileも合わせて用意しています。 FROM golang:1.14.3-alpine3.11 as deploy-builder WORKDIR /app RUN apk add --no-cache git ENV GO111MODULE=on COPY . . ARG REVISION="default" RUN go build -ldflags "-X main.revision=${REVISION}" FROM alpine as deploy RUN apk add --no-cache tzdata && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ echo "Asia/Tokyo" > /etc/timezone COPY --from=deploy-builder /app/app . CMD ["./app"] これらでどう嬉しくなったか 上記で紹介した以外にも脳死してコピペしていた .editorconfig なども最初から用意されるので、新規リポジトリ作成時の心のハードルが下がりました。 これからの課題としては、既存リポジトリの知見をTemplate Repositoryに反映していく流れや、デプロイフローについてのある程度の共有を図りたいと思っています。 最後に Template Repositoryは、とくに特別な工数が発生するわけではない手軽な方法として、身近な面倒事を減らせる手になります。活用の仕方として参考になれば幸いです。
アバター
こんにちは。BASE株式会社 取締役EVP of Developmentの藤川(えふしん)です。 新型コロナの影響で、広告やインバウンドなど成長と期待されてきたWebサービスの分野によっては採用等を抑える動きがある中で、多くの商品ジャンルを取り扱えるECプラットフォームを担う当社の採用活動に関するスタンスは引き続きポジティブです。その中で、解決したい問題についてお話させていただければと思います。 技術課題1:コンポーネント化、アーキテクチャ刷新に対する学習コストへの適応 手前味噌ではありますが、「BASE」はサービスを止めずにアーキテクチャを進化させてきました。本来であれば、BASE バージョン2のようなものを別ラインで作って入れ替えるような作業を、CTO、テックリードの元で動的にサービスを入れ替える形で実現しています。 思い起こせば、元々の「BASE」は、よくもわるくも、ただのシンプルなCakePHP2を活用したWebアプリだったように思えます。ソースコードは多いながらも、一つ一つは低い学習コストのpost / getとデータベースへの入出力コードの繰り返し。これを駆使してサービスを作ってきました。 それ故に、オンボーディングのコストは比較的低かったものの、増えゆくソースコードの中で全体の冗長性、複雑性は上がっていくばかり。 開発工程が破綻しなかったのは「シンプル」を売りにするからこそのサービス性に恵まれたところは否めません。 しかし、サービスがシンプルであるということには、時に高度さを求められるところがあります。 ユーザーにとっては1クリックで実現できるところが、サーバサイド、すなわち裏側では実はそんなにシンプルではなかったというケースが存在し、それを増えゆくトラフィックの中で維持しつづけるのは意外と大変だったりします。 とりわけエンジニア視点では機能分割したくなる部分も、ユーザビリティのためにそうせずに頑張らなくてならない部分などが存在します。 言い方を変えると、他社であればスケーラビリティを優先した仕様変更を行っていたところを、対応コストをユーザー負担に押し付けるのではなく、どうにか1クリックのままで収まるようにユーザ体験を維持するためには、様々なシステムリソースと引き換えに頑張っていかねばならないシーンというのがあります。 このような部分は、実に細かいことですが差別化要素とも言えます。 そういう頑張りの結果、CakePHP2に依存するWebアプリケーションを作るという範囲のメンタリティだと、ソースコードの複雑性が高くなるところが出てきます。 そのような部分では、「BASE」を織りなすアーキテクチャとしてソフトウエア構造を整理し、メンテナンス性を高くしていかないと、技術的負債として将来の機能追加が破綻する可能性を秘めていたわけです。 このような話は、歴史を紡げるだけの価値を生み、常に発展を模索してきたWebサービスであれば、多かれ少なかれ存在しているはずです。我々も幸いなことに、このような改善を行う機会に恵まれました。   機能が整理されてサービスが高度化する代償としては、学習コストの増加です。 Amazon.comがRestfulなマイクロサービスの集合体になる前は、モノリシックなシステム構造の中で、データベースのマイグレーションに伴うトラブルが部署間で起きていて、その結果、トップダウンでデータベースを分割するマイクロサービス化を行ったと、Amazon CTOのWerner氏の講演を聞いたことがあります。 つまりそうすべき理由があったからというのが一番重要で、それをする理由も見えてない段階で高度化しすぎるのも開発コストや組織的なリスクをもたらします。 そうすべき理由とは、さらなるサービスの成長によってもたらされるものです。 このような構造下で、ビジネスとサービスを成長させるエンジニアリングの両方を満たしていくためには、技術系のリーダーシップを取っていく人員が不足しているように考えています。BASEは基盤整備とサービス性の向上との距離感が、比較的シームレスに存在しているのが特徴です。 これがゲーム基盤とゲームアプリケーションであったり、配信基盤とコンテンツなどと、キレイにレイヤー分けされていれば、もう少しメリハリの効いたチーム構成になるところが、まだ当社においては、そこまでは切り分けられていません。 冒頭に書いた1クリックによるユーザ体験を優先しているが故に、そんな簡単に組織をレイヤー化できないというのがあり、普通にサービスを拡張するにあたって必要な技術とサービス知識が、相応に多岐に渡っています。 少しややこしい言い回しをしてきましたが、Vue.jsやTypeScriptを書ければフロントエンドが書けるわけではないし、PHPやCakePHPが書ければサーバサイドが作れるわけでもなく、サービス知識と設計技術、基礎技術を兼ね備えていることが求められます。 こういった課題解決にピンと来る方に技術リーダーシップを発揮していただいて、チーム全体の技術力の底上げをしていける方を募集しています。 技術課題2:新型コロナで時間軸が圧縮されたことで見えてきたもの 5月15日に100万ショップを超えたことを発表させていただきましたが、ここしばらく新型コロナの影響で新規のショップ開設数が急増しております。また、香取慎吾さんを起用したテレビCMなどの影響もあり、引き続き増加しています。 4月後半、5月のゴールデンウイークでは、新型コロナに対する不安や、自粛に伴う巣ごもり消費によりサーバ負荷やトランザクション数が急増しました。 ショップオーナー様にはピークタイムの大規模販売を5分10分ずらしていただいたりなどご迷惑をおかけ致しましたが、社内では増えゆくPV、増えゆくトランザクションを安全に処理するために、CTOやSREを始めとしたメンバーが日夜、サービスを改善してきたという経緯があります。 その結果、単位時間あたりの処理トランザクション数や受け入れ可能なPVを一気に増やすことに成功し、受け入れ可能な流通総額の向上が成果として現れています。 某製菓会社様がコロナ禍で販売した応援セール商品について自社ECで処理しきれなかった販売が、急遽設立されたBASE支店では難なく処理できたというのも、この改善の成果です。 そもそも歴史ある企業様のネットショップが1日で作れるというのも「BASE」の特徴で、今後もこのような状況が増えていくことを望んでいます。 一方で、このまま時間軸が進んでいき、サービスが成長していくと、最後は、ものすごくプリミティブなところに問題が集約していって、将来に解決できない技術的な壁が存在するところも見えてきました。このような部分もさらなる改善でカバーしていく必要があります。 結局、Webアプリケーションというのは最後はTCP/IPでどう通信するか?という問題に落ちていくので、開発言語がGoだのPHPなどに留まらない視野での改善が不可欠です。mixiやFacebook、Twitterなどはその問題を解決してきたサービスなのだと思います。我々も、こういった問題もまた並列で解決していかねばならないイシューとして顕在化してきてワクワクしています。 今回の改善でしばらく時間稼ぎができましたし、5月は間違いなく異常事態だったと思いますので、新型コロナの第二波、第三波が来ても、物流や経済の流れというECの基本要素さえ壊れない限り、ウイズコロナでは問題なく「BASE」というビジネスを継続していく見通しは立ちました。 繰り返しになりますが、この短期的な時間軸の圧縮を経験し、3年後5年後に向けてのサービス成長への道筋もまた見えてきたというのがあり、これも取り組んでいきたい課題になります。 その際のお話は、弊社のオンラインイベントで、私とCTOの川口との対談でお話させていただくので、是非ご覧ください。 こちらから参加登録いただけます。 base.connpass.com サービス開発を通じて、人の成長とサービスの成長を一緒に実現していきたいと思いますので、長くBASEのチームで働いてくれる方を募集しています。
アバター
はじめに こんにちは、Data Strategy所属の岡です。グループ会社BASE BANKで分析/モデリングなども兼務しています。 テキストデータを特徴量にもつ不均衡データ分類問題をDNNで解きたくなった際、下記の論文を参考にしたのでその内容を紹介します。 https://users.cs.fiu.edu/~chens/PDF/ISM15.pdf 不均衡データ分類問題ってなに? 何かしらのカテゴリを機械学習などで分類予測しようとする際、カテゴリごとのデータ件数に偏りがある、特に正例のデータが極端に少ないケースで予測精度が上がりにくい、という問題をこのように呼んでいます。 例: 不正決済と正常な注文、不正商品と健全な商品、がん患者と正常な患者 普通はどうやって対処するの? ベースとなるアプローチは下記3つにまとめられます。 アプローチ 内容 デメリット アンダーサンプリング 多数派データをランダムに減らして少数派データと均一にする 多数派データの多くを捨てるため、情報損失が生じうる オーバーサンプリング 少数派を増やし、多数派データと均一にする 例: SMOTE, ADASYN 少数派データの水増しになるため、過学習が懸念される 損失関数のカスタマイズ 損失関数に対して多数派データのコストを少数派データとの割合に応じて割り引くなど あまりデメリットについて明言されてるケースは少ないと思いますが、これも過学習になりうるという印象 個人的には、アンダーサンプリングの情報損失という弱点をカバーしている under sampling + bagging をよく使用しています。DNNでこれと似たようなアプローチができないか調べていたところ、冒頭の論文を発見しました。 ミニバッチでunder samplingするアプローチ 今回紹介する論文では、ミニバッチ作成時にラベルごとのサンプルサイズを合わせる方法を提案しています。 この処理フローは下図のようにまとめられます。 まず、多数派データ(P個)のみをバッチサイズ(ここではN個)分に分割してミニバッチ作成します。ここでミニバッチ1つあたりのサイズは(P / N)個です。 続いて少数派データ(Q個)から(P / N)個を重複がないようにランダムサンプリングし、最初に作った1個目のミニバッチのデータに混ぜます。このサンプリングを続いて2,3,4...N個目のミニバッチごとに繰り返し、ラベルの比率が均等なN個のミニバッチが作られます。 注意点として、ミニバッチ1個あたりに対して少数派データ(Q個)から(P / N)個を選び出すときは非復元抽出となるため、ミニバッチ単体で見ればデータの重複はありません。ただし、別のミニバッチを作るときには同じようにQ個から(P / N)個選び出すことになるので、バッチ全体としては少数派データの重複を許しつつサンプリングされています。 実装例 PyTorchでの実装例を示します。図示したミニバッチ作成部分だけ簡略化したコードだと下記のようになります。 class BinaryBalancedSampler : def __init__ (self, features, labels, n_samples): self.features = features self.labels = labels label_counts = np.bincount(labels) major_label = label_counts.argmax() minor_label = label_counts.argmin() self.major_indices = np.where(labels == major_label)[ 0 ] self.minor_indices = np.where(labels == minor_label)[ 0 ] np.random.shuffle(self.major_indices) np.random.shuffle(self.minor_indices) self.used_indices = 0 self.count = 0 self.n_samples = n_samples self.batch_size = self.n_samples * 2 def __iter__ (self): self.count = 0 while self.count + self.batch_size < len (self.major_indices): # 多数派データ(major_indices)からは順番に選び出し # 少数派データ(minor_indices)からはランダムに選び出す操作を繰り返す indices = self.major_indices[self.used_indices:self.used_indices + self.n_samples].tolist()\ + np.random.choice(self.minor_indices, self.n_samples, replace= False ).tolist() yield torch.tensor(self.features[indices]), torch.tensor(self.labels[indices]) self.used_indices += self.n_samples self.count += self.n_samples * 2 コメントでも触れられている↓の箇所のコードが今回の肝となる操作です。 indices = self.major_indices[self.used_indices:self.used_indices + self.n_samples].tolist()\ + np.random.choice(self.minor_indices, self.n_samples, replace= False ).tolist() 多数派データのインデックス(major_indices)からは順番に選び出し、少数派データのインデックス(minor_indices)からはランダムに選び出す操作をしています。それぞれのラベルから n_samples ずつ取り出して結合しています。 この操作は後でイテレータとして用いるので、 def __iter__(self) で定義しています。 yield の出力はたとえば下記のようになります。 test_iter = BinaryBalancedSampler(features=train_features, labels=train_labels, n_samples= 50 ) for i in test_iter: feature, label = i print (feature.shape) print (label.shape) print (np.bincount(label)) break > torch.Size([ 100 , 29 ]) > torch.Size([ 100 ]) > [ 50 50 ] 1イテレーションあたりに特徴量データと対応するラベルを返しています。ここでは n_samples=50 としたので2ラベル分で100個のデータが生成されています。ラベルの分布も [50 50] と均一になっているので、想定通りのミニバッチが作成できていそうです。 実験 不均衡データを普通に学習させた時と、均一になったミニバッチで学習させた場合の精度の差を見てみます。 学習結果の全容は こちらのgit に載せたので、ここでは簡単に説明していきます。 前処理 サンプルデータセットにはtensorflowの下記チュートリアルと同じものを用いました。 https://www.tensorflow.org/tutorials/structured_data/imbalanced_data こちらも不均衡データをどのように分類するかという内容になっています。 import pandas as pd from IPython.display import display raw_df = pd.read_csv( 'https://storage.googleapis.com/download.tensorflow.org/data/creditcard.csv' ) display(raw_df.head()) 読み込んだデータは上記のような中身になっていて、 Class 列が分類対象のラベルです。 このラベルの分布が偏っていることを確認します。 import numpy as np neg, pos = np.bincount(raw_df[ 'Class' ]) total = neg + pos print ( 'Examples: \n Total: {} \n Positive: {} ({:.2f}% of total) \n ' .format( total, pos, 100 * pos / total)) > Examples: > Total: 284807 > Positive: 492 ( 0.17 % of total) 1のラベルが全体の0.17%しかないという偏り具合で、かなりの不均衡データになっています。 続いてチュートリアルと同じように前処理し、訓練データとテストデータに分割します。 from sklearn.model_selection import train_test_split # Cleaning cleaned_df = raw_df.copy() # `Time` カラムは不要 cleaned_df.pop( 'Time' ) # `Amount` カラムは数値のレンジが広すぎるので対数化 eps = 0.001 cleaned_df[ 'LogAmount' ] = np.log(cleaned_df.pop( 'Amount' ) + eps) # split train and test. train_df, test_df = train_test_split(cleaned_df, test_size= 0.2 , random_state= 0 ) # split label and feature train_labels = np.array(train_df.pop( 'Class' )) test_labels = np.array(test_df.pop( 'Class' )) train_features = np.array(train_df) test_features = np.array(test_df) 使用するネットワークはかなりシンプルにしました。 import torch import torch.nn as nn import torch.nn.functional as F class SimpleNet (nn.Module): def __init__ (self): super (SimpleNet, self).__init__() self.fc1 = nn.Linear( 29 , 32 ) self.fc2 = nn.Linear( 32 , 16 ) self.fc3 = nn.Linear( 16 , 1 ) def forward (self, x): x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = torch.sigmoid(self.fc3(x)) return x 入力される特徴量が29ユニット、最終的に予測するラベルは0 or 1なので出力は1ユニットにしています。 その他、損失関数とオプティマイザーは下記を用いました。 import torch.optim as optim criterion = nn.BCELoss() # BCELoss: Binary Crossentropy optimizer = optim.Adam(simple_net.parameters(), lr= 1e-3 ) 普通に学習させた結果 学習部分のコードは下記のようになっています。 PyTorch特有の Dataset, DataLoader を使ってて見慣れない部分があるかもしれませんが、単純にミニバッチサイズは1000、エポック数は2で訓練させただけの普段通りの処理です。読み飛ばして構いません。 from torch.utils.data import Dataset, DataLoader class MyDataset (Dataset): def __init__ (self, feature, label): self.feature = feature self.label = label self.data_num = feature.shape[ 0 ] def __len__ (self): return self.data_num def __getitem__ (self, idx): out_feature = self.feature[idx] out_label = self.label[idx] return out_feature, out_label BATCH_SIZE = 1000 trainset = MyDataset(feature=train_features, label=train_labels) trainloader = DataLoader(trainset, batch_size=BATCH_SIZE, shuffle= True ) testset = MyDataset(feature=test_features, label=test_labels) testloader = DataLoader(testset, shuffle= False ) # training for epoch in range ( 2 ): running_loss = 0.0 for i, data in enumerate (trainloader, 0 ): inputs, labels = data # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = simple_net(inputs.float()) loss = criterion(outputs, labels.view(- 1 , 1 ).float()) loss.backward() optimizer.step() # print statistics running_loss += loss.item() if i % 100 == 99 : # print every 100 mini-batches print ( '[%d, %5d] loss: %.3f' % (epoch + 1 , i + 1 , running_loss / 100 )) running_loss = 0.0 print ( 'Finished Training' ) 次に学習し終えたネットワークでテストデータのラベルを予想させます。 pred = [] Y = [] for x, y in testloader: with torch.no_grad(): output = simple_net(x.float()) pred += [ 1 if output > 0.5 else 0 ] Y += [ int (l) for l in y] テストデータの予測結果をconfusion matrixで可視化すると下記のようになりました。 全データをラベル0(多数派)と予測していて、うまい具合に不均衡データの罠にハマっています。 ミニバッチでunder samplingして予測した結果 実装例のコードで書いた BinaryBalancedSampler を用いて学習させます。 少数派ラベルのサイズを考慮して、ここではミニバッチサイズは100、エポック数は2にしています。 balanced_net = SimpleNet() balanced_loader = BinaryBalancedSampler(features=train_features, labels=train_labels, n_samples= 50 ) criterion = nn.BCELoss() # BCELoss: Binary Crossentropy optimizer = optim.Adam(balanced_net.parameters(), lr= 1e-3 ) # training for epoch in range ( 2 ): running_loss = 0.0 for i, data in enumerate (balanced_loader, 0 ): inputs, labels = data # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = balanced_net(inputs.float()) loss = criterion(outputs, labels.view(- 1 , 1 ).float()) loss.backward() optimizer.step() # print statistics running_loss += loss.item() if i % 1000 == 999 : # print every 1000 mini-batches print ( '[%d, %5d] loss: %.3f' % (epoch + 1 , i + 1 , running_loss / 1000 )) running_loss = 0.0 print ( 'Finished Training' ) このネットワークでテストデータを予測させると下記のようになりました。 多数派ラベルの巻き込みも少なく(187 サンプル)、少数派ラベルの9割弱(88サンプル)を当てることができました。 実験のまとめ サンプルに使った不均衡ラベルのデータセットについては、ミニバッチでunder samplingするアプローチは有効そうです。 感想 この方法はミニバッチごとには均一なデータセットが得られますが、バッチ全体で見れば少数派データを複数回ピックアップするので、ある意味オーバーサンプリングとなり過学習の心配があります。early stoppingなどを組み合わせる必要がありそうです。 (あと発表が2015年とやや古い...) とはいえ実装はとても簡単なため、実務でサクッと試せる点が個人的に気に入っています。
アバター
こんにちは。バックエンドエンジニアの岡本です。 ネットショップ作成サービス「BASE」の新規機能開発や既存機能の改修・運用を担当するShop Groupに所属しています。 今回は私が入社後初めてアサインされたプロジェクトであるメールマガジンApp(※)のアップデートを通して経験したこと・考えたことをバックエンドエンジニアの視点から振り返っていこうと思います。 ※ネットショップ作成サービス「BASE」の拡張機能であるBASE Appsの機能の一つ プロジェクトメンバー構成 ・プロジェクトマネージャー ・デザイナー ・フロントエンドエンジニア ・バックエンドエンジニア(私) メールマガジンAppアップデートの場合、上記4つの役割に対して1人ずつメンバーがアサインされました。1人ずつと言ってもそれぞれの担当を全て1人でやるということではなく、入社間もないメンバーにはメンターがアサインされるなどフォロー体制が整っています。設計レベルからメンターや所属グループメンバーにアドバイスをもらいつつ、プロジェクトの主担当として作業を進めて行きます。 プロジェクトの流れ プロジェクトの流れとしては大きく下記の7つのフェーズに分けられます。 キックオフミーティング 設計・見積もり 実装 QAテスト リリース KPT(振り返り) プロジェクトお疲れ様会 1. キックオフミーティング プロジェクトの始まりにまずプロジェクトマネージャー(以下、PM)からプロジェクトの方向性・意味・想定仕様についての説明があります。PMが事前に用意したドキュメントをベースにざっと説明を行い、その後プロジェクトメンバー全員で不明点の確認や仕様の妥当性を議論していきます。 もちろん1度のミーティングでは仕様が確定しないことがほとんどなので、都度メンバー間でコミュニケーションを取りながら議論を深めていきます。 2. 設計・見積もり 大方の仕様が確定したタイミングでエンジニアは設計と見積もりを行います。BASEでは基本的にフロントエンドとバックエンドで実装担当が分かれているので、APIのレスポンス形式やバリデーションロジックについてそれぞれ意見を出し合い実装の方向性を決めていきます。 実装の方向性が決まった後、次は見積もりも含めた設計ドキュメントの作成に取り掛かっていきます。APIドキュメントについては API blueprint を利用し、その他バリデーションやDB関連の設計資料等は Kibela 記事にまとめていきました。設計ドキュメントが完成したタイミングで所属グループのメンバーにレビューしてもらいます。レビュー後のフィードバック対応が完了したらいよいよ実装フェーズに進みます。 3. 実装 実装フェーズは、 API実装 プルリクエストを作成し所属グループメンバーにレビュー依頼 フィードバック対応 レビュアーからLGTMを貰いレビュー完了 という作業をひたすら繰り返していきます。設計においても同様ですが実装フェーズにおいても所属グループメンバーからAPI単位で都度レビューしてもらえる環境があり、所属グループが支えてくれる感覚が実感としてありとても心強かったです。 4. QAテスト 開発が一通り完了し、プロジェクトはいよいよ佳境に入ります。QAテストはプロジェクトメンバー全員で分担し、それぞれが最終的なチェックを責任を持って行っていきます。比較的大きなデザインの課題が発見されたりするなど多少の問題は生じましたが、それぞれのメンバーがMove Fastに対応することで大きな滞りなくQAテストを完了させることができました。不具合の修正が完了したら後はリリース予定日を待つのみです。 5. リリース そして遂に2月3日(月)に本番環境へリリースし、特に大きなトラブルはなく無事に完遂することができました。リリース後は自分自身が関わったサービスを通してユーザー(オーナーズ)の活動を支えることができたという実感があり、エンジニア冥利に尽きるいい仕事だなとしみじみ感じました。 6. KPTでプロジェクトを振り返り 余韻に浸りたいところですがリリースが完了してもまだプロジェクトは終わりません。今回のプロジェクトから学びを得るべくKPTを行いました。内容としてはKPT(Keep・Problem・Try)ごとに一定時間(20分くらい)で意見を出し合い、最終的に皆で共有し今後のプロジェクトに生かせるようにドキュメントにまとめました。 <メールマガジンAppアップデートのKPT> Keep スケジュール通りリリースを完遂できたこと メンバー間でスムーズなコミュニケーションが取れたこと Problem QAテストで比較的大きい仕様の修正が入ってしまったこと Try 仕様のマスタドキュメント更新を全てのメンバーが責任を持って都度行う QAテストの段階で大きい修正が入らないようにできるだけ早い段階でテスト環境に動くソースをデプロイし、全てのプロジェクトメンバーが現状の実装状況を把握できるようにする 7. プロジェクトお疲れさま会 BASEには懇親会費用の補助制度があり、プロジェクト完遂後の打ち上げにもこの制度を利用することができます。プロジェクトの打ち上げは社内でも恒例となっており、今回は鉄板ステーキ屋に食事に行きました。入社後初プロジェクトをやり切った達成感からかはたまた高級店だった為か、お肉がとても美味しかったです。 プロジェクトを通して特に印象深かった事 改めてコミュニケーション大事 開発において手戻りを無くす為にエンジニア間のコミュニケーションは大事ということはもう周知の事実だと思いますが、やはり1番大事だなとプロジェクトを通し改めて感じました。コミュニケーションを密にとることの効用は何も認識齟齬だけではなく、信頼関係の構築という意味においてもプロジェクトの成功にとって避けては通れないものだと思います。 上記を意識してコミュニケーションを取った結果、今回のプロジェクトマネージャーからは下記の発言があり、プロジェクトを通して一定の信頼関係が構築できたと感じています。 またプロジェクトを通して弊社のSpeak Openlyという行動指針は何度も私の背中をそっと押してくれました。 「ここで確認するのはちょっと余計かな?」「この仕様少し疑問が残るけどどうしよう。」などと思った際、この行動指針を思い出すことで発言できる機会がいくつもありました。そして私のその発言に対してプロジェクトのメンバーはいつも真摯にHRTの精神を持って向き合ってくれました。 <HRTの精神> 謙虚(Humility) 世界の中心は君ではない。君は全知全能ではないし、絶対に正しいわけでもない。常に自分を改善しよう。 尊敬(Respect) 一緒に働く人のことを心から思いやろう。相手を一人の人間として扱い、その能力や功績を高く評価しよう。 信頼(Trust) 自分以外の人は有能であり、正しいことをすると信じよう。そうすれば仕事を自分以外の誰かに任せることができる。 出典: Team Geek ―Googleのギークたちはいかにしてチームを作るのか オーナーシップを持ってプロダクトを開発できるエンジニアは幸せ BASEには役割に関係なくプロダクトをより良いものにする為に仕様やデザインに対して積極的に意見することができる環境があります。今回のプロジェクトでの最も大きい個人的な気づきとして、エンジニアがオーナーシップを持って開発に取り組むことの楽しさがありました。前職では受託開発を中心に担当していた私からすると、この自由でかつ責任感が伴う開発の現場はとてもスリリングで心地良いものでした。 サービスを自分自身の課題として捉えることは開発に対しての強いモチベーションにもなり得ると私は思います。そして何よりエンジニア・PM・デザイナーなどの役割を超えて1つのチームとして同じ課題を解決していく過程はとても楽しく幸せなものです。 最後に BASEを一緒に支えてくれるエンジニアを絶賛募集中です!より良いプロダクトの開発の為に一緒に働きませんか? open.talentio.com
アバター
Native Application Groupの 大木 です。BASEでは、購入者向けのショッピングアプリ「 BASE 」、「 BASEライブ 」、ショップオーナー向けのショップ運営管理アプリ「BASE Creator」の3つのスマホアプリをリリースしております。今回は、その中の一つBASE Creatorを、React Nativeで置き換え、リリースしてみての話を、お伝え出来ればと思います。 課題と動機 https://help.thebase.in/hc/ja/articles/206417201-BASE-Creator- とはなんですか- BASE Creatorは、基本的にはWebViewで画面を表示するいわゆるガワネイティブアプリというものです。Webアプリとの違いは何処にあるかといいますと、商品が売れたり、購入者からメッセージが届くと、Push通知でお知らせ出来る機能があるところです。 アプリを運用していて出て来た課題としては、下記の点です。 現状、問い合わせによる不具合報告に対応するために、iOS/Androidのコードベースそれぞれを確認する必要がある スマホアプリは合計6つあり、チームメンバーも少数のため、WebViewベースのこのアプリは極力共通化したい。 これらの課題を解決するために、クロスプラットフォーム開発フレームワークの検討をしました。 React Native か Flutter か 開発プラットフォームとして上がったのは、React NativeとFlutterでした。どちらを選んでも問題は無さそうですが、今回はReact Nativeを採用しました。 重要視するポイント 既存技術を流用出来るか(社内、一般的なNative/Web技術含め) クロスプラットフォーム開発のノウハウが蓄積されているか 特に重要視していないポイント 統一されたガイドラインのようなものがある 新しい技術で開発 Flutterの方が後発で、挑戦してみたい気持ちもありました。しかし、Reactやnpmの技術を流用出来て、場合によってはWebのフロントエンドエンジニアでも対応できる可能性があるため、React Nativeを選択しました。 置き換えてみてどうなったか 結論から言うと、色々な良い影響をもたらすことが出来ました。 アプリケーションロジックを共通化出来た 最大の課題であった、 iOS/Androidそれぞれのコードベースを一つにする ことが出来、アプリケーションロジックを全てTypeScriptで記述することに成功しました。ネイティブ側のObjective-CやJavaのコードは、起動時に必要なコードやFirebase SDK用の初期化時コードくらいです。 別々のスキルセットを持つエンジニアとのコミュニケーションが増えた React Nativeで開発するとなると様々なスキルセットを必要とするため、Pull-Requestベースでレビューをもらいながら開発していきました。 メンテナンス可能なReact Nativeアプリを開発し続けるための構成を模索し構築できた Expoで管理するJavaScript/TypeScriptのみ動作させる環境を含むワークフローは"Managed workflow"と呼ばれます。対して、それを使わずNativeのIDE/SDKを使い、自分たちでReact Nativeの環境を整えるのを、Expoでは"Bare workflow"と読んでます。今回はFirebaseのNative SDKを含んだReact Nativeのモジュールを使うため、最終的にはこの"Bare workflow"でリリースする必要がありました。ただ、Expoの"Managed workflow"も素早く動作確認できる検証用環境として捨てがたいです。 幸いなことに、2019年はReact Native Re-Architecture実践の年で様々な改善をしていました。その動きに呼応するようにExpoもSDKに同梱されていたモジュールを分割するようになり、Expoベースの"Managed workflow"を使わなくても、Expoの便利モジュールを使えるようになりました。 両方の動作環境を一つのプロジェクトで共存させるために、 monorepo という仕組みを導入しました。この仕組みは、 Babel や React でも採用されています。 リポジトリのディレクトリ構成は、最終的に次のようになりました。 . ├── @types │   ├── metro-config │   └── react-web-vector-icons ├── docker │   └── android ├── packages │   ├── app │   ├── cli │   ├── components │   ├── core │   ├── expo-starter │   ├── functions │   ├── native-starter │   ├── platform │   ├── rn-metro-configurator │   └── tsconfig-paths-transformer └── tools ├── bin └── docker-bin また、分割したモジュールをどのように使うかの簡易的な概念図は次の通りです。 図の native-starter というモジュールが、通常のネイティブのIDE/SDKの設定と実装が必要な"Bare workflow"で動作させるためのエントリポイントとなっております。このモジュールからDebugビルドのアプリを起動したり、ストアリリースのためにReleaseビルドを作成したりします。また、 expo-starter というモジュールが、検証用にExpoの"Managed workflow"で動作させるためのエントリポイントとなっています。 monorepo構成で、React Nativeアプリを動作させるためには、色々なテクニックがいるのですが、長くなりそうなため、機会があれば別途解説記事を書ければと思っています。 Storybookの導入 React Nativeのコンポーネントを作成するに当たって、アプリケーションの特定の状態でしか発生しないUIの状態があり、その状況を再現したUIを素早く実装するためにStorybookを導入しました。 CodePushの導入 CodePush は、ユーザー端末に直接アプリの更新を配信できるMicrosoftのApp Centerのサービスです。リリース後、特定の古いOSでアプリが動作しない不具合が発生した時に、これを導入していたおかげで緊急アップデートをすることができました。 iOS 12.1以下で動作しないメソッドを使ってしまったため、CodePushで修正アップデート iOS 12.2以上でないと、 Object.fromEntires というメソッドは使えません。次のように修正し、 リリースした当日 に緊急アップデートで対処することができました。 @@ -42,14 +42,23 @@ export class FirebaseEventTracker implements EventTracker { } eventParams<T extends { [x: string]: string | number } = {}>(params: T) { - return Object.fromEntries( - Object.entries(params).map(([k, v]) => { - if (typeof v === 'string' && v.length > 0) { - return [k, v.substr(0, 100)]; - } - return [k, v]; - }) - ); + const values = Object.entries(params).map(([k, v]) => { + if (typeof v === 'string' && v.length > 0) { + return [k, v.substr(0, 100)]; + } + return [k, v]; + }); + + if (Object.fromEntries) { + return Object.fromEntries(values); + } + return values.reduce<{ + [x: string]: string | number; + [x: number]: string | number; + }>((acc, [k, v]) => { + acc[k] = v; + return acc; + }, {}); } React Native環境で利用できるJavaScript/npmの機能はできる限り試した これはチーム開発関係なく、個人的な興味になるのですが、ブラウザ環境でもNode環境でもないReact Native環境でどの程度最新技術をサポートしているのか、限界はどこかということを知っておきたいと考え、色々な検証をしました。 TypeScriptのDecorators導入 JavaのAnnotationのようなものが使いたくなり、TypeScriptの Decorators を導入しました。API Clientで、pathを定義したり、HTTP MethodがGETなのかPOSTなのかを定義したりで、次のような感じで使っております。 export default class StableVersionRequestService { private requestBuilder: RequestBuilder ; constructor( requestBuilder: RequestBuilder ) { this .requestBuilder = requestBuilder ; } @post @path ( '/path/to/check-api' ) checkVersion ( parameters: ServiceRequest < Data >) { // [...] IoCコンテナ(スプラッシュ画面の例) 複数のReact Native動作環境に対応するのであれば、当然使えるモジュールも違ってくることがありうると思いました。実際、アプリのスプラッシュ画面表示は、Expoの"Managed workflow"と"Bare workflow"とでは、利用できるモジュール異なることもあります。そこで、I/Fと実装を紐付けるためにIoCコンテナを導入しました。 まず、実装すべき共通のインタフェースを定義します。 export default interface Splash { preventAutoHide () : void ; hide () : void ; } export const SplashSymbol = Symbol. for( 'Splash' ); expo-starter では、Expoの SplashScreen が使えるので、次のように実装します。 import { SplashScreen } from 'expo' ; import { Splash } from '@universal-webcreator/app' ; export const splash: Splash = { preventAutoHide: () => SplashScreen.preventAutoHide (), hide: () => SplashScreen.hide (), } ; native-starter では、 react-native-splash-screen を使うように実装します。 import SplashScreen from 'react-native-splash-screen' ; import { Splash } from '@universal-webcreator/app' ; export const splash: Splash = { preventAutoHide: () => { // ネイティブ側のコード(Objective-C, Java)でスプラッシュを表示するため何もしない } , hide: () => SplashScreen.hide (), } ; そして、IoC Containerを使い、I/Fと実装を紐づけます。 export const dependencies = new ContainerModule ( bind => { // [...] bind < Splash >( SplashSymbol ) .toConstantValue ( splash ); // [...] } ); その他 その他、試して導入した機能は、主に次の通りです。 TypeScript 3.7 Redux/Redux-Saga React Hooks TypeScript Compiler API TypeScript Generics React Native開発の一年 この1年でReact Nativeならではの辛さや問題にも遭遇しました。 React Native環境構築 (2019年3月) 他のタスクがひと段落したため、本格的に環境構築を開始しました。公式ドキュメントを参考にしながら、ほとんどつまづくことなく開発することができました。 Jestを使ったスナップショットテスト を導入したり、CircleCIでlintやスペルチェックを回して、少しづつ環境を整えていました。 この時に使用した技術は次の通りです。 TypeScript v3.3.3333 Expo v32.0.5 Node v11.10.1 Jest v24.1.0 WebViewベースのアプリを開発するのに致命的な不具合を発見(2019年3月後半) 初回起動画面の実装やある程度開発環境も整え、要のWebViewを使った実装を行っていこうと考え、React Native本体の WebViewコンポーネント を使って動作確認しました。予想に反して、このコンポーネントには深刻な不具合があり、それにより、プロジェクトの存続すら怪しくなっていました。 完成度が低いReact Native本体のコンポーネントが、Communityに移管され難を逃れる 開発開始直後は、React Native関連の状況を理解していなかったのですが、2018年の Lean Core という提案により、WebViewの開発は、React Native Communityに移管されることに決定していたようです。 今のReact Native動作環境は、Expoの"Managed workflow"を利用しているため、すぐには移管されたWebViewは使えません。そのため、この環境を諦めるかどうかの選択に迫られました。そんな時、 Expo Developers のSlackにJoinしてみると、次のExpoのアップデートで、 React Native Community版のWebView に差し替えるという話があったため、他の開発をしながら、リリースを待つことにしました。 Expoのアップデートを待つ間に、他の機能を開発(2019年4月-2019年6月) 要のWebViewは不具合で開発を進められなかったため、他の機能を開発していくことにしました。待っている間に実装していた昨日は次の通りです。 IoCコンテナの導入 Core/Platformモデル・ユースケースの定義 Redux/Redux-Saga導入 CI用Node環境の整備 APIクライアント実装 文言の管理のため、i18next導入 TypeScriptのpathsによるモジュールパス解決に試行錯誤 一番最後のモジュールパス解決は試行錯誤していましたが、調べてみても、React Nativeのバージョンが古い時の方法であったり、パス解決の仕組みがよく分かっておらず、この時は断念しました。後日、最終的にMetroやBabelのモジュールパス解決の方法を組み合わせることで解決することができ、monorepo構成に移行するまでうまく動作しておりました。 Expo v33リリース!(2019年6月) 待てど暮らせど次期バージョンアップデートのアナウンスがなく、Expo DevelopersのSlackを定期的に覗く日々でした。様々な人が次のリリースはいつ?のような発言をしていた印象です。 いつものようにSlackをのぞいていると、いくつかのIssueを片付けたらリリースできるよと発言がありました。GitHubのリポジトリを確認してみると、すでにExpo v33があり、インストール可能な状態になっていました。 公式アナウンス を待ちきれず試してみると、普通に動くWebViewと対面することができました。 未知との遭遇(2019年6月) 基本的には動作していたWebViewですが、2つほど問題がありました。 target=_blank の挙動に準拠せず、勝手に同一WebViewで開いてしまう。 React Native側からWebViewでJavaScriptを実行しても実行結果を受け取れない。 これらの挙動のため、HTMLの何処に target=_blank のリンクが存在するか自分で確かめなければなりません。WebViewのJavaScript環境は、ユーザーの端末に依存するため、出来るだけレガシーなJavaScriptを書いてWebViewで動くようにしました。(ブラウザをアップデートしていないユーザーは古い機能しか利用できない)。また、BASEの管理画面は、 Vue + CakePHPで構築 されており、機能内のRoutingはVue Routerによる画面遷移で react-native-webview では検知できません。 そこで、 JavaScript : コールバックがないならDOMの変更を監視する を参考に、MutationObserverを使ったDOM変更監視で、Vue Routerでの画面遷移時に、 target=_blank のリンク取得するようにしました。 目的のリンクは取得できるようにはなりました。しかし、WebViewでJavaScriptを実行しても、実行結果を返すことはありません。一応 window.ReactNativeWebView.postMessage を使うことで解決が可能です。しかし、 window.ReactNativeWebView となっているので、 window オブジェクトにいつこれが設定されるかが問題で、ユーザーがリンクをタップするのが早いか、React Native側に実行結果を送信するのが早いかわからないという問題には、完全に対処できませんでした。 Expoの"Managed workflow"と"Bare worflow"を共存させる試みの失敗(2019年6月-7月) 結論から言うとこの試みは失敗しました。最初次の構成にすればうまくいくと考えました。 共通の部分は"Managed workflow"ベースで実装 それぞれの実行環境で必要な部分は共通のinterfaceを定義し、それに準拠させる実装をする 上の定義と実装を、ejsのテンプレートにし、コードジェネレーターやスクリプトで切り替える しばらく進めてみたのですが、ふと冷静に考えてみて、今後のReact Nativeのアップデートに追従していくためには、こんな複雑な仕組みメンテナンスできないと思い、考え直すことにしました。 monorepo構成の導入(2019年7月) しばらく色々試して迷走していましたが、1つのプロジェクトで複数のモジュールを管理できるような仕組みがあれば良いのではと考え、調査したところmonorepoについて知りました。monorepoを実現するツールの一つである Lerna を導入し、試してみました。この構成は現在も使っており導入してよかったと思いました。 実行環境の共存も、エントリポイントとなるモジュールを分割することにより別々に実行できるようになりました。 実行環境共通で使えないモジュールの解決は、共通interfaceを定義しそれぞれの実行環境ごとに実装したものを、IoCコンテナを通じてアクセスすることによって利用できるようになりました。この辺は 前述のIoCコンテナ(スプラッシュ画面の例) に例を載せています monorepo構成への完全移行とネイティブIDE/SDKの設定(2019年7月-8月) monorepoへ移行してからも、TypeScriptのpathsを使ったモジュール解決を使っていましたが、エディター上でモジュールをインポートしようとすると、ローカルPCのフルパスでインポートしたり、importの重複が発生したり何かと問題が発生していました。 pathsを使ってはいたのですが、そもそも機能ごとにグループ化し擬似モジュールのように扱っていたに過ぎません。モジュールのように扱っていたのであれば、monorepoの中でモジュールとして分割した方が管理しやすくなると考え、pathsで管理していたディレクトリーをそのままモジュールとして切り出すことにしました。これによってモジュールのインポート問題は解決することができました。 monorepoでJavaScriptレイヤーの問題は解決することはできましたが、ネイティブ側の設定はnpmのエコシステムに自動的に対応している訳ではありません。最終的に解決はできましたが、様々な問題が発生しました。それに関しては長くなるためここでは省略します。 毎回アプリを起動してUI実装するの面倒なためStorybookを導入(2019年8月-9月) 基本機能はほぼ出来上がっていましたが、次はUIの微調整が待っていました。毎回アプリを削除して、目的の画面まで遷移して特定の状態にして確認という作業を、繰り返していたため、フラストレーションが溜まっていました。 そこで、UIの状態を固定で確認できれば、アプリの実行環境で確認しなくてもいいのでは?と考えStoryboardを導入しました。結果的に、ブラウザ上で素早く確認できるようになりました。ちなみに、Storybook for React Nativeは使っておらず、Storybook for Reactをベースに react-native-web を利用しました。 リリースビルドをCircleCIで成功させるのに四苦八苦(2019年9月-11月) アプリのテスト配信には、Microsoftの App Center を選びました。React Nativeアプリの場合、CodePushを使えるのが採用した大きな理由です。 さて、配信サービスが決まったので、CircleCIでリリースビルドを作成してみるとなかなか上手くいきません。しかも一回のビルド時間が40分以上かかり確認にも時間がかかります。ここをクリアしないとリリースもできません。 絶対にローカルPCでリリースビルドを作るという作業はしたくありません。 この作業では、次のような問題が発生しました。 Androidビルドで、Javaメモリーエラーが発生する ビルドは作成できたが、署名が異なるため、端末にインストールできない アイコンフォント対応ライブラリで、リリースビルドのみアイコンが表示されない ビルド時間が長い またこの時期、iOS 13へのアップデート対応で、他アプリの対応もしなくてはならず、なかなか時間が取れませんでしたが、一つ一つ解決していきました。 QA(2019年11月後半) iOS 13へのアップデートもひと段落し、やっとリリース準備に漕ぎ着けました。- Done is better than perfect - のようにまずは終わらせろの気持ちでいた私ですが、全体を通しての動作確認はしておりません。そう、QAをしなければなりません。 QAフェースでも色々問題が発生しました。これは主にAndroidの知識不足が原因でのことです。 Androidのバックボタンでホームに戻って、アプリを再度開くと、React Nativeのコンポーネントが再生成されるのに、UI周りの再初期化できてない 不要な権限をAndroidManifestで消せてない また、QAを行なっていると、利用しているライブラリに関しても色々と気づくこともあり、修正Pull-Requestを送ったりしました。 use lane_context for android mapping text [expo-web-browser] [ios] Fixed SFSafariViewController presentation style リリース(2019年11月末) まだまだ、改善するところはあったのですが、紆余曲折を経て、リリースすることができました。 2019/11/27 Play StoreでAndroid版リリース 2019/12/2 App StoreでiOS版リリース リリース後の色々(2019年12月-) リリース後、Play StoreやApp Storeに再申請するほどの深刻な不具合が発生しなかったことにまずは安心しました。ただし、ユーザーに影響のあるものや運用開発環境の考慮漏れなど、いくつかの問題は発生してしまいました。確認不足やAndroidの知識不足に起因するものが多かったです。いくつか上げると次のようなことです。 古いOSで動作しないJavaScriptの機能を使ってしまっていた Android Crashlyticsの設定ミス Android CodePushの設定ミス まとめ 今回のプロジェクトでは、本当に多種多様な技術に触れ、大変なことも多かったのですが、様々な人の助言もありなんとか終わらせることができました。また、長期的な運用やチームでの開発を考えた実装を深く考えられた良い機会でした。React Nativeだからネイティブのことを考えなくてよい訳ではなく、ネイティブ起因の様々な問題が発生しました。その時には同じチームのAndroidエンジニアにも度々助けられました。 今、React NativeやExpoを取り巻く環境は、2019年の一年間で大幅に変化しそして改善しています。先日、 Shopifyの記事 にReact Nativeのことが書かれていました。2020年の今なら、React Nativeを採用するのも悪くない選択肢かなと思います。
アバター
この度は、2/9(日)~2/11(火)に練馬区の産業プラザ Coconeri ホールにて開催された PHPerKaigi2020 にプラチナスポンサーとして協賛し、また4名のメンバーが登壇しました。 今回は上記メンバーの他に一般聴講者として参加した4名のメンバーからの参加レポートをお届けします! 参加レポート(栗田) 概要 Service Dev Sectionに所属しています 栗田 です。 2020年2月9日(日)〜2月11日(火・祝)に開催されたPHPerKaigi 2020に聴講者として参加しました。 この記事は2日目の 2月10日(月)の参加レポートとなります。 当日は弊社から2名のトークセッションがあったりと、自分の知り合いのトークセッションがあり 盛りだくさんでした。 セッションを聞いたり、おかしをもぐもぐしたり、参加者と交流したり 茶会に参加したりなど充実した1日を過ごしました! 本文 練馬で行われた会場に到着 ここで受付です。 色々な会社のノベルティや自分専用にカスタマイズされたトレーディングカードもいただきました。 まずはじめにオープニングトークに参加しました! カンファレンスに対する想いが心に残りました。 今回弊社はPlatinumスポンサーとして協賛しております。 自分の会社のロゴが大勢の場の前に出るのは純粋に嬉しいですね。 同僚の @o0h_ さんのトークセッションに参加!! 続いて同僚の @budougumi0617 さんのトークセッションに参加!! 弊社から連続のトークセッションになり勢いを感じました。 ひと休憩して、ランチセッションではお弁当をいただき 午後は↓などに参加しました。 レンサバけもの道 磯野ー、MySQLのロック競合を表示しようぜー もっと気軽にOSSにPRを出そう! 知らないWebアプリケーションの開発に途中からJOINしたとき、どこから切り込むか? LT... etc などを聞きました。様々なスタイルのセッションがありどれも為になるお話でした。 詳細はリンクよりご確認ください。 最後に茶会に参加して参加者と更に交流を深めました。 ※ GMOインターネット株式会社さまからのご提供でした。 茶会にはボドゲなどの交流グッズなどもあり 様々なスタイルで交流する事ができました。 名刺代わりに交換をしたトレーディングカードも大分集まりました! 最後に 自分はPHPカンファレンスの参加経験はありましたが、PHPerKaigiは初の参加でした。 一言で感想をいうとアットホームな温かい場だと感じました。 ・初心者、上級者、老若男女 誰でも楽しめる場 ・コミュニケーションの場 ・1年に1回、ともだちと会う場 とオープニングセッションで紹介がありましたが、まさにそのとおりだと感じ コミュニティの暖かさを感じました。 自己紹介がしやすいようにトレーディングカード風の名刺をいただいたり スタッフの方がフレンドリーに話しかけてくれたり いたる所で参加者同士で気軽に交流を行われたり PHPerトークンを探しだす、PHPerチャレンジイベントなどもあり 初めての参加でも参加しやすいカンファレンスだなと感じたのと コミュニティの熱量を感じた1日でした。 参加レポート(長澤) SREに所属していますngswです。得意な領域はインフラ側で、前職でPHPも触ってきました。 今回はインフラ側への言及があった以下の3トークについて感想を書きたいと思います。 レンサバけもの道 by uzulla | トーク | PHPerKaigi 2020 #phperkaigi - fortee.jp 知らないWebアプリケーションの開発に途中からJOINしたとき、どこから切り込むか? by 小山健一郎 | トーク | PHPerKaigi 2020 #phperkaigi - fortee.jp PHPシステムをコンテナで動かすための取り組みのすべて by きくもと | トーク | PHPerKaigi 2020 #phperkaigi - fortee.jp レンサバけもの道 uzullaさん (@uzulla) / Twitter レンサバけもの道 - Speaker Deck 僕は以前ホスティングサーバを提供する側にいたことがありますので「これは他人事ではない」というトークでした。 レンサバ == 共用サーバの旨味である「アップデート追従などのマネジメント」と、その反面にある「使い勝手に関わってくる各種制約条件をどう打破するか」という内容です。SSHから始まり最新のバイナリ利用のためのビルドのtipsなど、自由度の高いセルフマネージドなVPSを渡り歩いて来たからこそ語ることのできる内容が盛りだくさんで聴き応えがありました。このトークの背骨となる「モダンを諦めない」「レンサバでもここまでできるんです」という主張はとてもエンジニアしていて好感が持てました。 知らないWebアプリケーションの開発に途中からJOINしたとき、どこから切り込むか? k1LoWさん (@k1LoW) / Twitter 知らないWebアプリケーションの開発に途中からJOINしたとき、どこから切り込むか? / PHPerKaigi 2020 - Speaker Deck 「既存プロダクトにアサインされたとき、どうすれば開発参加の初動オーバーヘッドを小さくできるか」という主旨のトークでした。 どのようなサービスか どのようなアーキテクチャか どのようにデータを保持するか(=どのようなテーブル設計か) どのような開発環境か(本番環境・開発環境) どのようなコードか 開発 https://speakerdeck.com/k1low/phperkaigi-2020?slide=28 「上記の6つのレイヤの情報が揃えば、あとは本人のスキルにあわせて成果が出せるよね」ということでした。 本質に近いもの(発表では上述した数値の小さい事柄のもの)ほど広い理解を要求される点も共感できる内容でした。 トークの最中「われわれのようなインフラ側の人間だとどういう情報があれば初動オーバーヘッドを小さくできるのかなあ」と考えていました。 個人的な経験では「どのようなサービスか」ということにはあまり頓着しなかった思い出があります。自分が一番はじめにほしいなと思う情報は サービスに利用されるFQDN一覧 サービスが利用するクラウドサービスのエンドポイント一覧 インスタンスの構築手順(コード化されたものも含む)、ないしは相当のものが存在しなければ踏み台へのログイン情報 だと考えています。少なくともこれだけあれば、あとは稼働しているデーモンとポートの関係などはログインして調べてしまえばいいじゃないかと考えてしまう質です。 ただこれがまさにオーバーヘッドなのですよね。そういった意味ではk1Lowさんの発表は高みを目指されていて凄みを感じました。またこの「初動オーバーヘッドを小さくする」ことに成功すれば「採用計画もより柔軟にできるのではないか」という発展性も感じました。われわれの業界はただでさえ即戦力を求めがちなのですから、「単なる一トークではない業界への提言ととってもいいのかもしれない」という気持ちを持ちました。 PHPシステムをコンテナで動かすための取り組みのすべて kikumotoさん (@takakiku) / Twitter PHPシステムをコンテナで動かすための取組みのすべて - Speaker Deck さまざまなツールを駆使してコンテナ化を実現されたその手法と、実際の運用に基づく含蓄のあるアドバイスが詰まっていて、 AWS移行を目指す中、オンプレミスでどこまで移行コストを減らす形にできるかという工夫に満ちたトークでした。 個人的に一番興奮してしまったのは「LVS」の話題が上がったところで、そこでテンションが上がりすぎてしまった結果、最後に変な質問を投げかけてしまったのでその点は個人的な反省点です。 ただLVS氏はものすごく賢くて、当該レイヤでやってほしいこと、これできたら嬉しいなってことをほんとに全部実現してくれるツールなので、テンション上がってしまったことは許していただければ幸いです。 参加レポート(炭田) 概要 Service Dev Sectionに所属しています@tac_tandenです。PHPで3年ほどWebアプリケーションの開発をしています。 自分は2020年2月9日(日)〜2月11日(火・祝)の3日間に参加しました。 カンファレンス初心者の自分にとって、一般聴講者としての参加であっても、最初は入っていけるのか正直不安でした。 しかし、PHPerKaigi 2020は運営のスタッフの方や参加者のみなさんはとてもオープンで、親切で、すごく楽しく素晴らしい経験になりました。 また、今回のPHPerKaigiでは、弊社から4名登壇されていて、登壇がより身近になりました(自分もいつかカンファレンスで登壇してみたいと考えています。) 今回の記事では、アプリケーションエンジニアの自分にとって印象に残った以下の2つのトークについて感想を書きたいと思います。 Deep Module in PHP もっと気軽にOSSにPRを出そう! 本文 Deep Module in PHP いとしょさん (@itosho) / Twitter Deep Module in PHP - Speaker Deck アプリケーションの実装をしていて、実装期間や仕様、依存関係などの制約がありつつも、もっと良いコードを書けないかなと日々試行錯誤されている方も多いと思います。 自分もその一人で、その中で「そもそも良いコードってなんだろう」と自問自答して色々調べたりすることも多いのですが、itoshoさんの発表ではその「良いコード」の一つの指針として、「Deep Module」という考え方があるということを紹介されていました。 発表の中で、良いコード=複雑ではないコードと定義して、多くの機能を提供しながらインターフェースがシンプルなモジュール(=Deep Module)を理想とするという指針を提示されていました。また、実際にDeepなModuleを実装するためのポイントや具体例もあり、とても参考になりました。 設計としての理想を追い求めるよりは、より現実に即した適用しやすい指針なのではないかと個人的には感じます。 Deep Moduleという視点も持って、会社のアプリケーションコードを読む&開発してみたいと思います。 もっと気軽にOSSにPRを出そう! DQNEOさん (@DQNEO) / Twitter もっと気軽にOSSにPRを出そう! - Speaker Deck 日々会社や個人で開発をしていて、OSSにお世話にならない場面はほとんどないと思います。 しかし、OSSへのコミットやPRを出すとなると、自分としては途端にハードルが高くなる気がしていました。 発表の中で、DQNEOさんもハードルの高さを指摘されていましたが、以下の4つの視点を持つことでPRを出しやすくなるとご紹介されていました。 1. 作者の関心ゾーンの外側を見る 2. 使っていなくてもコントリビュート 3. 業務で得たノウハウを横展開 4. ダメ元でも送ってみる スキルアップなどももちろんですが、OSSに日頃お世話になっている「恩返し」として、自分でも微力ながら気軽にPRだしてみようと思います。 また、発表セッションのあとの懇親会でも、DQNEOさんには面白いお話をたくさん聞かせていただきました! ありがとうございました! 発表を聴く中で感じたこと 登壇に関して、人脈を作ったり市場価値を上げるなどいうよりも、単純にすごく楽しそうだし、沢山のエンジニアの皆さんとつながることができるのは、素晴らしい体験なんじゃないかなと感じました。 なにより、登壇されている皆さんが、発表をとても楽しんでいるのが印象的でした。 途中で「なにかネタはないだろうか」と色々頭を巡らせていましたが、皆さんの発表を聴く中で、こうすれば発表できるトピックが作れるのではないかと考えました。 OSSにPRをだしてみる 会社での経験・知識を一般化して横展開できないか考える 自分のサービス開発を運用する 技術ブログを書く また、登壇された皆さんの発表がすごくわかりやすく、楽しめたのですが、聴講者目線で印象に残った登壇テクニック?をまとめてみました 発表に入る前に、発表と関連する経歴や自己紹介があると、なんでこんなことをしているか、なんでこんな発表をしているかがわかりやすくて内容が入ってきやすくなる。 他の発表との関連にも言及してみる。他の発表の知識が使えてより理解しやすくなる気がする。 聴講者にフィードバックが欲しいところを発表の途中途中で伝えてもらえると、発表者にフィードバックしやすい。 発表の中で聴講者に手を上げてもらうような質問をちょいちょい入れていくと、ライブ感がでる。 今後、発表する機会があったらぜひ実践してみたいと思います! 参加レポート (tenkoma) 基盤グループ所属の田中(@tenkoma)です。 3回目のPHPerKaigi参加となります。 参加したセッションの感想とPHPer Code Golf についてレポートします。 知らないWebアプリケーションの開発に途中からJOINしたとき、どこから切り込むか? 知らないWebアプリケーションの開発に途中からJOINしたとき、どこから切り込むか? / PHPerKaigi 2020 - Speaker Deck セッションを聞いた理由 自分が途中からプロジェクトに参加するときにどんな情報をあつめればいいのか、最近考えたことがない気がしたから 新しくjoinしてくるメンバーをサポートするための良い方法が知りたかったから でした。そんな疑問を考えるヒントが得られるよいセッションでした。 今だからこそ振り返る register_globals 今だからこそ振り返る register_globals / PHPerKaigi 2020 - Speaker Deck セッションを聞いた理由 最近のPHPって型(カタ)すぎませんか!?(型を使いすぎている、とか思っているわけではありません) 「例えば、PHPを避ける」なんて言われていた時代に、少しの時間でも戻ってみたかった 僕がPHPを使い始めた頃は古くてPHP4.3 を使っていたくらいの時期で、 register_globals = Off が既定値でした。 register_globals = On のアプリケーションを扱ったことはありませんし、 register_globals = On はセキュリティ上問題があるのでOffにするように社内情報共有されていました。 そのためこのセッションは、仕事に生かすかどうかも期待せず、ほぼ息抜きとして聴いたセッションでしたが、PHPの思想に触れることができる味わい深いセッションでした。 PHPer Code Golf by Pixiv 前回は全然参加できなかったな、今回はがんばってみようと思い、 PHPerチャレンジ でコードを探し入力していました。 しかし、1日目にPHPer Code Golf が始まってからは、そちらへの参加がメインになってしまいました。3問ありましたが、正解後もずっとコードを縮めることに注力した結果、表彰いただくくとができました。 PHPer code golf 賞ゲットしました!!pixivさん、楽しい問題を用意していただいてありがとうございます! #PHPerKaigi pic.twitter.com/1v6zlRG7rE — /; SameSite=Tenkoma; Secure (@tenkoma) February 11, 2020 正解するだけで無く、スコアを改善するためには途中のコードをどこかに保管しながらになるのですが、社内の #times_tenkoma にコードスニペットを投稿しながら改善していました。 1日目、帰宅後にベッドの上でFizzBuzzを改善していたときのログ 2日目、クロージング(17:10〜)の直前まで、上級編のコードを改善していたときのログ PHPerチャレンジは11位という結果に終わり残念でしたが、こちらで結果が残せて良かったです。 PHPerKaigi はセッションやIRTはもちろん、懇親会、PHPerチャレンジなど、他の企画も力が入っていて楽しめました。 賞を頂いたときのコードについては個人のブログで ⛳ PHPer Code Golf by pixiv(PHPerKaigi 2020) 上級編の回答について解説 の記事を書きましたので、そちらもご覧ください。 登壇資料 めもりー @m3m0r7 金城 @o0h_ 清水 @budougumi0617 東口 @hgsgtk 謝辞 今回弊社は登壇者含めて計9名のメンバーで参加させていただきまして、その中にはカンファレンス初参加のメンバーもございました。それぞれに刺激を受けたり、持ち帰れるものを得たりして大変実りのある時間を過ごさせていただきました。 それも実行委員長である 長谷川さん をはじめ、実行委員会の皆様のおかげです。心より御礼申し上げます。来年の開催は未定とのことですが、心より楽しみにしております。誠にありがとうございました!
アバター
こんにちは、BASE BANK株式会社 Dev Divisionにて、Software Developerをしている東口です。先日、2020年2月16日に開催された、 Object-Oriented Conference にスピーカーとして参加してきました。このカンファレンスには、BASEがブロンズスポンサーとして協賛しています。 非常に高度な内容がタイムスケジュールに並んだ濃密なカンファレンスで、オブジェクト指向や設計話にどっぷり浸かる一日になりました。 Object-Oriented Conferenceとは お茶の水女子大学で開催されたこのカンファレンスは、オブジェクト指向をテーマにした技術カンファレンスです。 ooc.dev Object-Oriented Conference はオブジェクト指向をテーマに、あれこれ共有したり、セッションを聴講することで、みなさんの知見を深めるためのイベントです。 冒頭に書いたとおり、BASEは、ブロンズスポンサーとして協賛しました。 発表内容:デザインパターンの使い方を パタン・ランゲージとの比較から考える 冒頭に上げていますが、この内容の課題感は自分自身が感じる「デザインパターンに対するもやもや感」でした。 GoF(Gang of Four)のデザインパターンは、我々が日々行う設計行為において基礎的な要素を占めています。ですが、一方で「デザインパターンをなんとなく知っている」状態から「デザインパターンを正しく使う」状態へ向かうには、大きな壁があると感じています。 正しく使うためには、その対象を知らないといけないですが、その切り口として、「デザインパターンの前」を見てみようという内容です。それが、パタン・ランゲージであり、この発表はパタン・ランゲージを理解し、その違いを理解することで、デザインパターンとの付き合い方を整理しようとしています。 発表後、ありがたいことにさまざまフィードバックを頂きました。 人は解決策をすぐに求めがちだけど、コンテキスト・問題を正しく理解してどうやって自分が解決策を導くのか、が大事なんだよなぁ #ooc_2020 #ooc_e — isop (@isop) February 16, 2020 『オブジェクト指向のこころ』をまた読み返したくなる素敵なトークだった #ooc_2020 #ooc_e — null | undefined | (@cheezenaan) February 16, 2020 動画で見たのですが、すごく良いセッションでした!問題提起から、数々の文献にあたり、最後に東口さんなりの結論を導きだしたのがとても良かったです。おつかれさまでした :) — Masashi Shinbara (@shin1x1) February 16, 2020 裏話をすると、発表時間を15分〜20分で、パタン・ランゲージとデザイン・パターンを比較するという性質上、パタン・ランゲージとその発想の背景にあるクリストファー・アレグザンダーのデザインに対する考え方を、ぎゅっと短い時間でまとめ上げることが必須で、その整理に非常に工面し、最後の最後まで時間をさきました。 10分でわかるアレグザンダー感がある。いいな。 #ooc_2020 #ooc_e — きょん@アジャイルコーチ、システムアーキテクト (@kyon_mm) February 16, 2020 「クリストファー・アレグザンダーの考え方に精通されている」と僕が認識している @kyon_mm さんにこう言っていただけたので、なんとかうまくいったようで安堵しています。 カンファレンスでアウトプットすることの醍醐味の一つですが、聴講頂いた方のコメントから、さらに関連する知識もいただけました。 アレグザンダーの『ノート』におけるデザインの3段階のモデルとアラン・ケイの"Doing with Images makes Symbols” のスローガンの心理学的な根拠が両方ともジェロム・ブルーナーの子供の認知機能の発達の過程という発見がそういえば最近あったことを思い出した。 https://t.co/HLbiHkOzE4 — Akira Motomura (@akira_motomura) February 16, 2020 とてもよかった ところでパターンが先になくとも原則に従ってリファクタリングする中で自然にデザインパターンが現れてくることを、Uncle Bobはアジャイルソフトウェア開発の奥義の中で「コードがデザインパターンに回帰していく」と表現していました。 #ooc_2020 #ooc_e https://t.co/FjFKWMHb19 — takasek (@takasek) February 16, 2020 発表したことによって、関連する新しい情報をもらえるのは本当にありがたいことです。この他にもたくさんのフィードバックを頂きました。貴重なお時間をいただけたこと、この場を借りて御礼申し上げます。 まとめ Object-Oriented Conferenceは今年初開催のカンファレンスでした。オンラインでの視聴者込みで1000人超えの来場者数で、5トラックある非常に大規模なカンファレンスにもかかわらず、非常に楽しく1日過ごさせていただきました。主催者の @hirodragon112 さんを始め、運営スタッフのみなさま誠にありがとうございました。
アバター
2020 年 3 月 28 日に開催される YAPC::Kyoto に BASE 基盤グループのエンジニアである めもりー が登壇します。 YAPC とは YAPCはYet Another Perl Conferenceの略で、Perlを軸としたITに関わる全ての人のためのカンファレンスです。 Perlだけにとどまらない技術者たちが、好きな技術の話をし交流するカンファレンスで、技術者であれば誰でも楽しめるお祭りです! 弊社で使用している技術スタックではないカンファレンスでの登壇は数多くなく、珍しい試みとなります。 セッションについて 「Perl 初心者の私が YAPC のために Perl で JVM を実装してみた」 2020 年 3 月 28 日 登壇者名: めもりー 10:50 開始 ルーム1 トーク内容 みなさんは JVM (Java Virtual Machine) を実装したことをありますか?私はあります。 ただ、それは Perl ではなく PHP と JavaScript で、です。 YAPC のために今まで使ったことのない言語である Perl を使って JVM を実装してみようと思います。 本トークでは、 Perl でどうやって実装したか、苦労した点は何か、そして Hello World を出力するところまでデモンストレーションできればと思っています。 最後に 下記から YAPC への参加申し込みが可能です。 yapcjapan.org
アバター
こんにちは。BASE株式会社でProduct Management Groupのマネージャーをしている山田です。 12/1から始まった「BASEアドベントカレンダー2019」はお楽しみいただけましたか?私の記事が最後の記事となります。 今年は約50名のメンバーが執筆に参加しました。エンジニアだけでなくデザイナーやProduct Managementのメンバーも筆を執っています。個性豊かな記事が集まっているので、ぜひご覧になってみてください。 devblog.thebase.in さて、私が最後の記事「閉会式」を担当するということで、簡単に自己紹介をさせていただきます。私は2019年4月に入社し、BASEは3社目となります。簡単な経歴は、新卒でワークスアプリケーションズ > リクルート > BASEとなります。1社目はエンジニアとして、2社目ではUI/UX、プロダクトマネジメントを担当しておりました。 入社して半年がたち改めて振り返ってみると めちゃ楽しかったなー というところなのですが、なぜBASEでのプロダクト作りが楽しいのかをさくっと振り返ってみます。 オーナーズが圧倒的に素敵 BASEではショップを開いてくださっている方をオーナーズと呼んでいます thebase.in オーナーさん達は作っている商品だけでなく生き方も素敵で、自分たちが作っているプロダクトのユーザーをむちゃくちゃ好きになりながらプロダクトを作れることって楽しく尊いことだなと思いながらプロダクトを作っています。 社内でも「それってオーナーズのためになってるんだっけ?」とプロダクト作りをする上での主語が自分たちでなく、オーナーズになっていることも、当たり前のように根付いて、じんわりいいなーと日々感じています。 変化 「BASE」というプロダクトは、インターネットが当たり前にある世界となり、新たな生き方/働き方ができる人が増えたことで、成長しているプロダクトだなと思っています。その世の中の変化の先っちょを肌で感じながらプロダクトを作っています。 先っちょであるが故に、会社が成長し、プロダクトが成長が成長し、そして上場したり、競争環境が変わったりと色々な変化がすごいスピードで起きています。 その変化に追いつくためには、自分達自身も変化し続ける必要があり、それはなかなか出来ない体験で、大変なことも含めて日々めちゃくちゃ楽しいです。 BASEには明文化された行動指針があります。 Be Hopeful:楽観的でいること。期待した未来は実現すると信じて、勇気ある選択をしよう。 Move Fast:速く動くこと。多くの挑戦から多くを学ぶために、まずはやってみよう。 Speak Openly:率直に話すこと。より良い結論を得るために、その場で意思を伝えよう。 入社当初は文化が浸透していていいな、と思っていたくらいだったのですが、改めてこの変化の激しい環境に適応していくためには、この行動指針はすごく良いなと最近より実感するようになりました。 Move Fastかっこいい 終わりに そんな感じで、BASEでのプロダクト作りを楽しんでいます。 私たちが目指してる世界に僕らはまだ圧倒的にたどり着いていません。 まだまだプロダクトも僕らも世の中も変わり続けて、ただその変化の先っちょいい続けるために突き進んでいければと思います。 こんな環境でプロダクト作りしたい仲間を絶賛募集中です! binc.jp これでBASEアドベントカレンダー2019は閉会です。読んでくださったみなさんありがとうございました!
アバター
  アドベントカレンダー最終日です!BASEで代表を務めている鶴岡です。宜しくお願いします。 いつもこの時期になると、ありがたい事にメディアさんから来年はどんな年になると思いますか?といったアンケートを頂くことがあります。 そもそもこういった質問にお答えすること自体あまり得意ではないのですが、一番悩む質問が、今年読んだ本の中で一番良かった本を教えてください。というものです。 完全に僕の課題なのですが、僕は本を読むのが苦手で、いまいち周りの起業家のようなカッコいい答えが思い浮かばないのです… そう話すと、周りの人たちからどうやって情報をインプットしているのかとよく聞かれます。 ある時、自分でも確かになと思い、よくよく考えた結果、僕は周りのコミュニティに助けられて学ばせてもらっているのだと気がつきました。 僕は本当にコミュニティに恵まれています。 まずコミュニティに恵まれた第一歩はインターネットでした。インターネットに本当に多くの価値観を学びました。CAMPFIREでインターンというキッカケをくれたのもインターネットです。インターネットさいこう! その後は、CAMPFIREでインターンをしていた都合上、この業界に来た時からインターネットが好きで好きでたまらないスター達に可愛がっていただき、気がつかぬうちに、完全にインターネットが好きになって作る側に回りたいと思っていたし。 ある時からは、気がつかぬうちにプロダクトを作るコードを書くのが好きな人たちに囲まれて、一晩中コードを書いたりプロダクトの未来を考えるのが好きになっていたし。 ある時からは、投資家に囲まれ、ファイナンスの方法を学び、企業や組織の成長のさせ方に興味が持てていたし。 ある時からは、初めには出会えないような先輩経営者に会えるようになり、大きな夢を見る大切さや、1秒1秒の大切さを実感できていたし。 僕としては初めにCAMPFIREに行こうと意思決定して以降、ジェットコースターにただ乗っているような感覚で各コミュニティにここまで育てていただきました。   上記に関しては気がつかぬうちに入っていたコミュニティなのですが、昨年くらいにこのコミュニティという存在の大切さに気がつき、今年からは意図して自分が身につけたい思考や能力が身につきそうなコミュニティにも入るようにしました。 例えば、ネットショップ作成サービス「BASE」のユーザーさん達です。 正直なところ今まではユーザーであるショップオーナーさんにはあまり会わないようにしていました。それは中途半端にお会いしてしまうと、仮にそのユーザーさんがBASEのサービスに不満を持たれて、別のサービスを使いたいと思ったときに、僕への情だったり気を遣われて、自由に次の選択をすることがやりづらくなるのではないか。それなのに僕自身は満足に相談にも乗ることができないのではないかと思っていたからです。 去年くらいからは日常業務の大部分を他のメンバーに移譲できていたので、今年は凄く多くのショップオーナーさまに会わせていただいて、本当に多くの刺激をもらいました。 毎日のようにお会いさせていただいている中で、ものづくりの大変さ、楽しさなどなど生きていく上で大切な価値観を本当に多く教えていただきました。 We are Ownersというメッセージを出させていただいたのもこれがキッカケです。 https://thebase.in/weareowners ここで出会った一部の方々とは友達としてプライベートでの交友もできました。 友達の中には、服を作っている人、音楽を作っている人、写真を撮っている人、映像を作っている人、自分という商品を作っている人。 第一線で頑張っている人もいれば、まだまだこれからだと焦っている人もいて様々だけれど、そんな友達と話していたり、成果物を見せてもらったりしていると、自分の無力感や思考の浅さを実感できて、最近では一番成長意欲を刺激してもらっているコミュニティな気がします。 いかなるジャンルであっても、どんな人であっても、悩んでない人などいないんだなと実感できるし、なんと言っても仕事が楽しそうで好きなのが伝わってくるので、僕自身の生きる活力になっています。自慢の友達です。 コミュニティが人生にもたらす影響に気がついて、新たなところに自ら足を伸ばして本当に良かったなと思います。 起業して以来初めて地元の友達にも会うようにもなりました。 完全になんとなく、自分への課題として、起業してから会っていなかったのですが、ある意味新たなコミュニティとして7年ぶりに会いました。 みんな様々な人生を送っていて、ただただ飲みながらこの7年間の話をしているだけで死ぬほど楽しかったです。毎日会っていたような感覚すらありました。 本当に友達は大切ですね。 しょうもない話ができる大切さも30歳を目前してようやく理解しました。 成長というものを前提に置いたとすると、個人的にはコミュニティには2つの性質があると思います。 成長するための知識や劣等感を得れて頑張る意欲を貰えるコミュニティ。 もう1つが、安心してなんでも話すことができるホームコミュニティ。 1つ目に関しては恐らくどんどん変わっていくもので、自分がチヤホヤされだして、成長意欲を削がれてしまうように感じたら次に行く合図かもしれません。 ここまで何が言いたいのかよく分からないですが、まとめとしては、どんなコミュニティにいるのか、そこでどんな人たちとどんな時間を一緒に過ごしたかが自分の人生に影響を与えるという事です。 もしも今、毎日をいまいちパッとしないと思って過ごしていたり、いまいち学びたいこと学べてないなと思っていたら、適切なコミュニティを見つけて飛び込んでみることをお勧めします。 僕は、ずっと知識や意欲をもらってばかりだったので、最近はそういう刺激を提供できる側にもなりたいなと思っています。 いろんな世界やいろんな価値観を知りたいのでぜひお友達になってください。 https://twitter.com/0Q7 本を読めるようにも頑張ります!! それでは良いお年を。
アバター
はじめまして。BASE株式会社 取締役COOの山村です! アドベントカレンダーはエンジニアじゃなくても書いていこう!というムードに乗せられてブログを書くことになりました。 2019年のBASEを振り返ると、CTOの交代や、東証マザーズへの上場、「BASE OWNERS DAY」を初開催するするなど、会社のステージも変わり、我々、経営陣にとっても、大幅なレベルアップする必要を感じた1年でした。 選んだのはコミュニケーションのスキル 専門領域を持たない自分が、これからもBASEの成長に貢献し続けるためにと考えて選んだのは、コーチングの技術でした。10数年前に出会って、そこから独学で少し学んだりしてはいましたが、1on1はBASEのカルチャーとして定着もしてきましたし、ここ最近、mentoやcotreeのように、コーチングを提供するスタートアップが出てきたり、身近でも話題に出ることが増えていたので、この機会に、あらためてスクールに通って学んでみることにしました。 無事にプロコーチになり 夏前から通い始めて、週末ごとにみっちり学び、秋には全過程を修了、そのまま GCSコーチ の認定試験にも合格しました。せっかく学んだ知識なので、簡単に使えるコーチングの基本を少しシェアしたいと思います! コーチングとは? 自身が考えるコーチングの定義は、「目標達成に向けて、対話によって対象者を勇気づけ、気付きを引き出し、自発的行動を促すコミュニケーションスキル、思考法」としています。コーチはアドバイスやコンサルティングを行うのではなく、あくまでも「答えは相手の中にある」と信じて、それを引き出す手伝いをします。 目標を与えられるのではなく、正解のない未来に向かって、自らビジョンを掲げ、ミッションを設定し、ゴールに向かっていくスタートアップとは、非常に相性のよいアプローチになります! 基本のストラクチャー 理想の状態を描いて達成すべきゴールを明確にする ゴールと現状の差を把握する 達成までのプロセスを設定する 行動する これを繰り返すのがコーチングの基本構造。理想の状態を描くことからスタートするのは、BASEの掲げる「Be Hopeful」という行動指針にも通じる考え方です。 セルフコーチングのススメ 質問や対話によって、目標達成の手助けをするのがコーチの役割なのですが、コーチを雇うのはハードルが高いという方には、自身で行うセルフコーチングがオススメです。これだけでも、かなり思考が整理されます。 例えば、「来年の夏休みをどう過ごすか」というテーマで、コーチングのストラクチャーを使って考えてみると、以下のようになります! テーマ:「来年の夏休みをどう過ごすか」 <目標設定> Q:どういう夏休みが理想ですか? A:いつもより長めに休みをとって、家族でハワイ島に渡って、のんびり過ごしたいな <現状把握> Q:その状態を「10」としたとき、今は何点ですか? A:「2」くらい Q:今つけた点数の中身は何ですか?(今出来ていることは何ですか?) A:家族の賛同や、会社の理解は得られそう   以前にも行ったことがあり、段取りのイメージがついている <現状と目標との乖離/プロセス設計> Q:これから目標達成に向かって、必要なことは何ですか? A:予定の確認・スケジュールの調整   航空券や宿の手配   不在時の業務調整   等々 <優先順位付け> Q:そのために何から始めますか? A:予定の確認・スケジュールの調整から   <行動を促す> Q:今日できることは何ですか? A:まずは家族に提案して日程の相談をはじめてみる! こうやって、自ら導き出した一歩目を踏み出してみる、これを定期的に繰り返すことで、着実に目標に近づくことができます。質問に対して自分自身で考えてみることによって、思考が整理され、行動が促される、というコーチングの雰囲気を感じていただけたでしょうか? 最後に この数週間は、BASEの未来を描くことにほとんどの時間を使っています。2019年も残り数日となりました。まだまだ力不足を実感する日々ですが、掲げるビジョンの実現に向けて頑張っていきます! 「Payment to the People,Power to the People.」 我々はまだまだ小さいチームです。自ら目標を掲げ、前に進んでいけるリーダーをたくさん募集しています!お気軽にお声かけください! https://binc.jp/jobs
アバター
この記事はBASE Advent Calendar 2019の25日目の記事です。 devblog.thebase.in BASE株式会社でCTOをやっている川口 ( @dmnlk ) です。 2019年7月1日にCTOに就任させていただきました。 そこからちょうど半年経った今、エンジニアが40名近い会社で自分がCTOとして感じたことや変化、その先への考えを綴りたいと思います。 BASEでCTOになった経緯については下記にて取り上げていただきました。 そもそもこういう媒体に自分が出るようになった、というのも目に見える変化だと感じています。 type.jp careerhack.en-japan.com 自分のキャリアについて登壇させていただく機会もいただきました。 今までの自分ではこういう機会は訪れなかったと思うので、立場やタイミングというのは得てしてこういうものがあるのだなぁと感じています。 devblog.thebase.in CTOに就任してからの最初の3ヶ月について 就任したその日から技術の責任者としての自覚を得られていたかというと正直そんなことはまったくありませんでした。 弊社では3ヶ月ごとに開発スケジュール組むことが多いのですが、その前にやっていた開発の残りがあったのでそのまま継続して行っていました。小さな不具合や改善なども自分で行ってしまっていました。 CTOを引き継ぐ際に前任CTOの藤川より「開発現場のリーダーが就き、技術的な意思決定を担う」とCTOの定義をされていたので自分が開発現場で日々の開発をしていても問題はないと考えていたこともあり、特に自分の考え方をアップデートせずリードエンジニアの思考のまま日々を過ごしている状態でした。 しかしこれは、現場のリーダーではありますがCTOとしての振る舞いとしてはあまりよくなかったと今は感じています。 もちろん、全くコードを書かないつもりはありません。 ですが、CTOとしてはメンバーの成長とプロダクトの成長を第一に考え次のプロダクトの非連続的な成長を迎えるために技術投資を行っていくことが重要です。 その次の3ヶ月 就任し3ヶ月も経った頃、ふと「このままでいいんだろうか」という気持ちになりました。 採用も進み、優秀なメンバーも増えています。 そんな折、コネヒトよりパネルディスカッションの機会をいただきました。 その時の模様は記事になっています。 type.jp ここで初めて他社のCTOという存在に直接関わりました。 特にコネヒトのCTOである伊藤さん( @itosho )は同じようなタイミングでCTOを引き継いだこともあり親近感を感じましたが、自分より遥かに組織を前に進めようと動いているなという焦りを感じました。 クックパッドの成田さん( @mirakui )も組織やプロダクトに向き合いながらもISUCONで優勝しており、自分より遥かに高い場所にいました。 このまま漫然と自分がやるべきでもないコードを書き(メンバーがやるべき雑務というわけではありません)立場だけCTOになっていていいのか、引き継いだ意味は本当にあったんだろうか?と自分がやるべき事を見直し始めました。 今では80万以上のショップ様に利用して頂いている「BASE」というプロダクトですが技術的な課題は非常に多くあります。 利用しているウェブフレームワークのEOL、モノリシックなアプリケーションにより開発速度の低下、耐障害性や負荷問題、データが均質化されていないことによる分析のしづらさ、枚挙に暇がありません。 非連続的な成長を成し遂げるための技術投資も行わなければなりません。 もちろんプロダクト自体のクオリティを高め、プロダクトを使って方々により良い体験を届けるための開発もしていくことも必要です。 これら全てをBASEの課題として認識し、一つ一つクリアにしていき解消するための方針を立て優秀なメンバーの能力を最大限に活かしながら前に進めていくことがCTOに求められている責任であると認識を改めることにしました。 今現在とこれから 現在のプロダクトに直接関わるようなコードは書かずたまに障害対応用の小さなコード群を書くくらいになりました。 代わりに現状のBASEを見つめ直し、課題に対する優先度を見つけたりその課題を解消できるような技術選定や検証を行うことが増えました。 採用に関しても、現状困っている部分に対してコミットしてくれるようなメンバーという視点だけでなく未来のBASEの問題に取り組んでくれるようなメンバーか?といった視点でも選考するようになりました。 考えてるだけでコード書けないのでは?と思われるのも厳しいので、もう少しなにかできないかというのは悩みです。 未来のBASEを作るアーキテクチャというものに悩んでいますが、それがこのままモノリシックなのかマイクロサービスアーキテクチャなのかモジュラーモノリスなのかといった辺りは非常に難しくまだまだ結論が出ません。 メンバーと1on1をするようにもなりました。これはある種の技術選定と同義だなと考えています。普段開発をしているチームのエンジニア達がどのような課題感を持っていたり志向性を持っているかで、次のアサインを決めていくのが重要なので日々の対話を疎かにすべきでないと思っています。人数が多いので大変ですが... 2020年は今のBASEのシステムに大きい変化を行っていく予定なので今から楽しみです。技術力とプロダクト理解、それぞれが求められるような変化なので僕もコード書いてコミットしていきたいです。 CTOになって良かった?後悔している? たまにこの事を知人には聞かれます。 正直な話、BASEじゃなかったらやりたくないなと思うくらいには大変だなと思います。 全然ゴールが見えないし、何をもってして自分がやりきったと言えるかがまだまだ不明ですし自分が決めた選択の重みが今までとは比べようもなく大きいと感じます。 ただ自分がやりたいインターネットだなと思っているプロダクトとチームが目の前にある中で大きな裁量を持って仕事できることは人生で数少ないので今やれることを精一杯やっていきたいです。 最後に この記事で上げたようなBASEにおける課題について共に考えて手を動かして「BASE」というプロダクトをもっと最高にしていく仲間を募集しています。 募集は下記にありますが、まずは僕とカジュアルにオフィスで話をしましょう。 binc.jp
アバター
BASE株式会社で執行役員VP of Productとしてプロダクトマネジメントをしている @7jin16 です。 プロダクトマネジメントについて書こうと思いましたが、世の中にたくさん記事もありますし、キャリアハックさんに記事を書いていただいたのでこちらをご覧ください🙏🏻 careerhack.en-japan.com プロダクトマネジメントに関わるまで 2013年頃、以前から知り合いだった代表の鶴岡から仕事の誘いのメッセージをもらって、カスタマーサポートのメンバーとしてBASEで働き始めたのが入社のきっかけです。 ※2013年の東京都の最低賃金は時給869円です。 カスタマーサポートとして入社しましたが、入社後すぐに年末キャンペーンのページをコーディングする機会をもらい、それ以降「BASE」本体の機能の画面設計や実装に関わることになり、コードを書いたりしながら数年かけてプロダクトマネージャーと呼ばれるような役割に移っていきました。 スーパーヒーローたちに憧れて BASEに入社する前からインターネットプロダクトが大好きだったのもあり、そこに全力を注げる環境もあるので、入社から今も変わらず毎日ほんとうにプロダクト作りが楽しいです。 インターネットプロダクトが好きな理由は、マーク・ザッカーバーグがかっこいいし、クリス・コックスもかっこいい。ショーン・パーカーもかっこいいし、エヴァン・シュピーゲルも、デビッド・カープも、ジャック・ドーシーもコリソン兄弟も、ビズ・ストーンも、アレクシス・オハニアンもかっこいいからです。ぼくにとってのスーパーヒーローです。 The Social Network | Netflix とかリスニング力が低くて英単語が聞き取れなくても音でどの場面か大体分かるくらい観ています。めちゃくちゃミーハーですね。いつか thebase.in の the を取りたいですね。 人々に熱烈に愛され続ける偉大なプロダクトをつくった偉人たちに憧れ「いつか自分も人々に熱烈に愛され続ける偉大なプロダクトを作りたい!」と思い始めて、10年弱たちますが、今もなお憧れ続けています。 プロダクト作りをしていると毎日いろいろな問題に直面します。そのたびに「まったく同じ状況下でもマーク・ザッカーバーグたちならもっと上手くやれるのかな。もっとユーザーのために頑張らないと。」と気が引き締まります。 入社当初から自分の何かが目に見えて成長したという実感は薄く、入社後に自身の1番成長した点を聞かれても回答に困りますが、毎日ユーザーに向き合い、プロダクト作りをしていたら役割が変わり、さらに楽しくなり、プロダクト作りに熱中する。そんな感じのループなのかもしれません。 毎日ユーザーに向き合い、熱烈に愛され続けるプロダクトを目指して作っていれば、いつの間にか自分自身も成長すると信じてプロダクトを作っています。ユーザーやプロダクト作りに関わるメンバーが増えれば増えるほど、スーパーヒーローたちを凄まじいと感じますが、背中すら見えないのでとても悔しいです。 今後もスーパーヒーローたちに憧れる心を忘れることなく、ユーザーから熱烈に愛され続けるプロダクトを目指します! プロダクト作りをしたい方は DM か、 こちら へ!! twitter.com 明日はCEOの鶴岡、COOの山村、CTOの川口が記事を投稿する予定ですのでお楽しみに〜〜〜!
アバター