共通関数継承のデメリットを説明せよ
共通関数継承とは、あるクラスで共通的に使うだろう関数やメンバを、親クラスのメソッドやメンバとして定義するパターンだ。Constant interfaceパターンやimport staticあたりが関係するアンチパターンとされるモノの一つで、神様ルートクラスを嫌い、POJOを好むのあたりの、ごく初歩な議論になるだろうと思う。
package spike; public abstract class SuperUtil { /** * 時刻形式の文字列から、日付部分を抜き出す */ protected String timestamp2Date(String timestamp) { if (validTimestamp(timestamp)) return timestamp.substring(0, 10); return ""; } /** * 時刻形式の文字列から、時間部分を抜き出す */ protected String timestamp2Time(String timestamp) { if (validTimestamp(timestamp)) return timestamp.substring(11, 8); return ""; } /** * 時刻形式の文字列かチェックする */ protected boolean validTimestamp(String str) { // ... return true; } }
package spike; public interface CommonMsg { public static final String ERROR_MSG_01 = "時刻形式が正しくありません"; }
package spike; public class SubClass extends SuperUtil implements CommonMsg { private String timestamp; public void setTimestamp(String timestamp) { if (validTimestamp(timestamp)) this.timestamp = timestamp; throw new RuntimeException(ERROR_MSG_01); } public String getDate() { return timestamp2Date(timestamp); } public String getTime() { return timestamp2Time(timestamp); } }
これは、とりあえず下のようにすべきだろう。とりあえず、だよ。
package spike; public class SuperUtil { /** * 時刻形式の文字列から、日付部分を抜き出す */ public static String timestamp2Date(String timestamp) { if (validTimestamp(timestamp)) return timestamp.substring(0, 10); return ""; } /** * 時刻形式の文字列から、時間部分を抜き出す */ public static String timestamp2Time(String timestamp) { if (validTimestamp(timestamp)) return timestamp.substring(11, 8); return ""; } /** * 時刻形式の文字列かチェックする */ public static boolean validTimestamp(String str) { // ... return true; } }
package spike; public class CommonMsg { public static String ERROR_MSG_01 = "時刻形式が正しくありません"; }
package spike; import static spike.CommonMsg.*; import static spike.SuperUtil.*; public class SubClass { private String timestamp; public void setTimestamp(String timestamp) { if (validTimestamp(timestamp)) this.timestamp = timestamp; throw new RuntimeException(ERROR_MSG_01); } public String getDate() { return timestamp2Date(timestamp); } public String getTime() { return timestamp2Time(timestamp); } }
さて。これを隣の同僚にどう説明したらいいものか悩み、先のエントリのアンチパターンからは外してみた。
リスコフの置換原則が破られる、試験性が落ちる、必要性がないなど、いろいろな理由は付けられるわけだけど、他のアンチパターンに見られるようなインパクトが見いだせないんだよなぁ。「どっちでもいいことにこだわりやがって」という印象を残さないくらい、強烈に説得したいんだが…。
ということで分けてみたよ、という言い訳エントリでした。