Vue.js
Vuex

DXを高めるためのVueコンポーネント設計


DX

今日はDXとVueの話をします。

https://yourmystar.connpass.com/event/116354/ の発表資料です。



Developer Experience

開発者は開発・運用という行為を通じたそのシステムのユーザー

DX: Developer Experience (開発体験)とは、あるシステムを「気持ちよく開発・保守できるかどうか」を示すもの


  • DXがよい


    • 日々の開発・運用を楽しめるようになる(モチベーションの向上)

    • コードの品質があがり保守時のデグレも減らせる

    • DXがよい事自体がDXを高める動機になる



  • DXが悪い


    • 開発を楽しめない

    • 本質的でない作業に時間を取られる

    • もしくは本質的な作業に時間をかけられない





DXが高い例


  • シンプルで可読性の高いコード

  • 快適な開発環境

  • 平穏に稼働する本番環境

  • 余裕のあるリリーススケジュール

  • 心理的安全性が確保されている



Developer Experience

エンジニアがプロダクト機能の開発以外(の傍から見るとどうでもよさそうなこと)で悩んでいる

≒DXを良くするために悩んでいる



DXは放置すると悪化する


  • DXがよくも悪くもない→時間が経つに連れDXが悪くなる

  • 積極的にDXを良くするための活動を奨励していきましょう



Vue.js


  • つよい

  • DXの観点からみると罠が多い


    • プロジェクトのディレクトリ構成

    • 混沌としたエコシステム

    • コンポーネント設計・分割





Vue.js - 今日は話しません


  • プロジェクトのディレクトリ構成

  • 混沌としたエコシステム

nuxtjs.png



Vue.js - 今日話します


  • コンポーネント設計・分割



Vue.js - コンポーネント設計・分割

難しい

開発者はそれぞれ何らかの思想をもってコンポーネントをデザインしているはず


  • 言語化されていない

  • チームにおける共通認識になっていない

  • レビューの度に宗教戦争が発生してつらい



つよい技術を使っているのにDXが悪化している!!



どうすればいい?


  • 人類はオブジェクト指向プログラミングの頃から似たような問題に悩まされてきた

  • そしていくつかの回答を獲得した

  • Vueの世界でも使えそう



2つの原則


  • 単一責任原則 (Single Responsibility Principle)

  • 開放/閉鎖原則 (Open-Close Principle)



単一責任原則


The single responsibility principle is a computer programming principle that states that every module, class, or function should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class.


Wikipediaより

単一責任原則とは、「すべてのモジュール・クラス・関数はソフトウェアが提供する機能性の単一の部分だけに責任を持ち、それを完全に隠蔽するように実装すべき」ということを述べたプログラミング原則である。



開放/閉鎖原則


開放/閉鎖原則とは、オブジェクト指向プログラミングにおいて、クラス(およびその他のプログラム単位)は

- 拡張に対して開いて (open) いなければならず、

- 修正に対して閉じて (closed) いなければならない

という設計上の原則である。


Wikipediaより

Vueの世界においては

- 変更するときに他のコンポーネントを修正しなくていい

- 変更しても他のコンポーネントに影響しない

ようなインタフェースを持つようにすべき、ということ。



よくある例

例) ユーザがログイン状態のときはユーザのプロフィール画像、ユーザがログイン状態でないときはログインボタンを表示するコンポーネントを作りたい。


component.vue

<template>

<div class="profile-circle">
  <img v-if="authenticated" :src="profileImage" />
<button v-else @click.native="signIn">ログイン</button>
</div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
props: {
profileImage: String
},
computed: mapGetters('user', { isAuthenticated: 'isAuthenticated'}),
methods: {
signIn: function() {
/* ログイン処理... */
}
}
}
</script>

<style>
img { /* 画像に対するスタイル */}

button { /* ログインボタンに対するスタイル */ }
</style>




「ログイン機能を修正したいんだけど」


  • 「修正するコンポーネントここであってる?」

  • 「なんでこのログイン機能のコンポーネント、プロフィール画像を受け取るんだっけ?」

  • 「このコンポーネント修正すると副作用ない?」


    • 単一責任原則・開放/閉鎖原則が守られていない(かもしれない)ことからくる疑心暗鬼

    • 大丈夫かどうか自信が持てない

    • レビュワーもどこまで見たら安全か分からない



  • どんなテストをすれば安心できるのか


    • ちゃんと調べてリグレッションテストしないと




  • DXが...!




なぜVueで単一責任原則・開放/閉鎖原則が守りにくいのか


  • コンポーネントの責務が自由に定義できちゃう


    • template, script, styleどこに主眼を置く?

    • 単一ファイルコンポーネント故の罠



  • Vuexが話をややこしくしている


    • 言ってみればただのグローバル変数

    • 状態をローカルステートに持つべきか、Vuexにしまうべきかの判断



  • Vueコンポーネントのインタフェースがわかりにくい


    • props

    • emit

    • slot

    • Vue storeとつながっている場合はstoreのactionも!





単一責任原則・開放/閉鎖原則を守るために


  • Don't Repeat Yourselfを正しく理解する


    • コードは重複してもいい

    • 同じ「知識」を2箇所以上に書いてはいけない

    • 「変更に強い」vs「凝集度が高い」



  • 昨今は捨てやすいコードのほうが喜ばれます


    • 共通機能を作ると、その再利用度が高ければ高いほどインタフェースが複雑になります

    • あらぬ複雑な依存を呼び、捨てにくくなります

    • 単一ファイルコンポーネントのメリットを損ねないようにしましょう





大事なこと


  • コードを書く人


    • 自分がどんな変更を予想しているのか聞かれたら答えられる状態にしておく

    • その予想した変更に対して強いコードを書く

    • 実際に発生する変更から学び、予測の精度をあげる



  • コードをレビューする人


    • コードを書いた人がどんな変更を予想しているのかよく考える

    • 「なんとなく治安が悪い」を設計の用語を使って言語化する



  • 偉い人もしくは強い人


    • 今後起こりそうな変更をなるべくはやくチームに共有

    • 情報やナレッジの共有もDXを向上しますよ!





まとめ


  • DXは大事だよ

  • Vueはつよいけど罠が多いよ

  • 設計原則は大事だよ



おわり