2015年4月15日水曜日

はてなブログ(http://ohbarye.hatenablog.jp/)に引っ越した

最近はもっぱらMarkdownを書くようになり、Bloggerがどんどん使いづらくなってきたのではてなブログに引っ越した。
http://ohbarye.hatenablog.jp/

下記リンク先が大変参考になり、10分ほどで作業を終えることができた。
http://nekonkeo.hatenablog.com/entry/2014/09/23/165817

2015年3月13日金曜日

グラフDB(Neo4j)を試してみる (2)BluePrintsで読み書き

BluePrints

各グラフDBに対するインタフェース、APIを提供するソフトウェア。
複数のグラフDBに対応している。

ライブラリ追加

blueprints-core と好きなGraphDB用のライブラリを追加する。
今回はNeo4jを選んだので blueprints-neo4j-graph を追加。
手元でちょうどPlay Framework触ってたのでビルドツールはSBT。
libraryDependencies ++= Seq(
  "com.tinkerpop.blueprints" % "blueprints-core" % "2.6.0",
  "com.tinkerpop.blueprints" % "blueprints-neo4j-graph" % "2.6.0"
)

DB初期化〜読み書き

DBの初期化からデータの追加、検索を行うとこんな感じになる。
package app;
 
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.neo4j.Neo4jGraph;
 
public class GraphDB {
 
 public static void main(String[] args) {

  /**
   * init
   * 使用するグラフDB用のディレクトリを指定する。
   * このタイミングでロックファイルを作成し、排他制御をかける。
   * ディレクトリが存在しない場合は初期化してくれる。
   */
  Graph g = new Neo4jGraph("data/graphdb");
  
  addData(g);
  showData(g);

  /**
   * close
   * プログラムを終了する時は必ずshutdown。
   * ロックの解放とか諸々やってるっぽい。
   */
  g.shutdown();
 }
 
 /**
  * Add Node and Edge
  * @param g
  */
 public static void addData(Graph g) {
  /**
   * insert
   * Vertex(頂点、Node)の追加+属性の追加。
   */
  Vertex v1 = g.addVertex(1);
  v1.setProperty("name", "Apache");
  
  Vertex v2 = g.addVertex(2);  
  v2.setProperty("name", "Nginx");
  
  /**
   * insert
   * Edge(辺、Link)の追加+属性の追加。
   */
  Edge e1 = g.addEdge(1, v1, v2, "similar");
  e1.setProperty("since", 2006);
 }
 
 /**
  * show graph data
  * @param g
  */
 public static void showData(Graph g) {
  /**
   * select
   * とりあえず全部取得して表示。
   */
  for (Vertex v : g.getVertices()) {
   System.out.println("Vertex id = " + v.getId().toString()
     + "  property 'name' = " + v.getProperty("name"));
  }
 
  for (Edge e : g.getEdges()) {
   System.out.println("Edge id = " + e.getId().toString()
     + "  property 'since' = " + e.getProperty("since"));
  }
 }
}
Vertex id = 1 property 'name' = Apache Vertex id = 2 property 'name' = Nginx Edge id = 0 property 'since' = 2006

初見の印象

とりあえず触ってみたところ、特に良いなと思ったのが下記。
  • サーバ構築不要
  • 移植性が高い
BruePrintsにはNeo4jのライブラリが同梱されているらしく、DBとはいうもののサーバ構築やサービス起動などの一般的なミドルウェア追加時の作業を行わなくても上記のコードだけで扱うことができる。

もちろん、サーバとして起動して外部からのアクセスを待ち受けたりもできるとのこと。

また、移植性も高い。
new Neo4jGraph(“data/graphdb”) で指定したディレクトリの移動だけで移植が完了する模様。

グラフDBにはスケールしづらいという弱点があるらしいが、その分これだけ軽量になっているのは魅力的。





2015年3月12日木曜日

グラフDB(Neo4j)を試してみる (1)グラフDBとは

会社の勉強会でグラフDBが紹介されて興味を持ったので実践してみた。
全然知らない領域だったのでいろいろ整理したい。

グラフDBとは

まずグラフDBとは何か。

グラフ理論をベースとし、ノード(頂点)とエッジ(関係)を構成要素とするNoSQLデータベースの一つ。関係性を表現が目的のため、その探索が用意。また、ノード・エッジはプロパティ(属性)を持つことができる。

とりあえずこんな理解。

一般的な「グラフ」とは意味合いが違うけれども、計算機科学や数学では「グラフ」といえばこちらを指すことが多いのだろうか。ちなみにWikipediaのグラフ理論がだいぶ参考になった。
グラフ理論(グラフりろん、graph theory)は、数学の一分野。ノード節点頂点[1])の集合とエッジ[2])の集合で構成されるグラフの性質について研究する学問である。なお「エッジ」をリンク[3]という場合もある。コンピュータのデータ構造アルゴリズムなどに広く応用されている。  
Wikipedia グラフ理論
このグラフ構造はRDBでも実現できるが、リレーションを辿る=結合の繰り返しになるのでクエリが複雑になったりパフォーマンスがひどいものになったりする。FacebookやTwitterに代表されるようなリレーションをコアとするアプリケーションでのデータ管理や表現への注目の高まり、

