「JSON色付け係」という自虐

フロントエンドエンジニアの間では、「私の仕事は JSON に色を付けることです」という有名な自虐ネタがある。 おそらく初出は以下のツイートなのだろう(*1)。ただ、出典はあまり詳しく調べていない。

JSON色付け係の元になったと思われるツイート

初めてこの言葉を見た時、面白い言い回しだなと思った。確かにフロントエンドの仕事にそういう側面はある。

実際、コンテンツの表示がメインのページで作業すると上記のような気持ちになる。この場合、フロントでやることといえばせいぜい日付の表示形式を適切にフォーマットするくらいだ。結局バックエンドからデータが返ってこないとフロントだけでは何もできないと思うこともある。

もちろん、フロントだけで簡潔する手書き風グラフ作成ツール excalidraw のようなものは別だし、フロントで複雑な状態を扱う部分を書いたり、フォームを使ってユーザー入力を受け付け、入力値を検証するバリデーションをしてからバックエンドに POST リクエストを送るような処理を書いていると、自分は JSON 色付け係だなんて思わない。やっぱりフロントエンドエンジニアは必要なんだなと思う。

ただ、なぜフロントエンドエンジニアは JSON 色付け係と自虐(自己卑下)するのか。

この言葉を知った時には次のように考えた。自分達はインフラやバックエンドのように高度なエンジニアリングをしているわけではなく、API から送られてくる JSON のデータをユーザーに表示しているだけで大したことをしていないという感覚を誰しもが持ったことがあるからだと。

しかし、これでは JSON 色付け係という言葉が指していることを説明しただけで、言葉が使われて受け入れられる背景にまでは辿り着けていないなあと漠然と思っていた。

JSON はシリアライズされた DTO である

そのうち「JSON 色付け係」という言葉は Twitter のタイムラインであまり見なくなった。 しかし、最近ある偶然から「JSON 色付け係」という言葉を使うメンタリティはこれだという洞察を得たので、ここで紹介したい。

その偶然とは、PoEAA本で DTO を調べてみたことである。調べた内容を 「GraphQL と Data Transfer Object は似ている」 という記事にした。そこで DTO は XML にも JSON にもシリアライズできるものだと書いた。

すると、その記事を読んでくれた元同僚が「CQRS を考案した Greg Young 氏が、DTO を介してサーバーとクライアントがやり取りするとドメイン知識は失われてしまうと指摘している」と教えてくれた(*2)。

ツイート「サーバーの奥にドメインモデルらしきものを作ってみたところでクライアントとサーバーがDTOやりとりしている時点で意味なんて失なわれているよの図です」

CQRS の文章を読むと確かに以下のように書かれている。抜粋した文章はクライアントから送られてくる DTO をバックエンドで処理する際の指摘だが、Greg Young 氏が考えている課題の内容が伝わってくる箇所だ。

One cannot even create and Anemic Domain Model with this architecture as then all of the business logic would be in services, here the services themselves are really just mapping DTO’s to domain objects, there is no actual business logic in them. In this case a large amount of business logic is not existing in the domain at all, nor in the Application Server, it may exist on the client but more likely it exists on either pieces of paper in a manual or in the heads of the people using the system.

CQRS Documents by Greg Young, p.7

超訳すると以下のようになる。

「クライアントから送られてくる DTO をバックエンドで受け取ってサービスが DTO をドメインオブジェクトに変換するだけだと、ビジネスロジックとドメイン知識がすっかり失われてしまう。ドメイン知識はクライアント側に存在するかもしれないが、それよりも紙のマニュアルやシステムを使う人の頭の中の方にあるのだろう」

つまり、ドメイン知識は DTO からも DTO を送られたバックエンド側からもなくなってしまい、マニュアルやシステム利用者の頭の中にしかないことになってしまうということだ。

ここで想定されているやりとりをコードで表現すると以下のようになる。ブログのシステムで、タイトルだけを編集することを考えてみよう。

まず、編集画面にバックエンドから JSON (DTO)が送られてくる。

{
  "title": "SEO的にイケてないタイトル",
  "body": "本文..."
}

これをクライアントで受け取り、画面からタイトルを編集した後、バックエンドに送られる JSON は以下のようになる。

{
  "title": "SEO的に超イケてるタイトル",
  "body": "本文..."
}

この JSON をサービス層でドメインオブジェクトにマップすると、タイトルを編集したというドメイン知識が失われるだろう。疑似コードで表現すると以下のようになる。

const json = handler(request)
const post = service.map(json)
repository.save(post)

これでは送られてくる JSON を保存しているだけだ。タイトルを更新するというドメイン知識は失われている(そして、この課題を解消するために CQRS パターンを使おうという話に繋がる)。

これはフロントのコードも同様だろう。以下のコードにビジネスロジックはどこにもない。

const App = () => {
  const { data: post } = useSWR('/api/posts/1', fetcher)
  
  return (<Post post={post} />)
}

type Post = {
  title: string
  body: string
}

const Post = (post: Post) => {
  return <div>
    <h1>{post.title}</h1>
    <div>{post.body}</div>
  </div>
}

つまり、DTO からはドメイン知識が失われてしまうというのが Greg Young 氏の指摘だ。 これはフロントからバックエンドに JSON を送る際にも、バックエンドからフロントに JSON を送る際にも同じことが言える。

この指摘が、「JSON 色付け係」という自虐のメンタリティを読み解く最後のピースになった。

JSON からはドメイン知識が抜け落ちている

これらをまとめると以下のようなロジック(三段論法)になる。

  1. DTO とそれをシリアライズ化した JSON はビジネスロジックを持たないため、ドメイン知識を保持できない。
  2. (表示がメインのアプリにおいて)フロントエンドは JSON のデータを表示するプレゼンテーションロジック担当である。
  3. よって、JSON を表示するだけのフロントエンドにはドメイン知識がない。

