Thinreports に SectionReport フォーマット機能を追加する pull request を作成した

こんにちは、Misoca開発チームの日高(@hidakatsuya)です。

以前、Thinreports の SectionReport フォーマット機能を公開したという記事を書きました。

tech.misoca.jp

この度、この機能を pull request 及び issueとして、Thinreports コミュニティに提案しましたので、その内容について紹介します。また、SectionReport フォーマットでは何ができるのかを知ってもらうために、いくつかの特徴もご紹介します。

SectionReport フォーマット機能のコミュニティへの提案

提案の概要

github.com

機能の概要や使い方、SectionReport フォーマット機能の今後の開発方針などを説明しています。SectionReport フォーマットという機能がどういうもので、どのような背景があり、どのような方針で実装されているかなど、この issue を読むことでそれらを把握することができます。

内容は概ね次の通りです。

  • コミュニティで提案されている仕様 をベースに SectionReport フォーマットを実装した
  • 未実装の仕様や既知の課題が残っているが、それらについてはコミュニティと一緒に開発していきたい
  • SectionReport フォーマットの仕様の説明として、いくつかのサンプルコード (Rubyコード、テンプレート、出力結果PDF) を作成したので参考にして欲しい
  • SectionReport フォーマットの使い方として Hello World を説明
  • 私たちが実装した SectionReport フォーマットは未完成で問題もあるが、今後はコミュニティと一緒に開発を進めたい。その提案として、一旦現状で取り込み、仕様の議論とタスクの整備を行って、広く開発に参加できる環境を作って進めてはどうだろう

実装の詳細 (pull request)

Thinreports の Generator (rubygem) と Editor (テンプレートデザイナ) の実装は、それぞれの pull request として作成しています。

github.com

github.com

pull request の説明では、使い方や実装ステータス (未実装、独自実装、既知の問題) について詳しく記載しています。

ぜひご意見ください

私たちが提案した SectionReport フォーマットは、未完成でいくつかの問題もあります。SectionReport フォーマットの機能としての仕様はもちろん、今後の開発の進め方など、広くディスカッションした上で、より良い形で開発を進めたいと考えています。

issue の内容への質問や意見、実際に動かしてみた感想や質問、コードに対する指摘などなど、ぜひご意見をいただけると嬉しいです。

SectionReport フォーマットで何ができるのか

現行の Thinreports のフォーマット (以降、現行のフォーマットと呼ぶ) との比較として、SectionReport フォーマットの特徴を二つ紹介します。

そもそも、SectionReport フォーマットって何?という方は、まず Thinreports コミュニティで提案されている仕様 をご覧ください。

ヘッダーやフッター、明細行を任意の数だけ定義し、組み合わせて出力することができる

現行のフォーマットでは、ヘッダーやフッターといった概念自体がありません。近い機能として「リスト」というツールがありますが、ヘッダーやフッター、明細行は一つだけしか定義することができません。

SectionReport フォーマットでは、次のように、いずれも任意の数だけ定義することができ、名前(ID)によって、それらを組み合わせることができます。

例えば、次のようなテンプレートを用意します。

f:id:hidakatsuya:20201012180259p:plain
テンプレート (Thinreports Editor)

次のコードで PDF を生成します。

report_params = {
  type: :section,
  layout_file: 'example1.tlf',
  params: {
    groups: [
      {
        headers: {
          header1: { items: { text_block1: 'タイトル' } },
          header2: { display: false }
        },
        details: [
          { id: :detail_a, items: { text_block1: '明細1行目' } },
          { id: :detail_a, items: { text_block1: '明細2行目' } },
          { id: :detail_b, items: { text_block1: '明細3行目' } },
          { id: :detail_b, items: { text_block1: '明細4行目' } },
          { id: :detail_a, items: { text_block1: '明細5行目' } }
        ],
        footers: {
          footer1: { display: false }
        }
      }
    ]
  }
}

File.binwrite('example1.pdf', Thinreports.generate(report_params))

出力される PDF は次のようになります。

f:id:hidakatsuya:20201012174550p:plain
出力結果PDF

パラメータによって、テンプレートに定義されたヘッダーを非表示にしたり (display: false)、複数の明細の定義を組み合わせて出力するといったことが可能です。

自動的に領域の高さが伸縮する

現行のフォーマットは、設定した用紙をキャンバスとして、テキストや図形などを配置してレイアウトを作成します。そのため、出力する PDF の高さも用紙の高さで固定され、テキストや図形などの描画位置やサイズも固定です。そのため、テキストの内容によって、図形の位置を下にずらしたり、領域の高さを動的に変更することが困難です。

SectionReport フォーマットでは、ヘッダーやフッター、明細行の高さの動的伸縮をサポートしています。また、動的伸縮によって、図形などの描画位置も動的に追従することが可能です。次の例をご覧ください。

次のようなテンプレートを用意します。

f:id:hidakatsuya:20201012175515p:plain
テンプレート (Thinreports Editor)

次のコードで PDF を生成します。

report_params = {
  type: :section,
  layout_file: 'example2.tlf',
  params: {
    groups: [
      {
        headers: {
          header1: { items: { title: '長いタイトル ' * 15 } },
        },
        details: [
          { id: :detail_a, items: { detail_text: '短い明細' } },
          { id: :detail_a, items: { detail_text: '長い明細 ' * 18 } },
          { id: :detail_a, items: { detail_text: '短い明細' } }
        ]
      }
    ]
  }
}
File.binwrite('example2.pdf', Thinreports.generate(report_params))

