ES2015 で空のオブジェクトを返すアロー関数を書いてハマる

普通に考えれば当たり前なんですが、最初なにが起きてるのか分からなくてハマりました...。

const func = () => {}
func() // => undefined

ようするに {} がオブジェクトのリテラルではなく、関数のブロックとして認識されているようです。で、return 文がないため undefined が返されます。

なので、これならOKです。

const func = () => { return {} }
func() // => {}

もしくはこう。

const func = () => new Object()
func() // => {}

あまり需要はないかもしれないですが。

その他

どうやら ES6 より ES2015 が推奨っぽいので、今日から ES2015 と呼ぶことにしよう。

追記 (2018/01/11)

括弧で囲めば式として扱われる模様。

const func = () => ({})
func() // => {}

2017年のふりかえりと2018年のこと

賀正。

2017年の行動指針 - kntmr-blog

2017年の初めにこんなエントリを書いていたので、これのふりかえりと2018年のことでも書いてみようかと。

『基本的に毎日勉強することが目標。』

これはさすがに無理でしたね。全然だめでした。圧倒的にだめでした。就寝前に勉強しようと思ってもついつい YouTube とか観ちゃうんですよね。まぁ、それがストレス発散になってるところもあるんですけど。

『平日の通勤時間を利用して英語を勉強する。』

一時期、mikan という英単語アプリで勉強してたんですが、1ヶ月程度しか続けられず...。2018年はもっとちゃんと頑張りたい。

Oracle Certified Java Programmer, Gold SE 8 認定資格』

取得しました。2017年はコードレビューする機会が多かったんですが、資格勉強の成果か、以前よりコードを読む力が向上したように感じます。たぶん。

Oracle Certified Java Programmer, Gold SE 8 認定資格 - kntmr-blog

JavaScript フレームワーク

2017年末頃から Vue.js を実案件で使っています。Vue + Vuex + axios の組み合わせ。最近は avoriaz を頑張っています。ついでに ES6 も学べていいですね。ところで ES6 と ES2015 はどっちで呼べばいいの。


というわけで、基本的に何か目標がないとだめだめマンみたいなので、今年は英語勉強の目標として TOEIC で600点あたりを目指してみようかな。あと、どこかで Java 9 と Spring 5 は腰を据えて学ばなければ。現場からは以上です。

Avoriaz で filters や methods の中身を差し替える

前回の続編。用途があるか不明ですが、こんな感じでできそうという話。

kntmr.hatenablog.com

filters を差し替える

例えば、こういうコンポーネントがあって、期待する値が出力されるかテストするパターン。ここでは、グローバルフィルターが設定されているものとする。

<template>
  <div>
    <span>{{ username | toUpper }}</span>
  </div>
</template>

<script>
export default {
  name: 'AvoriazTest',
  props: [ 'username' ]
}
</script>

この場合は、単純に Vue.filters で差し替える。というか、普通にテストを実行するとグローバルフィルターは参照不可のようで、何かしらのスタブは用意する必要がある模様...。ちなみにフィルター自体のテストは別途する前提。

import Vue from 'vue'
import { shallow } from 'avoriaz'
import AvoriazTest from '@/components/AvoriazTest'

Vue.filter('toUpper', (v) => 'TEST') // あらかじめフィルターにスタブをセットしておいて

describe('AvoriazTest.vue', () => {
  it('should render correct contents', () => {
    const wrapper = shallow(AvoriazTest, { propsData: { username: 'abc' } })
    expect(wrapper.find('span')[0].text()).to.equal('TEST') // 期待値が出力されることを確認する
  })
})
methods のメソッドを差し替える

例えば、レンダリング時に data で値を返す前に methods に食わせるパターン。

<template>
  <div>
    <span>{{ changedText }}</span>
  </div>
</template>

<script>
export default {
  name: 'AvoriazTest',
  props: [ 'username' ],
  data () {
    return {
      changedText: this.toUpper(this.username)
    }
  },
  methods: {
    toUpper (v) {
      return v.toUpperCase()
    }
  }
}
</script>

