Wiz テックブログ

Wizは、最新のIoTやICTサービスをお客様に届ける「ITの総合商社」です。

コロナ禍での他職種とのコミュニケーションについて

f:id:rainymoment0616:20210315183413j:plain

こんにちは、フロントエンドエンジニアの柳田です。

2020年、新型コロナウイルスの影響で、リモートワーク環境になった方は少なくないと思います。

弊社も同様にリモートワークになり、当初はコミュニケーションが取りづらくなることを懸念していましたが、バーチャルオフィスのoViceを導入したことで、その不安も払拭できたように感じます。

加えて、今までは会議室を利用して行っていた会議や勉強会なども、バーチャルオフィスの利用により、頻繁に行われるようになりました。

このテックブログでも、LT会輪読会の様子を紹介してきましたが、今回はエンジニア以外の職種のメンバーと取り組んでいるコミュニケーション施策について、ご紹介したいと思います。

事の発端はデザイナーからの協力要請

昨年の秋頃、弊社デザイナーから相談を受けました。

「異職種間での連携がちゃんと取れているか気になったから、デザイナーチームとフロントエンドチームにヒアリングをしたんだけど、うまくいっていないという意見が多くて…」

「これを解決したいんだけど、もし良かったら協力してくれない?」

私自身、たまにデザイナーと連携がスムーズに取れないことがあり、どうにかして改善できないかなー、でも自分ひとりだとなー…と行動に起こせずにいたので、「私でやれることなら全然手伝うよ!」と引き受けることにしました。

雑談会チーム発足!

そこから、他職種間での連携を取りやすくするためにどうすればいいのか、二人で施策を練ることにしました。

当初は、両職種間での業務における課題解決を目的にしていたので、「みんなで課題に思ってることを言い合って、業務改善できるようなルールを決めていく場を作るか!」と考えていました。

しかし、

  • そもそも仕事以外で話す機会もあまりないのに、そんなにざっくばらんに意見を言い合えるのか
  • 数回話し合ったところで解決できるような問題なのか(その問題が解決しても、また別の問題が浮上する可能性あり)

となり詰んでしまったため、上長にも相談。

「まずは課題解決をするのではなく、コミュニケーションを取る場を設けたら?」とアドバイスをいただき、結果、他職種間でのコミュニケーションを促進させ、心理的安全性を高めることで、業務におけるコミュニケーションコストを減らすことを目的として、改めて施策を練ることに。

話しやすい雰囲気を作りたかったため、雑談会というあまり固くなく畏まらないようなネーミングで、コミュニケーションを取る場を設けることにしました。

雑談会開催!

雑談会という名前をつけたときにもあったように、畏まった雰囲気を作りたくなかったため、

  • どの職種でも話しやすいテーマを設ける(テーマなしで臨むと、話しにくいメンバーも出てくる可能性があったため)
  • リモートだと大人数では話しにくいため、複数チームに分けて行う(6〜8人程度)
  • 自己紹介などのアイスブレイクを入れることで、話しやすい雰囲気を作る
  • カメラをONにして、面と向かって話してます感を出す
  • 基本的には任意参加にする(強制感を出したくなかったため)

など内容を詰めながら、2020年11月に1回目の雑談会を開催しました。

雑談会への参加は任意ですが、毎回ほとんどのメンバーが参加してくれていて、とても嬉しく思います。

f:id:rainymoment0616:20210316170332p:plain
【雑談会の様子】

第1回雑談会

初開催の雑談会は、デザイナーチームおよびフロントエンドエンジニアチームで行いました。

テーマは下記2点にして、両職種とも話しやすいテーマになるようにしました。

  • 自身の職種に関する情報、自身の職種以外の情報をどのように収集しているか
  • エンジニアやデザイナーはどんな風に勉強してる?業務に活かすためにインプットしてることは?

エンジニアもデザイナーもアンテナを張っている情報や収集する際のアプローチ法など異なっていて、聞いていてとても新鮮かつ楽しかったです。

また、最初に自己紹介を行ってもらい、その雰囲気のままテーマの話をしてもらうように。

終始楽しい雰囲気で行うことができました。

第2回雑談会(技術寄り雑談会)

1回目と同様、デザイナーチームおよびフロントエンドチームで行いました。

テーマについては、以前ヒアリングした際に出てきた、両職種間で課題に思っていることの中で意見が多かったものをピックアップして、下記3つに絞って行いました。

  • タブレット問題(各デバイスの画面幅によって起こる表示崩れの対応についての認識合わせ)
  • SVG問題(SVG画像の取り扱いについての認識合わせ)
  • フィードバック問題(修正指示の共有方法。円滑に製作作業を進めていくための認識合わせ)

このときは、チームでそれぞれ違うテーマ内容について話してもらったので、議事録を残し、他チームで話し合った内容について確認してもらえるような状態を作りました。

どの職種もUI/UXをより良くしようと、限られた時間の中でベストを尽くして作業しているのに、互いの認識違いが原因で、確認や調整に時間がかかりスムーズに進めることができないことが多くありました。

しかし、この会で認識を合わせることができただけでなく、「このようなルールで制作を進めていこう!」という流れになったことも、とても良かったです。

【番外編】年忘れ雑談会

年末の業務時間後に、1つのチームが4〜5人になるように分け、業務のことも含め、自由なテーマで話をしてもらう場を作りました。

Smgr雑談会

Smgr(サブマネージャー)と呼ばれる、弊社の役職者のみで集まって行う雑談会です。

  • 情報収集および部下への情報共有の仕方
  • 教育体制について(既存メンバーや新人に向けて)

一般社員のみで行う雑談会とは異なり、上記のような少し固めのテーマを展開していますが、普段Smgr同士でも話す機会があまりないため、雑談を踏まえながら行っています。

第3回雑談会

ディレクターチーム・デザイナーチーム・フロントエンドチーム(一部バックエンドチーム)の職種間で開催しました。

それぞれの職種が普段どのような仕事をしているのか、それぞれの職種の業務内容について話してもらいました。

ちょうど、この雑談会を開催したときには、フロントエンドとバックエンドにインターン生が在籍していたため、インターン生にも参加してもらいました。

各職種がどのような業務を行っているか、どのような考えで業務に取り組んでいるかを深く知ることができ、とても良い機会でした。

参加後アンケート

雑談会開催後はいつもアンケートをとっています。

企画している側としては、毎回ドキドキしながら開催しているのですが、毎回「良かった!」という声をいただいて、安堵しています。

今回はアンケートの内容を一部抜粋して、ここでご紹介したいと思います。