Neo4j

試してみたグラフDBはNeo4j。この他にもいろいろあるらしいけど未知。
グラフデータベース、NOSQL、Neo4jを見ると非OSSが多い印象。

TinkerPop

グラフDBを利用する為のフレームワーク、製品群。
ややキモいキャラクターが各プロダクトのトレードマークっぽい。
TinkerPop - http://goo.gl/zpCCC

今回はこのうちBluePrintsとGremlinを使ってグラフDBへアクセス、読み書きを行ってみた。

長くなりそうなのでコードは次の記事で書く。




2015年3月1日日曜日

[Play Framework] 多対多で自己再帰の関連を持つテーブルのEntity

多対多(Many To Many)で自己再帰的(self recursive)な関係をEbean の Model で表現するのに苦戦した。
あまり良い例ではないけど、
person には似てる人(similarPerson)が複数いる、という設定で書いてみた。
person と person の多対多を解消する中間テーブルは similar_person として定義してみる。
@Entity
public class Person {
    @Id
    public Long id;

    @ManyToMany
    @JoinTable(name = "similar_person",
            joinColumns = @JoinColumn(name = "person_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "similar_person_id", referencedColumnName = "id"))
    public List similarPersons;
}
ポイントは @JoinTable の引数の joinColumns と inverseJoinColumns 。
最初これらを書かずにいたら、similar_person テーブルで列名 person_id が重複しています と怒られた。

考えてみたらどちらも外部参照先 (person.id) は同じなんだから、列名指定せずに自動生成したらそうなるよな…。

上記のクラスを定義した上で Evolution を実行すると、下記SQL が自動生成される。
# --- Created by Ebean DDL
# To stop Ebean DDL generation, remove this comment and start using Evolutions

# --- !Ups

create table similar_person (
  person_id                     bigint not null,
  similar_person_id             bigint not null,
  constraint pk_similar_person primary key (person_id, similar_person_id))
;

alter table similar_person add constraint fk_similar_person_person_01 foreign key (person_id) references person (id) on delete restrict on update restrict;

alter table similar_person add constraint fk_similar_person_person_02 foreign key (similar_person_id) references person (id) on delete restrict on update restrict;

# --- !Downs

SET REFERENTIAL_INTEGRITY FALSE;

drop table if exists similar_person;

JPA をちゃんと理解してなかったのでけっこうハマった。

【参考】

JPA – Recursive ManyToMany-Relationship | stuetzpunkt -


[Play Framework] Play2.2.x で Java8 の記法で書いたらコンパイルエラーになった

Play2.2.x で play new したプロジェクトを素のまま使っていて Java8 の記法で書いたらコンパイルエラーになった。
2.2系は Java8 対応してないとのこと。

SBT のバージョン上げたら動くようにはなったけど、問題がありそうなので正式対応した 2.3系を使おう。

【参考】

[play-framework] Error Unknown constant: 18 - Grokbase - 


2015年2月4日水曜日

[Java][Excel][JETT] Excel帳票出力にJETTを試してみる

シフト表作成アプリ作る中で、Excel帳票を出力したくなったので軽くライブラリについて調べて見る。

調べる前に、以前に使ったことあるやつ

POI …以前に実務で帳票ガリガリ書いてたけど、かなりプリミティブで結構辛かった。なので生で使うのは本当に必要な時だけにしたい。
Fisshplate …テンプレートを使ってみて、やっぱりコレぐらいサクサク書けない と困ると実感した。ただ、今回出力したい xlsx 形式に対応していない(対応予定なし?)のでスルー。

Java × Excel だと POI の話題ばかり

Java8 / play framework でやっており、とりあえず最近だとどんなライブラリがあるのかと思い調べてみると、POI の話題ばかり。

どのライブラリも POI ベースでそれをラップするのが基本ぽいのに、もしかして皆 POI で頑張ってるのか…??

そんな中 Excel方眼紙を支える技術 - 新・たけぞう瀕死の日記 がかなり参考になった。

JETT を試して見る

なんとなく先端ぽく、↓の比較も面白かったので今回は帳票出力用ライブラリ JETT を試してみることにした。
本家サイトの jXLS との比較:JETT - Comparison to jXLS

とりあえずテンプレートファイルへの出力を試す。

1.テンプレートファイルを用意する。
2.出力コードを書く。

 public static File makeShift() {
  System.out.println(System.getProperty("user.dir"));
  
  List<employee> employees = Lists.newArrayList();
  
  Map<string object=""> beans = Maps.newHashMap();
  Employee emp = new Employee();
  emp.name = "Butcher";
  emp.skillLevel = "High";
  
  employees.add(emp);
  
  beans.put("employees", employees);
  
  String inPath  = "resources/shift_template.xlsx";
  String outPath = "resources/shift.xlsx";
  
  try (FileOutputStream fileOut = new FileOutputStream(outPath);
    InputStream fileIn       = new BufferedInputStream(new FileInputStream(inPath))) {

   ExcelTransformer transformer = new ExcelTransformer();
   Workbook workbook = transformer.transform(fileIn, beans);
   workbook.write(fileOut);
   fileOut.close();
   
  } catch (IOException e) {
   System.err.println("IOException reading " + inPath + ": " + e.getMessage());
  } catch (InvalidFormatException e) {
   System.err.println("InvalidFormatException reading " + inPath + ": " + e.getMessage());
  }
  
  return new File(outPath);  
 }

余分なコードが多いが、テンプレートへの出力処理は ExcelTransformer#transform で JavaBeans を渡すだけでOKなのでかなり簡潔。

テンプレートファイルに記述する構文もシンプルで良い。
個人的に、forEach タグを利用する時にデータの無い行や列にタグを書かなくて良いのは嬉しい。

番外

その他、調べて評判良かったのが ExCella だったけど、Maven repository に登録されておらずライブラリ管理を考えるのが面倒になってスルーした。
(今回は play なので build.sbt で管理)

2015年1月5日月曜日

[Heroku][Play Framework] New Relic APMを使って、一定時間アクセスが無くても Dyno をスリープさせないようにする

先日公開した Haiku Matcher で使っている Heroku の Dyno(プロセス) は一定時間(1時間?)アクセスが無いとスリープしてしまう。(IDLE状態になってしまう)

New Relic APM を使って叩き起こし続けることにした。

Heroku のスリープについて

会社の元同期に「Dyno寝てるっぽいよ」と教えてもらって、「あ、眠るんだ…」と知りました。

知っておきたい!Herokuを使う上では当たり前?の16の常識 | mah365 - 

確かに、暫く放置した後のアクセスにはレスポンスが急激に遅くなっていた。
また、Heroku の Personal Apps ページで対象のアプリケーションの六角形アイコンを見てみると、六角形の中に"zzz" が表示されていた。

Dynoとは
Dynoはアプリケーションサーバの1プロセスで、アプリケーションサーバThin(http://code.macournoyer.com/thin/)をベースにしているもののようです。Dynoは追加購入すれば、ユーザは柔軟に増やすことができ、2秒で起動するとのことです。
フレクトのクラウドBlog: Herokuについて調べたことのまとめ - 
スリープさせないためには。
  1. Dyno を増設する
  2. シェルなどで定期的に ping 打つ
  3. Heroku Addon の New Relic APM を使う
1.は課金することになってしまうので今回はパス。
2.は実行用の環境を用意するのが面倒なので今回はパス。

今回は無料プランがあり、Addon ということで簡単に導入できそうな3.を採用。

New Relic APM の導入

検索するといろんな言語での導入方法が出てくるが、今回は Java, かつ Play Framework を利用していたので下記を参考に実践した。
adding new relic addon to heroku play framework 2.2.1 java app - Stack Overflow - 

Amit Sharma 氏の answered Jan 28 '14 at 6:07 の投稿通りに実行した結果、1時間後でもスリープしていないことが確認できた。

上記内容で導入できたと思っていたら、できていなかった。
New Relic のページ見たらアプリケーション情報が表示されず、newrelic agent がそもそも起動してなかったと判明した…。

Java - Play2.2をherokuで動かした時にはまったポイント - Qiita - を参考にやり直したらうまくいったので、方法をきちんとまとめておく。

1) 決済情報を登録する。Heroku ダッシュボードから [Manage Account] → [Billing] で登録しておく。完了していればスキップする。登録していないと 2) で下記エラーが出る。
Adding newrelic:stark on your-app-name... failed
 !    Please verify your account to install this add-on plan (please enter a credit card)
 !    For more information, see https://devcenter.heroku.com/categories/billing

2) アドオンを入れる。
$ heroku addons:add newrelic:stark

