投稿日 2009年8月13日 木曜日 カテゴリ javascript 投稿者 morimotoコメント(0) » 

morimotoです。

前回の「jQueryでシンプルにExpanderを作る」の続編です。

前回作成したものを使ってみて思ったこと、「うーん、いまいち!」

ということで改良してみました。

(function($){
  var options = {
    initCollapse: true,
    bindEvent: 'click',
    collapsedClass: 'collapsed'
  };

  $.fn.simpleExpander = function(target, opts){
    if (opts) { $.extend(options, opts); }
    $(this).addClass('simpleExpander');
    if (options.initCollapse)
        $(this).addClass(options.collapsedClass);
    return initializeExpander(this, target, options);
  };
  function initializeExpander(trigger, target, options) {
    toggleTarget(trigger, target, options.collapsedClass);
    $(trigger).bind(options.bindEvent, function(){
      $(this).toggleClass(options.collapsedClass);
      toggleTarget(trigger, target, options.collapsedClass);
    });
    return $(trigger);
  }
  function toggleTarget(trigger, target, collapsedClass) {
    if(target) 
      $(trigger).hasClass(collapsedClass) ? 
          $(target).hide() : $(target).show();
  }

})(jQuery);

使い方

expand/collapseする対象をjQueryオブジェクトで指定する

Demo

クリックすると…

朝食にバナナボートを食べました。冗談です。
Code
<p id="expander-test-1"  
style="border:1px solid #666;background-color: #FEE">test 1</p>
<div id="test-1">
  <span>朝食にバナナ<b>ボート</b>を食べました。<b>冗談です。</b></span>
</div>
<script type="text/javascript"><!--
$('#expander-test-1').simpleExpander($('#test-1').find('b'));
// --></script>

Optionを入れてみる

Demo

マウスを乗せると…

Expand対象Expand対象外もselector次第です。
Code
<p id="expander-test-2" 
style="border:1px solid #666;background-color: #FEE">マウスを乗せると...</p>
<div id="test-2">
  <span><b>Expand対象</b>と<b>Expand対象外</b>もselector次第です。</span>
</div>
<script type="text/javascript"><!--
$('#expander-test-2').simpleExpander($('#test-2').find('span b:first'), 
{initCollapse: false, bindEvent: 'mouseover'});
// --></script>

以上、morimotoでした。。。

投稿日 2009年8月10日 月曜日 カテゴリ ソフトウェア開発, プロジェクト管理 投稿者 syojiコメントは受け付けていません。 

Peace Pipe: 効率の良いコードレビュー [software] を読んでソースコードレビューの必要性について考えてみたい。

ソースコードのレビューをやっているか?

ツールなどを使ったソースコードチェックは多くのSIerで行われていると思うが、ここではソースコードレビューについて。 プロジェクトによっては「全くやっていない」「重要なプログラムだけ選んでやっている」など、プロジェクトの状況、状態によって異なると思う。

自分の過去の開発経験では、プリントアウトしたソースコードを2人で組になって読み合わせをした。

  1. 1. 開発者がレビュアにロジックを説明する。
  2. 2. レビュアーは疑問に思ったことを聞く。
  3. 3. ここで、機能的な不具合、アルゴリズム、モジュール分割をみる

時間的な制限があるためすべてのコードについて実施できない場合がほとんどだったため、レビュー対象となるソースコードは次のような点を考慮してレビュー対象を決めていた気がする。

  • 特定の担当者が作成したコード
  • 共通モジュール
  • サーバサイドのコード
  • ソースコード(処理)が複雑であるコード(プロジェクトによって複雑度は異なる)
  • ソースコードをざっと眺め、引っかかるコード、気になったコードを見つけた場合

ソースコードレビューについて、誰が行うか、観点は?の説明されている以下のサイトが参考になる。

IPA ISEC 第2章 脆弱性回避策とソフトウェア開発工程:ソースコードレビュー

観点

  • コーディング規約、命名規約に従っているか
  • 言語特有の技術的なノウハウに違反していないか
  • ロジックエラー、仕様違反していないか
  • 深すぎるネスト、巨大すぎる関数など・・・

ソースコードレビューの必要性として特に言われることとして、以下の2点がある。

「開発者のスキルが上がる」