第1回アンケート

  • 仕事でかかわる機会が少ない人の声が聞けたのがよかったです。意外な趣味とか聞けるのも楽しいです。(仕事関係なし!)
  • 同じ役職のメンバーと同時話すことができたのが初めてだったので、とても新鮮で面白かった。また、(情報収集の仕方が)職種ごとに違うアプローチをとっていたので、興味深かった。
  • 普段話さないような事が出来る(してもいい)環境が用意されている事がよかった。仕事の事以外はあまり話しかけたらいけないような環境は息がつまるのでたまにはいいですね。

第2回アンケート

  • お互いチーム同士で協力して問題点など解決しようとする動きが良かった
  • フロント、デザイナーがお互いに、SVGに関する不明点やフワッとなっている部分(フローも含め)について、具体的な対応策や意見交換をすることができたので良かった。
  • フィードバック対応時のデザイナーの考えが分かり、コミュニケーションが取りやすくなりました。
  • フロント側の具体的な懸念点を知れたのと、そこからこうして行くべきという解決案が出たこと(デザインする際のルールの統一など)が良かった
  • 場の雰囲気が良かった!また、長年気になっていた事が聞けて、スッキリしました。

第3回アンケート

  • 他チームの取り組みを聞けて、ディレクターもなにかやろうと思えた。
  • 業務内容の共有というわけでなく、ざっくばらんにプライベートの会話ができていた点がよかった
  • 各職種の方々が、顔を合わせて話をするということ自体が良いことだなと思いました。顔を合わせて話をすることで、業務においてもスムーズなコミュニケーションを作りやすくなると思いました!
  • シャッフルタイムがあると全体で話せたかも
  • こういった組織にしたいよね、こういった運営したよねっていうゴールから何ができるかを色々アイディア出しできたら楽しそうだなと思いました!

また、全体的なアンケートを通して、いつもいただく意見として

  • 1時間じゃ足りないから、もっと開催頻度を増やしてほしい
  • 1チームあたりの人数が多いから、もう少し少ないほうがいいかも
  • まだ雑談会に参加していない職種とも話したい!
  • もっと他職種のこと知りたい!

という意見もいただいています。

まだまだ改善の余地がたくさんある雑談会…これからもがんばって企画していきたいと思います!!

最後に

私自身、自分から率先して話しかける機会があまり多くないので、雑談会を通して、普段話すことのないメンバーの普段の様子を垣間見ることができたり、仕事に対する姿勢や考えを聞くことができたり、とても良い機会だったと感じています。

また、開催して話す機会を増やしたことで「なかなか聞けなかったけど、この場なら聞けそう」「みんな同じことで悩んでるんだったらこの機会を利用して解決策を考えたい!」と考えるメンバーが少しずつ増えてきているようで、雑談会の目的である心理的安全性が少しずつ高くなっているのではと思っています。

より良い仕事を行うには、個人のスキルももちろん大切ですが、一緒にがんばっていくメンバーとの結束を固めることも大事な要素だと、私は考えています。

この雑談会をきっかけに、少しずつメンバー同士がざっくばらんに話すことができるようになり、より良いチームで、より良いサービスをお客さまに提供することができればと思っています。

そんなチームで一緒に働いてみませんか?

Wizではエンジニアを募集しております。 興味のある方、ぜひご覧ください。

careers.012grp.co.jp

E2Eテストの取り組みについて

はじめまして、フロントエンドエンジニアの菅野です。

今回は、E2Eテスト自動化の取り組みについてお話ししたいと思います。  

E2Eテストとは

End to Endを略してE2Eと呼ばれています。

例えば、

  • CV(コンバージョン)ポイントやログイン機能の動作確認
  • VRT(ビジュアルレグレッションテスト)

など、システム全体が正しく動作するかを確認するものです。

なぜE2Eテストを導入するのかというと、以下のような目的とメリットが挙げられます。

リリース時の確認コストの削減と品質担保

LPや2P~3Pといった小規模なサイトだと確認コストはそんなにかかりませんが、中〜大規模になると人の手で一つ一つ確認していくと時間と手間がかかりとても大変です。

そこで人が手を動かさずに各ページのUIや挙動をチェックすることができればコスト削減が見込まれます。

また、例えばリリース後に表示崩れが起きていたとします。

これまでだとリリースしてから5日後に気づいていたのが、リリース時にテストを実行することで1〜2時間といった短時間で発見でき、品質担保としても有効な手段となります。  

ツールの選定

E2Eテストツールはいくつかあり、

はよく耳にするのではないでしょうか。

他にはマイクロソフト製のPlaywrightというライブラリが2020年5月にリリースされています。

そんな様々なツールがある中で今回選んだのが「TestCafe」です。  

TestCafeとは

アメリカのDeveloper Express Inc.という企業が開発しているE2Eテストツールで、ブラウザテストを自動化するためのフレームワークです。

2016年にリリースされており、比較的新しいツールといえます。

特徴

  • async/awaitの仕様を前提にAPI設計がされている
  • TypeScriptサポート
    • 通常のJSだけでなくTypeScriptで記述したテストコードをそのまま実行できる
  • 構築が簡単
    • SeleniumではWebDriverのクライアントとテストを実行する各ブラウザのWebDriverのインストールが必要だが、TestCafeはnpmでTestCafeをインストールするだけでOK。設定ファイルも必要なくテスト環境が整う。
  • 非WebDriver依存
    • 一昔前のE2Eテストツールは、各種ブラウザベンダ間の差異を吸収し、抽象化して操作するためにWebDriverを使うのが常識でしたが、現在はブラウザ側がサポートするようになり、テストツール側が意識しなくてよくなった。TestCafeもこれを前提に設計されている。
  • BDD(ビヘイベア駆動開発)に則ったテストコード
    • UIテスト手順をメソッドチェーン形式で記述。これにより、ユーザー操作や外部仕様をまるで自然言語のようにコードで表現できる。つまり、テストコードがそのままテスト仕様書となる。
  • サポートブラウザが豊富
  • TestCafeだけでなく、Node.jsすらインストールされていない環境であっても、テストを実行することが可能
    • その場合、TestCafeが出力するURLを対象の環境のブラウザで開くだけでテストが開始される。ただし、TestCafeがインストールされているホストと対象とするデバイスが同一ネットワーク上に存在する必要がある。
  • BrowserStackとの連携をサポート
    • E2Eテストの実行環境は開発マシンとは別に用意しておくことが望ましい。そうすることで開発(実装)と並行してテストを実行しやすくなる。

以上の特徴があり、

  • サポートブラウザが豊富
  • 構築が簡単
  • async/awaitとを含む最新のJS機能とTSをサポート

が大きな選定理由となります(あとTestCafeっていう名前が可愛かった)

テスト項目

  • VRTテスト
  • CVポイント(フォーム)の基本動作確認
  • metaやOGPの取得
  • マークアップチェック

この4項目のテストを行います。

VRTテスト

