astamuse Lab

astamuse Labとは、アスタミューゼのエンジニアとデザイナーのブログです。アスタミューゼの事業・サービスを支えている知識と舞台裏の今を発信しています。

JavaフレームワークAsta4Dの話

ワームホール

弊社が作成、使用しているフレームワークAsta4Dの設計とメンテナンスを担当している劉です。 今回はそのAsta4Dの紹介させていただきたいと思います。

Asta4Dとは何か?

Asta4Dはデザインフレンドリーかつ開発に柔軟性を持たせるという特徴を持つWEBアプリケーションフレームワークです。

github.com

なぜAsta4Dか?

過去10年間に、様々なJavaフレームワークが作られてきました。特にMVCアーキテクチャとJSPタグリブ(もしくは他の伝統的なテンプレート技術)により、大幅に開発効率が上がりました。しかし、下記のような事柄がいまだに開発者の頭を悩ませ続けています:

  1. ページソースに動的コードが混在しており、ページの再設計やレイアウト調整を行う妨げになるとデザイナーやフロントエンドエンジニアから不満を持たれています。同様に、デザイナーやフロントエンドエンジニアがページの再設計とレイアウト調整を行うたびにページソースに埋め込まれた動的コードの挙動を壊してしまうことがバックエンドエンジニアの不満になります。ソースのリファクタリングに大きなコストかけてまでページの再設計や新しいページの設計に合わせることは困難であるためです。

  2. 開発者は、テンプレート言語の機能が貧弱であることに不満を抱いており、複雑なレンダリングロジックのために様々なおまじないのようなコードを書くことに疲れています。

  3. 開発者はMVCアーキテクチャの生産性が高くないことに不満を抱いており、従来のPHPのようなより開発効率の良い手法を求めています。

Asta4Dはどうか?

Asta4Dはこれらの問題点に対するソリューションです。Asta4Dは下記の点に焦点を当て作られました。

テンプレートとレンダリングの分離

テンプレートファイルには動的なコードが含まれません。Asta4Dのテンプレートファイルは常にフロントエンドエンジニアがメンテナンスし易い純粋なHTMLファイルです。非常にデザインフレンドリーであり、我々はソースリファクタリングに要する作業負荷を90%以上減らすことができます。

レンダリングロジックは独立なJavaクラスで実装していますので、開発者は新しいテンプレート言語の習得が要らなく、いつも慣れているJavaのままで開発し、Java言語のフルパワーを利用できます。

下記のようなテンプレートファイルに対して

<section>
    <article>
        <div afd:render="SimpleSnippet">dummy text</div>
        <afd:snippet render="SimpleSnippet:setProfile">
            <p id="name">name:<span>dummy name</span></p>
             <p id="age">age:<span>0</span></p>
         </afd:snippet>
    </article>
</section>

snippetクラス側では、css selectorを使ってレンダリングロジックを記述します。

public class SimpleSnippet {

    public Renderer render(String name) {
        if (StringUtils.isEmpty(name)) {
            name = "Asta4D";
        }
        return Renderer.create("div", name);
    }

    public Renderer setProfile() {
        Renderer render = Renderer.create();
        render.add("p#name span", "asta4d");
        render.add("p#age span", 20);
        return render;
    }
}

テスト可能なレンダリングロジック

すべでのレンダリングロジックはJUNITで単体テスト可能です。この特徴で半分ぐらいのselenimumテストはjunitに書き換えることができ、開発コストを大幅に削減しています。

    // prepare test target
    Renderer render = Renderer.create();
    render.add("#someIdForInt", 12345);

    // perform test
    RendererTester tester = RendererTester.forRenderer(render);
    Assert.assertEquals(tester.get("#someIdForInt"), 12345);

cross-siteホールから完全免疫の高い安全性

Asta4Dは設計上にcross site問題を完全回避しています。全てのレンダリング内容はデフォルトでエスケープされるので、開発者はそこまで配慮しないでも問題なく高い安全性を持つウェブサイトを構築できるようになっています。

View First

