2009年5月30日土曜日

情報感度を広げておくだけではいけない 一歩先へ

エンジニアとして大切なこととして一つ学んだのでメモ。

google リーダーはいつも見てます。
はてブのホットエントリーは欠かさずチェックしてます。
気になるワードはgoogle alertで確認しています。


これらはすごく重要だけれども、それだけではいけない。

これらの情報の中には一見、いいな!使ってみたいな!
と思える情報がたくさんあります。

ただし、それだけで終わるのではなく、ちゃんと考えることが重要。
特に、
「なぜ?だから何?」
「他には?」
という垂直型の志向プロセスと、水平型の志向プロセスを組んで考えた方がいい。

自社のサービスにとっていいと思える情報を見つけたとして、それがいいらしいということで終わるのではなく、
こういう理由でこの情報は有効であり、自社のサービスの中のこの問題を解決できる。という垂直思考。(ロジカルシンキング)

また、じゃあ、その問題に対して他に解決案はないのか、その情報を元にした取組を行う際に問題となる点はないか。という水平思考(ラテラルシンキング)

今後、意識して取り組んでいこう。

やるべきか、やらざるべきか ~KPT (keep, problem, try)~

事業計画について考えていて、現在考えている事業計画を実行するか否か、
KPTという観点で考えた方がいいというアドバイスを受けたので調べてみた。

K:keep=今後も続けること
P:problem=問題なので、やめること
T:try=今後、試してみたいこと

フレームワークとしては
tryが大枠としてあって、tryの項目をkeepやproblemに振り分けていくというもの。

アジャイル開発や反復型開発ではイテレーション(繰り返しの単位)ごとに作業の振り返りが推奨されるが、そのためのチーム反省会などでよく用いられるフォーマットである。

らしい。


個人的な仕事の振り返りにも使えるフレームワークであり、仕事の振り返りとして有効そうなPDCA(改善サイクル)、GTD(ストレスフリーな仕事術)よりもシンプルに仕事管理ができそうな気もした。

2009年5月28日木曜日

ヒアドキュメントを知らずにAptanaで苦労した

ヒアドキュメントでちょっと躓いたのでまとめ。
ヒアドキュメントとは

UNIXのシェル(csh、bashなど)が提供する、スクリプト用の機能の1つ。コマンドの標準入力に渡すデータをスクリプトファイル中に記述できる。これによって、スクリプトファイル中に比較的大量の定数テキストデータ(少量なら、echoコマンドで生成できる)を埋め込むことができ、管理が容易になる。ヒアドキュメントは、リダイレクト記号“<<"によって記述する。

by デジタル用語辞典

らしいですね。
要は長い文字列を扱うときに使いますよと。
Rubyでは例えばSQL文を直打ちするときに

sql = <<-SQL
  SELECT * FROM tables
WHERE ...
   ...
SQL

Model.find_by_sql( sql )

のように使う。別に

