2ヶ月前のブログエントリーで Aurelia という次世代のクライアントサイドフレームワークについて書きましたが、Aureliaの開発が更に進んでいて、私たちもそれに追随してサンプルアプリケーションの Typescript のバージョンを更新しました。変更個所をご紹介したいと思います。
リポジトリはこちらです。gulp のみで動作し、IDEに依存していません。
Archive for 2015
次世代のクライアントサイドフレームワーク Aurelia の開発がどんどん進んでいます
Posted in aurelia, client side framework, gulp, typescript
次世代のクライアントサイドフレームワーク Aurelia のご紹介
弊社がエンタープライズ向けのプロジェクトで利用したDurandalフレームワークの作者 Rob Eisenberg さんがこの間次世代のクライアントサイドフレームワークAurliaを発表しました 。
Get Started を和訳しました
ベースの技術が変わりましたが、Durandal の後継者だと言われているフレームワークですので、早速社内で試してみました。可能性を感じたので、Aurelia の Get Started セクションを和訳しました。興味がある方は是非参考にしていただきたいです。(pull requestを送ってマージされました。訳がおかしいところがあればお知らせください!)
Get Started 日本語版
また、サンプルアプリケーションをTypeScriptに変換しました
Aurelia のサンプルアプリケーションは ES6 で実装されていますが、弊社ではクライアントサイドの開発に TypeScript を使っているので、早速 TypeScript に変換しました。
TypeScriptで実装されたサンプルアプリケーションのリポジトリ
元々のサンンプル同様にGulp を使っていて、Visual Studio 等のIDEに依存していませんので、気軽に試していただけます。メインソース、ユニットテスト、結合テストが全て TypeScript に変換されています。
ソースマップも出力されているので、ChromeでTypeScriptのままデバッグができます。
サンプルのREADMEも和訳してありますので、参考にしていただけると幸いです。
Posted in client side framework, gulp, typescript
Knockout.js + Json Patch でモデルの差分検出/適用
最近手がけたプロジェクトではクライアントサイドとサーバーサイドのモデルを同期させるときの通信量を削減するために、JSON Patch RFC6902 を採用してみました。JSON Patch の簡単な説明とサーバーサイドの実装方法について、以前に紹介しましたが、今回はKnockout.jsを使ったクライアントサイド用の実装方法と利用パターンをご紹介したいと思います。
JSON Patch とは
簡単に前回の記事を振り返ると、JSON Patch は以下の2つのメイン機能を想定しています。
- モデルに変更を適用するためのオペレーションの定義。
- モデルに変更があったとき、その変更内容の検出と表記方法(オペレーションオブジェクト)。
利用パターン
- サーバーから JSON Patch データを受け取り、モデルを更新
- モデルを更新するダイアログウインドウとメイン画面の間のモデルの差分の通信
- モデルに対する変更の検出
実装方法
キーポイント
- プロパティに対する変更の適用と検出
- モデル(のインスタンス)に対する変更の適用と検出
プロパティに対する変更の適用と検出
機能概要 | 用途 | サンプルコードで の対応メソッド |
変更前の値の保持と現在の値との比較 | 変更の検出 | _getChanges |
変更前の値を現在の値にリセット | 変更の検出の結果を空にする | _resetChanges |
現在の値の変更 | JSON Patch による変更の適用 | _applyChanges |
extender を作成する前に、考慮しなければならない点が一つあります。observable が保持している値のタイプによって、_getChange、 _resetChange、_applyChange メソッドの実装が異なるので、以下の3つのタイプに合わせて、専用の extender を用意する必要があります。
observableの値のタイプ | extender名 |
プリミティブ | track |
モデル | trackObject |
モデルの配列 | trackObjectArray |
- JSON データから新規のインスタンスを生成するために、コンストラクタを使っていること
コンストラクタは extender のパラメータとして渡されます。 - 各メソッドが内部でそれぞれ koPatch.getChanges、koPatch.resetChanges、koPatch.applyChanges というメソッドを呼び出していること
モデルに対する変更の適用と検出をするための専用のメソッドです。このメソッドの実装方法は"モデルに対する変更の適用と検出"で説明します。
- 配列のエレメントの追加、削除、置き換え
- エレメント自体に対する変更の処理
また、_getChanges、_resetChanges、_applyChangesが呼ばれたときに、配列の各エレメントに対して、それぞれkoPatch.getChanges、koPatch.resetChanges、koPatch.applyChanges を呼び出し、2. の処理を行います。
コード2、3、4で定義した extender を登録します。
track、trackObject、trackObjectArray の extenders を利用して、モデルを作成します。
基本的に以下のようにモデルとプロパティの定義ができます。
モデルに対する変更の適用と検出
- getChanges
- resetChanges
- applyChanges
使い方のサンプル
コード9で定義したモデルを利用して、使い方のサンプルを紹介します。
このサンプルでは、ユーザーのプロフィールを編集し、DBに保存する操作をイメージします(実際のAJAXのやり取りは省略)。
終わりに
モデルのフィールドが多く、そのまま送ると転送量が多くなるような場合に、JSON Patch を利用して転送量を減らすことができます。レスポンスタイムの短縮につながりますので、モバイル、デスクトップのウェブアプリケーションのユーザーエクスペリエンスの向上ができます。今回ご説明したように実装は簡単です。皆様もぜひ検討してみてください。
著者について
グリシン キリルは、11年前にロシアから来日し、2013年からエンラプトでウェブアプリケーションの開発に従事する。Functional Reactive Programmingに夢中で、クライアントサイドの開発を簡単に、より確かにするための研究を行う。
Posted in JSON Patch, Knockout.js, rfc6902
TypeScriptラムダ式のライブラリ(jQuery、Knockoutjs)での利用
前回、TypeScriptとthisのおさらい という記事で TypeScriptでラムダ式を使った場合の this の留意点について簡単におさらいしました。
実際の開発現場では、色々なライブラリと一緒に使った場合に考慮する事があるでしょう。
弊社が経験した TypeScript と組み合わせたライブラリ( jQuery、Knockoutjs )での考慮点を、簡単なサンプルとともに紹介していきたいと思います。
Posted in javascript, jquery, knockoutjs, typescript
TypeScriptとthisのおさらい
今回はAltJsとして弊社がよく利用するTypeScriptにおけるthisについておさらいします。
基本的にはJavaScriptと変わらない、、、のですが。
TypeScriptとJavaScriptの違いとして、関数の定義方法によるところがあります。
- アロー関数式
- ()=>{}
- ラムダ [lambda]式でも通じるかと思います。
- 当記事では「ラムダ式」と記載します。
- 従来function式
- function(){}
このラムダ式ですが、略記以外に重要なポイントがあります。
TypeScriptのラムダ式ではthisの扱いが異なるという所です。(ハンドブック参照)
Posted in javascript, typescript
[Java] Bean validation 1.1(JSR303, JSR349)の拡張
Bean validation 1.1(JSR303, JSR349) とは
- アノテーションでオブジェクトの制約を表現できる
- 独自の制約を追加することができる
- オブジェクト(ネストしたオブジェクトを含む)をバリデーションするAPIを提供している
- メソッド、コンストラクターの引数、戻り値を検証するAPIを提供している
- (ローカライズされた)バリデーションエラーを取得できる
- Java EEに統合されている(Java EE以外でも使える)
Bean validationの用法紹介: Spring Controllerの引数を検証するために使う
上のコードの説明
それでは次にDocumentオブジェクトのidフィールドに対して、独自の制約(③ CustomConstraintアノテーション)を導入してみましょう。
独自の制約を作成する
これから見ていくサンプルを簡単に説明すると、CustomConstraintアノテーションのpayloadフィールドにバリデーション内容(Validatorインターフェースの実装クラス)を指定しておくとそのバリデーション内容が実行されるというものです。
コード6: Validators.java
コード7: Validator.java
コード8: Message.java
上のコードの説明
- message 制約に違反したときにこのメッセージが返されます。このメッセージにはローカライズ等の変換処理が施され返されます。変換に関する仕様はこちらに書かれています。 仕様ではResourceBundleにあるValidationMessages(ValidationMessages.properties)がメッセージの変換に使われますが、独自のメッセージ定義を使いたいときには、Springの場合、コード9に記載のあるようにWebConfigurerAdaptor#getValidatorをoverrideし独自の設定をすることでこれが実現できます。
- groups groupsを指定した場合、バリデーションする/しないを任意の単位で分割することができます。 例えば、「あるAPI Aではバリデーションしたいけど、別のAPI Bではバリデーションしたくない」といったときにAPI Aグループと、API Bグループをつくり、バリデーションするときにこのグループを指定すれば、指定したグループ単位のバリデーションが実施されます。(* Springでグループ単位のバリデーションをするには、javax.validation.Validアノテーションの代わりに、org.springframework.validation.annotation.Validatedアノテーションを使います)
- payload 制約アノテーション(e.g. NotNull)を付与するときに、制約に対して更に情報を付与したいときに使用します。 例えば、フィールドA、BにNotNullアノテーションを付けていて、フィールドAがnullのときはエラーとして扱い、フィールドBがnullのときは警告として扱いたいといったときに、フィールドAには@NotNull(payload=sample.Error.class)、フィールドBには@NotNull(payload=sample.Warning.class)を指定することで、バリデーションエラー受取側では、このpayloadに設定された値によって挙動を変えることができます。
Posted in java, jsr349, spring jsr303, validation
[Scala] Unfilteredで簡単ストリーミングダウンロード
Unfilteredとは?
ResponseBytes
- ダウンロード対象が大きいファイルの場合、データをArray[Byte]に溜め込んでしまうため、ダウンロード可能なファイルサイズがヒープ容量に依存。
- ダウンロード時も全てファイルデータを読み込んだ後にファイルダウンロード開始されるため、開始されるまで止まっているように見える。
Channel(Netty)
そこで、NettyのChannelを使い、ストリーミングすることでResponseBytesで起きた問題を解決することが可能となります。以上でストリーミングダウンロードが可能となりますが、Unfilteredフレームワークに限らず、ファイルダウンロードAPIを作成する際は、Channelなどを用いた非同期な実装を検討してみてはいかがでしょうか。
Posted in netty, scala, unfiltered
BEMに基づいたCSS設計手法のメリットについて
BEMの採用でCSSとHTMLの開発プロセスの改善をする
私はCSS/HTMLの開発の際、構成管理をどのようにすれば良いか考える機会がありました。どんなコードベースでも以下の点の改善ができれば、開発のプロセスがもっと早く、もっと簡易に、もっと確かになるためです。
- 再利用性
- 拡張性
- 開発生産性とメンテナンス性
上記の点の改善を可能にするCSSとHTML設計手法のうちの一つにBEMがあります。どのように改善ができるか、詳しく説明したいと思います。
再利用性
BEMにはブロックとエレメントいう2つの概念があります。
ブロックとは独立した存在で、デザインの「構成要素」であります。ブロックはコンテキスト(親HTMLエレメント等)に依存せずに、ページのどこの位置に配置されても自分の機能を保つべきものです。
ブロックを組み合わせて、アプリケーションページを組み立てます。
エレメントは、ブロックの一部分であり、特定の役割を果たしています。 エレメントはコンテキストに依存していて、そのエレメントが属するブロックだけで利用されています。
ブロックとブロックの中にネストされたエレメントの例:
ブロックの独立した性質のおかげで、他のブロックと自由な組み合わせでアプリケーションのどこのページにでも簡単に再利用ができます。
拡張性
BEMには更にモディファイヤーという概念があります。
モディファイヤーはブロックとエレメントのスタイルにバリエーションを持たせるためのものです。CSSとHTMLの開発フェーズが終わっていても、CSSのベーシックな知識しか持っていないチームメンバーでも新しいモディファイヤーを追加することで、既存のブロックやエレメントのデザインの変更が簡単にできます。
既存のブロックの背景色を変更するモディファイヤーを追加する例:
また、既存のモディファイヤーを組み合わせたりすることで、新しいデザインが作れます。
既存の二つのモディファイヤーの組み合わせで新しいデザインのボタンを作成する例(ボタンの色とサイズの組み合わせ):
開発生産性とメンテナンス性
ブロックはコンテキストに依存しない存在であるため、ブロックを組み合わせることでページの作成が可能になります。
CSSとHTMLの作成を外部デザイナーに依頼する場合、アプリケーションページの全体の作成ではなく、必要なブロックだけの作成を依頼すれば、あとは基本レベルのCSSとHTMLの知識を持つチームメンバーでもブロック利用して、アプリケーションページの組み立てができます。
2つのブロックの簡単な組み立ての例:
簡略化されたBEMへのアプローチ
BEM自体は結構大きなフレームワークです。CSS設計ルールだけではなくて、専用のテンプレートエンジンやビルドツールやJavaScriptを取り扱う方法などが含まれています。このフレームワークの全ての要素を導入するには、相当な努力が必要でしょう。
幸いなことに、ブロック、エレメント、モディファイヤーというコアコンセプトを有効に使うのに、全体のフレームワークを取り入れる必要はありません。BEMに基づいたCSS設計ルールだけを採用しても、BEMをはじめることができます。
弊社では、こういうCSS設計ルールセットを用意しております。この設計ルールセットのメインの部分を紹介したいと思います。
BEMに基づいたCSS設計ルール
-
クラスのネーミング
概念的に、クラスのネーミングルールはBEMのものと同じですが、ブロック、エレメント、モディファイヤーの区切り用のエレメントを自分の好みにあわせています。
各ブロックの定義は個別のファイルに納めることで、ブロック名の衝突を避けています。
-
カスケードセレクターを利用しない
コンテキストに依存してしまい、ブロックの再利用が困難になるため、カスケードのセレクターを利用しません。
エレメントの場合も同じです。理由は2つあります。
-
セレクターのspecificity(詳細度)が上がってしまうので、CSSルールが特殊になり、モディファイヤーでのスタイルの上書きが難しくなります。
Specificityというのは、CSSルールの優先順位のことです。複数のCSSルールが同じHTMLエレメントの同じ要素をコントロールしているとき、specificityが高い方が優先されます。基本的に、カスケードのあるセレクターのspecificityがカスケードのないセレクターより高いので、以下の例でテキストの色はredのままになり、モディファイヤーが効かなくなります。
だめな定義の例:
セレクターのspecificityが同じ場合、後から定義された方が優先になります。
-
クラスのネーミングルールによって、エレメントのクラス名にすでにブロック名が入っているため、他のブロックのエレメントのクラス名との衝突はおきません。
-
セレクターのspecificity(詳細度)が上がってしまうので、CSSルールが特殊になり、モディファイヤーでのスタイルの上書きが難しくなります。
-
タイプセレクターを利用しない(セレクタにタグ名が使われているセレクターのこと)
- カスケードセレクターと同じように、specificityが上がるので、モディファイヤーでのスタイルの上書きが難しくなります。
- 定義された以外のエレメントでの利用が不可になります。
-
セレクターにIDを利用しない
IDを使ってしまうと、そのブロックをページ内で一回しか使えなくなるために、再利用が不可になります。
簡単なブロックのCSSとHTMLのサンプル
以下に簡単なブロックとモディファイヤーの定義と利用方法のサンプルを紹介します。
結果

