システム開発で思うところ

Javaで主にシステム開発をしながら思うところをツラツラを綴る。主に自分向けのメモ。EE関連の情報が少なく自分自身がそういう情報があったら良いなぁということで他の人の参考になれば幸い

JSFのSelectItemを拡張したEnumで実装する

前回、Enumを拡張しました
vermeer.hatenablog.jp

これを使ってJSFのSelectItemを実装します。

ちなみに、Enumだけでも十分対応は出来るようです。
【メモ】JSFでenumのオブジェクトをselectOneMenuに使う方法 - mike-neckのブログ
JSFのConverterで見た闇の話 - mike-neckのブログ

固定値であればEnumが良いですが、例えば何かしらの一覧をリストから選択したい場合、コード値とプロパティのペアを動的に設定したいことは良くあります。
今回、Enumに加えてMapも同様に扱うようにしました。

中途半端ではありますが、ResourceBundleも扱ってみました。*1*2

propertyはmessage.propertiesで設定にして表示文字を外部に持たせてます。
Map側はRDBに保存している値を使用する想定なので国際化対応はしない想定です。*3

以下の実装では、Enum has code and propertyの性別を変更して【更新】ボタンを押下したら、Mapのお菓子リストが更新されます。

実行対象のクラス・インターフェース・メッセージプロパティ

Enum
@AllArgsConstructor @Getter
public enum Gender implements EnumCodePropertyInterface {
    MALE(1, "gender_male"), FEMALE(2, "gender_female");

    private final Integer code;
    private final String property;

}
Interface
public interface EnumCodePropertyInterface {

    public Object getCode();

    public String getProperty();

}
Enum(拡張)のFactory
public class EnumCodeProperty {

    public static <E extends Enum<E> & EnumCodePropertyInterface> E codeOf(Class<E> enumType, @NonNull Object code) {
	for (E type : enumType.getEnumConstants()) {
	    if (type.getCode().equals(code)) {
		return type;
	    }
	}
	throw new IllegalArgumentException();
    }

    public static <E extends Enum<E> & EnumCodePropertyInterface> E propertyOf(Class<E> enumType, @NonNull String property) {
	for (E type : enumType.getEnumConstants()) {
	    if (type.getProperty().equals(property)) {
		return type;
	    }
	}
	throw new IllegalArgumentException();
    }
}
message.properties
noselect=選択無し
gender_male=男
gender_female=女
JsfのSelectItemのFactory

Enum も Map も同じメソッド名で使えるようにオーバーロードしています。

package com.mycompany.samplejsf.infrastructure.part.jsf;

@RequiredArgsConstructor(staticName = "of") @Value
public class JsfSelectItem {

    private final List<SelectItem> values;

    public static <E extends Enum<E> & EnumCodePropertyInterface> JsfSelectItem of(Class<E> enumClass) {
	List<SelectItem> items = new ArrayList<>();
	ResourceBundle bundle = ResourceBundle.getBundle("message");
	for (E item : enumClass.getEnumConstants()) {
	    String value = bundle.containsKey(item.getProperty())
			   ? bundle.getString(item.getProperty())
			   : item.getProperty();
	    SelectItem selectItem = new SelectItem(item.getCode(), value);
	    items.add(selectItem);
	}
	return JsfSelectItem.of(items);
    }

    public static JsfSelectItem of(Map<?, String> itemMap) {
	List<SelectItem> items = new ArrayList<>();
	itemMap.entrySet().stream()
		.forEachOrdered(map -> {
		    SelectItem item = new SelectItem(map.getKey(), map.getValue());
		    items.add(item);
		});
	return JsfSelectItem.of(items);
    }
}

実行資産

ManagedBean
package com.mycompany.samplejsf.domain.selectitem;

@Named(value = "selectItem")
@SessionScoped
@NoArgsConstructor @Getter
public class SelectItemController implements Serializable {

    private static final long serialVersionUID = 1L;
    @Setter
    private Integer selectItemValueDirectWrite;

    @Setter
    private Integer selectItemValueEnumCodeProperty;

    @Setter
    private Integer selectItemValueMap;

    private JsfSelectItem enumCodeProperty;
    private JsfSelectItem selectItemMap;

    private Map<Integer, String> dummuyMap;