出力される結果は次のようになります。

f:id:hidakatsuya:20201012175703p:plain
出力結果PDF

定義した領域を超えるテキストをセットした場合でも、ヘッダー1 の領域の高さが自動的に拡張し、ヘッダー2 や明細A がその下に続いて正しく描画されます。また、明細Aの二行目では、拡張した領域に合わせて四角形の高さが拡張していることがわかると思います。

最後に

興味のある方はぜひ SectionReport フォーマットで遊んでみてください。

宣伝

Misoca 開発チームでは、積極的に OSS に貢献していきたいエンジニアを募集しています。

www.wantedly.com

Railsの複数DB機能で負荷を分散する

こんにちは。弥生で Misoca を開発している小坂と申します。インターネットには kosappi という名前で存在しています。

前回ご紹介した みんなのコンピュータサイエンス は読んでいただけたでしょうか?

9月末で事業年度が終わる会社は多いかと思います。みなさんは無事に10月を迎えることはできましたか?私は有給休暇の日数が付与されて、とても良い気分です 🏝

今回は、Rails の複数 DB 機能を利用して9月末の高負荷を乗り切った話を紹介いたします。

🔥 月末の高負荷

Misoca は請求書作成ソフトということもあり、月末にアクセスが増加します。

ユーザの増加や、機能が充実したことにより、DB への負荷も増加しています。8月末の負荷は DB の限界に近い値でした。 特に、文書の一覧や検索などの参照系のクエリの比重が高く、機能の充実によってクエリ自体も重いものになっており、問題になっています。

9月末は事業年度が終わるユーザも多く、8月末よりも負荷が高くなり、このままでは DB の処理能力の限界を超えてしまう事態が予想されました。

DB への負荷を改善する方法としては、下記のようなものがあると思います。

  • 重いクエリを見直して軽くする(SQLの改善)
  • DB インスタンスの強化(スケールアップ)
  • DB インスタンスを増やして負荷を分散させる(スケールアウト)

今回は参照系のクエリが問題になっていることもあるので、読み込み専用の DB インスタンス(リードレプリカ)を増やして、一部の重いクエリをそちらに向けることにしました。

🛠 Active Record による複数の DB 利用

Misoca は Ruby on Rails の上で開発されています。

Rails は 6 にバージョンアップした際に、複数の DB 利用をサポートしました。Rails 5 でも、追加の gem を使えば実現できたのですが、Rails 6 からは標準機能として提供されます。

参考 : Active Record で複数のデータベース利用

今回はこの機能を利用して、一部のクエリをリードレプリカに向けました。

一部のクエリをリードレプリカに向ける

まず DB を追加します。

事前に AWS の RDS で、普段使っているインスタンスをレプリケーションするインスタンスを作りました。 レプリケーションの遅延が発生しますが、これは 1ms 以内と示されていたので、今回は問題にならないと判断しています。

メインのDBを primary、リードレプリカを replica という名前にしています。 Rails が DB を判断するために、レプリカとして利用する DB には replica: true を書く必要があります。

production:
  primary: &primary
    <<: *default
    host: <%= ENV['PRIMARY_HOST']  %>
  replica:
    <<: *primary
    host: <%= ENV['REPLICA_HOST']  %>
    replica: true

そして全てのモデルで上記の DB が利用できるようにします。 今回はロールが writing の場合は primary を、 reading の場合は replica をそれぞれ利用します。

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  connects_to database: { writing: :primary, reading: :replica }
end

最後に、向き先を変えたいクエリを実行している箇所を、下記のようにブロックに含めればOKです。このブロックの外では必ず role: :writing でクエリが実行されます。 role 以外にも database を直接指定することもできますが、こちらは非推奨となっているので気をつけてください。

ActiveRecord::Base.connected_to(role: :reading) do
    # リードレプリカに向けたいクエリを実行するコード
end

今回は手動でロールを変更しましたが、自動的に切り替えることも可能です。 書き込むクエリの場合は primary、読み込みクエリの場合は replica を使う、といった振り分けを書くことができます。

参考 : Active Record で複数のデータベース利用#コネクションの自動切り替えを有効にする

📉 結果

以上の対策を施した上で、無事に9月末を乗り越えることができました。

DB の負荷はどうなっていたんでしょうか?

primary DB の IOPS 1 を見てみましょう。オレンジが READ、ブルーが WRITE の IOPS です。

リードレプリカの利用開始時期(9/15ごろ)から、READ の IOPS が下がっていることがわかります。 8月末と9月末を比較すると、かなり負荷を減らすことができました。

edited.png (178.5 kB)

今回は9月末の高負荷を、Rails の複数 DB 機能で乗り切ることができました。 今後は、2台に増えた DB のスペックを見直したり、他のクエリをリードレプリカに向けることを検討する予定です。

🎺 宣伝

Misoca 開発チームでは、Rails の新機能を使って課題を解決したいエンジニアを募集しています。


  1. Input/Output Per Second の略です。1秒あたりの入出力の多さを示しています。

みんなのコンピュータサイエンス読書会を完走しました

2週連続でこんにちは、弥生のMisoca開発チームの黒曜(@kokuyouwind)です。