まとめ
最近手がけたエンタープライズ向けプロジェクトでも上で説明したCSS設計手法を採用しています。その感想を簡単にシェアしたいと思います。
- 今回のプロジェクトではブロックのCSSとHTMLの作成を外部デザイナーに依頼していました。作成していただいたブロックを組み立て、合計で50以上の画面を作りましたた。ブロックの再利用が本当に簡単で、画面作成にかかるコストを大幅に減らせた印象があります。
- デザイナーからブロックのCSSとHTMLが納品された後でもデザインの多少の変更がありましたが、CSSの再設計を依頼せずに、モディファイヤーを利用することで既存のブロックの拡張が簡単にできました。
グリシン キリルは、11年前にロシアから来日し、2013年からエンラプトでウェブアプリケーションの開発に従事する。Functional Reactive Programmingに夢中で、クライアントサイドの開発を簡単に、より確かにするための研究を行う。
Blog Archive
Popular Posts
-
Scala Conference in Japan 2013 にて開催しましたコーディングチャレンジの結果を発表致します。 ■ 優秀賞 グリシンさんからご応募いただきました設問3に対する回答が優秀賞に選ばれました。 https://github.com/KirillGri...
-
Scala Conference in Japan 2013 にてコーディングチャレンジを配布しましたが、そこに記載しました応募用のメールアドレス codingchallenge@enrapt.jp に対して外部からの投稿が出来ない状況になっておりました。原因は Google ...
-
Javaでオブジェクトをバリデーションする仕様にBean validationがあります。 デフォルトのBean validationでは、 ”nullでないこと” 、 ”桁数が9桁以上であること” など、最小単位のバリデーションしか用意されていませんので、ある程度複雑なア...
-
先月終わったばっかりのエンタープライズ向けのプロジェクトで最近話題になっているシングルページアプリケーションを作ったので、感想をシェアしたいと思います。 シングルページアプリケーション(SPA)とは? シングルページアプリケーション(以下:SPA)という言葉、このペ...
-
今回はAltJsとして弊社がよく利用するTypeScriptにおけるthisについておさらいします。 基本的にはJavaScriptと変わらない、、、のですが。 TypeScriptとJavaScriptの違いとして、関数の定義方法によるところがあります。 アロー関数式...
-
イントロダクション ウェブアプリケーションは多くのケースで以下のようにサーバと同期します。 ボタンクリック時に画面で更新された値をサーバに送り、サーバから必要な情報を取得する スクロール時に表示に必要な情報を取得する ページ遷移時に次のページに必要な情報を取得する ...
-
イントロダクション まずは、私達がどのようにTypeScriptを使ってきたかを簡単に紹介します。 2012年の終わり頃から最近までの約1年半TypeScriptを使ってあるプロダクトの開発をしてきました。 作っていたものは、SPA(シングルページアプリケーション)で、...
-
BEMの採用でCSSとHTMLの開発プロセスの改善をする 私はCSS/HTMLの開発の際、構成管理をどのようにすれば良いか考える機会がありました。どんなコードベースでも以下の点の改善ができれば、開発のプロセスがもっと早く、もっと簡易に、もっと確かになるためです。 再利用...
-
忙しい人のためにScala 2.1で取り入れられたマクロを3分で知るための手順を用意しました。 では時間もないので早速、新しい作業ディレクトリを作ってください。 新しく作った作業ディレクトリを以下の構成にしてください。 ファイルはgistのコードが下にあるのでそこから...