VRTとは、画像回帰テストと呼ばれており、画面のスクリーンショットをリリース前後で比較することで表示崩れを確認することができるテストです。

TestCafeとreg-cli*1を組み合わせて実装していきます。

  1. まずはTestCafeを使って、指定するページのスクリーンショットを撮影します。
  2. reg-cliを使って差分比較を行います。

reg-cliで生成されたHTMLを見てみると reg-cli

このように差分を確認できるようになります。

おまけ

スクリーンショットが複数枚ある場合は、それぞれを連結させて1枚の画像にすると1枚1枚開いて確認する手間が省けるのでおすすめです。

sharpという画像編集ライブラリを使うと実装できます。

スクリーンショット連結

CVポイント(フォーム)の基本動作確認

フォームが入力〜送信まで問題なく動作するかをチェックします。

バリデーションや様々なパターンを想定してテストが実行できると良いですが、テストケースがかなりのボリュームになり、コストがかかり過ぎてしまう可能性もあるので、どこに重点を置くかを決めてテストケースを絞るのが現実的かなあと思います。

fixture('FormTest Start');
  .page('https://example.com');
  test('必須項目を入力し送信', async (t: TestController) => {
    const dataTarget = await Selector('[data-target-input]');
    const name = dataTarget.withAttribute('name', 'name');
    const mail = dataTarget.withAttribute('name', 'email');
    const phone = dataTarget.withAttribute('name', 'phone');
    const submitBtn = await Selector("button");

    await t
      .typeText(name, 'テスト名前')
      .typeText(mail, 'test_sample@gmail.com')
      .typeText(phone, '0312345678')
      .click(submitBtn.withExactText('送信'))
}); 

   このように直感的に書けるので分かりやすいのではないでしょうか。  

metaやOGPの取得

ページを一つ一つ開き、デベロッパーツールや拡張機能を使ってmeta情報を確認するのはとても面倒です。

スクリーンショットを撮るタイミングで各ページのmeta情報を取得し、jsonに吐き出すことで確認コストを削減します。

og:imageは外部のOGP確認ツールにアクセスし、スクリーンショットを撮影します。

テキスト情報だけでなくog:imageを視覚的に確認できるようにしています。  

{
 "meta": [
  {
   "page": "/",
   "title": [
    {
     "text": "株式会社Sample",
     "最大29文字程度": true
    }
   ],
     "description": [
    {
     "text": "株式会社Sampleのdescriptionが入ります。",
     "最大110字程度": true
    }
   ],
   "keyword": [
    {
     "text": "株式会社Sample,サンプル,sample,北海道,東京,大阪,福岡",
     "5〜6個程度": false
    }
   ],
   "og:title": "株式会社Sample",
   "og:url": "https://example.com/",
   "og:image": "https://example.com/img/ogp.png?1603865417442",
   "og:site_name": "株式会社Sample",
   "og:description": "株式会社Sampleのog:descriptionが入ります。",
   "canonical": "",
   "robots": null
  }
 ]
}

ogp確認スクリーンショット

マークアップチェック

テスト実行時にチェック用のCSSを挿入し、スタイルが当たった状態のスクリーンショットを撮影してマークアップチェックを行います。 ディレクターやデザイナーはソースコードをあまり見慣れていないため、視覚的に確認できるようにすることで、マークアップについてもチーム全体で意識を持ち、品質担保を目指すことができます。

markupチェック

  • ul,olの子要素にli以外のタグが入っている
  • dlの子要素にdt,dd,div以外のタグが入っている
  • imgタグのaltがないもしくは空
  • リンクにname属性もしくはhref属性にjavascriptが使われている
  • target="_blank"がついている場合にrel="noopener"

といった項目がチェックできるようになっています。


以上、4つの項目のテストを実行し、チェックを行っています。

実案件での使い方

コーポレートサイトと新卒採用サイトでは新規コンテンツ制作時や複数ページに及ぶ修正が発生した際に必要なテストを実行し、結果をSlackでプロジェクトチームに共有して確認を行っています。 最近だとmetaを変更したのでjsonを共有して確認に使用してもらいました。

slack_共有

今後やりたいこと

Qiitaに詳しい実装方法は書いており、それを参考にWiz cloudにも導入してもらっていますが、他の案件にもスムーズに取り入れてもらえるようドキュメントを鋭意制作中です。

これで完成ではなく、アップデートして継続できるE2Eテストにしていけたらと思います!

最後に

Wizではエンジニアを募集中です!

興味のある方、ぜひご覧下さい。

careers.012grp.co.jp

*1:VRTのためのコマンドラインインターフェイスです。 画像は別途用意する必要がありますが、アサートする画像を指定するだけで現在の画像と以前の画像を比較し、差分のHTMLを作成してくれます。

Gatsby v3リリース 差分ビルド検証

先日、(2021年3月3日) Gatsby v3.0がリリースされました。 Introducing Gatsby 3.0 – Faster in Every Way that Matters

いくつかの変更がありますが、特に気になった項目が

V3 for Content Editors: Faster build times on any service

(あらゆるサービスでのビルド時間の短縮) です。

Faster build times on any service

項目を大胆に丸々引用します。

Last year Gatsby introduced a breakthrough in static site generation with Incremental Builds. Instead of a content update kicking off a full rebuild of your entire site, we enabled a new feature that only updated pages that had new content to display. This dropped build times for sites from multiple minutes to under 10 seconds in many cases. Content editors were especially excited. With Incremental Builds, a Gatsby project now enabled the same rapid workflow and seamless feedback loop as the all-in-one CMSs they were familiar with using. An editor could fix or add content to a page and see change live in less than a minute. However, Incremental Builds was initially only available in Gatsby Cloud. We heard from the community that you wanted this key feature to be enabled in Gatsby open source, so the content editors you support could enjoy fast builds no matter what CI/CD service you choose. Today, with Gatsby v3 we’re thrilled that Gatsby open-source now has Incremental Builds enabled by default, anywhere you decide to run your project!

日本語訳です。

昨年、ギャツビーはインクリメンタルビルドによる静的サイト生成のブレークスルーを導入しました。 コンテンツの更新によってサイト全体の完全な再構築が開始される代わりに、新しいコンテンツが表示されるページのみを更新する新機能が有効になりました。 これにより、多くの場合、サイトのビルド時間が数分から10秒未満に短縮されました。

SSGといえば、変更が一箇所だけであってもプロジェクト全体をビルドしないといけないので、 どうしても再構築に時間がかかっていました。
これは画期的な機能です。

コンテンツ編集者は特に興奮していました。インクリメンタルビルドにより、Gatsbyプロジェクトは、使い慣れたオールインワンCMSと同じ迅速なワークフローとシームレスなフィードバックループを可能にしました。編集者は、ページにコンテンツを修正または追加して、変更を1分以内にライブで確認できます。