前回記事のはてブがやたら伸びていて、なんでかと思ったら@mugi_unoのツイートがバズっていました。

これがインフルエンサーか…!

📕 みんなのコンピュータサイエンス読書会

以前の記事で書きましたが、Misoca開発チームでは有志で集まりみんなのコンピュータサイエンスの読書会を開催していました。

tech.misoca.jp

みんなのコンピュータサイエンス

みんなのコンピュータサイエンス

こちらの読書会ですが、2020年8月28日を持って無事完走しました!🎉🎉🎉

参加者の皆さん、お疲れさまでした!!!

⏱ 読了にかかった時間

初回が2019年12月6日だったため、9ヶ月ほどかけて読み切ったことになります。

週に1回の予定でしたが、休みだったり参加者の都合が合わなかったりといった理由で中止になる週も多かったため、実際には月2回ほどの実施だったと思います。少し多めに見積もっても20回20時間程度で読みきった計算になりますね。

本の厚さから考えると、かなり時間をかけたほうだと思います。とはいえアルゴリズムや計算量の式をきちんと追いかけたり、実践と結びつけた議論を行ったりなど丁寧に読み解いたため、まぁ妥当な期間ではないでしょうか。

なにはともあれ、長期に渡る読書会をきちんと完走できて安心しました。

💬 参加者の感想

f:id:kokuyouwind:20200903114924p:plain:w40 @suer

本については一貫してできるだけコンピュータサイエンス初学者にとっつきやすい説明がされていたと思います。 日々の開発で何気なく扱っている各種事項にこういう背景があるのか、というのが概観できました。

この本単体ではコンピュータサイエンスの学習としては足りないですが、 この本から興味のある分野をピックアップして他の書籍をあたるなどして深堀りしていくとよさそうです。

勉強会の形式については読んだあとに議論する形式だったので、議論の中で本には書かれていない 発展的な内容に言及されることもあっておもしろかったですね。 特にDBのインデックスをどうつければいいのかという話はこの本には書かれていなかったですが、 自社プロダクトに絡めてそのあたりの話ができたのでとても理解が進みました。


f:id:kokuyouwind:20200903131027p:plain:w40 @thara

コンピュータサイエンスの全体像を概観できる、「みんなの」という修飾に見合うレベル感だった。 検索用に英語の単語も併記されているのが丁寧で、この本を出発点に興味ある分野を掘り下げやすくなっているのが良い。 反面、すでにコンピュータサイエンスを修めている人に取っては物足りなさを感じたかもしれない。

単なる輪読会で終始せずに、議論したり、時にはコード書いたりしたのが良かった。 簡単な数式の読みを勘違いして意味がわからなかったのをその場で気軽に質問したが、これも心理的安全性のなせる技だなぁと実感した。


f:id:kokuyouwind:20200903131329p:plain:w40 @RKTM

あんまり参加できなかったが、本の記述以外のことも持ち寄って話せるのは、独学ではできない価値のある体験でした。

広く、程よく深い(程よく浅い)という内容で、良い復習になりました。


f:id:kokuyouwind:20200903131456p:plain:w40 @mizukmb

学生の頃に勉強した内容を復習するような、コンピューターサイエンスについて広くわかりやすく解説された本でした。

輪読会についても、この本には書かれてなかった技術や歴史などについて参加者同士で議論することができ、個人的にとても実りのある会になりました。


f:id:kokuyouwind:20200903131600j:plain:w40 @KawamataRyo

コンピューターサイエンスの基礎知識ゼロの状態で輪読会に参加していたのですが、毎回難解なトピック(自分には)を、皆でmiroを使った図示やサンプルコードを用い噛み砕いて説明してくれたので大分理解が進みました。 この輪読会という形式でなければ、自分は読了することは出来なかったと思います。

本書の狙い通りコンピューターサイエンスの全体像を把握したことで、より詳細なトピックに興味を持ちました。 今後は個別のトピックについて自分なりに勉強していこうと思います!!


f:id:kokuyouwind:20190930142248p:plain:w40 @kokuyouwind

「自分が読みたいから」という理由大半で始めた読書会でしたが、蓋を開けてみると単に輪読するだけではなく深堀りした議論を行うことができ、ひとりで読むよりも多くの収穫を得ることができました。 狙いのひとつであったコンピュータサイエンス知識のベースラインを揃えるという点でも、平易ながら広い範囲を抑えた書籍でちょうどよい題材だったと思います。

またリモートワークでコミュニケーションが薄くなりがちな状況において、こうした読書会はコミュニケーションの場としても機能するという気付きがありました。 知識をインプットするだけではなくコミュニケーションを増やすという目的も兼ねて、今後はまた別の本を題材に読書会を開催していきたいと思います。

あらためて、皆さんご参加ありがとうございました!!!

📢 宣伝

Misoca開発チームでは読書会で地力を強化したいエンジニアを募集しています!

VSCodeでDraw.ioをLive Shareしたら最高の体験だった

こんにちは、弥生のMisoca開発チームの黒曜(@kokuyouwind)です。

Kaigi on Railsの登壇が決まったのでよろしくおねがいします。弥生社員としては初登壇になります。

前回の記事が濃厚だったため、今回はライトなTips記事です。よろしくおねがいします。

tech.misoca.jp

👯‍♀️ VSCode LiveShareを使ったリモートペアプログラミング