    @PostConstruct
    public void init() {
	this.selectItemValueDirectWrite = GenderEnumOnly.MALE.ordinal();

	this.selectItemValueEnumCodeProperty = Gender.FEMALE.getCode();
	this.enumCodeProperty = JsfSelectItem.of(Gender.class);

	this.replaceSelectItemMap();
	this.printLog("init");
    }

    public void submit() {
	this.replaceSelectItemMap();
	this.printLog("submit");
    }

    private void replaceSelectItemMap() {
	if (this.selectItemValueEnumCodeProperty.equals(Gender.MALE.getCode())) {
	    this.maleSnack();
	    return;
	}
	this.femaleSnack();
    }

    private void maleSnack() {
	Map<Integer, String> map = new LinkedHashMap<>();
	map.put(1, "大福");
	map.put(2, "おはぎ");
	map.put(3, "みたらしだんご");
	map.put(4, "せんべい");
	this.selectItemValueMap = map.keySet().iterator().next();
	this.selectItemMap = JsfSelectItem.of(map);
	this.dummuyMap = map;
    }

    private void femaleSnack() {
	Map<Integer, String> map = new LinkedHashMap<>();
	map.put(5, "チョコ");
	map.put(6, "クッキー");
	map.put(7, "プリン");
	map.put(8, "ゼリー");
	this.selectItemValueMap = map.keySet().iterator().next();
	this.selectItemMap = JsfSelectItem.of(map);
	this.dummuyMap = map;
    }

    private void printLog(String label) {
	System.out.println("label = " + label);
	System.out.println("selectItemValueDirectWrite = " + selectItemValueDirectWrite);
	System.out.println("selectItemValueEnumCodeProperty = " + selectItemValueEnumCodeProperty);
	System.out.println("selectItemValueEnumCodeProperty codeOf = " + EnumCodeProperty.codeOf(Gender.class, selectItemValueEnumCodeProperty));
	System.out.println("selectItemValueMap = " + selectItemValueMap);
	System.out.println("selectItemValueMap value = " + this.dummuyMap.get(this.selectItemValueMap));
    }
}
xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui">
    <head>
        <title>JSF SELECT ITEM</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
    </head>
    <body>
        <form jsfc="h:form" enctype="multipart/form-data">
            <h1>JSF SELECT ITEM PATTERN</h1>
            <dir>
                <h2>Direct Write</h2>
                <select jsfc="h:selectOneMenu" value="#{selectItem.selectItemValueDirectWrite}">
                    <option jsfc="f:selectItem" itemLabel="#{msg['gender_male']}" itemValue="0"></option>
                    <option jsfc="f:selectItem" itemLabel="#{msg['gender_female']}" itemValue="1"></option>
                </select>
            </dir>
            <hr />
            <dir>
                <h2>Enum has code and property </h2>
                <select jsfc="h:selectOneMenu"  value="#{selectItem.selectItemValueEnumCodeProperty}">
                    <option jsfc="f:selectItems" value="#{selectItem.enumCodeProperty.values}"></option>
                </select>
            </dir>
            <hr />
            <dir>
                <h2>Map</h2>
                <select jsfc="h:selectOneMenu"  value="#{selectItem.selectItemValueMap}">
                    <option jsfc="f:selectItems" value="#{selectItem.selectItemMap.values}"></option>
                </select>
            </dir>
            <hr />
            <dir>
                <input type="submit" jsfc="h:commandButton" value="更新" action="#{selectItem.submit()}"/>
            </dir>
        </form>
    </body>
</html>

実行結果

画面

f:id:vermeer-1977:20161219140146p:plain

コンソールログ
label = init
selectItemValueDirectWrite = 0
selectItemValueEnumCodeProperty = 2
selectItemValueEnumCodeProperty codeOf = FEMALE
selectItemValueMap = 5
selectItemValueMap value = チョコ
label = submit
selectItemValueDirectWrite = 0
selectItemValueEnumCodeProperty = 1
selectItemValueEnumCodeProperty codeOf = MALE
selectItemValueMap = 1
selectItemValueMap value = 大福
label = submit
selectItemValueDirectWrite = 0
selectItemValueEnumCodeProperty = 2
selectItemValueEnumCodeProperty codeOf = FEMALE
selectItemValueMap = 5
selectItemValueMap value = チョコ

さいごに

JSFのSelectItemは、今回のクラスで、Enumであれ、Mapであれ統一して処理できます。また、lombokのおかげで 可視化されていませんが of(List values) というメソッドも自動生成されています。
冗長的で使わないように思いますが、ファーストクラスコレクションとして統一した実装が出来るので用途が無いわけではないと思います。

