流され日記

好奇心の赴くまま、日々起こした行動の記録

Javaの略記法

長らく放置してたけど、転職してJavaをやることになったので、これを機にもう一度記事を書いていこうと思う。

Javaを始めて最初に思ったのが、「ハッシュはどうやって定義すんの?」ってこと。 だって、JavaScript だったら普通に

var map = {"hoge": 1, "fuga": 1};

とか書けるところを、

Map<String, Object> map = new HashMap<String, Object>();
map.put("hoge", 1);
map.put("fuga", 1);

とか書かなきゃいけない。 マジめんどい。 もうちょい簡単に書く方法があるだろJK。

うん、もうちょい簡単に書ける方法があった。

匿名クラス + 初期化ブロック

Java にはその場でクラスを拡張する方法がある。 また、コンストラクタを書くかわりに、初期化ブロックというインスタンス生成時に実行される処理の記述方法がある。 この2つを応用して、このように書ける。

Map<String, Object> map = new HashMap<String, Object>() {{
  put("hoge", 1);
  put("fuga", 1);
}}

Listの初期化なんかも同様に書ける。

行数はむしろ増えたけど、パラメータの初期化がカッコ内で行われているので、よりわかりやすいとは思う。

withみたいなことをstrictモードで!

withってなにげに便利なんだけど、strictモードでは使えない。
似たようなことをやる方法ないかと考えてみた。

'use strict';

myWith({hoge: 'fuga'}, function(){
  console.log(hoge);
});

こんなコードが動けば嬉しい。

Functionコンストラクタを使う

のっけから黒魔法使う。
関数を文字列化 → 変数宣言加える → えばる という発想。

function myWith(obj, fn){
  var vars = [];
  for(var n in obj){
    vars.push(n + '=this.' + n);
  }
  new Function('var ' + vars.join(',') + ';(' + fn.toString() + ')()').call(obj);
}

ただこの方法はスコープチェーンぶった切るので、

var hoge = 'hoge';

myWith({}, function(){
  console.log(hoge); //=> エラー!
});

のようにmyWithより前で宣言した変数にアクセスできない。困った。

引数として渡す

無理やりスコープチェーンに突っ込むことができないので、少々冗長になるが、引数として渡すようにする。

'use strict';

myWith({hoge: 'hoge'}, function(hoge){
  console.log(hoge);
});

このように呼び出せるようにする。

実装はこんな感じ。引数を解析して必要になるパラメータだけ渡す。

function myWith(obj, fn){
  var argNames = fn.toString().match(/function[^(]*\(([^)]+)\)/)[1].split(',');
  var args = [];
  for(var i = 0, len = argNames.length; i < len; i++){
    var name = argNames[i].replace(/^\s+|\s+/, '');
    args.push(obj[name]);
  }
  fn.apply(this, args);
}

思ったより便利かも

複数のオブジェクト引数にとれて、フォールバックするように実装したら便利かも。
例えばif文を使わずに古いブラウザでだけ自前で実装したObject.createを使うとか、Array.prototypeからよく使うメソッド引っこ抜くとか、両方一緒にやっちゃうとか。

var Polyfill = {
  create: function(){
    ...
  }
};

myWith(Object, Polyfill, [], function(create, slice){
  var obj = create({});
  ...
});

jQueryで要素を生成するときの注意点

jQuery使って要素を作るとき、$('<div id="' + data + '">').appendTo('body')とかやることあるけど、注意しないとXSS起こすよという話。

つまるところ、dataがどこから来たのかをちゃんと把握してないといけない。

例えばこんな例

server-side-template.htmlは、サーバーサイドのテンプレートエンジンによって{{ form.src }}がクエリの値で置き換えられる、よくあるCGIのテンプレートを想定しています。

この場合、http://mysite.com?src="><script>alert('XSS!')</script><div id="といったURLでXSSが可能となる。

どう対応すべきか

  1. 属性をメソッドで追加する
    $('<img>').attr('src', src).appendTo(container);

  2. ちゃんとエスケープする
    $('<img src="' + escape(src) + '">').appendTo(container);

なんか微妙。。

jQuery Deferred Timer

ページ開いて数秒後にポップアップをなめらかに閉じる処理とかをよく書くんだけど、setTimeoutとアニメーションの終了タイミングの絡みがフラグ使ったりで管理しなきゃいけなくてめんどくさいので、Deferredで全部書けるようにこれ書いた。

$.wait

$.waitメソッドは時間を引数にとってDeferredオブジェクトを返し、指定した時間後にステータスが変更される。 要はsetTimeoutをこんな感じに書ける。

$.wait(10000).done(function() {
  /* 1秒後に行う処理 */
});

