List of Whatever Cases

NameExample
flat casesamplenamingconvention
pascal case / capital camel caseSampleNamingConvention
camel casesampleNamingConvention
kebab case / chain case / spinal case / lisp case / caterpillar casesample-naming-convention
train caseSample-Naming-Convention
snake casesample_naming_convention
screaming snake case / macro caseSAMPLE_NAMING_CONVENTION

References

なんちゃらケース系の用語が多すぎるからまとめてみました。以上

Read More

「Kotlin Fest 2018」参加レポート

Kotlinは趣味でちょろっとしか書いていませんが、Kotlinの哲学である実用主義・簡潔・安全・相互運用性に魅了され、理想と現実のバランスをうまくとっているなと感心しましたので、Kotlin Fest 2018へ参加してきました。とても楽しかったし、勉強にもなった為、レポートとしてまとめたいと思いました。

Kotlinもう一歩

最初に参加したセッションはヤフーの森さんによる「Kotlinもう一歩」でした。Kotlinのタイプシステムを用いてGenericsとType Projectionを紹介していました。プレゼンの内容をよくまとめたのは下記の一枚です。

タイプシステムの観点で不変・共変・反変を説明してくれてとても印象的だと感じました。タイプシステムを一言で説明すれば、「タイプAが期待される全ての箇所で、タイプBが使用可能であれば、タイプBはサブタイプだと言える。逆に、タイプAはスーパータイプである。」になります。この一言さえ分かれば、「タイプAは自分自身のサブタイプであり、スーパータイプでもある」ということは理解できるでしょう(ちなみに、これはisSubtypeOfisSupertypeOfで検証できる)。また、「StringString?のサブタイプ」というのもわかるはずです。

How to Test Server-side Kotlin

実例を交えた説明でわかりやすかったです。特に技術選定時に考えたこととハマったポイントの紹介はとても参考になりました。テストコードを書きやすくする為に作られたFactlinkotlin-fill-classは確かに使いやすそうだなと感じました。

全体のイメージとして、Kotlin製のテストライブラリはまだまだ少ないと感じました。ただ、Javaの資産は基本的にそのまま使えるので、それほど困らないです。クラスがFinal、Immutable、Null許容しないなどの特性によってハックしなければいけないケースがあるものの、その場合はOSSで提供されているラッパー(i.e. mockito-kotlin)かプラグイン(i.e. all-open)、もしくはコード上の設定(i.e. @JvmStatic)を使えば大体回避できます。

Kotlin Linter

KotlinのLinterについて、一番主流のktlintしか知りませんでした。実際にktlint以外、detekt(detectの意味?w)とアンドロイド用のandroid-lintが存在します。その比較は下記のスライドにてまとめられています。

ktlintと比べてdetektは標準ルールがたくさんありますし、個別の設定ができるし、メッセージ表示も詳しいです。さらに、detekt-formattingを使えばktlintのルールすらサポートできてしまいます(formattingと言いつつも、自動フォーマットと無関係)。整形できないのは状況によって痛いかもしれませんが、選択肢として考えられますね。
また、ktlintのカスタムルールの作成方法は以下のようになります。

Read More

Vuex Plugin 101

Vue.js Tokyo v-meetup #7」にて発表させて頂きました。
スライドはこちらです。

発表したこと

  • Vuexのプラグインは簡単に作れますよ。
  • VuexのプラグインはよくsubscribeというストアインスタンスのAPIを使ってます。
  • ただし、subscribeのコールバックはmutate後呼ばれますので、もっと早い段階で処理を加えたければ、2.5.0から導入されたAPI(subscribeAction)を使いましょう。
  • Vuexのプラグインを探したければ、awesome-vueリポジトリはいいところです。

尺の関係で話せなかったこと(スライドに入れました)

  • 名前通りあくまでsubscribeなんで、いわゆるAOPのような使い方は期待しないでください。
  • vuex-shared-mutationsというタブ間の状態を同期してくれる素晴らしいVuexプラグインがあるが、実は考え方はとてもシンプルです。
  • 他にも色んな有用なプラグインがありますよ。

Read More

ある条件を満たすDOM要素を抽出するコード

週末にデモプログラムを作成する時、ある要素の中から、指定された条件を満たすDOM要素を抽出する機能が必要だった為、下記のようなコードを作りました。

1
2
3
4
5
const selectAll = el => condition => [el,
...Array.from(el.children)
.map(child => selectAll(child)(condition))
.reduce((arr, i) => arr.concat(i), [])
].filter(condition)

考え方

実は、主な作業は2つだけです。

  1. 全ての要素を羅列します。
  2. 条件に満たしている要素をフィルターリングで抽出します。

コードを書けばこうなります。(allElements=全ての要素、condition=条件)

1
const selectAll = (allElements, condition) => allElements.filter(condition)

関数の再利用を考えたら、コンポジション)を採用した方がいいでしょう。

1
const selectAll = allElements => condition => allElements.filter(condition)

1つ目の作業はどう実現するかは問題です。DOMはツリー構造なので、親要素の元に要素があり、その要素の中に、さらに子要素が存在する。ツリー構造のケースに対処する場合、再帰を使用することは一般的です。関数型風に書きたかったので、Array.prototye.mapとスプレッド構文を利用することにしました。DOM要素のchildrenはHTMLCollection型で、map関数が備えていません。よって、まずArray.from()で配列に変換する必要があります。