今回はSubmitでMapのリストが変更するようにしました。
でも、リストの更新のためだけにForm全てをリクエストするのは性能面で好ましくないです。
次回はAjaxを使って、性能面にも配慮のある実装をしてみたいと思います。

*1:mike-neckのブログで「あぁ、そうかちゃんとしたいんだったら国際化対応すべきだ」と思い至り、とりあえずでも実装しておこうと思いました。

*2:ResourceBundleは、ちゃんとやろうとすると結構なボリュームになるので今後の課題にしたいと思います

*3:RDBの表現と同じものをmessage.propertiesにすべて準備する?いえいえ、それはそもそも設計から見直した方が良いように思います

EnumにInterfaceを使ってユーティリティを作成する

前回の続き
vermeer.hatenablog.jp

前回のEnumのようにテーブル値と表記がペアとなっているものは
Interfaceを持たせて共通に操作する仕組みを作成しておくと便利です。

Enumクラスにメソッドを追加

package com.mycompany.samples.enumclass;

import lombok.NonNull;

public enum GenderNoLombok {
    MALE(1, "男"),
    FEMALE(2, "女");

    private final int code;
    private final String property;

    private GenderNoLombok(int code, String property) {
	this.code = code;
	this.property = property;
    }

    public int getCode() {
	return code;
    }

    public String getProperty() {
	return property;
    }

    public static GenderNoLombok codeOf(int code) {
	for (GenderNoLombok enumClass : values()) {
	    if (enumClass.getCode() == code) {
		return enumClass;
	    }
	}
	throw new IllegalArgumentException();
    }

    public static GenderNoLombok propertyOf(@NonNull String property) {
	for (GenderNoLombok enumClass : values()) {
	    if (enumClass.getProperty().equals(property)) {
		return enumClass;
	    }
	}
	throw new IllegalArgumentException();
    }
}

シンプルに実装すれば、こんな感じになると思います。
Interfaceもいりません。
これはこれでシンプルで良いと思いますし、嫌いではないです。*1
ただ、すべてのEnumクラスに同じような記述しないといけないので冗長です。

Interfaceとユーティリティを作成

Interface
package com.mycompany.samples.enumclass;

public interface EnumCodePropertyInterface {

    public Object getCode();

    public String getProperty();

}
Enumクラス

共通操作が出来るようにInterfaceをimpliment

package com.mycompany.samples.enumclass;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor @Getter
public enum Gender implements EnumCodePropertyInterface {
    MALE(1, "男"),
    FEMALE(2, "女");

    private final Integer code;
    private final String property;

}

Enumクラス側はlombokのおかげでOverrideの警告も出ません。

ユーティリティ

implimentしたInterfaceに合わせた操作を実装
今回は、code値/property値、それぞれの値から、その値とペアになるEnumクラスを生成するstaticメソッドを作成しました。
また、code値については、テーブル定義に左右されるのでObjectにしています。
もし型安全にするのであれば、想定する型のメソッドを準備してオーバーロードしておけば良いと思います。
propertyは明らかに文字列だけということでString固定にしています。

package com.mycompany.samples.enumclass;

import lombok.NonNull;

public class EnumCodeProperty {

    public static <E extends Enum<E> & EnumCodePropertyInterface> E codeOf(Class<E> enumType, @NonNull Object code) {
	for (E type : enumType.getEnumConstants()) {
	    if (type.getCode().equals(code)) {
		return type;
	    }
	}
	throw new IllegalArgumentException();
    }

    public static <E extends Enum<E> & EnumCodePropertyInterface> E propertyOf(Class<E> enumType, @NonNull String property) {
	for (E type : enumType.getEnumConstants()) {
	    if (type.getProperty().equals(property)) {
		return type;
	    }
	}
	throw new IllegalArgumentException();
    }
}
実行コード
package com.mycompany.samples.enumclass;

import lombok.NoArgsConstructor;

@NoArgsConstructor
public class EnumTest {