つまり、ドメイン知識が反映されたビジネスロジックと無縁のコードばかりを書かざるを得なくなった結果、エンジニアなのに大事な何か(ドメイン知識)に関与していないという心情が芽生えた。それこそが自らを「JSON 色付け係」と自虐させたのである。

ちなみに、ここでいう色とは「ドメイン知識とは無縁な、見た目を良くするためのプレゼンテーションロジック」だと理解している。「JSON色付け係」とは、なんとも上手い表現だと改めて思う。

以上が私の推理なのだが、みなさんはどうお考えだろうか。

最後に注意書きを。冒頭で紹介したように、今回はフロントエンドが価値の中心になるアプリやツールは議論の対象外だ。

「私は JSON 色付け係です」とフロントエンジニアが感じるような、データ表示が中心のページ・アプリを話題にしてそのメンタリティを読み解いているので、「全てのフロントエンドのアプリケーションにはドメインロジックがない」と主張しているわけではないので悪しからず。

(*1): https://twitter.com/YuG1224/status/1173194238139363329?s=20&t=j45fvJMEBGZvD2xVSRUn1w

(*2): https://twitter.com/tenjuu99/status/1527347738332975120?s=20&t=22hgo9RU4rEcpiUWnFiF3g

frontend
プログラミングをするパンダ
プログラミングをするパンダ (@Panda_Program)
Software Engineer

スクラムマスターがいるスクラムチームで開発している

この2ヶ月間、スクラムマスターがいるスクラムチームで開発しています。私のキャリア上、スクラムマスターがいるスクラムチームで開発をするのは初めてです。

アジャイル で Web アプリケーションを開発した経験は4年ほどあり、前職ではアジャイルに詳しいテックリードと同じチームで開発したり、スクラムに詳しいがスクラムマスターではない先輩エンジニアと Do Agile ではなく Be Agile な開発ができていたと思っています。

そのおかげで、アジャイル開発に対する知識や経験が溜まっていきました。それはスコープ・納期・予算・品質といった荒ぶる四天王とそのトレードオフスライダーやストーリーポイントや見積もりや、チームでの開発に対する心構えなどです。これは今でも役に立っているスキルです。

しかし、スクラムマスターのいるスクラムはやはりしっかりしていると思ったこと、スクラムというフレームワークの有用性を肌身に感じているので、所感レベルではあるものの記事に書き記しておきます。

スクラムマスターのいるスクラムがしっかりしている

スクラムマスターのいるスクラムがしっかりしていることとは、スクラムマスターが「スクラムの原則を徹底している」ことと「目の前の現象をスクラムの原則から捉え直す」ことを指しています。

まず、チームが結成されたときにスクラムガイド 2020年版を読み合わせしました。チームメンバーは、エンジニアリングマネージャー(EM。スクラムマスター)1人、プロダクトオーナー(PO)1人、バックエンドエンジニア4人、フロントエンドエンジニア2人の8人構成で、私はフロントエンドエンジニアとして所属しています。

なお、現職の会社ではスクラムマスターという役職はないものの、エンジニアリングマネージャーが認定スクラムマスターの資格を保有しているため、チームのエンジニアと週1で1on1をしながらスクラムマスターとして開発の計画会でファシリテート(司会進行)してくれています。

スクラムの原則を徹底している

さて、スクラムマスターが「スクラムの原則を徹底している」とは、スクラムイベントを省略せずに行っているということです。これは当たり前のようでいて中々実践できるものではないと思います。なぜなら、「スクラムは会議が多い」という現場からの圧力で何かのスクラムイベントを省略するケースがあると聞いたことがあるからです。

スクラムイベントは省かない

自分が所属しているチームでもスクラム開発をしていこうと意気込んだものの、2,3週間が経った頃に「会議が多いのでは」という声がエンジニアから挙がりました。しかし、スクラムマスターは「これは情報が集まりきっておらず、次のアクションに必要なことが決まっていないから」とメンバーを説得し、スクラムイベントを省略しない判断をしました。

後からわかったことなのですが、会議が多いとエンジニアが感じたのは、開発のフェーズから考えると仕方がないことでした。社内のあるチームが使う社内用ツールに対する新機能の開発でチームが組成されたものの、2ヶ月前は要求も仕様も固まっていませんでした。

社内のチームにPOがヒアリングをしていた段階だったこと既存機能をベースにした改修だったため、既存機能の DB やバッチ処理周りの調査がメインであり、コードを書いて手を動かせない状況だったため、エンジニアが「会議が多く先に進んでいない」と感じてしまっていたのです。

その後大まかな仕様が固まり、実際にコードを書き始めると「やっぱり必要なことを話し合っている」という意識が醸成され、会議が多いという意見は挙がらなくなりました。

デイリースクラムは15分

また、スクラム開発を始めて1ヶ月経った頃、デイリースクラム(デイリースタンドアップ、朝会)が短すぎて話が終わらないという意見が挙がりました。デイリースクラムは15分と設定されていたからです。

自分が今まで所属していたチームでは、朝会を昼休み前に行って好きなだけ話すというケースや、作業内容と進捗の共有だけを手短に終わらせて、個別で相談・議論が必要な場合は「〇〇さん、このちょっと後いいですか?」と声を掛けるケースを経験していました。

それに比べると、デイリースクラムは全員で参加して15分で終わり、全員が話題を知っていることを良しとするためデイリー後に個別で話し合うこともしていませんでした。それでは確かに全員が作業の進捗を共有してスプリントのゴールの障害の有無を確認すると議論の時間がなくなります。

自分も「それなら時間を延長して30分の枠を確保したらいいのではないか」と話したのですが、スクラムマスターによるとエッセンシャルスクラムという本がデイリースクラムを説明している箇所では15分以内とされているので、24ページ目を参照して欲しいとのことでした。