最初、前回のような wrapper.setMethods({ 'toUpper': stub }) でできるかと思ったんですが、これでは差し替えられず...。おそらくレンダリング時にはすでに data の内容が計算済みのためと思われる。

というわけで、今回は shallow または mount でラッパーオブジェクトを生成する際に propsData と同じように methods を指定してスタブを差し替える。

import { shallow } from 'avoriaz'
import AvoriazTest from '@/components/AvoriazTest'

describe('AvoriazTest.vue', () => {
  it('should render correct contents', () => {
    const stub = (v) => 'TEST' // スタブを用意して
    const wrapper = shallow(AvoriazTest, { propsData: { username: 'abc' }, methods: { toUpper: stub } }) // ここで差し替える
    expect(wrapper.find('span')[0].text()).to.equal('TEST')
  })
})

冒頭に書いた通り、これらの用途があるのか分かりませんが、いろいろいじくりまわしていると勉強になりますね。

Avoriaz と Sinon.JS で methods のメソッドが呼ばれたことをテストする

このあたりを調べたときのメモ。

  • avoriaz@6.3.0
  • sinon@4.0.0

例えば、こういうコンポーネントがあって、ボタンクリック時のイベントハンドラmethods のメソッドにバインドしているものとする。

<template>
  <div>
    <button @click="onClick">Submit</button>
  </div>
</template>

<script>
export default {
  name: 'AvoriazTest',
  methods: {
    onClick () {
      // ...
    }
  }
}
</script>

で、以下の方法でボタンクリックでメソッドが呼ばれたことをテストする。

import { shallow } from 'avoriaz'
import sinon from 'sinon'
import AvoriazTest from '@/components/AvoriazTest'

describe('AvoriazTest.vue', () => {
  it('calls methods when the button clicked', () => {
    const wrapper = shallow(AvoriazTest)

    const stub = sinon.stub() // スタブを作って
    wrapper.setMethods({ 'onClick': stub }) // setMethods で差し替えて

    wrapper.find('button')[0].trigger('click')
    expect(stub.calledOnce).to.equal(true) // 呼ばれたことを確認する
  })
})
その他

using with vuex · Avoriaz

Vuex の mapActionsmapGetters を使っていて、それらのメソッドが呼ばれたことをテストする方法は Avoriaz の公式ドキュメントに書いてあります。参考になり過ぎる。

コンポーネントの props で required を付けるときは default を定義した方がよさそう

小ネタですみませんが、Vue.js #4 Advent Calendar 2017 の15日目が空いてたので書きます。最近、Vue.js を実案件で使い始めました。Vue.js 歴は浅いです。

タイトルの通りなんですが、誤りや本来はこうあるべきというのがあればご指摘いただけますと幸いです。


Vue.js のスタイルガイドの「プロパティの定義」というセクションに「プロパティの定義はできる限り詳細とするべきです。」と書かれています。

プロパティの定義 - Vue.js

というわけで、

props: [ 'count' ]

と書いていたところをスタイルガイドの例に倣って次のように変更してみました。

props: {
  count: {
    type: Number,
    required: true
  }
}

が、コンソールに警告が出るようになりました。

[Vue warn]: Invalid prop: type check failed for prop "count". Expected Number, got Undefined.

で、このメッセージでググってみたら、この issue を発見。

github.com

この issue 自体は単純な定義ミスが原因のようなんですが、なんとなく 初期値をセットした方がよさそう なのかなと思い付きました。というわけで、次のように default を定義してみたところ、先述の警告は出なくなりました。

props: {
  count: {
    type: Number,
    required: true,
    default: 0 // これを追加
  }
}
補足

ちなみに、required を外すと default が未定義でも先述の警告は出ないようです。

なんとなく、requireddefault は一緒に定義するものなのかな?と思ったんですが、ドキュメントを探しても特にこれといったものは見つからず...。もしくは、コンポーネントの呼び出し方が原因なんだろうか。