    public void execUtil() {
	GenderNoLombok genderNoLombok = GenderNoLombok.codeOf(GenderNoLombok.MALE.getCode());
	System.out.println("genderNoLombok.getCode() = " + genderNoLombok.getCode());
	System.out.println("genderNoLombok.getProperty() = " + genderNoLombok.getProperty());

	genderNoLombok = GenderNoLombok.propertyOf(GenderNoLombok.FEMALE.getProperty());
	System.out.println("genderNoLombok.getCode() = " + genderNoLombok.getCode());
	System.out.println("genderNoLombok.getProperty() = " + genderNoLombok.getProperty());

	Gender gender = EnumCodeProperty.codeOf(Gender.class, Gender.MALE.getCode());
	System.out.println("gender.getCode() = " + gender.getCode());
	System.out.println("gender.getProperty() = " + gender.getProperty());

	gender = EnumCodeProperty.propertyOf(Gender.class, Gender.FEMALE.getProperty());
	System.out.println("gender.getCode() = " + gender.getCode());
	System.out.println("gender.getProperty() = " + gender.getProperty());

    }
}
実行結果
genderNoLombok.getCode() = 1
genderNoLombok.getProperty() = 男
genderNoLombok.getCode() = 2
genderNoLombok.getProperty() = 女
gender.getCode() = 1
gender.getProperty() = 男
gender.getCode() = 2
gender.getProperty() = 女

最後に

Enumが通常のクラスであればInterfaceではなく抽象クラスで今回と同様の操作を実装できるかもしれませんがEnumは継承をさせることが出来ません。
そういった技術的な側面もありますが、Enumは定数定義のためのクラスとして、あまり多くの事をしすぎないというのも、1つの整理なのかなぁと思ったりもします。*2

この「Interface+ユーティリティ」のやり方は、Enumだけでなく、リファクタリングをしているときに個人的によく使っています。
ユーティリティで実装の集約を一旦した上で、主語と述語を整理しユーティリティからクラスに格上げをする、というやり方をしています。ロジックだけを見たら似ている気がしたけど概念で考えると違ったり、ユーティリティで汎用的な実装へリファクタリングをしている中で、同分類とすべきドメインが見つかって更に見直しを深めるということは結構ありました。


次は、このEnumクラスを使って、JSFのSelectItemについて汎用的な部品クラスの作成について整理してみたいと思います。*3

追記:2017/1/2

EnumのInterfaceに共通処理を実装してみました。
vermeer.hatenablog.jp

*1:ちなみに以前は、こういう実装をしていました

*2:実はEnumでもInterfaceのdefault実装で対応をしよう色々としたのですが、うまくいかず、トータルの実装量を鑑みて落としどころをユーティリティしたというのが本当のところです

*3:実際の整理の流れは逆です。SelectItemの部品化をしようと思ったのが先で、その過程でEnumの整理に至りました

Enumはlombokとの組み合わせで振舞いを簡単に実装できる

Enumはとても便利。

とはいっても、そのまま使うことは少ないです。

テーブルの値や、画面におけるセレクトボックスの値などシステムにおける具体的な値と同期をとって使うことが多いように思います*1


今回は、性別をEnumで表現して画面などで使用するコード値と文字列のペアを実装したいと思います。

lombokを使わない

MALE、FEMALEは定数フィールド名です。
codeにはテーブルにおけるコード値、propertyは画面表示に使用する文字列を定義している想定です。

package com.mycompany.samples.enumclass;

public enum GenderNoLombok {
    MALE(1, "男"),
    FEMALE(2, "女");

    private final int code;
    private final String property;

    private GenderNoLombok(int code, String property) {
	this.code = code;
	this.property = property;
    }

    public int getCode() {
	return this.code;
    }

    public String getProperty() {
	return this.property;
    }
}
Enumの使い方

Enumは比較に使うとコードの可読性が良くなりますし、アクセッサで必要な値を取得できます。
Enumの比較は==でもequalsでも、どちらでもできます。

実行ソース

public class Executer {

    public static void main(String args[]) {
	GenderNoLombok gender = GenderNoLombok.FEMALE;
	if (gender == GenderNoLombok.MALE) {
	    System.out.println("gender.getCode() = " + gender.getCode());
	    System.out.println("gender.getProperty() = " + gender.getProperty());
	} else {
	    System.out.println("gender.getCode() = " + gender.getCode());
	    System.out.println("gender.getProperty() = " + gender.getProperty());
	}
    }
}

実行結果

gender.getCode() = 2
gender.getProperty() = 女

lombokを使う

必要な定義とフィールドと実装して
@AllArgsConstructor @Getter をクラス宣言のところに追記するだけです。

package com.mycompany.samples.enumclass;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor @Getter
public enum Gender {
    MALE(1, "男"),
    FEMALE(2, "女");