皆さん、ペア作業してますか?

ペアプログラミングはドライバー・オペレータの交代など具体的なノウハウも多く、このブログでも以前に紹介記事を書きました。

tech.misoca.jp

上記の記事ではリモートでのペアプログラミングについてscreenhero*1を使っていると書きましたが、現在ではVisual Studio CodeLive Share機能がよく使われています。

この機能は画面を共有するのではなくコードの編集結果のみを共有するため、以下のような利点があります。

  • 各自の設定・キーバインドでエディタを利用できる
  • 画面共有と比べて軽い

なお音声はZoomを使って繋ぐことが多いです。最近ではLive Share Audioがプレビュー公開されているため、こちらを使えばVisual Studio Codeのみでペアプロが完結できるようになるかもしれません。*2

✏️ draw.io を使ったペア設計

Misoca開発チームでは他にも、クリティカルな本番作業をペアオペレーションで行ったり、難易度の高いプルリクエストのレビューをモブレビューで行ったりなど、様々な作業がペア及びモブで行われることが多くあります。

今回は設計作業でVisual Studio CodeのDraw.io拡張を使ってみたところ、非常にスムーズなペア作業ができた話を紹介します。

f:id:kokuyouwind:20200831103341p:plain

Draw.io拡張を入れると、上記のようにVisual Studio Code内にDraw.ioのエディタがそのまま表示されます。(この図は本番のECS化について検討しているアーキテクチャ図です)

この図はLive Shareセッションを繋げば各自が自由に編集できるため、例えば「図にElasticacheが足りないから足しておくね」と言いつつアイコンを追加したり、「S3はNATゲートウェイ挟んでアクセスするんだっけ?」と確認して繋ぎ変えたりといったことが柔軟に行えました。

もちろんこれらはクラウドサービスとしてのDraw.ioを利用しても行えるのですが、比較すると以下のような利点があると感じました。

  • 拡張機能自体がローカルにあるためか、クラウドと比較して挙動が軽く、相手の変更が遅延なく反映される
  • ローカルファイルとして保存するため、ソースコードと一緒にGit管理できる
  • 他のソースコードと行き来して、ペア設計とペアプロをシームレスに行える

🛫 今後やりたいこと

上記のように利点を挙げましたが、今回のペア設計では既存のソースコードリポジトリと別の場所にファイルを置いているため、2番目と3番目のメリットは享受できていませんでした。

とても便利に使えることがわかったため、例えばペアプロの前のタイミングでクラス構成をざっと書いてからコーディングに入るなど、もっとライトに活用していけると良いなと思っています。

📢 宣伝

Misocaチームではペア設計を活用したいエンジニアを募集しています。

*1:現在ではSlackに統合され、Slack Callの画面共有機能になっています。

*2:筆者の環境でも試してみましたが、残念ながらうまく音声が繋がりませんでした。正式公開を待ってまた試したいと思います。

9年モノの Rails アプリで、古い Bootstrap を剥がして FLOCSS 化した話

9年モノの Rails アプリで、古い Bootstrap を剥がして FLOCSS 化した話

こんにちは、弥生 Misoca チームでマークアップをする方のデザイナー @kanizmb です。

今回、約1年をかけて古の Bootstrap の撤去および CSS 設計手法の導入(FLOCSS 化)をやり遂げたので、これらの変更をどのように進めていったかについてお話しします。

どういった状況だったか

Misoca ローンチは 2011年、当時最新であった Bootstrap 2.3.2 を用いて構築が始まりました。(*1)
当初は請求書の郵送に特化した非常にシンプルなサービスだったため、少しの上書きでスムーズに開発が進められ、Bootstrap のメリットを存分に生かせていたのだと思います。

Bootstrap2.3.2 を app.css で上書きしている図

しかし時は流れ、取引先管理、品目管理、外部サービスとの連携など、機能が増え続けるとどんどん綻びが出始めます。 設計方針もないままに野放図に差し込まれた CSS たちは、いつしか激しい詳細度バトルを繰り広げるようになります。

たとえば、コードで示すとこのような内容です。(コードはイメージです)

/* Bootstrap */
h2  { 
  font-size: 20px;
  margin: 20px 0;
 }

/* アプリ汎用スタイルを上書き */
.page-A,
.page-B,
.page-C,
.page-D {
    #main {
        h2 { 
          padding-bottom: 10px;
          border-bottom: 1px solid #eee;
        }
    }
}

/* 特定のページの一部を上書き */
.page-A {
    .team-member {
        h2 { 
          margin-top: 30px;
          padding-bottom: 0 !important;
          border: none !important;
        }
    }
}

/* 特定のコンポーネント用に上書き */
.modal {
    h2 {
      margin: 0 !important;
      padding-bottom: 20px !important;
    }
}

スコープが広い Bootstrap のスタイルを、全体用のスタイルで上書き、さらにそれらをページごとのスタイル・コンポーネントのスタイルで上書きしているため、 !important や冗長な指定が山盛りになっていました。

Bootstrap 2.3.2 を app.css, page.css, component.css の順で上書きしている図

新しくスタイルを追加するにはこれら既存のスタイルに打ち勝つ必要があり、さらに混沌を極めます。 こうなってしまうと容易に手が出せる状態ではありません。