その通りですね。データ変更が多いプロジェクトであればあるほどこの機能は素晴らしいものになります。

ただし、インクリメンタルビルドは当初GatsbyCloudでのみ利用可能でした。コミュニティから、この重要な機能をGatsbyオープンソースで有効にして、サポートするコンテンツエディターが、選択したCI / CDサービスに関係なく高速ビルドを楽しめるようにしたいとのことでした。

インクリメンタルビルド機能は私も実際にプロダクトに導入したかったのですが、 GatsbyCloudという有料プランでしかサポートされておらず(一部無料プランもあり)、断念していました。

今日、Gatsby v3では、Gatsbyオープンソースで、プロジェクトを実行することにした場所で、デフォルトでインクリメンタルビルドが有効になっていることに興奮しています。

つまり、その素敵なインクリメンタルビルド機能オープンソースGatsbyで無料で使えるようになった!!
ということです。これはすごい!!

検証

本当に私が想像していた(待ち望んでいた)差分ビルドなのでしょうか。
試してみるのが一番ですね。

Gatsbyプロジェクトの準備

検証用にGatsby + Contentful + Netlifyでサクッとアプリを作成しました。 参照: JAMstack Gatsby + Netlify + Contentfulの構成を試してみた

インクリメンタルビルドの為の各種設定

Netlifyにプラグインを追加します。 参照: 【Netlify x Gatsby.js】ビルド時間を短縮!差分だけビルドする機能(Incremental Builds)を導入するテスト!

Netlify上でPluginsを選択し、Gatsby cacheをインストールします。

f:id:iricocco:20210304201453p:plain
Netlify

また、package.jsonnpm run build--log-pagesというオプションを追加します。
これによって、どのページがアップデートされたのかがログで吐き出されるようになります。

  "scripts": {
    "develop": "gatsby develop",
    "start": "gatsby develop",
    -"build": "gatsby build",
    +"build": "gatsby build --log-pages",
    "serve": "gatsby serve",
    "clean": "gatsby clean"
  },

そして、contentfulなどで情報を更新してみてください。
今回トップページのみに影響のある範囲のデータを編集したところ、 トップのみが更新されているのがわかるかと思います。
404ページなどは更新されていません!! f:id:iricocco:20210304201722p:plain 期待する挙動が得られています。

一体どういう仕組みなのか

www.gatsbyjs.com

HTML生成時に、入力しているものをトラックしている、と書かれています。 主な追跡対象は以下です。
・どのテンプレートが使われているか
・ページクエリの結果
・ページテンプレートで使用されている静的クエリの結果
・フロントソースコード
このトラックに紐づくコードに変化があった時、そのHTMLを更新するという仕組みのようです。

上記で示した例は簡易的なリポジトリでしたが、ページ数が多いプロダクトでは、build時間が激変すること間違いなしです。

懸念点

検証していないのでまだ確かではありませんが、VercelでGatsbyのこの機能が使えるか怪しい...と思っています。

Gatsby Incremental builds · Discussion #5001 · vercel/vercel · GitHub

少し前ですが、このようなissueが挙げられていました。
VercelはNext.jsと同じチームなので、手厚くGatsbyをサポートするのはなかなか難しいのかな、と思ったり...
今後時間を作って調べてみたいです。

現在Wizでは一部プロダクトにNext.jsが使われていますが、更新の頻繁なサイト、ページ数の多いサイトにはGatsbyという選択肢もありかも、と今回のアップデートで思いました。

最後に

Wizではエンジニアを募集しております。 興味のある方、ぜひご覧下さい。

careers.012grp.co.jp

AOP、Laravelのライブラリ紹介

AOPとは

AOPAspect Oriented Programming)とは、コンピュータプログラムの特定の振る舞いを「アスペクト」と呼ばれる機能単位として分離して記述し、プログラム中の様々な対象に適用出来るようにする手法です。既存のオブジェクト指向プログラミング言語や開発環境に補助的に投入されることが多いです。

背景

オブジェクト指向プログラミングでは、お互いに関連するデータ(属性)とそれらに対する操作の集合でオブジェクトをプログラムの基礎単位として記述して行きますが、ロギング(Logging)のような様々なオブジェクトで共通して現れますが単一のオブジェクトやメソッドなどとして切り出して定義することが出来ないような横断的な機能(横断的関心事)が存在する場合があります。

例えばissueBookとreturnBookの2つのメソッドをもつクラスLibraryServiceの例を見てみましょう。仕様としては、パラメーターと返却値をログに記録することです。ここで、ロギングは、アプリケーションに実装したい横断的関心事です。

<?php
class LibraryService {
    public function issueBook(int $memberID, int $bookID): bool {
        \Log::info("Executing method issueBook($memberID, $bookID) of LibraryService");
        
        $status = false;
        
        // Business logic to issue a book from Library
        \Log::info("Returning from method issueBook of LibraryService : $status");
        
        return $status;
    }
    public function returnBook(int $memberID, int $bookID): bool {
        \Log::info("Executing method returnBook($memberID, $bookID) of LibraryService");
        
        $status = false;
        
        // Business logic to return the issues book
        \Log::info("Returning from method returnBook of LibraryService : $status");
        
        return $status;
    }
}

ここで、ライブラリに新しい本を追加する必要があるため、LibraryServiceに別のメソッドaddBookを記述します。メソッドaddBookを作成するときは、パラメータと返却値をログに記録する必要があります。したがって、addBookメソッドのコードは次のようになります。

<?php
    public function addBook(int $bookID): bool {
        \Log::info("Executing method addBook($bookID) of LibraryService");

        $status = false;
        // Business logic to return the issues book

        \Log::info("Returning from method addBook of LibraryService : $status");
        
        return $status;
    }

上記のような従来のアプローチの欠点:

  • パラメーターと返却値をログに記録する同様のロジックは、複数のメソッドに分散されているため、冗長なコードが作成されます。これにより、メンテナンスが非常に困難になります。
  • アプリケーションロギングの要件を変更すると、LibraryServiceの複数のメソッドのコードが変更されます。
  • LibraryServiceに新しいメソッドを追加すると、新しく追加されたメソッドでログコードが再度書き換えられます。したがって、既存のロギングロジックを再利用することはできません。
  • LibraryServiceの主な責任は、ロギングではなく、ライブラリのさまざまな操作を提供することです。LibraryServiceにロギングするコードを保持することはお勧めできません。

AOPは、上記の全ての欠点を克服するアプリケーションのロギングの関心(Concern)(および他のすべての横断的関心事)を実装するのに役立ちます。AOPは、横断的関心事をアプリケーションの主要なビジネスロジックから分離し、さまざまなアプリケーションオブジェクトに適切に織り込みます。

横断的関心事(Cross Cutting Concerns)