    private final int code;
    private final String property;
}

lombokを使ったものをdelombokで確認

package com.mycompany.samples.enumclass;

public enum Gender {
    MALE(1, "男"), FEMALE(2, "女");
    private final int code;
    private final String property;

    @java.lang.SuppressWarnings("all")
    @javax.annotation.Generated("lombok")
    private Gender(final int code, final String property) {
        this.code = code;
        this.property = property;
    }

    @java.lang.SuppressWarnings("all")
    @javax.annotation.Generated("lombok")
    public int getCode() {
        return this.code;
    }

    @java.lang.SuppressWarnings("all")
    @javax.annotation.Generated("lombok")
    public String getProperty() {
        return this.property;
    }
}

単純作業が1つ減るだけかもしれませんが、こういった積み重ねが地味に助かります。

次は、今回追加したような振舞いをinterfaceにして
汎用的なユーティリティを作ってみたいと思います。

*1:Yes/Noと言った二択といった単純な組み合わせであっても、No=0/Yes=1、Yes=0/No=1、どちらを良しとするか・・・。小さなことだけど、小さなことだからこそ、私は迷い始めたら手が止まってしまう妙なところがあります。

DDDでリファクタリング後を検討してみる

★この記事は過去の検討内容です

再検討のまとめ 

vermeer.hatenablog.jp

 

以下は過去の検討メモです。

振り返りができるように残します。

 現在、システムのリファクタリング中。

大きなシステムではないですし開発者も利用者も基本的に私一人です。

そんな中で、ああしたら良いかも、こうしたら良いかもと考えながらやっていたわけですが、闇雲にやるのは良くないなと。ということで、自分なりのゴールを一度整理しておいた方が良いだろうと思い、まとめてみました*1

 

なぜDDD?

システムの規模だけを考えたら無理をしてDDDじゃなくても問題はない気がしています。ただ、今後も拡張・メンテナンスをするシステムなのでDDDを取り入れるのが良さそうだと考え至りました。*2

 

どのように検討した?

先人の知恵を参考にしつつ、過去の経験を踏まえて分類・整理しました。

参考にさせていただいた知恵

 

全体図

前提・共通事項

レイヤー

要素

View

Domain

Infrastructure(Service)

Infrastructure(Common)

補足

 

[改訂版] UMLモデリング技能認定試験<入門レベル(L1)>問題集 -UML2.0対応

[改訂版] UMLモデリング技能認定試験<入門レベル(L1)>問題集 -UML2.0対応

 

 

エリック・エヴァンスのドメイン駆動設計

エリック・エヴァンスのドメイン駆動設計

 

 

実践ドメイン駆動設計

実践ドメイン駆動設計

 

 

検討メモ

2016/12/26:Ruleはstaticではなくクラスで(∵DI対象に拡張できるように)

 

2017/8/8:RepositoryはServiceではなくInfrastructure。

基盤=インフラという整理でビジネスに近いということでServiceと考えていたけれど調べてみると、Service(Domain)ではInterfaceを定義しておいて、Infrastructureで実装するということだった。こうしておくことでJPA依存からDomainを守ることが出来るという考え。

逆に基盤=インフラという整理の部分はレイヤーはInfrastructureで良いけれど、Commonとして別パッケージにしておいた方が、個人的にはシックリくるという整理にも至った。

 

 2017/8/10:トランザクションの境界はService

DDDにおいて、なぜ複数の集約にまたがってトランザクションをかけてはいけないのか(multiple aggregates in one transaction) - pospomeのプログラミング日記

(整理資料の更新は未実施)

・データの整合性を保つのが誰の役割なのかに注目する
・それがユーザー自身であれば、トランザクション整合性を保つようにすればいい
・それが別のユーザーであれば、結果整合性を保つようにすればいい 

 

 2017/9/2:

Repositoryは「コト」を経由して Aggregate(集約)のルートを返却すると良い?

つまりRepositoryクラスは「コトを表すEntity」または、概念(クラスが無いケースや外部サービス)で作ると良い?

もし集約ルートクラス単位でRepositoryを作成したらルート配下に何が存在するのか「知っている」ことになる(もしくは「知っていないといけない」)。そしてRepositoryのメソッドが大変多くなってしまう。

この仮説が正しいとしたら、これまで自分が作成していたRepository(というかDAO)の発想から変えたほうが良くなる。個人的には「コトをRepositoryにする」というのは良さそうな気がするので、実装実験をするときには1つの指針としてみよう。

 