開発者よりも高いスキルをもつレビュアが、ソースコードのレビューを行うことで、書き方の指導や考え方のトレースをすることになり、開発者のスキルを向上させることができる。 ソフトウェア開発では特にその”人”のスキルに依存しがちである。長い目で見て開発者のスキルを上げることが品質の良いシステムを開発する上で最も効果がある。

「ソースコードの質がよくなる」

ソースコードレビューによりバグを抽出することで品質が向上する。検出されなければいけない工程で確実に検出できることは必須であると思う。当然、前工程で検出されたバグ修正も少ないコストで可能である。 ソースコードが第三者の目に触れず、開発者だけが「正しい」と認識することは避けるべきであり、その仕組みをチーム内に作っておくことは重要である。 進捗ミーティングや報告会と同様にコードレビューを定着させるべきだと思う。

投稿日 2009年8月7日 金曜日 カテゴリ postfix 投稿者 sugimotoコメント(0) » 

sugimotoです。

インターネット向けのシステムでは、ユーザーからのメールを受信して自動的に処理をすることがあります。

  • メール投稿された記事をブログにアップする
  • 空メール送信による自動登録

postfix をメールサーバーにメール受信によるスクリプト実行の設定をする方法をメモしておきます。

1. postfixの設定

メール受信をするための細かい設定は省略しますが、スクリプト自動起動のため、alias の設定をします。

/etc/postfix/main.cf に以下の行を確認します。default で書いているので、そのままでいいですね。

alias_database = hash:/etc/aliases

受信するメールアドレスを正規表現で設定したい場合、正規表現アドレスを設定するファイルも追加しておきます。

alias_database = hash:/etc/aliases, regexp:/etc/aliases.regexp

2. aliasの設定

スクリプトを起動するメールアドレスを設定するために alias ファイルに設定を追加します。

groove@xxxxxx.xxx 宛てメールを受信したときに groove.php を実行する

[/etc/aliases]
groove: "| /usr/bin/php /var/lib/groove.php"

open-xxxxx@xxxxxx.xxx 宛てメールを受信したときに open.php を実行する

この場合、正規表現設定用のファイル /etc/aliases.regexp に正規表現で設定します。

[/etc/aliases.regexp]
/^open-/: "| /usr/bin/php /var/lib/open.php"

簡単です。。

3. postfixの設定

設定が終わったのでさっそくメールを送ると、以下のエラーで失敗してしまいました。

Command died with status 1: " /usr/bin/php
   /var/lib/groove.php". Command output: No log handling enabled -
   turning on stderr logging /usr/share/snmp/mibs/SNMP-COMMUNITY-MIB.txt:
   Permission denied /usr/share/snmp/mibs/NET-SNMP-TC.txt: Permission denied
   /usr/share/snmp/mibs/SNMPv2-TC.txt: Permission denied
   /usr/share/snmp/mibs/SNMPv2-SMI.txt: Permission denied
   /usr/share/snmp/mibs/SNMP-NOTIFICATION-MIB.txt: Permission denied
   /usr/share/snmp/mibs/SNMPv2-CONF.txt: Permission denied
   /usr/share/snmp/mibs/LM-SENSORS-MIB.txt: Permission denied
  ...中略・・・
   /usr/share/snmp/mibs/TRANSPORT-ADDRESS-MIB.txt: Permission denied
   /usr/share/snmp/mibs/IF-MIB.txt: Permission denied
   /usr/share/snmp/mibs/IPV6-UDP-MIB.txt: Permission denied Cannot find module
   (IP-MIB): At line 0 in (none) Cannot find module (IF-MIB): At line 0 in
   (none) Cannot find module (TCP-MIB): At line 0 in (none) Cannot find module
   (UDP-MIB): At line 0 in (none) Cannot find module (HOST-RESOURCES-MIB): At
   line 0 in (none) Cannot find module (SNMPv2-MIB): At line 0 in (none)
   Cannot find module (SNMPv2-SMI): At line 0 in (none) Cannot find module
   (NOTIFICATION-LOG-MIB): At line 0 in (none) Cannot find module
   (DISMAN-EVENT-MIB): At line 0 in (none) Cannot find mod

しばらく途方にくれていましたが、Googleで検索したところ、 selinux がONになっていたことが原因ということ。

[/etc/selinux/config]
SELINUX=disabled < < enforcingから変更