3) 依存ライブラリを追加する。build.sbt に下記を追記する。
"com.newrelic.agent.java" % "newrelic-agent" % "3.12.1"
※newrelic-api は不要だった。
※最初にてきとうに 3.1.0 を選んだらエラー出て、Java8に対応してなかった。今回はJava8を使っているので、対応しているバージョンを選択した。

4) New Relic 関連のファイルを配置する。
ファイル群は New Relic の管理ページ → Application タブのページから取得できるはず。(自分のアプリが正常に連携されてからそのページが開けなくなった…)
・newrelic.yml のみルートディレクトリに配置する。
・それ以外(jarなど)は lib/ に配置する。

5) Procfile にVM引数を追加する。
-J-javaagent:lib/newrelic.jar
※Play2.2から JAVA_OPTS に設定してもダメとのこと。

6) ここまでの変更をコミット、Heroku へデプロイする。
$ git add .
$ git commit -m "optional message"
$ git push heroku master
数分後、New Relic の管理ページ →アプリケーションタブのページに自分のアプリ名が表示される。

7) New Relic の Monitoring 対象に自分のサイトを加える。
New Relic の管理ページ → Applications タブ → [自分のアプリ名] → Availability Monitoring → URL Monitor に自分のサイトのURLを入力する。
(参考)1DynoなHerokuをNew Relicでアイドルを回避 - PILOG - 