2017/9/2:validation は service を経由しない検証ルール(とする)

 

2017/9/2:副作用のある操作には Assertions(表明)パターン「契約による設計」

操作の結果として何が保証されるかという事後条件(post-condition)と、操作の前後で変わらないものは何かという不変項(invariant)とを、明示的に示す。

ということらしい。ということは更新操作をするRepositoryには事後検証を必ずすべきということかな?性能面が心配だけど結果整合性を保証するという意味では正しい。

でも、これまで実装していて、こういう事後検証はしたことが無かったなぁ。やっていないから良いという訳ではなくて、本来はするべきだったんだろうなぁという気づき。

でも「単体テストで保証できる」ともあるから、これは実行時の話ではなくて実装時の話なのかな?んー良く分からない。

 

2017/9/2:Closures of Operations

値オブジェクトにおける計算の結果は同じ型の値オブジェクトの返却で表現をするべき?「計算の結果(例えば数値のようなプリミティブな型)」を返却せず、「計算」と「値の取得」の2段階にするべき?

 

2017/9/7:データ中心思考とオブジェクト指向の違い

データ中心指向とオブジェクト指向

 

 2018/2/23:レイヤードアーキテクチャの参考

中規模Web開発のためのMVC分割とレイヤアーキテクチャ - Qiita

 

2018/2/28:レイヤー構造の参考に

ウェブアプリケーションの構造について - じゅんいち☆かとうの技術日誌

 

2018/3/1:

外部設定関係は独立したパッケージ(プロジェクト)にした方が良いかも
インフラ層で発行したメッセージ(例外詳細)をドメイン層で扱うことを考えていた際に思ったところ。
インフラで発行した情報を変換なり利用なりしようとすると、その方が良いように思う。
実装面で考えたら、インフラ層で発生した情報の管理主体はインフラ層のプロジェクト配下になるけれど、そうしてしまうとドメイン層からは扱い辛い気がする。
Repository同様、インターフェース経由で、というのも考えどころではあるけれど、情報詳細に応じたハンドリングをする類のものだと考えるので、それも悩ましい。
例外という独立したドメインに対して要件を整理する、ということに注力するのであれば「独立したパッケージ(プロジェクト)」にするという構成が悩みが少ないかもしれない。
分割過剰な気もするので、実装含めて、ちゃんと検討が必要。

 

2018/3/14:ValueObjectの参考に

マニュアル: ドメイン駆動設計: Value Object - Hideki Ikemoto's Site

https://projectlombok.org/features/Value

*1:スライド貼り付けなので、若干やっつけ感がありますが・・・

*2:とはいえ、DDDについてですが、きちんと分かっていないと思います。有名どころの書籍も読んだことはありません。UMLもかなり昔に勉強したなぁ、という感じです。

投稿にあたって、自分ルールの整理

なぜ書く?

自分なりに考えたことを手帳やtwitterに残していたけれど、まとまった場所を1つ設けておこうと思ったから。

ひょっとしたら同じような悶々としている人にとって一助になるかもしれないし、コメントなどの意見で更に考察が深まるかもしれないと思ったから。

なにを書く?

システム開発に関することは正しいことではなく個人的な考察を書く。

思いつきのつぶやきも書く
twitterは索引でブログを本文という感じ

いつ書く?

ある程度、自分の考えがまとまったところで書きたい。

とはいえ、おもいつきの備忘として書くこともある。

どのように書く?

ある時点の自分の考えを素直に書き、過去の考察との整合性は過度に気にしない。

思いついたときのつぶやきレベルのものは、それとわかるようにラベルを設ける。

他人の考察に対して批判的なことを書かない。違いを考察することと自分の考察の押し付けは違うことを意識する。

引用は、考察の切欠の明示であって批判の元ネタではない。引用を使って、これは違うと思う云々ということは書かない。

なぜライセンス表記をする?(2016/12/27追記)

明らかにスニペットレベルの場合は付与しないが、ある程度のクラスになった場合、コードにLicense表記(Apache License 2.0)をする。これはロジックの使用を制限するのではなく、利用しても良いという意図を明確にするため。*1

いずれにしても、ご利用は利用側の責任の範疇でお願いしますということと、もしお役に立つことがあれば幸いという感じです。

*1:License表記をしないことで、逆に自分自身がそのクラスの利用を制限されてしまうケースが起こりうるということがあるようなので