どのエンタープライズアプリケーションでも、主要なビジネスロジックに加えて、対処する必要のある多くの関心事項があります。これらの関心は、アプリケーション全体および複数のアプリケーション層に広がっています。このような関心事項は、ロギング、トランザクション処理、パフォーマンスモニタリング、セキュリティなどがあります。これらの関心事項は、アプリケーションの横断的関心事として知られています。

f:id:FattyRabbit:20210226171047p:plain

AOPは、アプリケーションの横断的関心事を実装して、それらをメインのビジネスロジックから分離し、その結果、アプリケーションが疎結合になるようにします。

用語

Aspectアスペクト

アスペクトとは、ロギング、パフォーマンス監視、トランザクション処理など、アプリケーションに実装したい関心(横断的関心事)のことです。

Advice(アドバイス

アドバイスは、アスペクトの実際の実装です。アスペクトは概念であり、アドバイスは概念の具体的な実装です。

Join Point(ジョインポイント)

ジョインポイントは、アスペクトを適用することができるプログラムの実行中の位置やタイミングです。メソッドの実行前/実行後、例外をスローする前、インスタンス変数を変更する前/後などです。

Point cut(ポイントカット)

ポイントカットは、アスペクトが適用される結合ポイントを示します。アドバイスはポイントカット式に関連付けられ、ポイントカット式に一致する結合ポイントに適用されます。

その他

Target、Proxy、Weaving

Laravelのライブラリ

Laravelでよく使っているのが以下の物です。

github.com

PHPフレームワークのBEAR.Sundayのパッケージの一つであるRay.AOPをLaravel向けにラッパーしたライブラリです。Ray.AOPはLaravel以外でも利用可能です。

TransactionalやLogExceptions等既に使えるモジュールもあるし、新たにAOPのモジュールを追加することも可能です。

個人的な印象

個人的にはJavaのSpringBootで初めてAOPを経験したので、Laravel(Php)のPointCutの設定方法の違いを感じました。

Laravel-Aspectでは新しくアスペクトを作成する時もアノテーションを作成してそのアノテーションを対象になるクラスやメソッドに付け、インターセプター(MethodInterceptor)が取得しジョインポイントやポイントカットを判断する方法をとっています。

qiita.com

ですが、SpringBootではアスペクトにジョインポイントやポイントカット定義をアスペクトのメソッドにアノテーションで定義しています。

qiita.com

Laravelの機能との差

Laravelと似ている所は特定の層やイベントに限っていることでAOPとは差があります。

Middleware

LaravelのMiddlewareはControllerに利用させるためにHTTPリクエストに対して処理を追加する

Listener, Observer, Subscriber

特定のイベントを捕捉する仕組み

まとめ

AOPは以下の理由と利点があります。

  • 補助的に投入することで主要なビジネスロジックと分離
  • アプリケーション層に関係なく使用

最後に

Wizではエンジニアを募集しております。 興味のある方、ぜひご覧下さい。

careers.012grp.co.jp

GatsbyJsでWordPressをHeadless CMSとしてサイト構築deployまで試してみました。

f:id:thunder_fury:20210226181958p:plain

はじめに

皆さんこんにちは、フロントエンドエンジニアのWooです。
GatsbyJsでWordPressをHeadless CMSとして使用した構築方法や個人的に考えたメリットやデメリットをお話ししたいと思います。

WordPressのメリットとしてはサイト構築が楽でプラグインインストールで実装も簡単にできる便利なツールですが、サイトが多少重くてセキュリティ面でも不正な操作や攻撃を受けやすいのでバージョン管理やプラグインのバージョン管理などが大変です。

GatsbyJsで構築をするとWordPressのバージョン管理は行わなくて良くて、サイトもSSG(Static Site Generator)仕様なので非常に早いサイトを構築することができます。

WordPressが構築されている前提で、進めていきたいと思います。

GatsbyJsとは何か

GatsbyJsはReactベースの静的サイトジェネレーターです。
WordPressは、記事の「閲覧時」に動的にサイト内容が生成されますが、GatsbyJsは「ビルド時」にHTMLやCSSなどがあらかじめ生成されていることが特徴で、WordPressと比べてビルド時にhtmlを用意しているのでサイトが非常に早くなるメリットがあります。つまり、SSG(Static Site Generator) 仕様ということです。

GatsbyJs公式サイトは速度だけではなくサイトのセキュリティ補完もできると書かれています。 www.gatsbyjs.com

Security by default
Gatsby’s serverless rendering generates static HTML at build time. No server and no reachable database equals no malicious requests, DDOS attacks, or accidental exposure. A Gatsby site’s attack surface is nonexistent.

上記の内容を翻訳した内容です。

デフォルトのセキュリティ
Gatsbyのサーバーレスレンダリングは、ビルド時に静的HTMLを生成します。サーバーや到達可能なデータベースがないことは、悪意のある要求、DDOS攻撃、または偶発的な露出がないことを意味します。Gatsbyサイトの攻撃対象領域は存在しません。

WordPressのセキュリティの改善もできそうです。

GatsbyJs導入install

$ npx gatsby-cli gatsby new [project名]

ローカルサーバー起動

$ cd project名
$ gatsby develop

無事ローカルサーバーが起動できました。 f:id:thunder_fury:20210226123304p:plain

ローカルサーバーが立ち上がったところでページのレンダリングを確認をしてみると、GatsbyJsはマウスホバーをする時点でプリフェッチ (prefetch)と呼ばれる処理が走り、ページのdataが先に通信されるので早いなあと思いました。🤔

f:id:thunder_fury:20210226133314g:plain

WordPressと連動

GatsbyJsにはいろんなプラグインが存在していてWordPressと繋ぐのはgatsby-source-wordpressが一番簡単だったので自分はgatsby-source-wordpressをインストールしました。

$ npm i gatsby-source-wordpress

インストールが終わりましたらgatsby-config.jsに設定する必要があります。

module.exports = {
plugins: [
 ...省略...
  {
      resolve: `gatsby-source-wordpress`,
      options: {
        baseUrl: `〇〇〇〇.com`, // ワードプレスURL
        protocol: `https`,
        hostingWPCOM: false,
        useACF: true,
        // fetchしたいcontent
        includedRoutes: [
          "**/posts",
          "**/media",
        ],
      },
    },
 ...省略...
 ]
}

今回はpostsとmediaだけフェッチを行い、titleとアイキャッチの画像を取得したいと思います。 他にも習得できるkeyは存在しております。

  • "**/categories" カテゴリー
  • "**/pages" 固定ページ
  • "**/tags" タグ
  • "**/users" ユーザー情報(記事を書いた人の情報など)

GraphiQLからシミュレーションをしてみたらWordPressの最初の記事Hello Worldが取得されているのが分かります。

f:id:thunder_fury:20210227144451p:plain

GatsbyJs側の処理

config設定

const Promise = require("bluebird")
const { resolve } = require("path")
const path = require(`path`)

exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  return new Promise((resolve, reject) => {
    const wpPosts = path.resolve("./src/templates/blog-post.js")
    resolve(
      graphql(`
        {
          allWordpressPost(sort: { fields: [date] }) {
            edges {
              node {
                slug
              }
            }
          }
        }
      `).then(result => {
        if (result.errors) {
          reject(result.errors)
        }
       const posts = result.data.allWordpressPost.edges
       // { node }で記載のgraphqlデータを習得することができます。
        posts.forEach(({ node }) => {
          createPage({
            path: node.slug,
            component: path.resolve(`./src/templates/blog-post.js`),
            context: {
              slug: node.slug,
            },
          })
        })
      })
    )
  })
}