感想

簡単だと思ったら色々とハマった。Heroku Scheduler の方が簡単だったかも。

(参考)Heroku Scheduler

【環境 】

・Java8
・Play Framework 2.2.6


2014年12月31日水曜日

俳句調のツイートを検索して表示するWebアプリ作ってみた

俳句調のツイートを Twitter から検索して表示するWebアプリ作ってみた。

http://haiku-matcher.herokuapp.com/
https://github.com/ohbarye

テキストボックスに入力された値でツイートを取得して、その中から575調になっているものだけを表示する。
入力値がユーザ名なら、そのユーザのタイムラインから。ユーザ名でなければキーワード検索した結果からツイートを取得する。


言語/フレームワーク

  • Java8
  • Play Framework 2.2.6

□よかったこと
・やっぱりJava8で書くとコードが変わると思った。まだ知らない機能が多いので引き続き学びたい
・Play、噂通りで開発効率がかなり上がる
・特に立ち上げの速さ
・sbtによる依存性管理がストレスフリー
・Java EEから解放された感
 http://d.hatena.ne.jp/wyukawa/20140416/1397662264
・フルスタック感
・Hot Deploy
・scala templateの型安全性
…+まだやってないこといっぱいある

■困ったこと
・Play2.2系はJava8対応してなくて、sbtのバージョンあげたり結局諦めたエラーとかあった(2.3以降は対応済。よく調べずに2.2を選んだのは失敗)
・Playの更新頻度が高いので調べた情報が違うバージョンの情報…というのはよくあった

形態素解析

  • kuromoji

文章ぶち込むだけで解析結果を返してくれるライブラリ。全文検索エンジンの Solr とかでも使っているらしい。
Tweet から拾う単語は未知語(内蔵辞書に載ってない語)が多かった。今回は雑に処理したけど、そこらへん真面目にやろうとしたら自分で辞書用意する必要があるっぽくて震えた。

Twitter連携

  • twitter4j

直接 Twitter API を叩く必要ない。
ライブラリの問題じゃないけど、検索後によって401が返ってくるというよくわからないエラーでかなり悩んだ。時間を置いたりリトライしたら通るようになった。
いろいろググってたら Twitter から401エラーが返ってきて困った的な質問がめちゃ多くて世界中の悩み感があった。

プラットフォーム

  • heroku

初めて使ってみた。確かに爆速でデプロイできて便利っぽい。
環境・サーバ構築とかをほとんど考えなくてよくなったのでアプリ作る〜公開のハードルがまた下がった感がある。

けどまだ全然使いこなせてない。

git push heroku master した後の待ち時間が長いので休憩にしたりしてた。