エッセンシャルスクラムはチームの希望者全員に配布されています。自分も該当のページを参照したところ、確かに15分以内で行うとの記述がありました。さらに、「デイリースクラムは検査と適応の場であるため、問題解決のアクティビティではない」ともあります。結局、スクラムマスターから「デイリーは15分で終えるが、その後の15分を議論や雑談の時間に使おう」という提案があり、今ではその形に落ち着いています。

この一連の出来事を通して、プラクティスを徹底するとはこういうことなんだと理解が深まりました。スクラムに限らず重いプラクティスをアレンジするということはままあると思うのですが、デイリーのように一見軽いものに見えてもスクラムの原則を徹底するという姿勢こそが、ただの肩書きではなくスクラムマスターをスクラムマスターたらしめるものだなと思いました。

目の前の現象をスクラムの原則から捉え直す

もう一つ、「目の前の現象をスクラムの原則から捉え直す」こともスクラムマスターは行っています。エッセンシャルスクラムやスクラムガイドは聖書ではありません。しかし、開発の際に起きる事象がそこに既に書かれていることが多いです。

これはスクラムに限ったことではありませんが、目の前にある個別具体的な事象を理論や原則の視点から捉え直すことで、その事象の構造や背景、問題が起きるところと解決できる道筋が見えてくることがあります。

コーディングを例に挙げると、AとBはXの関係にあるからここではZパターンが適用できるというようなケースです。Zパターンを知らなければ自分でそのパターンを発見するかZパターンに永遠に気づかないままです。そして、これがエンジニアの自主学習による知識の獲得や新人エンジニアに対する教育が奨励される理由です。

同じものを見ていても、知っている人と知らない人では捉え方が異なります。POやエンジニアの質問に対してスクラムマスターが Slack で回答しているところを見ると、「それについてスクラムでは以下のように考えます。A、B、C。よければエッセンシャルスクラムのXページを参照してみてください」というパターンだなと気付きました。

これは簡単なように見えて、開発のアクティビティをスクラムの視点から考えようと常日頃から思っていないと実践できないと思います。調査する(学ぶ)コストは大きいため、人は自分なりの解釈、判断に従いがちだからです。孔子の言うように「思いて学ばざれば則ち殆(あやう)し」ですね。

例えば、メンバーから「ベロシティの考え方がいまいちわからない。ストーリポイントでアイテムの大きさを見積もり、過去のベロシティと同じくらいになるようにスプリントでアイテムを選ぶことはわかるが、選んだアイテムをスプリント内で全て消化しなければならないと思ってしまう」という発言がありました。

それに対してスクラムマスターは、「ベロシティは過去の参考値だから絶対に達成しなければならないものではない。チームの状況を知る体温のようなものです。勤務時間は週に40時間が一番パフォーマンスがいいという研究もありますし、毎日遅くまで働きすぎると持続可能性がなくなります。エッセンシャルスクラムのXページを参照」と回答していました。

(正直、この節タイトルに対する例の内容が合ってない気がしていますので、そのうちいい例があったら書き換えます。ここでは「メンバーがある現象が起きていると話したら、スクラムマスターがそれはスクラムではこういう名前がついていますと回答した」という例が適切ですね)

私見を述べると、ベロシティの例えは山登りの例が一番わかりやすいかなと思います。それは以下のようなストーリーです。

バックログアイテムは優先順位通り(登山ルートに沿って)に並んだ地図上のチェックポイントです。平均2スプリントではA地点まで登れました。同じように考えると、同じ距離を次のスプリントでも登ることができます。

しかし、山の天候は変わりやすいです。雨が降って道がぬかるむかもしれないし、霧が出て視界が悪くなるかもしれません。地図になかった川が出てきたり、安全(セキュリティ)のために今までになかった谷沿いの道をゆっくり慎重に進まなければならないこともあります。

先のことは誰にもわからないため、実際に進むしかありません(経験主義)。このため、ベロシティはあくまで参考値なのですと。まあ例なので伝わればなんでもいいのですが、自分ではなかなか良い例えなのではないかと思います。XPのプラクティスの「メタファー」ですね。

スクラム開発に対する所感

さて、次に2ヶ月ほどスクラム開発をした所感を紹介していきます。

スクラム開発のキモはスプリントレビュー

スクラムイベントの一つに、スプリントレビューというものがあります。自分が所属するチームでは、このスプリントレビューで社内のチームのメンバーに対するユーザーインタビューを行なっています。

具体的には、POが機能を使うシナリオを予め考え、社内チームのメンバーにそのシナリオに沿ってその機能を使ってもらい、フィードバックを貰います。スプリントレビューでは、社内チームのメンバーが画面を操作する様子を Zoom で共有してもらい、会話で出た内容と開発メンバーが画面操作を見ながら気づいたポイントを議事録に書いてきます。これを毎週行います。

社内メンバーに対するプロトタイプのレビューでありながらも、できるだけバグを出さないように事前チェックをしたり、片付いてないアイテムを終えなければならないという心理的なプレッシャーが毎回かかります。それでもレビューは収穫が多いです。

その機能を使う社内のチームにとっては、初期リリースでは最低限ここまで欲しいという要望がすぐに出せること、ある機能が欲しいと思っても開発の観点からは求めすぎているのか、或いは簡単に実現できるのか、動くソフトウェアという実物を見ながら期待値の擦り合わせができることがメリットです。

また、プロダクトオーナーにとっては、「おそらくこのチームはこの機能をこのように使うだろう」という推測ではなく、現実に使って貰う姿を見ることで、頭の中で生まれた現実には起こり得ないケースに対する対処を省けたり、そのチームの興味関心がどこにあるのかリアルに把握できます。