これらの根本的な負債解消のために、デザイナー主導で CSS 改善プロジェクトを立ち上げて対応することにしました。

まずは相手を知る

嘆いていてもなにも始まらないので、まずは現存するファイル・スタイルの用途や影響範囲を調べていきます。

現状のディレクトリごとにスプレッドシートを作成し、既存の各ファイルがどこでどのように使われているか大まかに記入します。

各CSSファイルごとに何が書かれていて、どのファイル(テンプレート)で使われているかを記入しているスプレッドシート

各CSSファイルごとに何が書かれていて、どのファイル(テンプレート)で使われているかを記入しているスプレッドシート

調査の過程で過去の担当者からの叫び(FIXMEコメント)が多数発掘され、使命感が高まります。

FIXMEコメントのキャプチャ「アプリケーション全体的に使うメインのコンテンツを内包するコンポーネント/FIXME: 作りが非常に悪いので main というクラスとともに早急に見直すこと。/FIXME: header下のスタイルはコンポーネントとして切り出せるはずなので、うまく切り出したい。」

FIXMEコメントのキャプチャ「FIXME: 本来であれば各一覧でのアクション等の見た目は一貫性をもたせるべきだが、取引先だけ古いままなので特別に専用のコンポーネントとなっている」

FIXMEコメントのキャプチャ「各文書の明細のコンポーネント/FIXME: 各スタイルで table等を使っているため詳細度を上げて優先的にスタイルが当たるようにするためにエレメントを直で指定していたりするが、好ましくないので、全体的に見直し修正すること」

FLOCSS 化

改変後の CSS 設計手法は、FLOCSS を採用しました。 後発の手法で導入事例も多く、日本語のドキュメントもあり、今後のチーム開発でルールや作法の共有がスムーズに行えると判断したためです。

(FLOCSS の具体的な設計手法の解説は公式ドキュメントやそれ以外にたくさん記事があるため、ここでは省略します)

github.com

作業に入る前に CSS 改善担当者間で FLOCSS 提唱者である谷 拓樹さんの「柴犬でもわかるFLOCSS」を読み合わせて認識の統一をしたのち、以下の手順で進めました。

booth.pm

STEP1. FLOCSS ルールに沿ってディレクトリ分類

先のファイルごと用途調査を元に、既存のファイルを FLOCSS のルールに沿ったディレクトリに分類していきます。1つのファイルで分類がまたがるスタイルが混在するものもありましたが、ここでは細かな点は一旦無視しています。

この段階ではまだ微妙なバランスの上に成り立っているスタイルが多いため、ファイルの移動により読み込み順が変わって表示崩れが起こらないか、慎重に確認しながら少しづつ移動しました。

なお、1ファイルで用途が多岐に渡る巨大な汎用ファイルについては保留にして触らずに置いておきます。

STEP2. FLOCSS ルールに沿った命名変更とスタイルの整理

大まかな分類が終わったら、各ファイルごとに記述されているスタイルがどこでどのように使われているかをスプレッドシートに書き出し、新しい命名や分類を検討しました。

新しい命名・分類では以下の点に配慮しています。

  • HTML の構造に依存しすぎない
  • スコープが絞り込まれていない状態で要素セレクタを使用しない(foundation は除く)
  • BEM (MindBEMding) を使用し、名前から影響範囲や役割が想像できるようにする
  • 今後の HTML 構造の変更や機能の追加に耐えられるよう、詳細度をなるべく低く抑える

たとえば以下のような変更です。

/* before */
body.team  {
    .member-list {
        ul { ... }
    }
}

/* after */
.p-team-member__list { ... }

命名変更とあわせて他と共通化できる部分は統合し、重複するもの、似ているけど微妙に異なるもの、不要になっていたスタイルもバッサリと整理・削除しました。

この時、見た目が似ているからといって何も考えずに統合すると後から困る可能性があるため、その要素の性質や今後のデザイン方針を踏まえた変更でなければなりません。 このあたりはデザイナーが直接担当していることで、シームレスに判断しながら作業を進められました。

ユーティリティスタイルの併用

変更前のスタイルは要素セレクタが多用されるなどでスコープが広いスタイルが多く、整理の際にこちらを立てるとあちらが立たずといった場面がとても多くありました。

このような谷を埋めるためにマージンやフォントサイズ、色や配置指定のためのユーティリティスタイルを用意しました。
わずかな差はこのユーティリティスタイルで吸収しながら、コツコツ整理していきます。

ユーティリティーディレクトリのファイル一覧のキャプチャ、clearfix, margin, cursor, flex, float, display, text など用のファイルが並んでいる

自前の CSS コンポーネントへの置き換え

CSS 改善と並行して、ボタンやタブ、フォーム・ページングなどを Bootstrap のものから、自前のコンポーネントスタイルに置き換えるプロジェクトも動いていました。

Bootstrapのコンポーネントと自前のデザインコンポーネント一覧 ビフォーアフター

この作業によって、アプリで使用されていた Bootstrap の CSS コンポーネントはすべて自前のスタイルに置き換えられました。 こちらの取り組みについて、詳しくは以下の記事にあります。

tech.misoca.jp

Bootstrap 撤廃

FLOCSS 化と自前のコンポーネントへの置き換えが終わった後、Bootstrap 用の CSS はほとんど用済みになっていました。 不要なものは削除し、どうしても必要なものは FLOCSS 分類したディレクトリに移し変えてすべての関連ファイルを削除します。