フロントサイド

  • webjars
  • Bootstrap
  • LESS

フロントサイドの知識全然無いけど、この辺組み合わせるのがややモダンらしいので試してみた。
jqueryとか、クライアントサイドライブラリ揃えるのも確かに面倒なので webjars のこと知れてよかったという気持ちがある。

あまりよく知らないのでデザイン領域触れたくなかったけど、Bootstrap とか LESS とか試してみたら思ったより軽く書けたのでちょっと興味湧いた。けど深入りしたくない感じ。

その他感想

仕事で試す日が来ることは暫く無さそうで辛い(からい)。

2014年12月24日水曜日

[Play Framework] 設定ファイル(application.conf)から値を取得する

設定ファイル:application.conf に定義した値を取得する方法。意外と簡単で良かった。

とりあえず取得

key="value"
まず conf ファイルに定義する。
文字列にダブルクォーテーション付ける必要があるので注意。
Play.application()
       .configuration()
       .getString("key");    // "value" が取得できる

Configulationクラス

Configulation クラスには getString 以外にも getBoolean, getDouble など様々な型での値の取得が可能で便利だが、上記の書き方だとやたら長いのでラップしたメソッドを用意して使ってる。
 public static String getString(String key) {  
     return Play.application()
       .configuration()
       .getString(key);
 }

 public static boolean getBoolean(String key) {  
     return Play.application()
       .configuration()
       .getBoolean(key);
 }

2014年12月23日火曜日

[Play Framework] controllers 内でサブパッケージを作成する場合の注意点

Play Framework 始めた。

controllers 内にサブパッケージを作成して、その中のクラスおよびメソッドへのルーティングで一度失敗したのでメモ。

controller 直下のクラスにアクセスする

まず基本のおさらい。
パッケージ名:controllers
クラス名:MyClass
メソッド名:index
↑ココにアクセスしたい場合は以下のように routes とテンプレートファイルを編集する。
POST /index  controllers.MyClass.index()
@form(action = routes.MyClass.index) {
    <!-- 省略 -->
} 

controller 下のサブパッケージのクラスにアクセスする

本題はこのクラスのサブパッケージ内に作成する場合。
パッケージ名:controllers.sub
クラス名:MyClass
メソッド名:index
まず routes を修正する。
POST /index  controllers.sub.MyClass.index()
その後に scala.html 内のPOST先 action を修正。
サブパッケージ名をクラス名に付けてみる。
@form(action = routes.sub.MyClass.index) {
    <!-- 省略 -->
}
これでアクセスしてみると…
value sub is not a member of object controllers.routes
「"sub"なんてオブジェクトないよ」とのエラーメッセージ。
調べてみたところ完全修飾名で書けばOKとのこと。
There is a routes subpackage for each controller package. So the rightfully qualified name of your route is:@controllers.foo.routes.Home.index()
It's done this way to "see" the routes subpackage relatively from any
controllet package as "routes" 
[2.0] [Scala] routes for controller sub-packages - Google Groups -  
下記の通り修正したら無事通るようになった。
@form(action = controllers.sub.routes.MyClass.index) {
    <!-- 省略 -->
}

2014年12月22日月曜日

ローカルで作成したGitリポジトリを GitHub に push する

最近Git使い始めた。(仕事ではもっぱらSVN)
ローカル作業のバージョン管理だけやってたけどせっかくならGitHubも利用してみたい…ということでローカルに作成したリポジトリをGitHubに push する方法を調べた。

ほとんど↓に書いてある方法で出来たが、使ったことないコマンドあったのでメモしておく。
GitHubで、ローカルで作ったリポジトリから新規作成する - by shigemk2 - 

1. ローカルリポジトリ作成

今回はすでに完了していたけれども、まずローカルでリポジトリ作成〜コミットまで。
$ git init 
$ git add -A
$ git commit -m "optional message"

2. GitHubでリポジトリ作成

GitHubで "new repository" 。

3. リモートリポジトリを追加する

下記コマンドでリモートリポジトリ追加。
$ git remote add origin "https://github.com/<user name>/<repository name>"

4. ようやく push

$ git fetch
$ git merge origin/master
$ git push -u origin master

"-u branch master" は紐付けのために初回のみ必要とのこと。

git fetch ってとは。
git merge はなんとなくわかるがどんな挙動なんだ…というのは下記で。
fetch【リモートリポジトリ】 | サルでもわかるGit入門 〜バージョン管理を使いこなそう〜 | どこでもプロジェクト管理バックログ - 
git fetchの理解からgit mergeとpullの役割 - Qiita - 