さらに、エンジニアにとっては、新機能を使って貰える人の顔が見えることと、操作に困っていそうなら画面や表示するメッセージを改善しなければと自発的に考えることなど、同じチームメンバーに閉じていては得られない情報が山ほどあります。

しかも、ソフトウェアエンジニアにとってはユーザーの喜ぶ姿を見ることが一番のモチベーションにつながる(「顧客の満足度向上が仕事に対するモチベーションを向上に繋がる」という章を参照)こと、レビュー会はそのような場になっていることから、難しい判断を迫られることがあっても開発チームのメンバーのモチベーションは高いままでいられます。

そして何より、両チームともにこの機能に関して何かあっても隠したり躊躇ったり責めたり文句を言うのではなく、すぐに連絡し合って問題の解決に向かうという信頼感が醸成されていると私は感じています。

アジャイルソフトウェア開発宣言が重視する「個人と対話」「動くソフトウェア」「顧客との協調」(認識合わせや擦り合わせ)「変化への対応」(フィードバックに対する新しい対応)の全てがレビュー会に凝縮されています。スプリントレビューがスクラムイベントにビルトインされていることで、スクラムに従えばしっかりアジャイルを体現できるのだと再認識させられます。

スクラムは軽量フレームワークである

もう一つスクラムに対して理解が深まったことがあります。それはスクラムガイドに書かれているように、スクラムは軽量フレームワークであるということです。

個人的にアジャイルといえば XP (エクストリームプログラミング 2nd Edition)が好きで、またLeanとDevOpsの科学を読んでから DevOps のプラクティスを実践していきたいと考えていました。結論から書くと、スクラムはこれらを実践することに何の妨げもありません。

チームで実施している XP と DevOps のプラクティス

まず、XP と DevOps で実践しているプラクティスを紹介します。

今のチームではエンジニアが合計6名います。このため、ペア・モブプロで開発をしたいと提案し、また私が Software Design に TDD を実践する特集を寄稿したことから(寄稿の経緯)、チームのバックエンドエンジニアから TDD を実際にやってみたいという話があがったので、ペアプロで TDD をしつつ開発しています。XPのプラクティスですね。

ツールは Gather というオンラインミーティングのツールと、 PhpStorm の Code With Me を使って開発しています。昼休憩やデイリー、1on1 がある時以外はずっとみんな Gather にログインしており、常にどこかでペアプロがされています。

開発が進むにつれて、テストケースも順調に増えていっています。

https://twitter.com/Panda_Program/status/1527579779557638144

もちろん CI でテストを実行しており、リグレッションにすぐ気づけるようにしています。

また、LeanとDevOpsの科学で紹介されているトランクベース開発を実践しています。まだリリース前の機能なのでリリーストグルではなくダークローンチという手法を使っていますが、おそらくブランチを切ってコードの変更をコミットしてから PR のデプロイまでにかかる時間は最短1時間、平均1日半、長くても2日半ほどかと思います。

午後の初めに書いたコードが、夕方にはレビューが終わってデプロイされるというようなスピード感です。これには Gather 上での同期レビューと、レビューの指摘はリファクタリングとして別ブランチで対応するテクニックが功奏してます。後日、ちゃんと計測してグラフ化しようと思っています。

スクラムは開発プラクティスを阻害しない

さて、スクラムが XP や DevOps のプラクティスとバッティングしない軽量フレームワークであるということは、スクラムイベント以外はそのプラクティスに集中できるということです。

具体的には、現在チームではスプリントの期間を1週間とし、毎週火曜日にスプリントレビューとスプリントレトロスペクティブを行なっており、水曜日にバックログアイテムのリファインメントとスプリントプランニングを実施しています。ここで達成したことを見てもらい、やったことを振り返り、これからやること洗い出してストーリーポイントをつけて優先順位を決めます。

すると、残りの木、金、月は開発に集中できます。XP や DevOps の開発寄りのプラクティス(DevOps はスクラムなどアジャイルな開発プロセスと組み合わせることを良しとしている)はこの日に実行すればよいのです。

これがスクラムは軽量であるという理由です。実際、スクラムガイドでも以下のように書かれています。

スクラムフレームワークの中で、さまざまなプロセス、技法、⼿法を使⽤できる。スクラムは既存のプラクティスを包み込む。あるいは、その存在を不要にする。スクラムによって現在のマネジメント、環境、作業技術の相対的な有効性が可視化され、改善が可能になるのである。

スクラムガイド p.4 より

まとめ

先日スクラムマスターが言ってくれた言葉が嬉しかったので以下のツイートをしました。

https://twitter.com/Panda_Program/status/1527654795603226624

そして、このツイートに反響があったのでこの記事を書くことにしました。

アジャイルの開発は不確実性に対応するだけではなく、不確実なことから手をつけ始めるので、未来を引き寄せているイメージがあります。その分、情報集めと判断の連続で大変なんですけど、チームでやってるからめげずに進められるのです。

この記事で少しでもスクラム開発の雰囲気が伝われば幸いです。

ScrumAgile
プログラミングをするパンダ
プログラミングをするパンダ (@Panda_Program)
Software Engineer

ビールのレビュー投稿サイト Beer Break を5月1日にリリースしました(β版)。私はソフトウェアエンジニアなので、企画からデザイン、実装まで自分で行いました。

https://twitter.com/Panda_Program/status/1520737630534930432

Beer Break はビールの写真と感想を添えてレビューを投稿できるサイトです。自分はお酒はビールも日本酒もウィスキーも何でも好きなのですが、ビールのレビューサイトって意外と見当たらないなと思い、自分で作ることにしました。

ビールのレビューを投稿する方、ビールが好きでレビューを読みたい方に使っていただければと思っています。

ビールを飲む方の課題を解決したい