なお、JS 部分は別途フロントエンドチームが全て削除してくれています!

tech.misoca.jp

CSS 改善を支える仕組み

CSS 改善プロジェクトは非エンジニア2名によるプロジェクトだったため、リソース不足や技術的な壁にぶつかる懸念もありましたが、実際のところほとんど支障なく進行出来ました。

主な理由は以下の3点です。

高速・高品質コードレビュー

CSS のレビューはなかなか手をつけづらく滞りがちなものですが、Misoca ではレビュー待ち数を増やさないよう所属プロジェクトを問わず協力し合ってレビューし合う体制があるため、CSS 改善の PR も例外なくスムーズにレビューが通っていました。 この際、単純な見た目の違いはもちろん特別な操作を行った時にだけ表示される部分や、他の箇所との整合性までしっかり見てもらえます。

レビューや巻き戻しをしやすくするために PR を小さめに分けていた都合で後続の作業に影響が出やすい状況でしたが、全く困ることがありませんでした。

遊軍チームのサポート

デザイナーがリファクタリングを担当する事で、リファクタリングに伴うデザイン変更の細かな判断や今後の変更を前提とした設計がスムーズになる一方、動的な UI の変更や複雑な spec 修正が絡む変更はどうしてもやりきれない部分が出てきます。

こんな時、気軽に声をかけられるのがこぼれタスクを専門に扱う「遊軍」チームです。
「テスト通らない助けて〜」「やります!」と、気負わず相談できる環境にはとても助けられました。

tech.misoca.jp

最後の砦 ビジュアルリグレッションテスト

影響範囲の広いスタイルの移動や削除・命名変更では思わぬ差分が出てしまうことがあります。 リリース前にこれらの差分をとらえてくれるのが、ビジュアルリグレッションテストです。 変更前後のスクリーンショットを比較して、前後で差分が出ていないか検証してくれます

tech.misoca.jp

アプリ全体で微妙なズレまで拾ってくれるので、きちんと意図通りに変更されているかをしっかり確かめてから安全にリリースができました。

ビジュアルリグレッションテスト、reg-suit のキャプチャ。表示差分が赤く表示されている。

ビジュアルリグレッションテスト、reg suit のキャプチャ。前後のスクリーンショットを並べて、表示が変わっていることが判断できる。

Bootstrap 撤廃 & FLOCSS 化 を終えて

FLOCSS化を終えたディレクトリのツリー。余計なファイルやディレクトリがなくなっている。

よかったこと

  • !important 地獄からの脱却
  • 設計・命名ルールが定まり、どこにどう書くかを判断する基準が出来た
  • 適用範囲が明確になり、変更や削除をあまり気を使わずに出来るようになった
  • component の再利用性が高まって、新しくスタイルを書く量が減った
  • HTML 側に書かれた class 名からスタイルがどのファイルに書かれているかすぐにわかり、grep して探さなくて良くなった
  • 令和になっても Boostrap 2.3.2 を使っている負い目から解放された

気になること

  • まだ判断に迷う部分がある
    • project に置くか、component に置くか
    • Modifer として扱うか、 .is-xxx のような補助的な名前にするか
  • BEM の Block 粒度のばらつき(特に project 内)
    • 大きいものだとページ(Rails の Controller)単位だけど、コレジャナイ感
  • BEM で命名が長大になってしまう場合の対処
    • Block の中で Element が入れ子になる場合、みんなどうしているんだろう…?

今後やってみたいこと

  • 現在部分的に導入している Scoped CSS を利用した Vue コンポーネント化範囲の拡張


まだまだ改善の余地はあると感じますが、ひとまず各スタイルが HTML の構造や他のスタイルと疎結合になり、今後新たな方針で進めるにしても舵を切りやすくなったと思います。

約1年をかけてコツコツ進めてきた CSS 改善がやっと形になって、感慨もひとしおです。(膨大すぎる作業を支えてくれたパートナースタッフの @riszw に感謝!)

宣伝

Misoca ではつらくない CSS 環境で開発を進めたいエンジニア・デザイナーを募集しています。

www.wantedly.com


  1. 正確に言うと 2系が出たのは 2012年1月なので、ローンチ初期の段階は適宜アップデートしていて、ある時期に固定されたものと思われます。(追記)Misoca創業者の証言によるとローンチ時は1系で、1〜2年後に2系にアップデートされたとのことです。

Misocaサービスの機能利用率見える化をしました

こんにちは。弥生Misocaチームでマーケティングを担当しているnezurikaです。

今回は、Misocaサービス各機能の利用率見える化をしたお話をしたいと思います。

プロジェクトの立ち上げ

この取り組みは「顧客分析をしたい」という一言から始まりました。

Misocaでは、Redashを利用してサービスに関する様々な数値をダッシュボードで見れるようにしています。

そのダッシュボードでは、新規登録者数の推移や、MAUの推移、総ユーザー数など「過去+現在」の数字が見れるようになっていました。
もちろんこれらの数字からも改善のヒントを得ることはできていたのですが、「いま」明確にどんなユーザーがMisocaに価値を感じてくれているのか分からない、などの課題を解決することはできませんでした。
そこから、最終的にMisocaの優良顧客が何に価値を感じているかを可視化することをゴールに顧客分析プロジェクトがはじまりました。

