Apache Wicketとアトミックデザインについてようやく猛省できた話

はじめまして。初投稿になります。
GxPの@tesaito-gxpです。

この記事は<a href=https://qiita.com/advent-calendar/2020/gxp>グロースエクスパートナーズ Advent Calendar 2020</a>の18日目の記事となります。

アドベントカレンダーのテーマが<code>今年の学びを振り返る</code>とのことでしたが、配属されてからの3年間でようやく他人にお伝えできる位には<code>Apache Wicket</code>について身についたのかなと思い書き綴っていこうかなと思います。

ここ最近はあまり触れてなかったですが、上半期ではバリバリに使っていたので、それについて書いていこうかと思います。


<h2>Apache Wicketについて</h2>
Apache Wicket(以下、Wicket)はJavaWebアプリケーションフレームワーク、その中でもユーザインターフェイスに特化したフレームワークになります。

基本的にフレームワークというのは、「如何にしてソースコードを書かずに実現するか」を考えられて作られていると思いますが、Wicketの思想というのは全くの逆で「すべてをJavaで実現したい」というフレームワークになります。
もちろん多少の設定ファイル（web.xml）はありますが、Wicketで記載するのはページのテンプレートとしてのHTMLとJavaのソースコードだけになります。

webアプリケーションを作る際は、xmlファイルを書いて、JSPを作成し、サーブレットを用意、フレームワーク用の設定ファイル、プロパティファイルを作って・・・と、開発作業は様々な工程を踏む必要があります。
しかし、Wicketでの開発ではHTMLを用意したら後はひたすらJavaを書くだけになります。GETだのPOSTだのに応じて呼ばれるメソッドではなく、ただクラス定義として記述することができます。

もちろん、一長一短ですが。

Wicketの大きな特徴は以下の通り。
<ol>
  <li>Javaらしいコードを書ける</li>先ほども触れたとおり、WicketではJavaを用いてWebアプリケーションを作ることができます。「Javaらしい」となればオブジェクト指向を活用し、継承やカプセル化による部品化が挙げられます。
Wicketではこれらをうまく活用し、継承による画面レイアウトの共通化や、共通部品のクラス化を可能としています。

  <li>Ajaxが統合されている</li>WicketにはAjaxが内包されているので、応答性の良いアプリケーションを容易に作ることができます。

  <li>バックエンドとフロントエンドのデータの結合を実現するModelの提供</li>WicketではModelという概念を用い、画面とバックエンド側のデータのやりとりを容易に行うことができます。
</ol>

<h2>アトミックデザインについて</h2>
アトミックデザインについては<a href=https://qiita.com/yokuyama-gxp/items/06b6cceb91689bc0f127>アドベントカレンダー11日目</a>で奥山さんが書いてくださっています。

>アトミックデザインはUIは小さな構成要素の入れ子の組み合わせという考えを元に、化学のメタファーを用いて階層と粒度を定義した設計手法
<ul>
<li>原子（Atom）: 最も小さい粒度の要素</li>
<li>分子（molecule）: 2つ以上の原子を組み合わせたシンプルなUI要素</li>
<li>有機体（organism）: 切り離して単体でも機能する分子の集まり</li>
<li>テンプレート（Templates）: いくつかの有機体・分子・原子から成り立っている骨組み</li>
<li>ページ（Pages）: テンプレートに実際のコンテンツを適用したもの</li>
</ul>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906419/e575fd68-d1a9-09dd-5870-8c365bef1487.png)
引用：https://uxdaystokyo.com/articles/glossary/atomic-design/

参照元: <a herf="https://atomicdesign.bradfrost.com/chapter-2/">Atomic Design Chapter2</a>

このアトミックデザインというものを知ってから今までやってたことが間違ってたんだなぁ。。。と思い知らされました。

Wicketの話に戻します。

<h2>サンプルコード</h2>
Wicketで画面をデザインする際に、どうやって実現するのか極々簡単なパターンを２つ書いてみようかと思います。
今回実装するのはブラウザ上に「WicketでLabelを置いたよ」とただ一文表示するという簡素なものを書きます。