Model.find_by_sql("
SELECT * FROM tables
WHERE ...
   ...
")

でも同じ結果が出る。

と、思ってたけど文字列を指定する部分の中が長くなりすぎるとよくないみたい。
Aptanaで開発する場合には。

ヒアドキュメントを使わずにちょっと長めのSQL文を書いてAptana経由でリポジトリにコミットかけようとしたらエラー発生。。
長めの文字列を指定するときにはヒアドキュメントを使うようにしよう。

2009年5月18日月曜日

カーソルについてMindMapでまとめてみた

カーソルについてのマインドマップでのまとめ

ポイントは
非手続き型言語であるSQLに対して繰り返し処理ができるということ。

カーソルの指定の仕方は
①カーソルの宣言
②カーソルを開く
③1行ごとにデータを取り出す
④カーソルを閉じる



まとめてみたのはいいものの、どこで使えばいいのかの見当は立っておらず。。

RailsでSQLを直打ちする方法 ~使うメソッドの違いによる戻り値の違い~

RailsでSQLを直打ちする方法は2種類あるらしい。
でも、それぞれの戻り値のデータ型に違いがある。

①find_by_sqlを使う方法
②select_allを使う方法

find_by_sqlを使う方法だと、戻り値はActiveRecordオブジェクトの配列となり、select_allを使うとハッシュの配列となる。

なので、たとえばarticlesテーブルのモデルArticleに対して、このテーブルがdetailというカラムを持っているとしよう。このとき、

articles = Articles.find_by_sql("select * from articles")

とすると、articlesテーブルのある行のdetailカラムへのアクセスは、

articles[0].detail

となり、

articles = Articles.connection.select_all("select * from articles")

とすると、

articles[0][detail]

となる。
ちょっと注意ですね。

2009年5月16日土曜日

トランザクションについてMindMapでまとめてみた

トランザクションについてのマインドマップでのまとめ。

ポイントは以下の3点
①ACID特性
②コミットとロールバック
③排他制御

Ruby on Rails どうしてもエラーの原因がわからない時には

①文字コードがおかしなことになってませんか?
②予約語を使ってませんか?

あたりをチェックしてみるといい。



文字コードがおかしなことになってませんか?


Railsが処理する文字コードはUTF-8。

ウインドウズ環境で
ruby script/generate
によるファイル生成をにより生成されるファイルの文字コードはSHIFT-JIS。

エディタで編集して保存するときにはそのまま保存するのではなくutf-8で保存するという点に注意が必要。
AptanaやEclipseなどの統合開発環境で保存するときには勝手にやってくれるみたいなのであまり意識する必要はないけど、Eclipseから軽い秀丸エディタあたりに変えた時にはまりそうなので注意しとこう。


予約語を使ってませんか?


予約語は変数名やテーブルのカラム名に使うとエラーが出る。またそのエラーがわかりにくい。
rubyの予約語、railsの予約語、SQLの予約語についてまとめる。

①Ruby予約語
BEGIN class ensure nil self when
END def false not super while
alias defined? for or then yield
and do if redo true
begin else in rescue undef
break elsif module retry unless
case end next return until

クラス名、変数名などに用いることはできないみたい。接頭辞$, @、@@が先頭についたものは予約語とは見なされないので使うことが可能。また、def のあとやメソッド呼び出しのピリオドのあとなどメソッド名であるとはっきり分かる場所ではメソッド名として用いることができる。

参考:
http://www.ruby-lang.org/ja/man/html/_BBFAB6E7B9BDC2A4.html

②rails予約語
多すぎるので参考リンクのみ。
http://wiki.rubyonrails.org/rails/pages/
ReservedWords#reserved_words_you_can_t_use


Other Names Reported to Have Caused Trouble
"トラブルが報告された他の名前"

という語も使っちゃだめらしい。

③sqlの予約語
テーブル名・カラム名にこれらの言葉を使うのはやめましょう。
http://msdn.microsoft.com/ja-jp/library/ms173340.aspx

webサイト表示の体感速度を上げる方法 cssは先に、javascriptは後に

webサイトを構成する際、HTMLの中にcssとjavascriptのタグをインラインで組み込むことが多いと思う。
その際、cssは先に、javascriptはあとに書いた方がいいよというお話。

簡単に説明すると、
①ブラウザはダウンロードしてきたものから順次レンダリングしようとする
②cssはHTMLを表示するためのレイアウトを決定し、javascriptはHTML表示後の動きを決定する

ということがポイント。


HTMLが呼ばれた順番にブラウザ上ではページが表示されていく。よってページのレイアウトを決めるCSSが先に読み込まれていた方が表示は早い。再度レイアウトを変更する必要がないから。
また、javascriptはHTML構成後の動きを決定する部分で在るので、HTMLが完全に読み込まれた後でもいい。言ってみれば完全にブラウザ上でページが構成された後でもいい。


なので、cssは先に、javascriptはあとに書くことでHTMLの「体感速度」が向上するわけですね。


ちなみにcssとjavascriptをできるだけ外部コンポーネントとして構成してあげるとブラウザにページキャッシュとして保存されるのでより高速化するみたいですね。


ポイントは
①css、javascriptはできるだけ外部コンポーネント化
②どうしてもインラインに記述する場合はcssが先、javascriptが後。


参考:
http://www.onflow.jp/cyano/archives/143
http://www.inter-office.co.jp/contents/188/

2009年5月14日木曜日

zipファイルの展開後のディレクトリ構造について

たとえばimagesディレクトリのfile1.jpgとfile2.jpgをzip圧縮しようとするときの話。
linuxのコマンドで、


zip image.zip images/file1.jpg images/file2.jpg


と打ってzipファイルを生成すると、展開先のディレクトリにはimagesディレクトリの下にfile1.jpg、file2.jpgファイルが展開される。

展開先ディレクトリ直下に直接圧縮ファイルをおきたい場合は、一旦ディレクトリを移動したのち圧縮をかける必要がある。


cd images; zip image.zip file1.jpg file2.jpg; cd ..;

2009年5月13日水曜日

HTTPに関することをMindMapでまとめてみた

これから覚えよう。

参考
http://www.studyinghttp.net/
http://www.tohoho-web.com/ex/http.htm

2009年5月12日火曜日

blankとnil

blankの意味は空っぽ
nilの意味は存在しない

あるオブジェクトが
 nilならばblankは真
 blankならばnilは偽

  
nil.nil? => true
nil.blank? => true
[].blank? => true
[].nil? => false
[nil].blank? => false
[nil].nil? => false
[nil].first.blank? => true
[nil].first.nil? => true


オブジェクトが変数になってると意外と見落とすところ(特に最後)

ファイル転送

ファイル転送メソッドについて。

  
require 'net/ftp'

def self.upload(file, options)

  ftp = Net::FTP.new
  ftp.connect(options[:ftp_server])
  ftp.login(options[:user], options[:passwd])
  ftp.binary = true
  ftp.chdir(options[:dir]) if options[:dir] 
  ftp.put( file )
  ftp.quit

end

と書いてあげればファイルのFTPアップロードができる。
ちなみに引数は以下の通り。
  
files #転送したいファイルのファイル名を要素に持つ配列
options[:ftp_server] # サーバーのホスト名
options[:user] # ユーザ名
options[:passwd] # パスワード
options[:dir] # 転送先ディレクトリ

ruby リファレンスによると、
  
Net::FTP#put(localfile, remotefile = File.basename(localfile), blocksize = DEFAULT_BLOCKSIZE)
Net::FTP#put(localfile, remotefile = File.basename(localfile), blocksize = DEFAULT_BLOCKSIZE) { |data| .... }

binaryの値に従ってローカルファイル localfile を送信し、 remotefile をファイル名とするリモートファイルに保存します。 remotefileが省略されるとlocalfileのベースネームが仮定されます。 block_sizeが省略されるとDEFAULT_BLOCLSIZEが仮定されます。この値は binary が真であるときのみ有効です。
---

らしいので、転送先で指定したファイル名で転送先に保存したい場合はputの引数に保存するファイル名を指定してあげるとよい。

2009年5月11日月曜日

find関数のincludeオプションで気をつけること

大きな子関連を持つデータベースから情報を引っ張ってくるときにincludeオプションを使うと便利だけど、よくよく考えないといけないよというお話。

データベースから情報を引っ張ってきて、その内容をcsvに吐き出す処理書いているのだけれども、全部で1000件以上あるデータを処理しようとすると、

[FATAL] failed to allocate memory

ってエラーが出てきて処理が途中で止まってしまう。。


ファイル入出力が原因か?
ループの中で毎回配列のメモリを割り当ててるのが原因か?

と、いろいろ原因を探っていったのだけれども、結局大きな原因だったのがfindのincludeオプション。

find関数を使うときに単にincludeで関連テーブルを追加で引っ張ってくるだけだと必要でないデータも一緒に読み込むのでメモリに使用される情報が非常に大きくなる。

で、上記のエラーが出たと。

とりあえずconditionsオプションに必要な情報のみincludeで指定して実行してみたところ、
以前に比べて1/5くらいの速度で処理が進むようになり、上記エラーも出なくなりました。


現状だと一度に読み込む情報量は減った分、必要な時に毎回SQLのクエリを投げて情報を引っ張ってきてるのでまだまだ改善の余地はありますが。。

select句を使って必要な情報のみとってくればもっと早くなるらしいのですが、それについては今後検討したいと思います。。