TDDはあんまり使わなくなったけど心の中にある

今日は娘たちとコログ探しして楽しかった。

f:id:bufferings:20170910220749j:plain

この数年間、頭の中にTDDを入れた状態で開発をしてきたんだけど。タイトルに書いた風に思う。

良い所がいっぱいある

見失わずに済む

僕にとってTDDの良さは、まず、自分が何をしようとしているかを見失わずに済むところ。一歩先にゴールを立てて、そこに向かって一歩進む、たどり着いたら、次の一歩を進める。その繰り返し。だから、遠く離れたゴールに対して、急いで走って、途中で道に迷ってどこに向かってるか分かんなくなったりしないで済む。

余計なものを作らなくて済む

「必要なものはこれだよね?」という確認から入って、それを実現するための実装に集中するから余計なものを作らなくて済む。実装を先に作ると「こういう機能もあるといいかもだから入れとこうかな」ってついつい入れてしまう。

リファクタリングできる

まず最初に動くものを作ってから、その状態をキープしたまま、実装の改善をすることができる。

最初のクライアントになれる

テストを先に書くことで、その実装がどのように使われるかを、クライアント目線で考えることができる。

「考えたとおりに動いている」と言える

テストを通っているので開発者が「自分が考えたとおりに動いている」と自信を持って言える。「開発『は』終わりました!」って言わなくて済む。

とかとか。

でもあんまり使わなくなった

こんなに良いところがいっぱいあるのに、どうしてあんまり使わなくなったんだっけ?

もう少し大きな単位で考えるようになった

TDDで進めるときは、クラス単位とかメソッド単位で考えてしまうんだけど、複数のクラスを組み合わせた、もう少し大きめの「機能」の単位で最近は考えるようになったかなぁと思う。その単位でもテストを先に考えたりはするけど、それはRed->Green->Refactoringのリズムというよりは、最終的にこれが全部通ってたら大丈夫だね。というようなものなので、ちょっとTDDとは違うかなと思う。

実装をがらっと変えたりする

チームのスキルに合わせて、まずは手続き型でもいいから機能が動く状態に持って行く。その後、その機能が動く状態をキープしながら、中の実装をオブジェクト指向に変えていく。というようなことをちょくちょくやっている。そういうときには、クラスレベルのユニットテストはかえって邪魔になってしまうので、そういうのは手でやったら良くて。どうせ後で使わないし。リファクタリングするときには機能レベルのテストがあれば良いなーと。

あぁ、そうか。僕は最近は機能レベルのテストを使って、ちょっと大きめのサイクルを回すようになったのかもな。

心の中にある?

あんまり使わなくなったとはいっても、TDDの良さについては常に心の中にある。というのは、例えばちょっと要らないものを自分が作ろうとしていることに気づいた時には「それってどういうケースで必要になるんだっけ?」ってテストを頭の中で考えてみて「うむ。要らん。」って言ってみたり、何かに悩み始めたときには「まず一歩進めようかな」って言ってタスクを小さく切り分けて一歩ずつ進めようとしてみたりしてる。のだ。TDDのエッセンスが心の中にあって。そのループは頭の中で回しながら、手を動かすときは、もう少し大きな範囲でループを回してる。という感じ。

だから、TDDはあんまり使わなくなったけど、自分の心の中に染みこんでるなぁ、って思うのでした。

おまけ

僕には「こういうときにはTDDを使う」ってのがある。それは、メンバーに考え方を伝えるとき。「全部を相手にせずに、まずはこのテストを通そう。OKだね、じゃ次にいこう。こういう場合はどうなるのが正しい挙動かな?」とかで、自分の考える順番を伝えたい人がいるときは、TDD使う。「あぁ。今は綺麗にしなくていいよ。まずは動くコードを作ろう。」って。

今日はもう寝ようかな。おやすみなさい。

Maven Centralで公開するときの自分メモ

もりすさんのところにだいたい全部書いてあります。ありがとうございます。

tagomoris.hatenablog.com

全体の流れ

もりすさんも書いてるように、ここに流れが書いてある。

http://central.sonatype.org/pages/ossrh-guide.html

Maven Centralに上げるための要件

http://central.sonatype.org/pages/requirements.html

色々と情報をpomに書いておく必要がある。

デプロイのためのpomの設定

http://central.sonatype.org/pages/apache-maven.html

GPG署名用のプラグインとか色々。

できあがったpom

最低限のものになってるかなと思う。

https://github.com/bufferings/thymeleaf-extras-nl2br/blob/master/pom.xml

Thymeleaf extras nl2br 1.0.1 is released

There's no feature changes, but improved the source code. (Thank you Kazuki Shimizu (@kazuki43zoo) | Twitter !)

You can use it by Maven.

<dependency>
  <groupId>com.github.bufferings</groupId>
  <artifactId>thymeleaf-extras-nl2br</artifactId>
  <version>1.0.1</version>
</dependency>

Reference post (for 1.0.0 release)

bufferings.hatenablog.com

Thymeleaf extras nl2br is released

You can use nl2br:text="${sample}" attribute, which firstly escapes the HTML special characters in the input text, then inserts <br /> tags before newlines.

github.com

Background