自分でもビールを飲むので、以下のような課題を感じていました。

  • ビールはよく新製品が投入されるし、新しいビールを試してみたいけど外すのはイヤ。味はどうなんだろう

  • 最近ビールを飲むけど、この1週間でどれくらい飲んだか覚えていない。飲み過ぎではないだろうか

  • たまには定番のビールだけではなく、珍しい輸入ものののビールも飲んでみたい

そこで、これらの課題を解決しようとビールのレビューサイト Beer Break を作りました。

課題1「ビールは飲むまで味がわからない」

1つ目の「ビールは飲むまで味がわからない」という課題に対しては、ビールのレビューが溜まれば溜まるほど、色々な方が投稿すればするほど解決できる可能性が高まります。 正直なところ、投稿件数とその幅の広さが Beer Break の成否の鍵になると思っています。

例えば、新発売のビール(プレミアムモルツのホワイトエール)や、定番商品でも味がリニューアルされたビール(アサヒスーパードライ)の味がどうなのか気になる場合、Beer Break を見れば他の方の評価がわかるとレビューを読んだ方の購買意欲に繋がります。

また、ノンアルコールビールの中で一番評判の良いものを探すという使い方もできるでしょう。これはレビューを読む方がサイトを使ってもらうメリットです。

これに関してはレビュー数が増えると自然に解決できる課題と考えています。

課題2「最近ビールをどれほど飲んだかわからない」

2つ目の「最近ビールをどれほど飲んだかわからない」という課題に対しては、レビューの投稿を元に飲んだ量を自動で計算する機能を実装することで解決を図っています。

Beer Break は「家飲み需要」に答えたいプロダクトであるため、居酒屋での写真映えする大ジョッキの写真は現段階では投稿されていません。このため、1投稿で飲んだ量は 350ml と仮定して飲酒量を計算しています。 現在では、直近の1週間に飲んだ量と投稿数をログイン後のページで算出しています。

直近の1週間で飲んだ量と投稿数

ビールを飲んだら写真に撮影し、そのまま Beer Break に投稿してもらうことでレビューの投稿のみならず、自分の飲酒量の記録になるのです。

なお、Beer Break は Web サイトであり、スマホアプリではありません。それでもビールの投稿に手間をかけずに済むように、PWA という仕組みを利用して、ブラウザからアクセスする手間を省いています。

スマホのホーム画面にアイコンを設置できるので、写真を撮ったらすぐに Beer Break にアクセスして写真を投稿できます。

課題3「珍しいビールを試してみたい」

3つ目の「珍しいビールを試してみたい」という課題に対しても、Beer Break で解決していきたいです。投稿してくださるユーザーさんの幅が広がり、趣味嗜好、住んでいる場所が多様になり、レビューの投稿数が増えると解決できると踏んでいます。

これに関しては、Beer Break によく投稿してくださるkanikama さんの投稿(WCB ウェストコーストブルーイング トリプルバレル)や、ふくいさんの投稿(マンゴー&レモンビール ラ・ガジェガ)を見ていると、自分が知らないビールの投稿をしていただいているので一定手応えを感じています。

「WCB ウェストコーストブルーイング トリプルバレル」の Beer Break のレビュー画面

「マンゴー&レモンビール ラ・ガジェガ」の Beer Break のレビュー画面

自分が知らない美味しそうなビールの投稿を見ていると、自分も買って飲んでみたくなります。そこで、ほとんどのビールのレビューページに購入ボタンを設置しており Amazon へのリンクとしています。 気になるビールはすぐに試せるよう、スムーズに購入できるようにしております。

Beer Break の機能について

サイトの紹介と解決したい課題について語った後、ちょっとだけ Beer Break の機能面の解説をします。

簡単にレビューの投稿ができる

一番こだわったところが「レビューの投稿ハードルを可能な限り下げること」です。

Beer Break でレビューを投稿するにあたり、感想の入力以外は画面のクリック(もしくはスマホのタップ)だけで済むように投稿画面を設計しています。頻繁にビールを飲む方が、投稿は面倒だと思われないようにするためです。

ビールの画像を選び、ビールの名前を一覧、もしくはサジェストから選んで(サイトに登録がなければ自分で入力)、本文を記入し、評価とテイストをクリックして選んで「投稿する」を押すだけです。

Beer Break のレビュー投稿画面

ビールのレビューの本文は「うまい」というシンプルな一言だけでも問題ないようにしています。飲んだビールの味を「bitter」「sweet」「fruity」「sour(酸味がある)」「clear(キレがある)」の5種類から選ぶことができ、この組み合わせを見るだけで自分が好きなビールの味かどうかを判断できるからです。

テイストの選択画面

ユーザー登録も可能な限り簡単にしています。Google アカウントと連携して登録し、自分のユーザー名と生年月日を入力すれば登録完了です。生年月日は未成年が登録できないようにしているため入力必須にしています。

ビール好きの方はぜひ Beer Break に投稿をお願いします!

今は Beer Break はβ版ですが、ユーザー登録、レビューの投稿、レビューに対するいいねやコメントは既に可能で、レビューサイトとして一通りの機能は揃えています。

それでもなぜβ版なのかというと、それはプロダクトに対する自分の心の持ちようです(笑)。システムが安定稼働して正式リリースができれば、もっと大々的に宣伝して多くの方に使って頂きたいと思っております。が、現段階では宣伝はまだ控え目にして、レビューを集めつつ機能を追加・調整して安定稼働を目指しています。

この記事を読んで頂いたビール好きの方はぜひユーザー登録をして、ビールを飲んだ時にレビューを投稿してみてください。 自分の好きなビール、飲んで美味しかったビールをぜひ広めていきましょう!

もしお口に合わなくても、もしかしたらそのテイストが他の方の好みかもしれません。投稿していただいた内容は、必ず誰かの役に立ちます。ビールの写真を撮ったらぜひ Beer Break にレビューの投稿をお願いします!