このあたりは仕組みをきちんと理解しないとだめですね...。中途半端ですみませんが、現場からは以上です。

Spring Fest 2017 に行ってきた #jsug

簡単に所感をまとめます。

springfest2017.springframework.jp

What's New in Spring

会場に到着したらすでに翻訳機がなくなってたのでスライドから雰囲気だけ感じ取る。内容は Spring 5 と Spring Boot 2.0 について。Spring MVC ではこう書いていたコードが Spring WebFlux ではこう書くよというデモ。spring-boot-starter-webflux を依存に入れるだけでランタイムが Tomcat から Netty に変わる。あとは、Spring WebClient の話。Spring WebClient Scatter Gather ってなんだろうか。要復習。

Introduction to Spring WebFlux

www.slideshare.net

こちらも Spring WebFlux の話。100程度のリクエストを10スレッドくらいで処理できる。プロセッサーの数だけスレッドを立ち上げるらしい。Spring MVC のコードでランタイムを Netty に変えるだけで Reactive の恩恵を受けられるっぽい。flatMap は裏で subscribe してくれるが、map は subscribe してくれないので注意が必要。WebFlux を使うときは Blocking な処理を書かないこと。どうしても Blocking な処理が必要なら別スレッドで処理させる。RDBを使うシステムの場合、JDBCが Blocking なので別のスレッドで処理させるか、非同期JDBCのサポートを待つのがよい。

ところで、Blocking/Non-blocking はスレッドを占有するかしないか、同期/非同期は別スレッドで処理させるかどうか、と理解したんですが合ってるんだろうか...。

Spring Security 5 解剖速報

www.slideshare.net

Spring Security 5 では、WebFlux と OAuth 2.0 が対応される。従来の Spring Security は Servlet API に依存しているが、WebFlux では Servlet API に依存しない。ただし、Servlet API 依存のアーキテクチャがなくなるわけではない。Spring WebTestClient を使うと WebFlux のエンドポイントをテストできる。これまでは各サブプロジェクトが OAuth2 対応していたが、今後は Spring Security が OAuth2 をサポートし、サブプロジェクトは Spring Security の機能を使う。

Struts -> Spring 移植のテクニックとノウハウを公開

struts-config.xml や validation.xml から Controller のスケルトンコードや Form クラス/バリデーションを自動生成する。移植元のアプリで独自に拡張されたものは手で移植する。フレームワークの移植では不具合修正やリファクタリングに手を出さないことがポイント。

自分もフレームワーク移植をやりましたが、バリデーションロジックとかの移植は割と大変でした。自動化については移植元のアプリの作りにかなり影響されると思うし、きれいに作られているとは限らないので結局は手作業が多くなるんではないかと思っています。

また、フレームワークの移植では再現性を重視するようですが、重視し過ぎるのもどうなのかなと思っています。再現性を重視するあまりオリジナルのフレームワークの機能拡張に追随できなくなったりしないだろうか、移植先のフレームワークのお作法に従う方がいいのではないかと考えてしまうわけです。まぁ、コストはかかるし、そううまくはいかないかもだけど。

Pivotal認定講師が教える!Spring Data JPAによるデータアクセス徹底入門

www.slideshare.net

JPA の特徴やハマりどころの話。めっちゃ分かり易かった。要復習。

Spring と TDD

www.slideshare.net

Spring にはテストの仕組みがたくさん用意されているよという話。いろいろなパターンのテストの仕方が説明されていてよかったが、TDD はあまり関係なかった。ちょうど テスト駆動開発 を読んでるところだったので少し残念。

Spring BootとSpring Cloudで始めるマイクロサービス

前半はマイクロサービスの話、後半は Spring Boot と Spring Cloud の話。せろさんのマイクロサービスの話は何回か聴いたことはあるが、分かり易いし納得感がある。

その他

あとで読む。