ただ、ゴールは決めたものの「現状知らない・決まっていない」ことが多かったため、このスコープではいま利用してくれているMisocaユーザーの各機能の利用率を可視化することになりました。

Misocaサービスを知る

「Misocaのユーザーは何に価値を感じてくれているのか?」を調べることになりましたが、今回のプロジェクトメンバーは社内でも社歴の浅いメンバーだったので、そもそもMisoca自体がどんな価値を提供したくて立ち上がったサービスなのかをきちんと把握できていませんでした。

そのため、まずはMisocaの歴史を知ろう、と思い、創業者が残していたMisoca開発ストーリーを読み解いて、当初のターゲット・提供したいと考えていた価値をまとめました。
そして、それらと比較して今はどんな価値を提供できているのか、ということもまとめました。

f:id:nezurika:20200728170318p:plain

これにより、Misocaが今までどんなサービスで、どのように変化して今はどんな価値を提供しようとしているのかがわかりやすくなりました。

Misocaの場合は

  • 作成
  • 発送(発行)
  • 管理
  • 取引先

というカテゴリができていることがわかったので、それぞれのカテゴリで、Misocaでユーザーに提供できている機能を洗い出しました。

一例

f:id:nezurika:20200728170439p:plain

機能を定義する

「請求書の作成」や「請求書の複製」という機能を洗い出したものの、このワードだけでは人によって解釈が異なってしまう恐れがありました。

また、この機能が使われている、と判断するには一体どんな動作をしたら「使った」と言えるのかも定義しておかないと実際の計測ができないため、さらにここから「どうしたら」使ったと言えるのかもすべて書き出しました。

一例

f:id:nezurika:20200728170503p:plain

Misocaの機能は、「取引先の登録」のように、何度も使う可能性のある機能と、「自社情報の登録」のように一度設定したらそのあとはめったに変更することのない機能があります。

それらの機能についてもそれぞれ記載しました。

機能ごとの利用ユーザー数をだす

どうやって計測するか決める

機能を洗い出す前に、機能の利用率をどうやって測るかということも決めていました。

前提として、今回は「現在のユーザーが何の機能に価値を感じているかを知る」ために行います。
それを踏まえて、利用率を出して実際どのように使うかを考えました。

  • 過去(指定した期間)の数字や、今の数字を知りたいときに調べる・見る
  • それを元に、未来(施策実施後)どのような数字になるかの目安がわかるようになる
  • 施策後に数値に変化がでたのか確認できるようになる

という3つがあがりました。

そこからもっと具体的な利用イメージを考えて、「◯月〜◯月の間にログインしたユーザーのうち、〇〇の機能を利用したユーザーの割合」というものを想定することができたので、

  • 集計期間を絞る
  • その期間のうちに機能を利用したユニークユーザー数をだす

という2点を集計で出せるようにしました。

利用率の前に、どれぐらいのユーザーがその機能を利用しているか知る必要があったので、各機能の利用者数と、分母とするアクティブユーザー数(今回の場合は一度でもログインしたユーザーを指しています)をRedash(SQL)とGoogle Analyticsでだしました。

基本的にはSQLでの結果を見ていくつもりではいましたが、計測したい数字すべてを出せるわけではなく、「これはGAで取ったほうが楽なのでは?」「SQLでは取れないけどGAでは取れる」という数字もあったため、両方の数字を見ることにしました。

ただ、SQLとGAでは若干数字に誤差がでる懸念がありました。
そのため、

  • 分母と分子はそれぞれ同じ条件(SQLならSQL、GAならGA)で計測したものにする
  • GAとSQLの「数字」同士での比較はしない

という決まり事をつくりました。

数字の抽出をする

SQLは、エンジニアにチェックや助言をもらいながらもデザイナーがガンガン書いていました。すごい。

GAは、スプレッドシートにGoogle Analyticsのアドオンを追加し、レポートを作成してそのあとは日付を変えたら自動で取得するようなものを作りました。

最終的にはRedashで出した数字もスプレッドシートにまとめるようにし、一覧で利用率がわかるようにしました。

一覧の一部

f:id:nezurika:20200728171404p:plain

もちろん自分たちが知りたい、というところからはじめたプロジェクトですが、自分たち以外の人も簡単に使えるようにならないと今後の業務に活かせられないので、簡単で分かりやすいものができるようにする点は意識しました。

利用率の見える化ができた

最終的には、このプロジェクトで作ったものを社内のメンバーに共有をして一旦は一区切りです。

最後の利用率の一覧もですが、プロジェクトの最初に作ったMisocaの価値についての表や、機能の定義なども共有をしました。

このプロジェクトの当初の目的には入ってはいませんでしたが、改めて「機能」を定義しまとめることができたり、過去提供していたものから、数年が経ちどのように今は変化しているかを把握できたこともこのプロジェクトで良かった点だと思っています。

今後

ダッシュボードなどの数字見える化プロジェクトは、出しただけではなく運用にのせることが一番大変だと思っています。

また、今回はあくまでも定量データに関する取り組みを行いました。

ユーザーに価値を与えられているか、機能がちゃんと使われているかというのは定量データだけではなく定性データとも組み合わせることでようやく把握できるものだと思っているので、今後Misocaでは定性データへの取り組みもすすめていく予定です。

最後に