Asta4Dでは従来のMVCのcontorllerを排除し、URLからルールの配置して直接テンプレートファイルにマッチングするというView First仕組みを提供している。従来のMVCアキテクチャーより生産性を向上し、システムもより柔軟的に変更できます。

View Firstの開発スタイルでは、ページの表示結果を前提としてロジックを実装します。多くの人は表示結果を前提とした場所に動的コードを実装することは、昔のPHPのようにソースがより複雑になり理解が困難になると言うかもしれません。その主張は間違ってはいませんが、Asta4Dではテンプレートファイルとレンダリングロジックとを分離しているため問題となりません。生産性の面では、開発者は複雑なソースの構成を気にすることなく本質的な開発に専念することができます。

request handlerを用いた副作用の分離とマルチスレッドレンダリング

関数型の言語から「副作用」という概念を導入し、その「副作用」を慎重的に管理するべきと考えています。全ての「副作用」をrequest handlerの仕組みで管理し、ビュー層の機能を純粋にし、ソースをより綺麗でメンテナンスし易くするようになっています。

これは、Asta4Dがひとつのページをマルチスレッドでレンダリングすることを容易にしています。なぜなら、レンダリング処理は副作用から解放されているからです。

システム上に「副作用を伴う挙動」と「副作用を伴わない挙動」と呼ばれている二つタイプの操作があります。システムの状態を変更するような作用のある挙動を、「副作用を伴う挙動」と定義します。例えば、同じURLに対してログインチェックが行われる場合、ログイン前と認証に成功したログイン後ではおそらく異なるページが表示されるでしょう。このようなログイン処理は「副作用を伴う挙動」です。また別の分かりやすい例としては、データベース更新処理があります。更新処理がコミットされれば、それに関連したページは更新処理前とは異なる表示をするでしょう。これもまた「副作用を伴う挙動」の一種です。データベース検索処理はどうでしょうか。検索処理は副作用を伴わない挙動です。これは何回検索処理を行ったかに関わらず、常に同じ結果を返すことを意味しています。

より進化したMVCアキテクチャーとビルトインのForm Flow

Asta4Dはview first仕組みを提供していますが、MVCをサポートしないというわけではありません。逆に、従来のMVCの弱点に対して改善された進化したMVC仕組みを提供しています。

例えば、従来のMVCアキテクチャーでは、lazy loadの問題を解決するためにトランザクションをviewレイヤーに拡張することはよくありますが、このような汚い解決方法になる原因はcontrollerに多くの役割を担当させていることに起因しています。

また、controllerはmodelとviewの連携についてたくさん関わっているので、viewレイヤーの修正だけでもcontrollerの実装を直さなければいけないことがよくあります。レイヤーの疎結合をするために設けたにも拘わらずまったく疎結合の目標を達成できていません。

Asta4Dが提供しているより進化したMVCは、システムの役割分担を下記のように設計しています。

  • request handler

    前述の通り、全ての副作用のある操作はこちらで行います

  • result matching

    handlerの結果によって該当ページの表示に移します

  • snippet class ページの描画のみを担当させます

さらに、上記の基本思想に踏まえて、ビルトインのForm Flowを提供しています。開発者はビジネスロジックにより専念することが可能です。基本的に、Form Flowを利用する時、下記の二つメソッドをオーバーライドすれば仕事が済みます。

public class SingleInputFormHandler extends OneStepFormHandler<PersonForm> {

    @Override
    protected PersonForm createInitForm() throws Exception {
        ...
    }

    @Override
    protected void updateForm(PersonForm form) {
        ...
    }

}

ページのレンダリングはフレームワークが自動的に行いますので、htmlのテンプレートを提供すること以外の作業は基本的にありません。

終わりに

今回の内容は弊社前社員の大谷さんが作成したものを加筆・修正しているものです。素晴らしい資料だったため、手間なく作ることが出来ました。とても感謝しております。

また、日本語の添削を弊社のnkgwにしてもらいました。こちらにも感謝しています。

次回はそのnkgwが担当の回になり、Asta4Dの入門記事全6回で書いていくということなので、この記事を見て気になった方は是非とも見てください!

Copyright © astamuse company, ltd. all rights reserved.