最後に

まだまだリリースしたてですが、これからも快適に使ってもらえるように開発していき、ビール愛好家の課題を解決し、ビール好きの健全なコミュニティ作りに貢献できるよう頑張っていきます!

最後に。自分が一番好きなテイストは、「sweet」「fruity」で、好きなビールはプレモルの香るエール白濁(しろにごり)です。

👇 Beer Break へアクセス👇

Beer Break トップページ

https://beerbreak.info/

プログラミングをするパンダ
プログラミングをするパンダ (@Panda_Program)
Software Engineer

技術エッセイです。

EoPAA の Data Transfer Object

「技術はレイヤーだ。今の技術は、過去の技術の積み重ねの上にある」という koriym さん(PHP フレームワーク BEAR.Sunday の作者で、前職の技術顧問)の言葉を今も覚えています。

この2ヶ月間、業務でサーバーサイドエンジニアとペア・モブプログラミングをしながら PHP を書いているため、ちゃんとオブジェクト指向プログラミング(OOP)と向き合おうと「エンタープライズアプリケーションアーキテクチャパターン(通称 PoEAA)」を読んでいます。

PoEAA の邦訳の出版は2005年です。記述が古くなっているところももちろんありますが、それでも今でも開発の現場で使われている OOP の語彙を理解、説明するために有用な記述もたくさんあります。

EoPAA を通して、自分が過去に目にしてもその内容を理解しきれていなかった用語の内容を把握するため、また人に意図を説明するときに適切な語彙を選択できるようにするため総ざらいのような気持ちで読んでいます。

さて、このような古典に対する自分の読み方はまた別の記事に譲るとして、今回は一見関係のないような事柄に対する面白い共通事項を発見したので、それを書き留めて起きます。

それは Data Transfer Object と RESTful ではない(いわゆる Restishな) API のレスポンス、そして GraphQL についてです。

Data Transfer Object

Data Transfer Object は、メモリとは異なり、ネットワークや DB を経由するため取得にコストがかかる値たちをまとめるオブジェクトです。EoPAA では分散パターンの章で紹介されています。

(なお、原文にはネットワークへの言及しかないですが、Google 検索してみると主に DB からの値の取得に使うのだという記述が散見されたので、両方書いてます。)

DTO には getter と setter しかなく、ドメインロジックは記述しません。プロパティにはプリミティブな値もしくは他の DTO を保持すると書籍には書かれています。

雑誌を例に挙げると、DB の Magazine テーブル、Article テーブル、Author テーブルのそれぞれから一度ずつデータを読み込むより、一度読み込んだデータを DTO に保持しておく方が良いというところでしょうか。DB のデータにアクセスするオブジェクトを Data Access Object(DAO)として疑似コードを書いてみます。

class Publisher {
  pub func main() {
    magazine = this.getMagazine(1)
    article = this.getArticle(2)
    author = this.getAuthor(3)
    // ...
  }
  
  pub func sub() {
    magazine = this.getMagazine(1)
    article = this.getArticle(2)
    author = this.getAuthor(3)
    // ...
  }
  
  priv func getMagazine(id) {
    return dao.magazine.find(id)
  }

  priv func getArticle(id) {
    return dao.article.find(id)
  }

  priv func getAuthor(id) {
    return dao.author.find(id)
  }
}

このようなコードでは、Magazine、 Article、Author の値を求めるたびに、DB へのアクセス数が嵩みます。そこで、DAO に Magazine、Article、Author をまとめてしまうと DB へのアクセス効率が良くなります。

RDB であれば、それぞれのテーブルに対して Select 文を合計3回発行していたところ、リレーションを使ってテーブルを join すれば getMagazineDto 内のクエリ実行は一度で済みます。

class Publisher {
  pub func main() {
    magazineDto = dao.getMagazineDto(1, 2, 3)
    magazineTitle = magazineDto.magazineTitle
    articleTitle = magazineDto.articleTitle
    authorName = magazineDto.authorName
    // ...
  }
  
  pub func sub() {
    magazineDto = dao.getMagazineDto(1, 2, 3)
    magazineTitle = magazineDto.magazineTitle
    // ...
  }
}

本書では DTO はシリアライズ可能であるとされているので、以下のようなオブジェクトになっていると想像できます。

class MagazineDto {
  public magazineId: number
  public magazineTitle: string
  public articleId: number
  public articleTitle: string
  public authorId: number
  public authorName: string
}

DTO 自体は昔からあるパターンです。しかし、これが RESTful ではない API のレスポンスの形に似ていると思いました。

RESTful ではない API レスポンス

ここでいう「RESTful ではない API レスポンス」とは、API を境界として、フロントエンドエンジニアとバックエンドエンジニアが分業をして開発する現場でよくある、フロントエンドの画面が欲しいデータが全部入りで入っている API レスポンスのことです。

RESTful API では、エンドポイントをリソース単位で用意します。この考え方では、v1、v2で区切ってバージョニングするなんてもっての他です。上記の雑誌の例を引き続き使うと、雑誌のデータは /api/magazines/:id から、記事は /api/articles/:id から、著者は /api/authors/:id から、GET メソッドの HTTP リクエストを使って取得します(なお、便宜的に /api をパスにつけていますが、これは RESTful API の考え方とは無関係で、わかりやすくしているだけです)。

しかし、雑誌のレスポンスに含まれている記事 ID を取得して記事のエンドポイントにリクエストを投げ、それを著者でも繰り返すと API リクエストの数は増えてしまいます。これは Round Trip(原義は往復旅行)と呼ばれています 1