結果、GitHubに push できた。
https://github.com/ohbarye/PlayPractice

【余談】

途中、リモートリポジトリ名を間違えた。再度 git remote add しようとしたら、エラーが出た。その時の対応は下記。
【githubエラー】fatal: remote origin already exists.の対処 - iwaheiもといロックソルジャーのweb(メモ||日記) - 

APPLE MacBook Pro Retinaディスプレイ 2200/15.4 MGXA2J/A 買ったら最高だった

 Mac mini 売った

MacBook Pro 買ったと言いつつ、まず Mac mini 打った話。

長らく Windows を使いつつも Mac に対する漠然とした憧れがあって今年6月に Mac mini を買った。主に開発と音楽編集とかやろうと思ってた。

けど周辺機器を全然揃えてなかったのでほとんど使えなかった。
  • ディスプレイがないのでテレビにHDMI接続してたけど、解像度を合わせるのも面倒でそのまま見てたら目が疲れた
  • Mac 用のキーボードがないので Windows 用のキーボードを使っていたけど、キー配置が訳わからなくなって入力に疲れた
  • トラックパッドがないので操作時にはマウスを使うことになってこれも疲れた
いろいろ揃えればなんとかなるってわかってももはや面倒くさくて熱が冷めていたので、テレビで映画観る時には Mac mini から再生する…ぐらいにしか使ってなかった。

Mac の利点をまったく活かせていないどころかPCとして全然機能しておらずインテリアになっていたので ¥44,000 で売却した。

全部自分のせいっちゃせいなんだけど、こういうのをいちいち調べて揃えるのも面倒な人はけっこういると思う。Mac mini、低価格で Mac に触れられるのは良いと思うけど、そいう意味で自分には向いてなかった。ケチって失敗したパターンだと思う。

MacBook 買った

なので最初からオールインワンになってる MacBook Pro 買うことにした。この時、もともと使ってた Lenovo のノートが限界近かった&ので選択肢はノート一択。

先に書いた通りめんどうくさがりで機能を全部集約したく、もう「コレ買っておけばもういいだろ」的なやつをケチらずに買おうとしてたので 15.4 インチの 16GB, SSD 256GB の MacBook Pro Retina : MGXA2J/A にした。

購入価格 ¥180,000 ぐらいだったので mini の売却資金差し引いてもややキツかったけど、買ってよかった。この買い物は全肯定できる。

ファーストインプレッション

いろんな人がいろんな利点を褒めてるので今更感しかないけれども、
第一印象はこんな感じ。

  • Retina ディスプレイ、フォントが良い。目に優しいし、ブラウジングもコーディングも長時間集中してても疲れにくくなった。たしかにこの後に Windows 触ったら文字がギザギザして見えた。
  • トラックパッドのおかげでマウス捨てた。iPhone みたいに操作できてストレスがない。
  • 見た目がかっこいい。出社するときに家に置いて行きたくない。
  • ボディ、トラックパッドの質感が良い。すべすべしてるので指がひっかかったりしない。
  • いちいちヌルヌル動くのが良い。トラックパッドでスクロールした時に指を離しても吹っ飛んでいったり、最下まで行ったあとにバウンドするように戻っていったりする。なんでこんな無駄っぽい動きに感動するんだろう、って思ったけど、これ本能っぽい。自然界の慣性を模倣した動きを前にすると優しい気持ちになれる気がする。感性学とかで説明してほしい。
  • SSDだと起動がめちゃ早い。Windows、基本的に再起動したくなかった。パッチ適用〜再起動とかいう最悪の定期作業で大体5分ぐらいかかっててその間は休憩するか〜とか言って携帯で twitter 見てた。二度とやりたくない。

MacBook に触ってるうちに「PCに対して自分が今までどれだけ我慢してきたか」に気づいた。これまで意識もしてなかったことが、実は積もり積もってけっこうなストレスになっていたっぽい。書いてて熟年離婚感がある。

高価な買い物して魔法にかかっている感も否めないけれども、PCは毎日触るので毎日満足感に浸れる。なので今年一番の満足してる。
とにかく家でPCに向かうのが以前より遥かに好きになったので良かった。

ただ会社では支給される Windows7 しか使えないのでいろいろ辛い。

2014年12月2日火曜日

選挙での「白票」を「社会を変える力がある」と主張していた団体について、福沢諭吉的な観点から思ったこと