記事一覧ページ

記事リストを展開表示する処理は下記です。 自分はtopに表示したかったのでpages/index.jsに記載をしました。 もし、別ページにしたい場合はディレクトリーのpagesの中にファイルを追加して別ページに記載することも可能です。

import React from "react"
import { Link, graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"

export const Index = ({
  data
})  => {
  const posts = data.allWordpressPost.edges
  return (
    <Layout>
      <SEO title="home" />
      <h1>My WordPress Blog</h1>
      <h4>Posts</h4>
      <ul>
        {posts.map((post, index) => {
          return (
            <li key={post.node.slug}>
              <img src={post.node.featured_media.source_url} alt="thunder fury"/>
              <Link to={post.node.slug}>{post.node.title}</Link>
            </li>
         )})}
      </ul>
    </Layout>
  )
}

export const pageQuery = graphql`
  query {
    allWordpressPost {
      edges {
        node {
          title
          slug
          featured_media {
            source_url
            title
          }
        }
      }
    }
  }
`
export default Index

f:id:thunder_fury:20210301121433p:plain

記事テンプレート作成

import React from "react"
import Layout from "../components/layout"
import { graphql } from "gatsby"
import styled from "styled-components"

export default ({ data }) => {
  const post = data.allWordpressPost.edges[0].node
  return (
    <Layout>
      <div>
        <h1>{post.title}</h1>
        <Img src={post.featured_media.source_url} alt="thunder fury" />
      </div>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
    </Layout>
  )
}
export const query = graphql`
  query($slug: String!) {
    allWordpressPost(filter: { slug: { eq: $slug } }) { 
      edges {
        node {
          title
          slug
          content
          featured_media {
            source_url
            title
          }
        }
      }
    }
  }
`

記事ページも問題なく表示されました。

f:id:thunder_fury:20210227145735p:plain

NetlifyでDeploy

f:id:thunder_fury:20210301131500p:plain

Netlifyとは何か

Netlifyは静的なページを無料で作成し、Deployすることができるホスティングサービスです。

特徴としてはHTTPSを提供し、GitHubの特定Repoの特定のブランチがPushされるたびに自動的にビルドのデプロイを行ってくれるという点です。

無料枠としては1チームまで毎月300回Deployができて同時ビルドは一人しかできませんが個人であれば十分使えると思いました。

デプロイ手順

  1. Netlifyに加入する。
  2. GitHub、GitLab、Bitbucketの中から接続するサービスを選択。
  3. 選択したサービスの特定のRepoを選択。
  4. 選択したRepoのBranchを選択。
  5. ビルドスクリプト(例gatsby build)を入力。
  6. 作成されたフォルダ(例/public)を入力。
  7. ビルドとデプロイの実行を見守る。

参考イメージ

f:id:thunder_fury:20210301124130p:plain

f:id:thunder_fury:20210301124647p:plain

f:id:thunder_fury:20210301124627p:plain

3ステップで簡単にDeployができます。

まとめ

WordPressをHeadless CMSとして使えるか試しに環境構築をしてみました。

GatsbyJsはWordPressと簡単に繋げることができ、WordPressのデメリットをGatsbyJsが補完してくれるため、編集者はいつも通りWordPressで管理が出来るようになります。

フロントエンドエンジニアはビューの開発に集中できる印象を受けました。

記事の検索や関連記事表示のサイトの機能は全部自分で用意をしないといけませんが、サイトのパフォーマンスがよくなるので一度チャレンジしてもありかと思いました。


最後になりますが、Wizではエンジニアを募集中です!

色んな案件の経験ができるので興味のある方は是非覗いてみてください↓

careers.012grp.co.jp

gitでpushする前にコミットを整理する

こんにちは。バックエンドエンジニアの河内です。

今回は、コミットを整理する方法のうち、個人的に使用頻度が高いものについて書きます。

前提方針

コミットログを整えるために編集を加えるのは、ローカルリポジトリのコミットだけとします。 逆に言うと、リモートリポジトリにpushされたコミットについては編集を加えないということです。

たとえば、以下リモートリポジトリで(C)が最新の場合、 ローカルリポジトリで編集してよいのは(d)と(e)です。

[リモートリポジトリ]

※ 行頭の(A)などの識別子は説明のため加えており、実際には表示されません

(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

[自分のローカルリポジトリ

(e) 58e6b3a コミットe ← 編集してもよい
(d) 3c36383 コミットd ← 編集してもよい
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

各行頭の識別子に関し、ローカルのコミットログについてはアルファベット小文字で表現しました。 後述の事例でも区別のため、そのルールで表記します。

よくある事例とその対処

最新のコミットに対して

(1) 最新のコミットのメッセージを間違えた

以下のコミットログを見てみると…「官僚」ではなく「完了」のような気がします。

(d)はローカルリポジトリのコミットなのでまだ間に合います。

git log --oneline

(d) ee17560 事例1用管理画面実装官僚
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

[対処]

git commit --amend

エディタが開くので、メッセージを「官僚」→「完了」と編集し、保存します。

事例1管理画面実装官僚

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#

:

修正できました。

ハッシュ値は変わります。既存コミットは上書き保存され、別物になりました。

git log --oneline

(d) 03a9339 事例1用管理画面実装完了
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

前提方針でリモートリポジトリにpushされたコミットに編集を加えない、としたのは、このようにコミットが上書き保存される操作のためです。

上書きしたコミットを再pushした場合、上書きされる前のコミットをすでにローカルリポジトリに取り込んでいた別の作業者がいたら不整合が発生するので、なんらかのすり合わせ作業が必要となってしまいます。

次の事例に進みます。

(2) 現在の変更点を最新のコミットに含めたかった

git log --oneline

(d) ce9ed66 事例2用管理画面実装完了
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

(d)のコミットのあとindex.phpを編集したが、この内容は(d)に含めたかった…とします。

[対処]

git add index.php
git commit --amend

まず、index.phpをインデックスに登録します。

git add index.php

そして、git commit --amendです。

すると、addした内容が(d)のコミットに含まれる形でコミットログの編集を求められます。 メッセージはこのままでよいので編集せずに保存。

事例2用管理画面実装完了

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#

:

コミットを増やさず保存できました。

git log --oneline

(d) 5d75642 事例2用管理画面実装完了
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

ちなみに、(1)と(2)が同時に起こった場合、(2)でメッセージ編集をすればよいわけなので1回のgit commit --amendでいけますね。

最新のコミットより前のコミットに対して

(3) 最新のコミットの1つ前のコミットのメッセージを間違えた

(1)、(2)は最新のコミットに対しての話でしたが、それより前のコミットとなると別のアプローチをとる必要があります。

今回は、(d)のコミットメッセージを間違えているようです。

git log --oneline

(e) 0e647f2 リファクタ
(d) 7cfd024 事例3用管理画面実装官僚
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

[対処]

git rebase -i 32096c2 ※ 「r, reword」利用

git rebaseを使います。

git rebaseには他のブランチを巻き込む編集も存在しますが、今回は現行のブランチだけを対象とし過去のコミットに対してまとめて編集を加える、-i (--interactive)オプションを使います。

引数には、編集対象の1つ前のコミットを指定します。 今回は(d)の直前の(C)なので、ハッシュ値「32096c2」を指定しました*1

すると、以下のように表示されます。git logの順と違い、上から古い順である(d)、(e)の順で表示されます。

よく見ると、コメント部の「Commands:」にできることが書いています。 今回したいことは、コミットメッセージの編集なので、これには「r, reword」を使います。

(d) pick 7cfd024 事例3用管理画面実装官僚
(e) pick 0e647f2 リファクタ

# Rebase 32096c2..0e647f2 onto 32096c2 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

該当コミットの「pick」を「r」もしくは「reword」に置き換えます*2。 今回は短い「r」を使用します。置き換えたら保存します。

(d) r 7cfd024 事例3用管理画面実装官僚
(e) pick 0e647f2 リファクタ

:

すると、そのコミットログの編集を求められます。(1)の時と同様、メッセージ編集〜保存すると反映されます。

事例3用管理画面実装官僚

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#

:

(d)のハッシュ値のほかに、内容としては何も変更のなかったはずの(e)のハッシュ値も変更されています。 対象コミットの後続のコミットすべてのコミットについて、このように変更がなされます。

逆に、「(d)以降」を指定するためにgit rebase -iのオプションに(C)のハッシュ値を渡しましたが、(C)に影響はありません。

git log --oneline

(e) 0dad9a6 リファクタ
(d) 79377c3 事例3用管理画面実装完了
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

(4) 現在の変更点を最新のコミットの1つ前のコミットに含めたかった

(2)と同様、index.phpを編集しましたが、この編集内容は(d)に含めたかったです。メッセージは正しそうです。

git log --oneline

(e) 2092de6 リファクタ
(d) b3fed10 事例4用管理画面実装完了
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

[対処]

git add index.php
git commit
git rebase -i 32096c2 ※ 「f, fixup」利用

同じくgit rebase -iですが、「f, fixup」を使います。 まず、index.phpの編集内容をコミットします。

git add index.php
git commit

このあと(d)に取り込まれるので、コミットメッセージはなんでもよいです。

事例4用管理画面実装完了の作業漏れ

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#

:

(f)ができました。(f)を(d)に取り込みます。

git log --oneline

(f) adfec57 事例4用管理画面実装完了の作業漏れ
(e) 2092de6 リファクタ
(d) b3fed10 事例4用管理画面実装完了
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

git rebase -i 32096c2と打つと編集モードになります。

(d) pick b3fed10 事例4用管理画面実装完了
(e) pick 2092de6 リファクタ
(f) pick adfec57 事例4用管理画面実装完了の作業漏れ

# Rebase 32096c2..adfec57 onto 32096c2 (3 commands)
#
# Commands:

:

含めたいコミット(f)を、含め先のコミット(d)の直下に移動します。そして、(f)の「pick」を「f」に書き換えて保存します。

(d) pick b3fed10 事例4用管理画面実装完了
(f) f adfec57 事例4用管理画面実装完了の作業漏れ
(e) pick 2092de6 リファクタ

# Rebase 32096c2..adfec57 onto 32096c2 (3 commands)
#
# Commands:

:

すると、(f)は(d)に吸収されます。ハッシュ値は、(d)以降のコミットについて変更されています。

git log --oneline

(e) 605cb37 リファクタ
(d) 533f9bb 事例4用管理画面実装完了
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

――上記のフローを理解した上で、少しだけ早い方法を使うこともできます。

[少しだけ早い対処]

git add index.php
git commit --fixup=b3fed10
git rebase -i 32096c2 --autosquash

コミットの時に、含め先のコミット(d)のハッシュ値を--fixupで指定します。 すると、プレフィックスのついたコミットメッセージを持つコミットが生成されます。

git log --oneline

(f) b230d6b fixup! 事例4用管理画面実装完了の作業漏れ
(e) 2092de6 リファクタ
(d) b3fed10 事例4用管理画面実装完了
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

そして、git rebase -i 32096c2のオプションに--autosquashをつけると、コミットの移動と「pick」の置き換えが自動でおこなわれた状態で編集モードに入ります。「pick」の置き換えは「f」ではなく正式な「fixup」となるようですね。

(d) pick b3fed10 事例4用管理画面実装完了
(f) fixup b230d6b fixup! 事例4用管理画面実装完了の作業漏れ
(e) pick 2092de6 リファクタ

# Rebase 32096c2..b230d6b onto 32096c2 (3 commands)
#
# Commands:

:

保存すれば、目的達成です。

(5) 現在の変更点を最新のコミットの1つ前のコミットに含め、メッセージも変更したい。

では、(2)で同時に(1)、(2)の操作をおこなうことを考えたように、(3)と(4)を同時におこないたい場合どうしたらよいでしょうか。もちろん、(3)と(4)を別々におこなうこともできますが、同時にもおこなえます。

[対処]

git add index.php
git commit
git rebase -i 32096c2 ※ 「s, squash」利用

git rebaseでの編集まで(4)と同じ流れです。

コミット。

git add index.php
git commit

メッセージ編集〜保存。

事例5用管理画面実装官僚の作業漏れ

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#

:

(f)ができました。

git log --oneline

(f) 547cd2b 事例5用管理画面実装官僚の作業漏れ
(e) 9a636f7 リファクタ
(d) 16b489d 事例5用管理画面実装官僚
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

(f)を(d)に取り込みます。git rebase -i 32096c2ですね。

含めたいコミット(f)を、含め先のコミット(d)の直下に移動するところまでは(4)と同じです。 ここで、(f)の「pick」を「s」に書き換えて保存するだけです。

(d) pick 事例5用管理画面実装官僚
(f) s 547cd2b 事例5用管理画面実装官僚の作業漏れ
(e) pick 9a636f7 リファクタ

# Rebase 32096c2..16b489d onto 32096c2 (3 commands)
#
# Commands:

:

すると、2つのメッセージが上下に配置された状態で編集モードに入ります。

# This is a combination of 2 commits.
# This is the 1st commit message:

事例5用管理画面実装官僚

# This is the commit message #2:

事例5用管理画面実装官僚の作業漏れ

# Please enter the commit message for your changes. Lines starting

:

上記のまま保存すると、以下のようなコミットメッセージになってしまいます。

事例5用管理画面実装官僚

事例5用管理画面実装官僚の作業漏れ

以下のように編集して保存します。

# This is a combination of 2 commits.
# This is the 1st commit message:

事例5用管理画面実装完了

# Please enter the commit message for your changes. Lines starting

:

すると、(f)は(d)に吸収されメッセージも編集されました。

git log --oneline

(e) 2536867 リファクタ
(d) 35bcb56 事例5用管理画面実装完了
(C) 32096c2 コミットC
(B) ae4f281 コミットB
(A) 6dcd4ce コミットA

まとめ

小分けのコミットを心がけると整理も容易になります。また、逆に整理を意識するとコミットを小分けするよう意識が向きます。

コミットログは今ままで自分が何をしてきたかの歴史となるので、きれいに記せていければよいのかな、と思います。

最後に

Wizではエンジニアを募集しております。 興味のある方、ぜひご覧下さい。

careers.012grp.co.jp

*1:ハッシュ値に限らず、コミットを指し示せればよいのでHEAD^2といった指定でも可。

*2:ここのメッセージを編集しても反映されません。たまに、ついやってしまいます。

輪読会を開催した話とその感想

はじめまして、フロントエンドエンジニアの髙橋です。

 

バーチャルオフィス導入の影響もあり、Wiz社内でのオンラインのLT会もくもく会などイベントが増えてきております。

その一環でWizでは今期から毎週輪読会を行っており、その内容や感想などをご紹介したいと思います!

 

輪読会を開催した目的 

輪読会にはさまざまな効果がありますが、今回の目的は2つです!

 

- インプット / アウトプットの場を設ける

- 技術的なディスカッションをして、みんなで理解を深める

 

増えてきたとはいえ、社内でのこういったイベントはまだまだ少ないと感じています。(勉強会等に参加されている方は多いですが)

内容を理解し、話し合うことでただ「本を読む」以上の効果を期待して開催しました!

 

輪読会の内容

そもそも輪読会とは??

輪読会とは、複数人が同じ本を回し読み、お互いの意見などを話し合う会です!

Wizでは、slackでteam-rindokuというチャンネルを作り、(そのままですね…)

そこでアナウンスやアンケートをとったりしています。

f:id:sotq17:20210218200403p:plain


実際の内容(初回)

■対象書籍
リーダブルコード

■読書予定範囲
2章ずつ (おおよそ1時間)

■進め方
 - 1~2章順番に音読+軽くディスカッション
 - 読んでいて疑問点があれば、それについても話し合う
 - 準備は特に必要なし
 - 本は各自でご用意を

 

書籍は以下の理由でお馴染みのリーダブルコードにしました!

- 読んだことのある人も読み直すことで新しい気づきがあるため

- 読んだことのない人には自信を持って勧められる本のため

- 読んだ後のディスカッションがしやすいため

 

開催に際して、気をつけていること

- なるべく参加ハードルは低くする

自由参加ということもあり、参加ハードルが高ければ集まりづらく、続かない可能性があると思っています。

今回のリーダブルコード輪読会は準備不要にするなど、なるべく気軽に参加してもらえるようにしました!

 

- 最低開催人数を決めておく

開催日時によって参加できる人数にばらつきがあるので、最低このくらい集まったら開催する、といったボーダーを決めています。

そうすることで一定のペースで開催し続けることができたのではないかと思います。

 

感想

良かった点

■より深い理解になった

読書って途中から集中力が切れて、内容が頭に入らない部分が多いと思うのです。(私だけですかね…?)

人に聞かれるのでしっかり読まねば!という意識が働き、集中力を保ったまま読むことができました。一人の時よりも内容がしっかり残っている気がします。

また、難しい箇所が出ても、すぐに質問できるので疑問点が残りづらく、それも輪読会のメリットの一つだと感じています。

 

■ディスカッションでさらに理解が深まる

ディスカッションをすることで、自分とは違う感想を聞くことができたり、新しい発見をしたりと、考えの幅が広がるのではないかと思います!

「コード書いている時、リーダブルコード思い出しました!」

という声もあり、多少なりとも業務に還元できたのでは?と感じています。

 

また、ディスカッション時に脱線して話をしたり、わいわいしながら進められているので個人的には楽しみながら勉強できているので、このディスカッションが最も大切だと感じています。

 

■別の輪読会に派生すること

他のメンバーも useEffectガイド の輪読会を開催してくれるなど別の輪読会に派生しています!(嬉しい…)

個人的にもひとりで読み切るのが辛かったのですごく助かりました。

輪読会という方式が広がっていけば効率良く勉強できそうなので、どんどん広げていきたいですね。

 

課題

まだ探り探り進めているので、いくつか課題もあります。

 

■ディスカッションへの参加について

大体参加者が5人前後くらいで収まっているのですが、

人数が増えてくるとディスカッションに積極的に参加する人/しない人が別れてくる印象がありました。(この辺りはオンラインでやる難しさですね。。)

前回3人しか集まらなかった時は、全員で話ができたので

細かくチーム分けするのも面白いかも知れません。

 

■輪読会のスタイルについて

輪読会にも色々な方法があるようで、

- 担当を決めてまとめて発表するスタイル
- 本を順番に回し読むスタイル
- 問題のみ共有し、事前に読んできて話し合うスタイル

などがあります。

 

リーダブルコードなどの、概念的な読み物の場合は順番に読んでいく方式で良さそうですが、他の読み物の場合どうなのか?など、進め方の課題もまだまだ残っています。

 

おわりに

輪読会を通し、個人的には楽しく、刺激を受けながら勉強できています。

まだまだ課題はありますが、まずは継続して、より良い方式を模索していく予定です!

 

余談ですが、参加者の皆さんに取り扱いたい本のアンケートをとり、興味がある本がいっぱい出てきました。

全て輪読会で扱えないので自分一人でも読んでおきたいと思います…!

 

Wizではエンジニアを募集しております。

興味のある方、ぜひご覧下さい。

https://careers.012grp.co.jp/engineer