JJUG CCC 2017 Fall に行ってきた #jjug_ccc

簡単に所感をまとめます。セッション資料はどこかで公開されるはず。

www.java-users.jp

Selenide or Geb? あなたはそのときどちらを使う?

  • Selenide
    • Java製WebDriverラッパー
    • DSLによるjQueryライクなセレクタ
    • IDEの補完を活用できる
    • Ajaxなどの非同期処理に対する記述が書きやすい
  • Geb

    • じぇぶ
    • Groovy製WebDriverラッパー
    • DSLによるjQueryライクなセレクタ
    • waitが書きやすい
  • Selenideのメリ/デメ

  • Gepのメリ/デメ

    • Selenideより細かい制御ができる
    • Groovy/Gradleの知識が必要
    • IDEの補完は効きづらい
  • ローカルでは動くのにJenkins上では落ちることがある

    • おそらく環境依存などが原因 (jsのロードが遅れるなど)
    • Selenideは失敗して落ちるとスクリーンショットとHTMLが残る
  • マルチブラウザテスト

    • GebConfig上でWebDriverの生成処理を変更することで対応
    • Selenideも設定ファイルでWebDriverの生成処理を変更することができる
  • PhantomJSやChromeのヘッドレスモードを使ってテストする

    • E2Eのテストなので実際は本物のブラウザでテストするべきという考えがある
  • 読むのを楽にしたいか/書くのを楽にしたいか

    • 書きやすさならSelenide
    • 読みやすさならGeb
  • SelenideはIDEのサポートがあるので取っ付きやすい
  • Gebは学習コストがやや高め
  • Selenideはテスティングフレームワーク (簡単なアサーションはある)
  • GebはSpockなどと組み合わせる

最近、Selenide を試してみたところだったので話が聴けてよかったです。両方ともIDEのサポートはあるものの、Intellij IDEA との親和性が高そう。書くのをラクにしたいか、読むのをラクにしたいかで選べばよい、とのこと。確かに、Selenide は書きやすそうな印象。非同期処理に対する記述のところは調べておきたい。

Apache Camel + hawtio + Spring Boot によるモダンなインテグレーション・マイクロサービス

  • インテグレーションマイクロサービス
  • Smart Endpoints and Dump Pipes

    • マイクロサービス自体に他のサービスと連携する機能を持たせる
    • ルーティングロジックがエンドポイント(各マイクロサービス)の中にある
    • パイプはシンプルにする
  • マイクロサービス間が連携したらスパゲッティにならないか

    • そのために Enterprise Service Bus がある
  • コンウェイの法則

    • サービスと開発チームが小さくなる
    • インテグレーションはスパゲッティになるが、個々の開発チームはシンプルになる
  • Apache Camel

  • ルーティングはXMLでも書ける (Spring XML DSL)

    • IDEGUIを使う場合はXMLを使う必要あり
  • Content-Based Router

    • コンテンツの内容に応じてルーティング先を決める
    • choice / when / to
  • hawtio

    • Angular 1.x + Jolokia ベースの監視ツール
    • HTTP/JSONで通信
    • Spring Boot 連携 (監視用のポートで起動する)
    • Camelサポートが豊富
      • ルーティングがグラフィカルに見れる
      • やり取りしているメッセージが見れる
  • Camelのテストフレームワークでルーティングのテストができる

  • コンポーネントが多いので選定などは大変っぽい

マイクロサービスの開発自体あまりなく名前程度しか知らなかったんですが、Apache Camel はよさそうです。機会があれば使ってみたい。hawtio は初めて聞いた。