Read More

2017年Product Huntで紹介されたプロダクト12選

Product Huntより公開された電子ブック「The Best Product Launches of 2017」を読み終えました。全体的に人工知能系と仮想通貨系(特に下半期)のモノが多かったと感じています。ここで、個人的に気になった12つのプロダクトを紹介したいと思います。(読む前にすでに使用している・知っているプロダクトは含まれていません。)

12. The Startup Way

Cover of The Startup Way

ひとことコメント:ベストセーラー「The Lean Startup」の作者の新作です。

11. Product Frameworks

Product Frameworks introduces Basecamp Product Cycles

ひとことコメント:(プログラミングではなく)プロダクト開発でよく使われているフレームワークをまとめてくれたサイトです。

10. Intercom on Starting up

Intercom on Starting up

ひとことコメント:Intercomから出したスタートアップに関する書籍で、GoodReadsで4.2の高評価をマークしています。

Read More

オブジェクトにあるプロパティが存在するかをチェックする

手法

JSのオブジェクトを扱う際に、あるプロパティが存在するかをチェックする作業はしばしば発生します。実は、この一見簡単そうな作業を実施する為に、いくつかのやり方が存在します。考え方で分けて見れば、以下の2種類になるかと思います。

該当プロパティの値をチェックする

よく見かける手法はundefined !== obj[prop]もしくはundefined !== obj.propでしょう(obj = オブジェクト、prop = プロパティ)。まずオブジェクトからプロパティを出して値をみます。もしオブジェクトに該当プロパティが存在しなければ、値はundefinedになりますので、この特性を利用する手法ですね。
この手法の異種として、void(0) !== obj[prop]があります。void演算子が分かればすぐ理解できるでしょう。void(0)の戻り値がundefinedになるからですね。
また、'undefined' !== typeof obj[prop]という書き方もあります。値の型を取得し、undefined型であるかを判別する考えです。
更に、もっとお洒落な書き方も存在します。!!obj[prop]です。下記のように書くことが可能になります。

1
if(!!obj.prop) return 'OK';

エクスクラメーションマークを2つ先頭に追加することで、結果の反転を二回行います。「False→True→False」みたいに、元の結果に戻すやり方ですね。

undefined !== obj[prop]がもっと直感的なのに、なぜわざわざvoid(0) !== obj[prop]'undefined' !== typeof obj[prop]を使うか、疑問を感じたので、ベンチマックを行ってみました。実は後二者の効率は前者の3倍程になります。なるほど〜
あともう一つ気を付けなければいけないのは元々プロパティの値はundefinedになっているケースです。上記の手法を使ってしまったら、該当プロパティが存在していても、falseが出てしまいます。
特に!!obj[prop]を使用する時、もっと注意を払わなければなりません。0nullの反転結果はtrueになるから、該当プロパティに入る値の型を100%把握していなければ、使用するのをやめておいた方が安全でしょう。

該当プロパティの存在を確認する

抽出を行わず、直接チェックする方法もあります。inもしくはhasOwnPropertyの使用です。

1
2
3
4
5
// in
if(prop in obj) return 'OK';

// Object.prototype.hasOwnProperty
if(obj.hasOwnProperty(prop)) return 'OK';

Read More

OptionalのorElseとorElseGet

最近OptionalのorElseorElseGetの区別は社内でちょっと話題になっていました。これらは同じように見えますが、使い方に気をつけなければハマってしまうかもしれません。まあ、まずJavaDocをみてみましょう。

定義

オラクルのドキュメントの中にorElseの定義は下記のように書かれています。

public T orElse(T other)
存在する場合は値を返し、それ以外の場合はotherを返します。

パラメータ:
other - 存在する値がない場合に返される値、nullも可

戻り値:
値(存在する場合)、それ以外の場合はother

一方、orElseGetこんな感じです。

public T orElseGet(Supplier<? extends T> other)
値が存在する場合はその値を返し、そうでない場合はotherを呼び出し、その呼び出しの結果を返します。

パラメータ:
other - Supplier(値が存在しない場合は、これの結果が返される)

戻り値:
値(存在する場合)、それ以外の場合はother.get()の結果

例外:
NullPointerException - 値が存在せずotherがnullの場合

やはり説明も似ていますね。でも、nullについての説明は違います。前者の説明の中に、nullも可が入っていますが、後者にはそれがなく、逆にNullPointerExceptionという例外の説明が入っています。すなわち、Optional.ofNullable(null).orElse(null)はnullを返してくれますが、Optional.ofNullable(null).orElseGet(null)は例外をスローしてしまいます。
それはそうでしょう。引数は確実に違うからですね。orElseの引数は値で、orElseGetはSupplierというラムダ式を取っています。Supplierのgetメソッドに通じて値を取得するので、Supplier自体がnullになってしまったら、NullPointerExceptionがスローされてもおかしくありません。

遅延実行

でしたら、下記のコードの実施結果は同じように思えますよね。

1
2
3
4
5
6
7
8
9
10
11
public class MyTest1 {
private final static Supplier<String> test = () -> {
final String result = "test";
System.out.print(result);
return result;
};

public static void main(String[] args) {
System.out.print(Optional.of("test").orElseGet(test));
}
}

Read More