以上、で成功しました。

zeera document search

エンタープライズ検索 zeera document search

zeera document searchで社内文書検索

投稿日 2009年8月5日 水曜日 カテゴリ Python 投稿者 omaeコメント(0) » 

omae です。

今回は Python でタイムゾーンが扱いたくなり Trac 0.11 より利用されている pytz を使ってみました。

pytz はタイムゾーンのデータベースを中に取り込んでおり、プラットホームに依存せずにタイムゾーンを扱えるようになっています。同種のライブラリとして Ruby では TZInfo などがあるようです。

大抵の Linux ディストリビューションでは /usr/share/zoneinfo にタイムゾーンのデータベース(tzdata)がインストールされているので二重にデータベースを持っているのが個人的には少し気持ち悪い感じがします。(連携できないのかな?)

http://pypi.python.org/pypi/pytz には egg ファイルが用意されているので、すぐにインストールできるようになっています。ということでさくっとインストールしてみてください。今回使用したのは pytz-2009j です。それでは使ってみます。

まずは、日本のタイムゾーンを取得します。これには pytz.timezone を用います。

>>> from datetime import datetime, tzinfo
>>> import pytz
>>> tz_tokyo = pytz.timezone('Asia/Tokyo')
>>> tz_tokyo
<DstTzInfo 'Asia/Tokyo' CJT+9:00:00 STD>
>>> isinstance(tz_tokyo, tzinfo)
True

ここで返ってくるインスタンスは datetime.tzinfo のインスタンスになります。
次に UTC の現時刻を取得しますが、datetime.utcnow() は使わずに datetime.now(), pytz.utc を使ってタイムゾーンが指定された datetime インスタンスを取得しておきます。

>>> pytz.utc
<UTC>
>>> isinstance(pytz.utc, tzinfo)
True
>>> utcnow = datetime.now(pytz.utc)
>>> utcnow
datetime.datetime(2009, 8, 5, 14, 10, 10, 744246, tzinfo=<UTC>)
>>> format = '%Y-%m-%d %H:%M:%S %Z%z'
>>> utcnow.strftime(format)
'2009-08-05 14:11:26 UTC+0000'

datetime.utcnow() を使用しない理由ですが、tzinfo クラスのメソッドのいくつかは datetime インスタンスにタイムゾーンが指定されていないと動作しないものがあるためです。たとえば pytz.utc.fromutc() に datetime.utcnow() を渡すとエラーになってしまいます。

>>> pytz.utc.fromutc(datetime.utcnow())
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: fromutc: dt.tzinfo is not self
>>> pytz.utc.fromutc(utcnow)
datetime.datetime(2009, 8, 5, 14, 11, 26, 183394, tzinfo=<UTC>)

さて、tz_tokyo と utcnow を使って日本時間を表示してみます。