Misocaではわたしたちと一緒に顧客分析もすすめてくれるデザイナーを募集しています。

松江オフィスの思い出

こんにちは、弥生の日高です。

スタンディングデスクにしたら体調が良くなった気がしなくもないです。

松江オフィスを閉鎖しました

2020年6月末をもって松江オフィス (島根県松江市) を閉鎖しました。

閉鎖に至った理由は、世界的にリモートワークが浸透する昨今の状況と、それ以前から約半数以上のメンバーが自宅等でフルリモートワークをしていた社としての状況も踏まえ、オフィスとして拠点を構えるあり方を再検討したことによるものです。

今回は、そんな松江オフィスの歴史を振り返りつつ、みんなの思い出を綴っていきたいと思います。

歴史

松江オフィスは、2016年10月に株式会社Misoca の島根県松江市の開発拠点として立ち上げました。

今でこそ、たくさんのメンバーがフルリモートワークをしていますが、当時は島根県松江市の私だけでした。その縁もあって、2016年6月ごろに松江市様の支援のもと島根合宿を行いました。

合宿でお世話になった旅館です。

f:id:hidakatsuya:20160622174502j:plain

旅館の眼前にはこんな綺麗な海が広がっていました。

f:id:hidakatsuya:20160623124639j:plain

そして、この合宿をきっかけに、2016年10月に松江オフィスを立ち上げました。入社してちょうど1年後のことでしたが、このスピード感に驚いたことを覚えています。

立ち上げ当初のオフィスはこんな感じでした。何もない...このソファが私の作業場でした。

f:id:hidakatsuya:20161107151105j:plain

地元松江で開催される RubyWorld Conference に合わせてミートアップなんかもやりました。

tech.misoca.jp

その後、採用活動などを通して徐々に仲間が増え、オフィスも充実していきます。

最初の写真と見比べると同じオフィスとは思えないですね。実際、とても快適なオフィスでした。この辺りはこまたつがガンガン整備してくれたおかげです。

f:id:hidakatsuya:20190213150116j:plain

f:id:hidakatsuya:20190213105537j:plain

こまたつがボードゲーム好きということもあり、メンバーでボードゲームで遊んだのも良い思い出です。

f:id:hidakatsuya:20200716164918j:plain

Android エンジニアのこまたつによる Android ハンズオンも開催しました。

misoca.doorkeeper.jp

f:id:hidakatsuya:20200716171847j:plain

そして、2020年6月19日に松江オフィスを撤去。最後は段ボールの上に zoom 端末を置いて朝会に参加しました。

f:id:hidakatsuya:20200716170202j:plain

ビル入り口の Misoca の案内標識で記念撮影。

f:id:hidakatsuya:20200717102244j:plain

その後 2020年6月26日にオフィスの引き渡しが完了し、約4年の松江オフィスの幕を閉じました。

思い出

続いて、他のメンバーのそれぞれの思い出を綴ってもらいます。

こまたつ

実家の近くにオフィスあるじゃん!と思ったのがMisocaに興味を持ったきっかけなので感慨深いですね〜。 今でこそ猫も杓子もリモートワークをしていますが、当時はリモートワークに対応している企業は少なく不安があったのですが「最悪オフィスいけばいいか」と思えたおかげで踏ん切りがつきました。

初めてオフィスに来たとき、ドアをあけたらすぐに執務スペースでめちゃくちゃビックリしたのを覚えています(受付があるんだろうな...と思っていた) そんなオフィスを日高さんたちと一緒に快適な空間へ改善していくのもひとつの楽しみだったなあ〜と感じます。

オフィスに入り浸っていたわけではないですが、天候不良でなかなかたどり着けない同僚がいたり、電気が使い放題になったり、ポストが全然あけられなかったり、集まってボードゲームをしたり楽しい思い出がたくさんあります。

閉鎖は残念ですが人がいなくなるわけではないので、これからはより広い地域のよりたくさんの同僚と一緒に楽しくがんばっていこうと思います。

はらだ

入社してから5回ぐらいしかオフィスに出社しなかったので思い入れがそんなに無いのですが、オフィスビルの裏にある「たかの屋」のランチは美味しかったのでオススメです。

田上

私は現在フリーランスで活動しており、独立して初めての業務委託元がMisocaでした。最終面接をおこなったのも松江オフィスを利用してのリモート面談で、その後もボードゲーム会を開催するなど、楽しい思い出が残っています。

最後に

松江オフィスは閉鎖しましたが、メンバーはリモートワークという形で引き続き松江近隣で活動していきます。今後も、地域のイベントや勉強会等でお会いする機会もあると思います。また、私たち自身も引き続き勉強会等を開催していければと思っています。その際はどうぞよろしくお願いします!

最後に、松江オフィスの立ち上げをサポートしてくださった皆様、立ち上げのお祝いを下さった皆様、松江センタービルの他の企業の皆様、オフィスに遊びに来ていただいた皆様、松江オフィスに関わった全ての皆様にこの場を借りて感謝申し上げます。

また、これまで松江オフィスを一緒に支え盛り上げてくれた松江メンバーと Misoca のメンバー、そしてオフィス運営を支えてくれた弊社にも、立ち上げメンバーの一人としてこの場を借りてお礼を言いたいと思います。

皆様本当にありがとうございました。また、これからも弥生と Misoca と松江メンバーを引き続きよろしくお願いします。