そこで「現場の」エンジニアが考え出した解決策は、画面が欲しいデータをレスポンスに可能な限り突っ込むことです。これはよくみられます。特に、元々 MVC のフレームワークを使っていて、Controller から View(テンプレートエンジン)に値を返していたのを、API で JSON を返すように変えたというケースでは当たり前にあることではないでしょうか。

イメージとしては以下のような JSON です。/api/magazine/1 にリクエストを送ったと仮定すると、レスポンスは以下のようになるでしょう。

{
  "id": 1,
  "title": "雑誌のタイトル",
  "articles": [
    {
      "id": 1,
      "title": "記事タイトル1",
      "author": "著者名1"
    },
    {
      "id": 2,
      "title": "記事タイトル2",
      "author": "著者名2"
    }
  ]
}

その良し悪しはここでは置くとして、これが Data Transfer Object に似ているなと思い、以下のようなツイートをしました。

https://twitter.com/Panda_Program/status/1527000293732364288

パターンの再発見です。他の誰かも過去に発見していたでしょうし、別の誰かが未来に発見するでしょう。パターンとは現実から見出されるものだからです。

GraphQL のレスポンスにも似ている

この DTO と上記の JSON が似ているなと思い至ったところで、GraphQL にも似ているなと思いました。同僚も同様の趣旨のツイートをリプライでくれています。

https://twitter.com/glassmonekey/status/1527218922428108800

そこで思い返したのが、「初めてのGraphQL」 という書籍にあった記述です。

関連記事: 「初めてのGraphQL」を読んでGraphQLの概要を学んだ

元々 GraphQL は「マシンパワーの弱いスマートフォンで、アプリの動作効率を上げるために通信を最適化する」という目的で考えられたとこの書籍で紹介されています。

通信を最適化するとは、画面の表示に必要十分なデータを API のレスポンスで取得するということです。多くても少なくてもいけません。データが含まれている場合はオーバーフェッチ、データが足りない場合はアンダーフェッチと呼ばれています。

記事のタイトルに立ち返ると、これは DTO の目的そのものです。DTO の定義は「メモリとは異なり、ネットワークや DB を経由するため取得にコストがかかる値たちをまとめるオブジェクト」でした。GraphQL から返ってくる JSON は以下のような見た目です。

{
  "data": {
    "magazine": {
      "name": "雑誌タイトル",
      "articles": [
        {
          "name": "記事タイトル1"
        },
        {
          "name": "記事タイトル2"
        }
      ]
    }
  }
}

DTO はオブジェクトであり、GraphQL のレスポンスは JSON ですが、考え方としては同じといって差し支えないと思います。実際、PoEAA の著者であるマーティン・ファウラーは 別のブログ記事で「DTOのようなものを使うとよいのは、プレゼンテーション層のモデルとドメインモデルとの間に大きなミスマッチがある場合です」と書いています。

異なるものの間に共通項を見出して抽象化する。これはパターンの力と言えるでしょう。

古典は温故知新に繋がる

いわゆる Connecting The Dots やアハ体験と呼ばれる、記憶の別の引き出しに放り込んでおいた知識が互いに繋がる発見はなかなか得難いものです。

まさか EoPAA という古典を読んでこのような思いつきに至るとは、書籍を手に取る前には想像もしていませんでした。まさに温故知新(古きを訪ねて新しきを知る)だなと思った「発見」でした。

追記

早速友人が「XMLへのシリアライズの言及が書籍内にある」と教えてくれました。

https://twitter.com/TSUCHIYA_Naoki/status/1527334944778858496

確かに該当箇所を読んでみると、「データ変換オブジェクトで直面する一般的な問題の一つは、シリアライズ形式をテキストまたはバイナリのどちらにするかと言うことである。テキストのシリアライズの場合、読み込みが容易なので何が通信されているかもすぐにわかる」と書いてあります。そして、この文と同じ段落に XML への言及がありました。

なお、書籍ではシリアライズという単語が直列化と訳されており、最初に読んだ時なにを指してるかわからず該当箇所を読み飛ばしていました(本記事を書く直前に直列化がシリアライズを指すとあるブログで知りました)。

XML を JSON と読み替えて考えると、やはりマーティン・ファウラーの慧眼もしかり、ソフトウェア界隈で今も昔も変わらないことはあるのだなあと感慨深いです。流行に振り回されず、このような基礎を追っていきたいものです。

Footnotes

  1. さらに、クライアント側では取得したレスポンスのデータをもとに、次に欲しい情報を取得するためのコードを記述しなければなりません。ただし、これは HATEOAS という設計思想を適用すればその煩雑さを避けられるそうです。ただ、自分が HATEOAS を理解しきれてないです。ハイパーメディアに詳しいサーバーサイドエンジニアで友人の Tsuchiya 君がこの辺りのことを指摘していました。

GraphQL
プログラミングをするパンダ
プログラミングをするパンダ (@Panda_Program)
Software Engineer

PHPerKaigi 2022 にオンライン参加した

PHPerKaigi 2022 にオンライン参加しました。最近フロントエンドの発信をメインにしていますが、元々自分はエンジニアとしてのキャリアを PHP のサーバーサイドエンジニアから始めました。

前職の弁護士ドットコムではバックエンドに PHP を採用しているため、弁コムがスポンサーをしていた PHP Conference には何度か参加したことがありました。

現在の勤務先である BASE でもバックエンドは PHP のフレームワークである CakePHP を採用しており、PHPerKaigi のスポンサーでもあります。

私は PHPerKaigi には参加したことがありませんでした。かつて私がエンジニアとして最初に入った会社で「あのカンファレンスは PHP を使うすごい人たちが集まるところなんだ」と教えられ、なんとなく敷居が高いイメージがあったからです。

PHPerKaigi に参加した経緯

3月ごろ、今年の2022年の PHPerKaigi には BASE のバックエンドのメンバーに参加しないかと声をかけて貰いました。

