Edited at

filterしたListは別物として定義してみたらどうか

Listをfilterする機会は多々あると思います。

業務でコードを書いたときに何回か以下のようなコードを書いた/見たことがあってなかなか悩みました。

たとえばこんなコード。

class トマト提供Service {

@Autowired
private 冷蔵庫Repository 冷蔵庫Repository;

public List<トマト> 取り出す() {
return 冷蔵庫Repository.getトマト().stream
.filter(v -> v.is新鮮())
.collect(Collectors.toList());
}

この時、返却されるトマト型は新鮮かどうかを表現していないので、このServiceを使う側は新鮮であることを信用して使うことになります。

このままでは調理工程が後半になるにつれ、「このトマトは本当に新鮮なんだろうか、腐ってないだろうか」と心配になってきてしまいます。もう一回新鮮かどうかチェックしてしまうかもしれません。

なので、新鮮であることをクラスで表現してみます。

class トマト提供Service {

@Autowired
private 冷蔵庫Repository 冷蔵庫Repository;

public List<新鮮なトマト> 取り出す() {
return 冷蔵庫Repository.getトマト().stream
.filter(v -> v.is新鮮())
.map(v -> new 新鮮なトマト(v)
.collect(Collectors.toList());
}

class 新鮮なトマト {
private トマト トマト;
}

クラス名に新鮮であることが明記されているので安心して調理を進められます。

ただ、このままでは名前を変えただけなのでもうちょっと工夫してみます。

class トマト提供Service {

@Autowired
private 冷蔵庫Repository 冷蔵庫Repository;

public List<新鮮なトマト> 取り出す() {
return 新鮮なトマト.create(冷蔵庫Repository.getトマト());
}
}

class 新鮮なトマト {
private トマト トマト;

public List<新鮮なトマト> create(List<トマト> トマト){
return トマト.stream
.filter(v -> v.is新鮮())
.map(v -> new 新鮮なトマト(v)
.collect(Collectors.toList();
}
}

どうやって新鮮なトマトを選んだかは新鮮なトマトクラスを見るだけでよくなりました。

元のリストにfilter処理を施したとき、別クラスのリストで返した方が後工程で不安にならないので安心です。