<h4>パターン１：クラスを継承させる</h4>

```html:SamplePage1.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" xml:lang="ja" lang="ja" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <!--ここから下は継承したクラスで書くよ-->
    <wicket:extend />
</body>
</html>
```


```java:SamplePage1.java
import org.apache.wicket.markup.html.WebPage;

public abstract class SamplePage1 extends WebPage {
}
```

```html:SamplePage1Impl.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" xml:lang="ja" lang="ja" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <wicket:child>
        <div wicket:id="sampleLabel" />
    </wicket:child>
</body>
</html>
```

```java:SamplePage1Impl.java
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.Model;

public class SamplePage1Impl extends SamplePage1 {

    public java:SamplePage1Impl() {
        super();
        Label sampleLabel = new Label("sampleLabel", Model.of("WicketでLabelを置いたよ"));
        this.add(sampleLabel);
    }
}
```

このような感じで、ヘッダー(bodyに書いていますが)などのどのページでも変わらない要素を親クラスで持ちつつ、継承した子クラスで必要な要素を追加することによって機能を実装していきます。
子クラスで様々な機能を追加で実装していくためポリモフィズムを意識して実装を行うことができます。

実際のページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906419/5ebaa09c-b42f-53d4-9f43-448845c84e2c.png)





<h4>パターン２:Panelを使用する</h4>

```html:SamplePage2.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" xml:lang="ja" lang="ja" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <div>↓ここから下はPanelクラスで書くよ↓</div>
    <wicket:panel wicket:id="samplePanel" />
</body>
</html>

```


```java:SamplePage2.java
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.panel.Panel;

public class SamplePage2 extends WebPage {

    public SamplePage2() {
        super();
        Panel samplePanel = new SamplePanel("samplePanel");
        this.add(samplePanel);
    }
}
```

```html:SamplePanel.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" xml:lang="ja" lang="ja" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <div>
        <span  wicket:id="sampleLabel"  />
    </div>
</body>
</html>
```

```java:SamplePanel.java
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;

public class SamplePanel extends Panel {

    public SamplePanel(String componentId) {
        super(componentId);
        Label sampleLabel = new Label("sampleLabel", Model.of("WicketでLabelを置いたよSample2"));
        this.add(sampleLabel);
    }
}
```

こちらの書き方は、アトミックデザインに近いものになります。
新たにPanelというクラスを実装しましたが、アトミックデザインでいうところのテンプレートに該当します。
Panelに様々な要素を置くことで再利用可能なプログラミングを行なうことができます。

（今回はLabelを１つしか置いていませんので分子や有機体という過程を飛ばしてます。）

実際のページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906419/aa8e3301-de66-7f8c-1686-f9b335d1c3c0.png)

両パターン簡単に表すとこんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906419/e2f8112b-5ece-40cd-d433-f3e7c04c3fce.png)
どちらの実装が良いかというのはプロジェクトの指針などがあるので一概には言えませんが、頭の中ではパターン２で考えていたのに・・・完成形はパターン１だったなんてこともありました。
この辺りの考え方を自分の中ではうまくまとめられたのかなと思います。

<h2>猛省</h2>
私がアトミックデザインというものを知ったのはおそらく1年ちょっと前かと思いますが、これまでもWicketをガンガンに使って画面を作成していました。
もともと既存システムの保守ということもあり過去の書き方を参考に・・・ということもあったんですが、上記の2パターンを混合して使っておりました。
「パターン１でもパターン２でも再利用できるもの書けるじゃん！どっちでもいいじゃん！！」そんな風に思っていたわけです。その結果、どうなった・・・というのは有りませんが、今となってみればあまり考えずにプログラミングをしていたと猛省するばかりです。

アトミックデザインを知ってからはパターン２で書くことが多くなり、そのおかげで例えばコードレビューの際も自分の中で指針が持ちやすかったり、追加で変更がある場合でも書き方に迷わなくなりました。
プロジェクトや個人レベルで方針が決まってるとやりやすい部分できたのかなぁと思います。

あぁ過去の自分をぶん殴りたい。