I wanted to show a multiple lines input with <br /> tag for the newlines. There’re several ways to realize it: using th:utext after converting newlines to <br />, or having lines as list then using th:block with th:each. But I don’t want to allow other html tags, nor to write th:block with th:each many times. Finally, I decided to create it.

Usage

Maven

<dependency>
  <groupId>com.github.bufferings</groupId>
  <artifactId>thymeleaf-extras-nl2br</artifactId>
  <version>1.0.0</version>
</dependency>

Code

templateEngine.addDialect(new Nl2brDialect());

or if your application is Spring Boot application, you can add the dialect like this:

@Bean
public Nl2brDialect dialect() {
  return new Nl2brDialect();
}

Template

Then you can use nl2br:text attribute like this:

<p nl2br:text="${sample}">Hello!</p>

If you want to stop your IDE’s warning, you can add xmlns attribute like this:

<html lang="en" xmlns="http://www.w3.org/1999/html"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:nl2br="https://github.com/bufferings/thymeleaf-extras-nl2br">

Example Project

github.com

f:id:bufferings:20170826164931p:plain

hope this serves someone :)

どう共通化する?しない?

コードを書いてると「これ、同じようなコードあるから共通化した方がいいな」ということがよくある。

共通化する?

(僕はJava好きなのでJavaを思い浮かべながら書くけど)親クラスにくくりだしたり、ユーティリティクラスをつくったり。

そうすることで、ロジックをひとつの場所にまとめることができて、仕様が変わったときにはそこだけ修正すれば大丈夫。平和。

コードレビューで気づくのも伝えるのもそんなに難しくないし、伝えられた側も「確かに」って対応しやすい。

 

どう共通化する?

ちょっと難しいなと思うのは「同じような処理だけど意味が違う」場合。

例えば、消費税計算で価格の8%を計算して返す処理と、8%の割引をするときに計算して返す処理とは、同じ「8%を計算する」という処理だけど、どう共通化するかはちょっと考えたい。

消費税が10%になったときに、割引も10%にはなって欲しくない(あ、いや、買う方としてはそうなってくれたら嬉しいけど!)。

その場合は「8%を計算する」という処理は共通化することができるけど、「消費税を計算する」と「割引を計算する」は共通化しないってことなんだろう(実際は、僕は「8%を計算する」という処理自体、共通化しないだろうな)。

これをコードレビューで見つけるためには、処理自体だけじゃなくて、意味を考える必要があるし、伝えるときにも意味のディスカッションをすることになる。

共通化しない?

んで、難しいなと思うのは、処理だけじゃなくて意味も同じようなものなんだけど、レイヤーやコンテキストが違う場合。

例えば、DBのデータモデルと、ドメインモデルと、ビューモデルで、同じようなモデルを持ってるんだけど、それを全部共通化して1つのモデルで表現しようとすると、どっかのレイヤーの変更が別のレイヤーにまで影響してしまう。

コンテキストって点だと、複数のアプリで「このロジックは意味が同じだから共通化しよう!」って安易に共通化すると、そのロジックが変更されるときに両方のアプリをリリースしなきゃいけなくなってしまったり。

別のチームに分かれてる場合は分かり易いけど、同じチームで両方見てる場合には、レビューでも伝えるのむずいかなぁ。

 

ここでちからつきた。おはよー。(*´∀`*)ノ

共通化の方法には

  • 同じコードベースで共通化
  • ライブラリとしてくくりだす(別プロジェクトに切り出す)
  • ライブラリとしてくくりだす(mavenリポジトリとかにおく)
  • サービスとしてくくりだす

とかあるね。今日もがんばるー!

 

てことでValidationの実装を書いてみた

今日の昼にValidationについて考えて、「こんな感じだといいかなー?」ってテストだけ書いたんだけど。

bufferings.hatenablog.com

それの実装を書いた。とりあえずテストだけパスするような感じであります! T がいっぱいでてきて泣きながら書いた。

ソースはGithubに置いてる

https://github.com/bufferings/validation/tree/a671531fb0c1fed081da2289f31cc91eff60955c

メインはこのクラス

課題

  • all メソッドで @SuppressWarnings("unchecked") してる。型パラメータつきのクラスの可変長引数がだめっぽい。どうしたらいいんだろう?
  • notNull メソッドとかで渡してるSupplierの省略ができるようにデフォルトのSupplierを作りたい。けどどうやって?コンストラクターで渡すのかな?
  • throwIfInvalid メソッドの Collector<T, A, String> messageGenerator で失敗結果リストを元に例外メッセージを作るのもデフォルトが指定できたらいいな。

テスト

今はこうなってる。色々省略できるといいんだけどな。

こんな感じのValidationどうかなぁ?「この方が好き」ってあったら知りたいです!

バリデーションについてぼーっと考えてて、この辺見ながら「なるほどわからん!」ってなりながら

面白そうなので、自分だったらこんな感じでValidationできるの欲しいかも?ってのを書いてみた。実装はまだない。

なんか「こういう方がいいと思うよー」ってあったら知りたいです!書きながら、型パラメータみたいなのが必要そうだなぁって思った。

github.com

実装したらちょくちょく更新していこうかな。