自分は BASE でフロントエンドエンジニアとして働いており、WEB+DB Press で PHP のアップデートに伴う新機能の紹介記事を読むくらいで、それ以外は最近の PHP 事情をあまり追っておらず PHP のコードも1年以上書いていません。

最初は断ろうかと思っていました。しかし、よく話を聞いてみると資料を作成して登壇して発表するのではなく、アンカンファレンスというオーディエンスの方とインタラクティブなやり取りをする発表で良いこと、そのアンカンファレンスで先日私が Sofware Design に寄稿した TDD の話などをしてほしいということでした。

実際に過去の PHPerKaigi のアンカンファレンスの発表を見ると、開発や組織に関する意見交換や雑談のようなものだったり、みんなでコードリーディングをするような物がメインでした。

最新の開発状況を共有したりする必要もなく、事前の準備もそこまで必要なさそうだ。それなら一つやってみようと思い、ネタを探すことにしました。

発表内容の決定と事前準備

当日の発表内容は PHP8 で JSON パーサーを作るというものにしました。

自分は最新の PHP の言語事情も知れるし、JSON パーサーの作り方も学べる。また、ライブコーディングとすることで、JSON パーサーの作り方を自分から学ぶというのは腰が重いが、コーディングしているところを見るだけなら見ている方も一歩を踏み出しやすいだろうと思ったからです。

自分の想定していた対象者は、PHP である程度作りたいものを作れるようになった中級者の方でした。しかし、今回自分がオンライン参加だったこと、また全く同時刻に BASE とメルカリの社員が組織と開発について対談するという現地アンカンファレンスをすることが当日決まったことから、宣伝と集客の面で劣ってしまい、そもそも参加者が7名という少人数になっていました。

ライブコーディング当日

また、当日は70分の枠を確保したもののかなり駆け足でコーディングしており、こちらが一方的に書いて一方的に解説することになり、 Zoom で参加してくださった方との交流まではできませんでした。

私はライブコーディングの事前準備として時間を測りながら JSON パーサーの作成を 2周しました((GitHub にコードを掲載しています))。その結果、ライブコーディングを聞いてくださった方と自分の間で仕様の理解度に差がついてしまい、解説が早すぎたかもしれないと反省しました。

発表の枠は70分あります。最初の10分くらいは参加者が増えるのを待ったりしていたので、実質コーディングをしていた時間は60分です。その60分間では、緊張も相まって短距離走のように初めから全力コーディングをし(そうしないと終了に間に合わない)、しかも普段ペアプロでするようにずっと「今やっていること。そのコードの意図」を喋りっぱなしでした。

面白いことに、コーディングを初めてきっかり50分たったところから、タイポ言い間違い、言葉がすぐに出てこないことが頻発しました。集中が明らかに切れてしまったのです。それでもなんとかパーサーとレキサーの作成が完了し、事前に用意していたテストも全て通りました。

惜しむらくは、パーサーとレキサーを組み合わせて呼び出す main 処理だけが書けませんでした。たった数行なのですが、ギリギリのところで時間が来てしまい、Zoom の会議が無慈悲にも閉じられてしまいました。

それでも、Zoom で顔出ししてくださった方の反応が見れたり、BASE の現地参加メンバーが出展ブースでパソコンの画面に自分の発表を映してくれていて、パソコンを覗き込んでいる人が数名いるのが見えたことです。

オンラインでカンファレンスに参加する方は、ぜひ顔出しをして頂けると嬉しいです。発表者のモチベーションに直結すると思いました(録画型の発表は事情が別ではあると思いますが)。

さて、今回のライブコーディングで学んだことは、以下の3点です。

  • 聴衆と発表者の間で仕様の理解度に差がありすぎるとよくない。誰でも知ってる題材か、どちらも詳しく知らない題材を選ぶ
  • 50分を越えてコーディングをするのは体力、気力的に無理。今回は自宅からだったが、壇上からだと30分までにしたほうがいいかもしれない
  • テストが落ちたりエラーが出ても、みんなでデバッグすればいい。誰かが気づいて教えてくれるので問題ない(モブプロのいいところ)

PHPerKaigi で発表をする、JSON パーサーの作り方を知る、PHP8 の機能を知るという当初の自分の目標は達成できました。また、発表を聞いてくださった方のおかげでライブコーディングについても学ぶことができました。

ただ、自分の目的は達成したものの、発表を聞いてくださった方には楽しんで貰えたのかが、オンライン参加だったため確認できませんでした。自分の後には発表枠がなかったので、オフライン参加であれば少し時間をオーバーしても最後までコードを書ききれたでしょう。

オンライン参加なので、「カンファレンスの廊下」という技術者同士の雑談もありませんでした。ただ、PHPerKaigi の週と自分の引っ越しと重なっており、新居に引っ越したばっかりでバタバタしていたため仕方なかったかなとも思います。

もし来年も PHPerKaigi に参加することがあれば、もっと参加者の方と交流できるような題材を選び、必ずオフラインで参加しようと思います。

それは全部の発表が終わった後、完全に自分のエンジンがかかっており、その熱がしばらく冷めなかったからです。

アンカンファレンスの発表をした後、たまたま上の階の方が挨拶に来てくださいました。初対面特有のしっとりした挨拶が求められる場面だったのですが、何分自分が全力で発表をした後だったので、勢いそのままに受け答えをしてしまって温度感に差が…(笑)。

まあそんな後日譚もありました。最後に、テーマの元になったスライドを作成してくださった @shin1x1 さん、PHPerKaigi の主催者・運営メンバーの方、参加者の方、声をかけてくれた BASE のメンバー、また関わってくださった全ての方に感謝して筆を置くことにします。

PHP
プログラミングをするパンダ
プログラミングをするパンダ (@Panda_Program)
Software Engineer