>>> tz_tokyo.fromutc(utcnow)
datetime.datetime(2009, 8, 5, 23, 11, 26, 183394, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
>>> tz_tokyo.fromutc(utcnow).strftime(format)
'2009-08-05 23:11:26 JST+0900'

ちゃんと +9 時間になっています。ついでにスウェーデンの現地時刻も表示してみます。

>>> tz_sweden = pytz.timezone('Europe/Stockholm')
>>> tz_sweden
<DstTzInfo 'Europe/Stockholm' CET+1:00:00 STD>
>>> tz_sweden.fromutc(utcnow).strftime(format)
'2009-08-05 15:37:07 CEST+0200'

日本時間から見て -7 時間のようです。

次は pytz からタイムゾーンの一覧ですが、これには pytz.common_timezones を用います。pytz.all_timezones というのもありますが、こちらにはすでに廃止されたタイムゾーンなども含まれているので通常使う分には common_timezones で問題ないと思います。

>>> len(pytz.common_timezones)
393
>>> pytz.common_timezones[:10]
['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', 'Africa/Algiers', 'Africa/Asmara', 'Africa/Bamako', 'Africa/Bangui', 'Africa/Banjul', 'Africa/Bissau', 'Africa/Blantyre']
>>> pytz.common_timezones[-10:]
['Pacific/Wake', 'Pacific/Wallis', 'US/Alaska', 'US/Arizona', 'US/Central', 'US/Eastern', 'US/Hawaii', 'US/Mountain', 'US/Pacific', 'UTC']

このようにタイムゾーン名のリストになっています。実際には利用者に 300 を超えるタイムゾーンの中から選択してもらうのは大変ですので、タイムゾーンごとに GMT からのオフセットを取得することを考えてみます。

tzinfo のリファレンスを参照してみると utcoffset() というメソッドがありオフセットを取得するよいように見えるのですが、pytz が返してくる tzinfo インスタンスに対して utcoffset() を使用すると間違った値を返してくるタイムゾーンが出てきます。

>>> tz_tokyo.utcoffset(utcnow)
datetime.timedelta(0, 32400)    # GMT+09:00
>>> tz_sweden.utcoffset(utcnow)
datetime.timedelta(0, 3600)     # GMT+02:00
>>> tz_fiji = pytz.timezone('Pacific/Fiji')
>>> tz_fiji.utcoffset(utcnow)
datetime.timedelta(0, 42840)    # GMT+11:54?

フィジーのタイムゾーンは http://ja.wikipedia.org/wiki/フィジー にある通り GMT+12:00 (43200) ですが GMT+11:54 (42840) という中途半端な値を返してきてしまいます。

この症状に似たのはないかとバグデータベースのほうを探してみると当てはまるものがあり workaround も示されていました。Bug #310606 in pytz: “Incorrect utcoffset returned from timezones” です。これに従いやり直してみると

>>> tmp = datetime.now()
>>> pytz.utc.localize(tmp) - tz_fiji.localize(tmp)
datetime.timedelta(0, 43200)    # GMT+12:00

となります。この式を用いて (GMT+12:00) Pacific/Fiji のような文字列に変換しオフセットでソートすれば少しは選択しやすくなると思います。

さらに選択しやすくするには

  • 国(ISO-3166)を選択してもらい pytz.country_timezones から該当するタイムゾーンだけを表示する (Google Calendar ではこのようになっています)
  • javascript を用いて new Date().getTimezoneOffset() に該当するタイムゾーンだけを表示する

などの方法があるかと思います。

日本にいると夏時間がなく使用するタイムゾーンは1つしかないので、タイムゾーンを意識してコードを書くことはほとんどありませんが、pytz を知っておけば今後どこかで役に立つことがあるかも知れません。

投稿日 2009年8月3日 月曜日 カテゴリ javascript 投稿者 morimotoコメント(0) » 

morimotoです。

「もっと画面をすっきりとしたいな・・・」と思う時に良く使われるのが、閉じたり開いたりするExpand機能かと思います。 そのExpandをするために毎回javascriptを書くのは面倒くさい。

そこで簡単にExpandさせれるようにjQueryでPluginを書いてみました。 (完成しているとはいえませんが。。。)

(function($){
  $.fn.simpleExpander = function(options){
    var target = options.target || undefined;
    var trigger = options.trigger || 'click';
    var collapsedClass = options.collapsedClass || 'collapsed';
    if (typeof(options) == 'string') target = options;
    if (target) {
      $(this).addClass('expander');
      targetToggle(this, target, collapsedClass);
      $(this).bind(trigger, function(){
        $(this).toggleClass(collapsedClass);
        targetToggle(this, target, collapsedClass);
      });
    }
    return this;
  };

  function targetToggle(el, target, collapsedClass) {
    if ($(el).hasClass(collapsedClass)) { 
      $(target).hide(); 
    } else { 
      $(target).show(); 
    }
  }
})(jQuery);

使い方


<button id="trigger1">button 1</button>
<button id="trigger2">button 2</button>

<div class="target apple">window 1</div>
<div class="target banana">window 2</div>
<div class="target grape">window 3</div>

<script type="text/javascript">
$('#trigger1').simpleExpander('div.target');
$('#trigger2').simpleExpander('div.target.banana');
$('div.apple').simpleExpander({target: 'div.target.grape', trigger: 'mouseover'});
</script>

demo

target apple
target banana
target grape

ボタン1はdiv全てがtoggleします。 ボタン2は真ん中のdivのみtoggleします。 一番上のdivをマウスオーバーすると一番下のdivがtoggleします。

もっとシンプルに作れるのかもしれないですが、こんなのもあるんだなという程度で見ていただくとありがたいです。

以上、morimotoでした。。。

« 前ページへ次ページへ »