選挙での「白票」を「社会を変える力がある」とミスリードする謎の集団「日本未来ネットワーク」のサイトが突如出現 | BUZZAP!(バザップ!) - http://goo.gl/Fx820u

こういうのに飛びつく人間が周囲にいたので、なんだかなぁ…と思っていた。
思っているだけだったので、諭吉の言葉などを使って表現してみた。

政治に関心の無い人間の一例として、"コンディショナル・グッド-条件付き善-"、つまり絶対的な価値判断でなくて状況によって制約された善悪というものを理解していない。かんたんに言えば相対的な価値判断ができない。

価値判断ではたびたび、ベストな選択ではなくベターな選択を強いられる。また、政治的な判断に代表されるように、「悪さ加減」が価値判断の根拠となることもある。これは状況認識の話だが、悪いものばかり並べてみるのは精神的に苦痛、という精神衛生にも関わってくる。こうした状況に手っ取り早い結論を求めるようなひ弱な精神は耐えられない。だから判断を投げ出す。

投げ出すだけならまだ良いのだが、投げ出す行為にあたかも主体性があるかのように振る舞うタイプの人間もいる。これは独立ではなく単なる機会主義であり、やはり"惑溺"の一種なのである。

この"惑溺"こそ福沢が激しく批判した状況認識・判断の誤りであるからこそ、絶対にブッ飛ばす必要があるのでムカついてたとわかった。

2014年10月25日土曜日

『プロとしてのデータモデリング入門』書評

担当案件でDB設計やることになった。
ERDなどの設計書類は読んでいたけれども、ゼロからどうやって設計するのかをきちんと理解しないとな~と思い、評判良かった『プロとしてのデータモデリング入門』を読んだ。

とにかく実践的で良かった。
データモデリング、データベース設計の入門におすすめ。

説明が丁寧

入門と付くだけあって平易な表現で基礎的な説明から入っていき、説明に冗長な印象もあったが入門ということで特に気にはならなかった。何より、なぜその要素が大切なのか?現場ではどのように捉えられているのか?をしっかり解説してくれていので丁寧さと映った。

特に、モデリングにて最重要となるER図の書き方には多くのページを割いていて、これ一冊でER図は書けるようになる。

実用的なテクニックが多い

アプリケーションとの連携や実運用をきちんと見据えた方法論を提示してくれていて、これがまた良い。現場ですぐに使える。
  • 業務要件が固まっている場合のトップダウン・アプローチ、画面イメージから入る場合のボトムアップ・アプローチ
  • 性能要件を満たすための導出項目の設計や非正規化
  • データの更新・参照頻度を意識した索引の設計  etc.

スーパータイプ/サブタイプ使える

個人的に最も役に立ったのがスーパータイプとサブタイプの分割。
オブジェクト指向的な考え方をデータ設計でもできるのか~と眼から鱗。

これを実際に現場で試してみて、現実で単一/複数のエンティティでも、実態を整理すると分割/統合できることがわかり、そうして整理することでより説明に適したERDが書けるようになった。

また、概念的にスーパー/サブタイプに分かれていても、論理設計(テーブル設計)では必ずしも分割する必要は無い、というのも実践的なポイント。これを取り入れることで、概念的なERと実際のテーブルの関連それぞれを多層的に捉えられるようになった。


当然ながらこれ一冊でDB設計が完璧になることはない。
処理(プロセス)との関連を含めて最適なアーキテクチャを探る方法や、データベース製品の機能を利用して実現できるプラクティスについて多くは触れていない。そこを考える以前の話なので。

データモデリングの基礎の理解が曖昧で、もう少し正確に理解したい…という人にはおすすめ。
DB設計面白い。

2014年10月22日水曜日

[DB設計] リレーショナルデータベースでは履歴の管理をすべきでない?

リレーショナルデータベースで履歴の管理は難しい。


いまDB設計を担当している案件で、業務用件として履歴管理が現れた。
「データの更新の度に更新前後のデータを保持し、過去のある時点のデータを再現したい」という。

どう実装するか。。

追加のみ行うよう設計する

はじめに考えたのはテーブルAにはレコードの追加のみ行う、という方法。
しかし…下記の理由により断念。
  1. テーブルAのオカレンスは頻繁に更新され、レコード数が大変なことになる。オンライン処理の為、厳しい。
  2. また、今回はテーブルAだけでなく、テーブルAとリレーションを持つ他の幾つかのテーブルの履歴も持たなければならない。つまり、テーブルAを更新する為に他の複数のテーブルにINSERTを行わなければならなくなってしまう。これをアプリケーション実装者に強いるのはリスク。