$.loop

$.loopメソッドはコールバック関数を引数にとってDeferredオブジェクトを返し、非同期にコールバック関数を繰り返し呼ぶ。 返り値(もしくはコールバック関数の引数)のDeferredオブジェクトをresolve/rejectすることによって、ループを止めることができる。 コールバック関数内でDeferredオブジェクトを返した場合、そのDeferredオブジェクトが解決するまでループを停止する。

$.loop(function(dfd){
  // リクエスト投げてる時とデータ取得後500msループを停止する
  return $.get('data.json').pipe(function(data){
      /* 成功時の処理 */
      return $.wait(500);
    }, function(){
      // 失敗時はループを止める
      dfd.reject();
    });
  })
});

PlantUML

クラス図をスケッチするツールを探していて、見つかったのがこれ、PlantUML

Java製のコマンドラインツールで、独自記法で書かれたテキストをUMLに変換できます。 Macでも使える。GOOD。

使用感

WYSIWIGでグリグリ書かなくていいのがいい感じです。キーボードとタッチパッドを行き来しなくていいし、馴染みのテキストエディタ使えるので思考の流れが阻害されにくいです。

あと、テキストベースなので、Gitなどとも相性がいいのもなにげにポイント高い。 自分一人で使うには申し分ない。

記法

記法は独特ですが、覚えにくいというほどのものでも無いと思います。 記述を見て図を想像できるくらいには直感的。

シーケンス図、クラス図、オブジェクト図、ユースケース、アクティビティ図、状態遷移図、コンポーネント図などが書ける様子。

参考

記法を日本語でまとめてくれています。感謝!

PlantUML | プログラマーズ雑記帳

CSSだけで画面を縦に分割する方法

画面内目一杯に広がった要素を縦に分割したい時、CSSだけでやるにはどうすればよいでしょうか。
例えばヘッダーを画面上部、フッターを画面下部に常に固定し、コンテンツが多すぎる場合はコンテンツ部分のみにスクロールバーを出すようなことをやりたい場合です。

f:id:kakusuke07:20121115233724p:plain

こんなことをやりたい。。。

2つほど発見したので、記録しときたいと思います。

オーソドックスな方法

OKWave|スタイルシートで画面を上下に分割,高さを上部はpxで指定,下部は残り全部にする方法
使い古されたCSSの記述だけでできる方法です。 top・bottom を使ってコンテンツの高さ調整をし、absolute でヘッダー・フッターに重ならないよう配置します。 IE6への対応方法もあるようです。

display box を使う方法

box-orientation: vertical で垂直に配置し、コンテンツに box-flex: 1 を指定して、高さを可変にします。 FireFox では overflow: auto を指定しても高さが固定されないので、内部に absolute の要素を配置します。

サンプルコード

何か間違いとかがあればコメントお願いします。

UX Kyoto #07 参加しました!

UX Kyoto #07 参加しました!

今回の内容は「ストーリーテリング」(正確に言うと、「ユーザーエクスペリエンスのためのストーリーテリング」)でした。
全体的にふわふわしている感じでいまいち飲み込めてない感はあるのですが、飲み会でした話の内容も含めてまとめてみたいと思います。

ストーリーテリングとは

物語形式でメッセージを構築し伝える事によって、物事を自分なりに整理し、他人と共有するためのフレームワーク
あくまで他人と「共感」し、問題点などを「示唆」することを目的としており、「説得」を目的とした、プレゼンのための技術ではない。
(ただ、共感は説得力を生むし、プレゼンにも活かすことができる)

ストーリーの構築手順例

  1. アネクドート(個人的な体験談)・コンテキスト(物理的・情緒的・知覚的情報)を集める
  2. アネクドート・コンテキストを選ぶ
  3. ストーリーを紡ぐ
  4. ストーリーを伝える

ストーリーを紡ぐ際、まずストーリーの構造を決め、その構造に沿った形でアネクドート・コンテキストを配置していく。
最終的に一つのストーリーとして整合性が保たれるよう、プロットを作成する。
同時にペルソナも作成する。
プロットから、ストーリーを導き出す。
各工程は自由に行ったり戻ったりしてよい。

ストーリーの構造

受け入れられるストーリーには一定の構造がある。
物語論という学問分野で研究されている。

今回は「英雄構造」をもとにストーリーを作成した。
「英雄構造」は以下の項目からなる。

  • 日常の世界
  • 冒険へのきっかけ
  • はじまりと試練
  • 冒険の世界
  • 目的の達成
  • 日常への帰還

以上

本日のワークショップで学んだことでした。
何か間違いとか言いたいことがあればコメントお願いします。