DDD × CQRS - コマンドとクエリでORMを使い分けた話

  • CQRS
    • コマンドクエリ責務分離
    • 単独でも適用可能
    • イベントソーシングと組み合わせる必要はない
  • 書き込みと読み込みのモデルを分離する

  • 従来は単一のデータストアで同じモデルが読み書きを担う

    • 1モデルの処理が複雑になる
  • そもそも読み込みと書き込みの要件は異なる

    • パフォーマンスを求められるのは参照系
  • 1モデルに詰めるとどこかで無理がでてくる

  • モデルを読み書きで分離する

  • データストアを分離する

    • 参照系は read-only なレプリカにするなど
  • イベントソーシング

    • すべてのアクションをイベントとして記録する
    • 既存のデータはupdateしない
    • Writeモデルはイベントとして記録される
    • Readモデルはイベントから変形される
  • 読み込み書き込みそれぞれの要件に合わせてORMを選定する
  • JOOQ
    • SQLに近い記述でタイプセーフにSQLが書ける
  • Writeモデルの制約はコンストラクタと公開メソッドで実現する

CQRS についてはよく分かってないマンですが、読み込みと書き込みでモデルを分けるというのは参考になりました。特に要件に合わせてORMも分けるというのは思い付かなかった...。

劇的改善 CI4時間から5分へ〜私がやった10のこと〜

  • R-SET
  • CIは10分で終わらせるのがいい (遅くとも20分以内が望ましい)

  • レイヤごとにテストの責務を閉じる

    • RepositoryとRDBはまとめてテスト
  • Controllerのテストは @WebMvcTest にする
    • @SpringBootTest はすべてのBeanを登録してアプリケーションを起動するので遅い
  • ServiceレイヤのテストではDIは使わない
    • Springの機能は使わない (RepositoryはMock化する)
  • RepositoryはFilterでBeanを選択する
    • @MyBatis or @MyBatisTest で必要なBeanのみを登録する
    • MyBatisに限らず必要なBeanをフィルタリングするのは大事
  • テストサイズ導入, テストサイズによる実行タイミングの分割
    • Googleが提唱している
    • Small, Medium, Large
    • 実行タイミングはプルリクエストやブランチのマージなど
    • LargeテストはいわゆるE2Eテスト
    • JUnit@Category, maven-surefire-plugin の groups で実現する
    • mvn の Profile で実行するテストサイズを切り替える

たぶん、無駄なテストを改善する/除去するというのが最も効果ありそう。テストサイズについては初めて知りました。あとで調べてみよう。

Java SE 9の紹介: モジュール・システムを中心に

Java SE 9の紹介: モジュール・システムを中心に

  • Maven, Gradle を使っても複数バージョン混在地獄は解決できない

    • jarファイルの名前しか見ないため (中身までは見ない)
  • モジュールシステム

    • モジュール単位で依存関係を整理する
    • 内部パッケージの使用を制限する
  • 複数のモジュールで同一パッケージが含まれる場合、JVM起動時点で検知される
  • module-info.java

    • 外部に公開するパッケージは exports 命令で指定する
    • 自分が使うモジュールは requires 命令で指定する
    • requires したモジュールの exports されたパッケージの public なクラスが使える
    • それ以外を使うとコンパイルエラー/実行時例外
  • 標準ライブラリである java.base モジュールは暗黙的に requires される

  • モジュールシステムはリフレクションにも適用される

    • opens 命令で外部からリフレクションでアクセスできるようになる
    • モジュール宣言に open を修飾するとすべてのパッケージが opens 指定される
  • モジュールパスとクラスパスは別

  • 無名モジュール/自動モジュール

  • ライブラリ提供者はすぐにモジュール化すること

    • 使う側が requires 命令を書けない
  • Properties クラスは Latin-1 のまま

この日、最も聴きたかったセッション。モジュールシステムの概要が分かってよかった。要復習。なんとなく、ちゃんと作ってるライブラリであれば、モジュール化はそこまで難しくなさそうな印象。

その他

今年春のCCCは参加できなかったのですが、参加人数が多くてかなり混雑してた模様。今回は、前回より参加人数が少なかったのか、それほど混雑は感じられませんでした。というか、通路が一方通行になってたりいろいろ工夫されてたのがよかったのかも。移動がいつもよりずっとラクでした。