本体と履歴の情報を分ける

テーブルAとは別にテーブルA履歴を用意する方法。履歴テーブルにはテーブルAの主キーとリビジョンなどを持たせる。最新のデータを取得するにはテーブルAを見るだけで良いので問題1.は解決。

テーブルAの更新と同時にテーブルA履歴にINSERT。これも問題2.を孕んでいるが、テーブルUPDATE,INSERT,DELETE時に履歴系テーブルにINSERTするトリガーを作成することでやや改善する。データの追加・更新・削除は履歴を意識せず、本体に行えば良いのでアプリ実装負担にはならないはず。


ひとまずこんな感じで設計したが、未だ残る一番の懸念は履歴に対する検索処理。とにかく重そう。
集計表としてマテリアライズド・ビューの作成も検討しているが、検索条件の柔軟な変更に対応できるだろうか?また、対応コストは高くつかないだろうか?
もう少し、考えてみたい。

履歴とは


ちなみに【DOAコラム】-更新と履歴によると、履歴には3種類があるという。(詳細はリンク先参照)
1.単純に行為・出来事の事実を記録する履歴
2.元の行為・出来事が変更されるので、変更前の状態を記録する履歴
3.継続的な発生を前提にして、行為・出来事の事実を記録する履歴
今回の要件では2.に当たる。このうち1.と3.の実態はイベント(行為/出来事)の集積であって、イベントテーブルを作ってそこにレコードを追加していけばよいとのこと。

【参考】


2014年10月9日木曜日

[html] name属性を定義していないinputタグのformデータは送信されない

当たり前のことだけどこれの不理解に起因するバグがあって時間とられたのが悔しいのでメモ。
まぁ、テンプレートエンジン使ってると見落としがちなのかもしれないが…。

[JavaScript] wait~リトライを行う処理

クライアントサイドJavaScriptでwait処理に相当するものが必要になったので調べてみた。

そもそもJavaScriptにはwait / sleep に相当する関数が無いみたいだが、
遅延処理を実現する setInterval() / clearInterval() の2つのメソッドにて同様の関数を実装できると判明。

今回は純粋なwait処理だけでなく、非同期に行われる処理との同期をとるためのチェックも行える必要があったのでこんな関数を書いた。

/* 
 * 条件を満たすか、指定回数だけリトライするまで待つ
 * ループ処理としても使える
 * [引数]    test        :終了条件を満たすかどうか判断する関数
 *             callback    :終了条件を満たした後に呼び出す関数
 *             time        :ポーリングタイム(ms)
 *             retry        :リトライ回数
 */
function wait(test,callback,time,retry) {
    // リトライ指定が無い場合はデフォルト回数を設定
    if(retry === undefined) { retry = 3; }
    
    var count = 0;
    
    // wait条件を満たすまで繰り返す処理
    var process = function() {
                        count++;
                        if(test() || (count > max)) {
                            clearInterval(timer);
                            callback();
                        }
                    };
    var timer = setInterval(process(),time);
}


参考にしたサイトでも指摘されていたが、時刻の取得→比較を繰り返すのはブラウザが固まってしまうアンチパターンなのでNG。

普段はJavaばかり書いてるので、JavaScriptでクロージャを意識したコードを書くの楽しい。

【参考】
【JavaScript】処理の実行タイミングを遅らせる方法 | Web制作会社スタイル
遅延実行 | JavaScript プログラミング解説
javascript で wait処理 - 新みのる日記

2014年9月19日金曜日

[カメラ] 逆光を利用して写真を撮る

友達の記事:井山の写真の解説 | 写真をちょっといい感じにする方法集を読んで感化されたので谷中近辺を散策しつつ、実践してみた。

とりあえず一枚…
それらしき感じのが撮れて良かったが、この花の名前がわからないので誰かに同定してほしい次第。





Bloggerでデザインを変更したらHTMLテンプレートが初期化された

タイトルそのままだが、Bloggerでデザインを変更したらHTMLテンプレートが初期化された。

デザイン変更直後にSyntaxHighlighterが効かなくなってるな~と思っていたら、jsファイルを読み込んで無かったのでもしやと思い確認したところ、やっぱり初期化されていた。

↓をHTMLに追記して、OK。


<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'/>
<script language='javascript'>
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = &#39;http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf&#39;;
SyntaxHighlighter.all();
</script>