木曜日, 10月 30, 2008

【雑記】 失敗しないことがよいことか このエントリーを含むはてなブックマーク


 小野さんのサイトで勧められていたので今こういう本を読んでいる↓。



 この本では、IBMのトーマス・J・ワトソンの言葉が数回出てくる。トーマス・J・ワトソン・シニアの名言・格言

 早く成功したいなら、失敗を二倍の速度で経験することだ。成功は失敗の向こう側にあるのだから・・・・


 要は失敗を恐れずに何事も果敢に取り組めということだが無謀な挑戦をやれといっているわけではない。やる前に少なくとも次の2つの検証は必要だと思われる。


 1)目的がはっきりしているか
 2)致命的な失敗にならないか


 発明王トーマス・エジソンも、「失敗は成功の母である」という言葉を残している。失敗から学んで次に生かすことは、「電球を発明する」などの目的があってはじめて成り立つことだと思う。
 また、何かをやるには大小のリスクは必ずある。それを無謀というかどうかは意見の分かれるところでもある。失敗には致命的な失敗とそうでない失敗の2種類あり、致命的な失敗さえしなければリスクを取っても気にする必要はない。失敗することを心配するのではなく致命的な失敗の危険性をどれだけ回避するかが重要である。致命的な失敗さえしなければ次のアクションをとることができる。(←こういう感じの話が本に書いてあった)

 ところで、失敗を好んでやっているとしか思えない確信犯的な企業がある。

 GoogleはGmailでメールをWeb化している。メール情報を預かるリスクは相当高いが、それを使う側にも分担させる(覚悟してもらう)ことで成り立たせている。つまり、データ損失や漏洩などの事故が起きる危険性はゼロではなく無償サービスということで免責されているが、それを承知で私を含め多くの人が使っている。
 その他、Youtube、Google Book Searchでは著作権問題を抱えており、Street Viewではプライバシー問題と向き合っている。これらのサービスが問題になることはやる前から分かっていたはずで、googleにとっては、ある程度起こることを見越した問題であったことは間違いないだろう。

 googleのすごいところは決して目的がぶれず後ずさりしないこと。以下の記事は一例であるが、情報公開の自由化と著作権者保護という2つの相容れない問題を「手打ち」により同時に解決させている。動画像のアップロードなどは限りなく違法コピーに近く、著作権をないがしろにしているように見えるが、一方で著作権者を保護することで著作権者と消費者の双方に支持されるモデルとなった。そのベースには広告モデルがあり、この文化が定着すれば広告モデルの可能性がまた大きくクローズアップされるかもしれない。いずれにしても、Googleが人柱となってこの業界を進化させているのは間違いない。恐るべしGoogle。

「Google Book Search」訴訟で米出版業界と和解合意

YouTubeとJASRACが利用許諾契約、演奏動画の投稿が可能に

水曜日, 10月 29, 2008

【クラウドコンピューティング】 Microsoft Azure このエントリーを含むはてなブックマーク


丸山先生のPDC報告です。


ロスアンゼルスで開催されている、MSさんのイベント、Professional Developer Conference 2008に出ています。
他のメーリングリストに投稿した内容ですが、次回の僕のCloud研究会での報告に関連していますので、ダブル・ポストします。
---------------------------------------------------------------------------------------------------

初日のレイ・オジー(チーフ・ソフトウェア・アーキテクト)のキーノートは、
すべて、同社のクラウド製品、Azure Software Platformにあてられました。MS
が、公式にCloudサービスへの参入を表明したことは、とても大きな意味のある
ことだと思います。すでに、日本のメディアにも、いろいろな紹介が行われてい
ると思いますが、僕には、とても面白いものでした。

どんなものかといわれると、AmazonのEC2/S3+SimpleDBにGoogleのGoogle App
Engineを足して、もっと、使いやすくしたようなものです。サービスの中核は、
前から僕が予想していたように、SSDS(SQL Service Data Service)によるデー
タ・サービスです。

AmazonのEC2との対比で言うと、EC2が潜在的には前提にしていた、Cloud上での
サーバやディスク等のリソース管理の機能を、明示的に、「CloudのOS」として
のAzureが担うことを明確にしています。EC2では、Cloudの利用者は、具体的に
は、AmazonのCloud OSが提供する、個々のマシンを利用するのですが、Azureで
は、MSのCloud OSであるAzureの提供するサービスを利用することになります。
同じだろうと思うかも知れませんが、その違いは、大きいのです。

Google App Engineでも、利用者は、知らないうちに、Googleの提供するCloud
サービスを利用しているのですが、Azureでは、Cloudサービスの利用は、もっと
Cloudのリソースの利用に、自覚的です。例えば、EC2のように、個々のサーバ利
用を意識する必要はないのですが、Webのサーバをいくつ立てて、ビジネスロ
ジック用のプロセスをいくつは知らせるかというような設定が、Azureでは可能
になります。その点では、僕のCloud研究会の第一回の資料で指摘した、「Multi
-TierアプリのScale-out戦略」の図を見てもらうと、そのイメージはわかりやす
いと思います。Cloud内のいくつかの基本的なサービスのブロック(ロードバラ
ンサ、Web、Worker)のコンフィグが、AppLogicのように、簡単にできます。

この点では、Azureは、Google App Engineと同様に、エンタープライズでの開発
の中心である、Webアプリの開発のCloud化に、明確に焦点を合わせています。
MapReduceのような、汎用の分散アルゴリズムのサポートは、ありません。た
だ、Cloudで動くWebアプリの開発、deploy、実行は、Google App Engineより、
はるかに、簡単で、直観的です。

余談になりますが、キーノートでは、Cloud上で動く、Hello Worldのデモが行わ
れたのですが、これはちょっとわかりにくかったかも。だって、Hello Worldの
文字列が、直接ページに埋め込まれているのか、あるいは、隣のサーバが返す
ページに入っているのか、はたまた、Cloudから来たものかは、見ている人には
わかりませんからね。もっとも、このあたりは、Cloudを概念的にとらえること
の難しさを示しているのかも知れません。

その他、いくつかの特徴があります。思いつくままに触れると、

・Cloud アプリの開発環境の提供。
・Cloud上でのユーザの認証、アクセス管理。(OpenIDを使うのだと思います)
・既存のWeb Appsをクラウド化する手段の提供。
これは、.NET Servicesという製品群にまとめられていますが、以前の
BizTalkの機能をまとめたものですね。個人的には、SOAの発展形としての
Cloud利用という切り口が明確で、面白かったです。
・Cloud内のサービスの連携に、非同期なメッセージングを使うとか、Queuを
使うという話も、なるほどと思って興味深いものでした。もっとも、この
あたりは、数年前から、SOAの世界では言われてきたもので、大事だと思い
つつ、僕は、爆睡してしまいましたが。
・MSのOffice製品群のCloud利用を可能にする、SharePointとの連携。
・企業内(On Premise)既存サービスと、Cloudとの区別と関連付け

最後の点は、IBMさんにしろOracleさんにしろ、既存の製品群とCloud利用が、あ
る点では競合するという問題を、MSさん自身も抱えているという点を示している
訳で、面白い問題だと思っています。

聞いていたひとの反応は、「地味だった」という声が多かったように、思いま
す。以前、マルメでも書いたのですが、このPDCの焦点の一つが、MSのCloudへの
参入の表明にあるという意識は、事前には弱かったのですが、まだ、ちょっと実
感がわいていないようです。(Vistaの後継としてのWindows 7に対する関心の方
が、ずっと高いですね) 講演者も、例えば、Cloudにとって、本質的に重要
な、SSDSのScale-outする特徴に、踏み込まないまま、SSDSの説明をしようとし
たり、MS内部でも、明確な語り口が統一されていないようなところもありました。

ただ、初日のキーノート、まるまるすべてAzureに使ったわけで、それなりに関
心は高まったとは思います。Bill Gatesが引退して、はじめてのPDCらしいので
すが、僕には、別の意味でも、歴史的な会議になるだろうと思っています。

http://www.microsoft.com/azure/solutions.mspx
に、すでに、情報が出ています。是非、チェックしてください。

P.S. CloudのSOA利用のセッションは、激しく寝てしまったのですが、
寝ようと思って出た、「C#の未来」というセッションは、とても
面白かったです。C# 4.0って、Dynamic言語に対応するんですね。
「静的な型として、dynamicという型を導入するんだ」という彼の
説明に、つい笑ってしまったのですが、なかなかの人でした。

火曜日, 10月 28, 2008

【本日の嵌り】 SVNレポジトリを作成する このエントリーを含むはてなブックマーク


SVNレポジトリを最初から作りたい。さあ、どうしよう。

まず、

mkdir /usr/local/svn/repos
svnadmin create /usr/local/svn/repos


とやってsvnのdbを作成する。(bdbとかfsとか細かいことは省略)

実際に作業したいフォルダに移動して、
home/hoge/svnの上で


svn import file:///usr/local/svn/repos -m "" 


とするとインポートされる。次に、


svn co file:///usr/local/svn/repos      


とやってチェックアウトすると


  home/hoge/svn/repos


ができるので以後、


svn up /home/hoge/svn/repos/fuga.csv    アップデートや
svn ci /home/hoge/svn/repos/fuga.csv -m "" コミット


などができるようになる。これで解決。

月曜日, 10月 27, 2008

【EC開発体験記-EDI-】 SVNを業務で使い倒す このエントリーを含むはてなブックマーク



 EDIで外部システムとの連携を考えるときに最も注意しなければならないのはデータの不整合である。これは、送ったはずのデータが送られていない、あるいは、受け取ったはずのデータがなくななるといったことであるが、基本的にこういったものは「性悪説のスタンス」で設計した方がよく、むしろ、日常茶飯事でトラブルが起きるぐらいの覚悟でいるとちょうどよいと思われる。
 
 ということで、EDIをSVNで管理することを考えてみた。SVNといえば、ソースコードやドキュメントの履歴管理によく使われる、開発者にとってはお馴染みのバージョン管理ソフトである。これをEDIに活用して、送受信データをいつでも再送/再受信できるようにしようというわけだ。特に人手を介して入手するマスター類の登録などでは真価を発揮する。いつも送った送らないで揉める人間系でもSVNの履歴には反論の余地がない。SVNを業務アプリケーションに使うことに違和感を覚える方も多いと思われるが一度利用してみることをおすすめする。


<SVNによるEDI> 


<SVNをEDIで使うメリット>

1)一貫性確保 ・・・ コミットしたものと送受信したものが同一であることを保障できる
2)実績確認  ・・・ いつ何をどれくらい送受信したか実績を確認できる
3)リカバリ対応・・・ 履歴から過去データを取り出せるためいつでも再送できる

<SVNをEDIとして使うケース>

1)物流      ・・・ 物流業者への出荷指示データの送信と出荷済データの受信
2)商品マスタ  ・・・ 商品部からの商品マスタの受信とホームページへの反映
3)在庫管理    ・・・ 倉庫からの在庫データの受信とたな卸しデータの送信


 一貫性が保障できて実績が確認できればエビデンスとしても利用できる。対外システム側との取り決めが必要だが、例えば、SVNファイルを正と取り決めておけば、物流業者の請求金額についてはSVNファイルの「出荷済」のレコード数をカウントすることで確認できる。また受け取ったデータをそのままコミットしておけばトラブルがあったときにリカバリーも確実に行えて原因を突き止めることが容易になる。
 EDIでは、まず、送ったものと受け取ったものを確実に管理することが重要である。基本はトランザクション処理と同様の考え方で、成功でコミット、失敗でロールバックとすればよい。以下の例では、SVNのDIFFをとり新規分があればupdateして送信するが、失敗すればリビジョンを元に戻すという動きをする。これは実際に使っている全銀システムと通信するコードの抜粋である。全銀ISDN回線で話中で数回に1回の確率で失敗するようなFuck!な連携システムでもSVN履歴管理はとても有効である。


# 未送信分チェック(送信すべき新規のファイルがSVNにあるかどうかをDIFFを使って調べる)
DIFF1=`svn diff --revision BASE:HEAD hoge.dat`
if [ $? != "0" ]; then
    echo [`date`] ファイルが未更新
else
    if [ -n "$DIFF1" ]; then
      echo [`date`] ファイルが更新されています
      svn update hoge.dat

      # 送信処理
       ・・・
      # 送信成功?
      if [ $? != "0" ]; then
        # もし送れなかったらエラーを報告してリビジョンを1つ前に戻す
        echo [`date` ] エラーが発生したため処理を中断します。
        svn update -r PREV hoge.dat

      else
        # 送信成功
        echo "送信成功!"
      fi
    fi
fi



 また、TortoiseSVNとの組み合わせにより、Windowsフォルダを操作する感覚でSVNを扱えるのも嬉しい。これにより、オペレータさんなど、SVNコマンドの特別な知識がない方でも扱えるようになる。オペレータさんは通常はデータを生で見ることはあまりないが、エラー発生時のファイルの状態やコミット時間、件数を報告してもらうとトラブルに迅速に対応できるようになる。

 たまに、SVNのdb内で不整合が発生してエラーになることがあるが大抵svnadminコマンドでリカバリーできる。


/usr/bin/svnadmin recover /usr/local/svn



 SVNエラーは大きいファイルをhttp(https)でコミットしようとすると起きやすいため、svn+sshで接続することをおすすめする。実際にsvn+sshで50万件の商品マスタを毎日コミットしていたが特に問題なく運用できていた。
 TortoiseSVNからsvn+sshで接続するのは以下のように設定するとよい。






 ちなみに、弊社では上記のSVN EDIソリューションを、Reflexパッケージとともに提供していきたいと考えている。SVNは内部的にberkeley dbを使用しているため再販するためにはOracleライセンスが必要になるが、弊社はReflexパッケージのなかでライセンス許諾権を結ぶことでOracle社と基本合意している。(11月中に締結予定)
 
<関連>

【EC開発体験記-スケーラビリティ-】信頼性とジレンマ
【EC開発体験記-トランザクション処理-】古くて新しい永遠のテーマ

金曜日, 10月 24, 2008

【クラウドコンピューティング】 クラウドの本質と動向 このエントリーを含むはてなブックマーク


今、あるお客様にクラウドの提案を行っている。
クラウドによって何か新しいことができそうという期待感がある一方で、クラウドという言葉がバズワード化する中で、かえって誤解が多くなって苦戦を強いられている。
今回はそのことについて説明したい。

クラウドに限らないことだが、「XXとは何か」といった議論をするのが私は大嫌いだ。
もし社内でこういった議論に明け暮れているようなら時間の無駄だと思った方がいい。こういった議論は大体、声の大きな人が勝つことになっているからだ。

しかし、お客様に対しては、こちらに目を惹きつけないといけないので、バズワードであってもクラウドという言葉を使いたくなる。ちなみに、バズワードは、Wikipediaにはこのように説明されている。

その分野に明るくない人にイメージだけを押し付けたり、「よくわからないが凄そうなこと」を想起させることを目的とした宣伝文句として使うことも可能であり、言葉だけが先歩きして広まることも多いため、事情を知らない多くの人は価値のある言葉として捉えてしまうことがある。

要は、お客様の都合のいいように解釈してもらって、興味をもってもらえたらそれでOKということなのだが、前述したように、具体的な提案の段階に入ると先入観が邪魔をして誤解だらけとなり、なかなか前に進まなくなる。

具体的には、大規模なトランザクションを抱えているお客様への「企業内クラウド」の提案を行ったのだが、それが、クラウドという言葉とAmazonやGoogleを強く結びつけると、基幹系ではちょっとね、と短絡的に受け取られてしまった。
 クラウドを説明するときのAmazonやGoogleなどのPaaS/SaaSのメッセージが強すぎるのも悪いのだが、そもそも、提案する側がよく整理できていないままミソクソに話してしまったことが一番悪い。というわけで、自分なりに「クラウドとは何か」を整理することにした。

まず、
クラウドの目的と要件

 1.どんなにトランザクションが増えてもスケールできること
 2.その大規模なシステムを安く利用できること
 3.サービスレベルを保証できること


 要は、サービスレベルを保証しつつスケールできるシステムを安く提供することが第一の目的である。
サービスレベルの保証とは、主にパフォーマンスと耐障害性の保証で、トランザクションの量が増えてもパフォーマンスが劣化しないようにすること、また、一部のノードが故障しても動的なノードの追加/削除機能により回復できてダウンタイムを最小にできることである。

実際に、AmazonやGoogleなどのPaaSなどを利用したり、Hadoopなどのオープンソース分散システムを活用することで、サーバやソフトウェアの利用コストを削減できる。また、本日、AmazonのEC2が正式サービスになってSLA稼働率99.95%保障という発表を行っている。(EC2は正式サービスじゃなかったのね・・)

これらに共通するアーキテクチャーが、Scale-outモデル。Scale-outできれば、高価な高性能なマシンは必要なく、比較的安価なマシンで十分である。ただし、これまでのSMPやクラスタリングによるScale-upのアーキテクチャから、Grid的なScale-outのアーキテクチャへの移行が必要となる。

また、多くはRDBではなくkey/valueで格納する方式をとっている。
key/value方式における検索技術では、memcachedなどの分散メモリー・キャッシュ技術や、MapReduceなどの並列分散処理技術が注目されている。

次に、
クラウドの提供手段

 1.企業内クラウド
 2.PaaS/SaaS型クラウド
 

 OracleのCoherence、IBMのWebsphere XD Data Gridといった、Scale-outモデルのエンタープライズ製品がある。
これらは、キャッシュ機能を前面に出しているものの、key/valueで格納するというアーキテクチャーになっておりScale-outできる。ベンダはこれらを「企業内クラウド」と呼んでいる。
年々増加するトランザクションに対応するには、Scale-upのアーキテクチャではいずれ破綻すると考えられるので、Scale-outアーキテクチャへの移行は早い段階で準備すべきである、というのが企業内クラウドのキーメッセージ。
 また、現在すでに金融系の大手で大量なトランザクション処理を安価なクラスターで、高信頼に実施している実績があり、クラウドというイメージよりは基幹系そのものというイメージになってきている。(By IBM Sさん)
 特に、最初はお客様のシステムにキャッシュを目的で導入したが、最後はシンプルなAPIで統一された企業内クラウドとしての形になって、DB性能がボトルネックにならなくなった、という結果は非常に評価できる。(By Aさん)



 PaaS/SaaS型クラウドは、AmazonやGoogleなどが提供するサービス。企業内クラウドとアーキテクチャは同じであるが、従量制サービスであることが違う。
また、格納する場所が自社のデータセンターか、あるいは、AmazonやGoogleという雲の上のストレージかの違いはある。
 下図は、ECサイトのクラウド利用例であるが、商品詳細ページや画像といったものをクラウド上に置くことで、検索レスポンスの向上、および、自社サーバへの負荷軽減をもたらす。商品情報は、原価などを除けばセキュリティを心配する類のものではなく、基本的に人の目に触れさせるべきものなので社内のサーバにおく必要はない。



最後に、

クラウドの本質と動向


 1.抽象的に定義されたデータベースサービスへのアクセス手段である
 2.企業内クラウドとPaaS/SaaS型クラウドの融合


 クラウドで重要なのは、データの格納場所というよりは、データの検索、更新といった処理を含めて、サービスとして、データベースのサービスを受け取るというところにある。(By M先生)
クラウドを抽象的に定義されたデータベースサービスへのアクセス手段と定義するのはどうだろう。



 企業内クラウドは、最初は大手ベンダーによるキャッシュ目的で導入され、最後はアーキテクチャ変更をもたらす。
柔軟にScale-outする複数の比較的安価なサーバー構成のもとで、企業内クラウド製品を提案できれば、お客様のニーズにもこたえられると思われるが、ベンダーにとって安いサーバをいれてビジネスになるかどうかは疑問である。ただ、Cloudが本格的に立ち上がるまでの、この数年の間は、こうしたスタイルで、ベンダーさんが「企業内クラウド」で頑張るしかないだろう。
そして、数年後には、これらのシステムををベンダーさんのクラウドが引き取ることになるかもしれない。(By M先生)

 基幹系システムを雲の上に置くなんてナンセンスである、なんて思われない日が将来やってくるのだろうか。

<関連>
クラウドを15の否定で表現
セキュリティは最後の難問題

Object Grid(IBMのWebsphere XD Data Grid)に関する情報:

WebSphere
清水さんの資料 オブジェクト・グリッド


Object Gridは、Billy Newportという方が作ったもの。(IBM社員らしくない天才といわれているらしい)
Billy Newport's blog
OGのすべての説明が書かれているWikiがあります。例えば、EntityManagerに関しては:
Entity Manager

ReferenceタグやSampleなどのタグから色々な情報に移れます。
読みやすいのは、例えば、
Reference Sample
でしょうか。

月曜日, 10月 20, 2008

【雑記】 書けないことを書いてみる このエントリーを含むはてなブックマーク


 先週から今週にかけてイベント盛りだくさんだったのでネタは豊富にあるのだがなぜか書けない。Inputが多いとOutputできないといった方がいたがそれは本当のことだ。

今、頭の整理中。

1)クラウド研究会の話(Oracle Coherence、楽天ROMA)
2)JUGGの話(JavsScript高速化、Android)
3)企業内クラウドを提案してみて思ったこと

火曜日, 10月 14, 2008

【本日の嵌り】 MySQLバックアップファイルから部分的に復元する このエントリーを含むはてなブックマーク


 あるテーブルを復元したいのだが、mysqldumpで取っているバックアップファイルから復元すると、すべてのテーブルが対象になって何時間もかかってしまう。さあ、どうしよう。
 
 そこで、csplitでファイルを分割して該当のものだけ復元することにした。
 まず、egrep 'CREATE TABLE' xxxx.sql で何個目にあるかを調べる。xxxx.sqlはmysqldumpで取ったときのバックアップファイルである。

[hoge@hoge batch]$ egrep 'CREATE TABLE' xxxx.sql
 CREATE TABLE `aaaa` (
 CREATE TABLE `bbbb` (
  ・・・
 CREATE TABLE `koreda` ( <= 35番目



次に、以下を実行して分割する

[hoge@hoge batch]$ csplit xxxx.sql /^DROP/ {*}



そこから特定のテーブルのみ復元するには、35番目の分割ファイルだけを指定すればよい。xx35はcssplitが作成する35番目の分割ファイルである。

[hoge@hoge batch]$ mysql --user=hoge --password=xx sampledb < xx35



これで解決。

土曜日, 10月 11, 2008

【EC開発体験記-出荷-】 ヤマトB2と連携する このエントリーを含むはてなブックマーク


 今回は出荷管理システムについて説明する。

 受注管理機能や決済機能が充実しているECサイトは多いが出荷機能が備わっているものは意外と少ない。楽天やYahooなどの大手のモールであっても、実際には受注だけが可能であり、出荷のためには別途システムを使わなければならないのが現状である。通常は、その日に受付けた注文をモールからEXPORTして出荷管理システムにIMPORTしなおすといったことをしなければならない。また、実際の商品の出荷では送り状が必要になるため、送り状発行ソフトとの連携も必要になる。

このように出荷管理システムでは以下のようなモールには備わっていない機能が必要となる。


1.受け付けた注文を取込む機能
2.送り状発行ソフトに渡す出荷データを出力する機能
3.(送り状発行ソフトから)出荷済となったものを取込む機能
4.納品書発行機能
5.ステータス管理機能(受付、確定、出荷済、キャンセル、配完、返品など)

また、必須ではないが以下のような機能も求められる。

6.確定時のカードオーソリ機能
7.受付時と出荷時に案内メールを送信する機能


 送り状発行ソフトは、4辺160㎝までの小物商品であればヤマト運輸のB2という送り状発行ソフトを使うと便利である。B2には、顧客データの一括取込機能があるので、出荷管理システム側でB2の指定するレイアウトにしたがってCSVを出力する機能を用意すればよい。また、ステータスの一括出力機能もあるため、出荷管理システム側で、出荷済となったステータスデータを取込み、商品のステータスを一括で更新する機能を持たせればよい。

B2 顧客データの一括取込

<B2用CSVを出力PHPサンプル>


# データ出力
$n = 0;
while ($n < mysql_num_rows($res)) {

  $l = array();

  # CSV編集
  $l[] = date('Ymd');   # 出荷日
  $l[] = $d[$n]["odrno"]; # 受注番号
  if($d[$n]["pay_flg"]=="1") {
    # 代引受注のとき
    $l[] = "2";
  }else {
    # その他
    $l[] = "0";
  }
  $l[] = "";
  $l[] = "";
  $l[] = $d[$n]["to_tel"]; # 届先電話番号
  $l[] = "";
  $l[] = $d[$n]["to_name"]; #届先氏名
  $l[] = $d[$n]["to_zip"];  #届先郵便番号
  $l[] = $d[$n]["to_add1"] . $d[$n]["to_add2"] . $d[$n]["to_add3"];  $l[] = ""; #届先住所
  $l[] = "";
  $l[] = "";
  $l[] = mb_convert_encoding("様", "CP932","UTF-8");
  $l[] = "";
  $l[] = "0311112222"; # 電話番号
  $l[] = "";
  $l[] = mb_convert_encoding("XXXX商店", "CP932","UTF-8"); # 送主名
  $l[] = "1050014"; # 送主郵便番号
  $l[] = mb_convert_encoding("東京都港区芝3-X-X","CP932","UTF-8"); # 送主住所
  $l[] = "";
  $l[] = "XXXXXXXXX"; # B2契約番号
  $l[] = "";
  $l[] = "1";
  $l[] = $d[$n]["product_code"]; # 商品コード
  $l[] = mb_convert_encoding("XXXXご注文商品", "CP932","UTF-8");
  $l[] = "";
  $l[] = "";
  $l[] = "";
  $l[] = "";
  $l[] = "";
  $l[] = $d[$n]["sitei_date"];
  if($d[$n]["sitei_class"]=="1") {
    # 午前中指定のとき
    $l[] = "0812";
  }else {
    # それ以外    
    if($d[$n]["sitei_class"]=="2") {
    # 午前中指定のとき
      $l[] = "1214";
    }else {
      if($d[$n]["sitei_class"]=="3") {
      # 1214指定のとき
        $l[] = "1416";
      }else {        
        if($d[$n]["sitei_class"]=="4") {
        # 1618指定のとき
          $l[] = "1618";
        }else {
            if($d[$n]["sitei_class"]=="5") {
          # 1820指定のとき
            $l[] = "1820";
          }else {
            if($d[$n]["sitei_class"]=="6") {
            # 2021指定のとき
              $l[] = "2021";
            }else {
              if($d[$n]["sitei_class"]=="7") {
              # 午前後指定のとき
                $l[] = "0017";
              }else {
              # その他
                $l[] = "";
              }
            }
          }
        }
      }
    }    
  }
  $l[] = $d[$n]["amt"]; # 金額
  
  fwrite($h, join(",", $l) . "\r\n");  # MS改行コード
  
  $n ++;
}



木曜日, 10月 09, 2008

【EC開発体験記-Mashup-】 商品情報とカテゴリの正規化 このエントリーを含むはてなブックマーク


 暮らしのデザインサイト(http://kurashide.com)がリニューアルオープンした。これに関連して今回は商品情報とカテゴリの正規化について述べたいと思う。

 サイトの設計方針の一つはMashupである。つまり、自己完結したEntityの集合であるResourceをMashupして1つのページに編集する仕組みを取り入れること。また、ResourceをRESTfulにしてCoolURIとなるように設計することである。

例えば、サイトでは以下のようにCoolURIとなるように設計している。


1) http://kurashide.com/item/4979247561321.html のように、item/{JANコード}.htmlでJANコードさえ分かれば簡単に商品ページを表示できる。

2) http://kurashide.com/category/sofa_zaisu_cushion/sofa/systemsofa/ のように、category/{大カテゴリ}/{中カテゴリ}/{小カテゴリ}といったように、直感的なURL指定でカテゴリに属する商品の一覧を表示できる。また、{小カテゴリ}を省略すると{中カテゴリ}に属する/{小カテゴリ}の一覧が表示され、さらに{中カテゴリ}を省略すると{大カテゴリ}に属する{中カテゴリ}の一覧が表示される。


 Resourceの設計ではまずEntityの正規化を考える。お互いに干渉するところのない、自己完結した集合を見いだすのがEntityの正規化である。例えば、単品の詳細ページとカテゴリは別々のEntityにできる。単品詳細ページでは商品の詳細情報をEntityとするが、カテゴリではEntityのURIの集合という形で定義する。(中カテゴリは小カテゴリの集合であり大カテゴリは中カテゴリの集合となる。)
 このように単品の詳細ページとカテゴリは、同じ商品に関する情報であるが、お互いに干渉するところがないように、敢えて1つに括らないようにする。 また、そうすることで、商品情報プロバイダ、カテゴリプロバイダといったように、それぞれのサービスプロバイダを立てることができる。プロバイダでは単にXMLやJSONで出力できればよい。HTMLページを生成するのはMashupの仕事であり、それをPHPリクエスタが行っている。Reflex設計的に整理すると、サービスプロバイダがResource層、PHPリクエスタがMashup層、ブラウザがView層となる。
 この考え方は、ソーシャルブックマークサービスと似ている。ブックマークサービスはHTMLページを管理するのではなく、リンクされるURLとそれに紐づくタグやコメントなどを管理するだけである。

 Reflex設計による疎結合なサービス化がもたらすメリットは、主に並行開発ができるようになること、スケーラビリティが高くなることの2つである。特に商品情報とカテゴリについてはクラウド化などを見据えたときに非常に有効になる。クラウドではセキュリティ確保の心配があるが、そもそも商品情報は(原価などを除いて)人目に触れさせるべき情報なのでクラウドにフィットすると思われる。さらには商品詳細を静的なものとして分離してAmazonS3に置けばCDS対応もしているのでレスポンス速度向上も期待できる。ただし、商品詳細には商品ごとにお届け目安日や在庫数など、リアルタイム表示が要求される項目もあるので、ページ表示後にJSONPで再検索するなどの変更が必要となってくる。一方、お届け目安日の取得サービスや在庫数検索サービスなどは既に作成されているので、そのまま利用できる。

 ちなみに、これらのサービスプロバイダはReflexで構築されている。 

火曜日, 10月 07, 2008

【Reflex】 小さな政府によるガバナンス このエントリーを含むはてなブックマーク


 タイムリーな記事を発見。

完璧なSOAなんてあり得ないからこそガバナンスが重要 - ミコ・マツムラ氏

 先日の記事のコメントで「小さな政府」という表現でどのようにガバナンスを考えればよいかを説明したが、ミコ・マツムラ氏も同様の意見をお持ちのようである。

理想的な実装が難しい現実


最初に述べたように、SOAのブループリント策定はうまく行ってもIT実装は難しい、この理由はごく簡単です。ユートピア(理想郷)の青写真を描くだけなら、つまるところ、誰にでもできるわけです。だが、それを実現するには、"部族間主義"のような人間のもつ自然な本質を越える必要があります。一ベンダがそこまで企業の内部に立ち入るのは難しい。


大きな開発は失敗するリスクが高い


何千とあるSOA導入失敗例を見てきてつくづく思うことは、SOA導入とは「ロケットの発射」に非常によく似ている、ということです。言うまでもなく、ロケットというのは非常に大きなシステムで、それを発射させるにもさまざまな仕組みが必要です。そして発射が失敗するとき、たいていは大きなシステムの中にある小さなコンポーネントどうしの依存関係に問題があります。SOAも同じです。サービスそのものの大きさ(粗さ)よりも、あるサービスは、別のどのサービスにどれだけ依存しているのか、それに対する認識があいまいだと失敗も生じやすくなります。


個別に柔軟に対応することが重要


トップダウンか、ボトムアップか -- SOAに限らずITシステムの導入/リプレースを議論する際、よく登場するフレーズだが、結局のところ、そのどちらであっても組織内から100%の合意が得られることはまずあり得ない。トップから押しつけられた、下の人間が勝手にやった、といった類の言い訳はいつの時代、どこの組織、どのソリューションを使っていても起こるものである。
だが100%は無理でも、少なからず多くの人々が気持ちよく使えるITシステムがあるとしたら、それはやはり、ある一定のルールの下で運営されていることが条件になるだろう。そしてそのルールは、時代と組織に合わせて柔軟な変更が可能であることも求められる。SOAガバナンスの基本はそこにある。


月曜日, 10月 06, 2008

【Reflex】 RESTfulな新3層アーキテクチャ このエントリーを含むはてなブックマーク


 従来の典型的なWebアプリの設計では、下図のように主にサービス層がEntityを包含するイメージとなる。オブジェクト設計をすることで、Serviceを見いだすという段取りとなるが、ここでも述べたとおりうまくいっていない。



 一方、Reflexでは、ここ で説明したように、オブジェクト設計をやらず、ドメインを単なるデータの集合とみなす。Entityという形で取り出したデータをシステム全体で使用し、また、サービス(Blogic)を各層で実装するため下図のようなきれいな3層構造となる。




 このような新しい3層アーキテクチャは、RESTfulな設計思想に基づいている。つまり、RESTのような疎結合APIがなければ実現できないモデルである。特に、AJAXやMashupの概念は重要で、サーバでHTMLを生成するのではなくクライアントとはデータだけをやりとりする。

 APIをやめデータ構造に着目するより抜粋

 これは要するに、システム共通のentityを定義して、それをやりとりすることだけに注力しようということだ。SOAPやAtomPubなどのAPIを介さないし、そのような共通APIに該当するものを敢えて開発しない。しかし、最低限は必要になるので、先に挙げたリソース志向を踏まえて定義する。具体的には次のような非常にシンプルなAPIを定義することになる。

<API例(entityはリソースの1インスタンス)>

entity = create(entity);
entity = retrieve(entity);
entity = update(entity);
entity = delete(entity);


<関連>
ヘテロ環境のインターオペラビリティを考える

土曜日, 10月 04, 2008

【JavaScript】 TABキーで移動後にFocus、Select このエントリーを含むはてなブックマーク


 複数の入力ボックスがある画面で、TABキーで移動させる際に、思ったところに移動できるよう細かく順番を指定したいことがある。そこで、JavaScriptを利用して以下のようなものを考えてみた。

TABをjavascriptで制御

1.入力ボックスの移動順に入力ボックスIDの配列を作成し
2.タブキーが押されたら
3.次の入力ボックスを取得して
4.focus()→select()


 order = ['input_box_id_01', 'input_box_id_04', 'input_box_id_02','input_box_id_03'...]
 if (window.event.keyCode == 9) {
  //_getNextCell()は次の順番を知るための自前関数
  var ele = document.getElementById(_getNextCell(order));
  ele.focus();
  ele.select();
 }



しかし、これだとShift+Tabで前の入力ボックスに移動できない。(必要であれば実装してあげないといけない。)また、フォーカスは移動するが、select()がかからないことが時々あるので強引にHTMLのタグにonfocus="this.select();"を付けて対処する必要がある。これはHTMLのすべてのInputboxに付けてあげなければならない。

HTML側で使っていたタグ

 <input onblur="control(this.id, this.value);" type="text" id="hoge"
 <span style="font-weight:bold;">onfocus="this.select();"</span>>



いろいろ面倒なので、JavaScriptの利用をやめてtabindexに順番を入れてあげるようにした。
これであれば、TabキーもShift+Tabキーもブラウザが勝手に解釈して動かしてくれるので楽だ。

tabindexに順番を入れる


1.入力ボックスの移動順に入力ボックスIDの配列を作成し
2.入力ボックスのtabIndex属性に順番をセットして
3.onfocusイベントにselect()を追加してあげる



 order = ['input_box_id_01', 'input_box_id_04', 'input_box_id_02','input_box_id_03'...]
 for (var i = 0, l = order.length; i < l; i++) {
  //ele[i]は入力ボックスオブジェクトを予め格納しておいたもの
  ele[i].tabIndex = i+1;
  ele[i].onfocus = function(e) {this.select();}
 }



金曜日, 10月 03, 2008

【本日の嵌り】 OutputStreamをInputStreamに変換する このエントリーを含むはてなブックマーク


OutputStreamからInputStreamに変換するにはどうしたらいいか。Pipeを使ってもOutputStreamと互換性がないので簡単にはいかない。さあ、どうしよう。

まず、ByteArrayOutputStream(baos)からByteArrayOutputStream(bais)への変換であれば以下のようにすればできる。

 // baosの生成
 ByteArrayOutputStream baos = new ByteArrayOutputStream();

 // baosへの書込
 baos.write(・・・);
 ・・・

 // baosのからbaisへの変換
 bais = new ByteArrayInputStream(baos.toByteArray());


なので、OutputStreamからByteArrayOutputStreamを取り出せれば何とかなりそうである。
それは以下のようにすればよい。


 //追加コード
 public void hoge(OutputStream out){
 ByteArrayOutputStream temp = new ByteArrayOutputStream();
 hogeByteArray(temp);

 // byteArrayをoutする
 out.write(temp.toByteArray());
 }

 // 既存のコード
 public void hogeByteArray(ByteArrayOutputStream bOut){
 // <既存のものと同じ内容>
 }



これで解決。

木曜日, 10月 02, 2008

【クラウドコンピューティング】 MapReduceの復習 このエントリーを含むはてなブックマーク


 昨日の丸山先生のMapReduceのレクチャーのメモを記す。自己中心的なまとめかたであることをご容赦願いたい。

MapReduceは以下の動作とほぼ同じ

 cat $* | woWord | sort | uniq -c


Mapは分割可能性(≒どう分割しても並列処理できる)があるがReduceは条件付で分割可能性がある。reduceの分割可能性はキー境界をまたがないこと。Reduceに渡す結果の束ね方重要。


map部分の処理は、複数のマシン上で分割可能である。
同様に、reduce部分の処理も、URL_AやURL_Kのようなデータの繰り返しの境界を破らなければ、容易に分割可能である。
問題は、mapの出力を分割してsortして、reduceに渡す方法である。
このとき、mapの出力を、同じキーは同じグループに属するように分割すればいい。


それで、(reduceが分散可能なように)キー境界を破らないようなpartitionを別ける。
代表となるMasterを選出してWorkerに指示をするパターンをMaster/Workerパターンといい、並列処理システムではオーソドックスなパターン。


MapReduceのライブラリは、まず、入力ファイルを、M個にsplitする。
沢山のマシンのクラスタ上で、 MapReduceのプログラムのコピーを起動する。
プログラムの一つは、特別で、MapReduceのmasterとなる。
残りは、masterによって仕事が割り当てられるworkerになる。
M個のmapのタスクとR個のreduceのタスクが割り当てられる。
masterは、仕事をしていないworkerに、これらの仕事を割り当てる。
map関数の産み出す中間出力のkey/valueのペアは、メモリ上にバッファされる。
バッファ上のペアは、partition関数によって、R個に分割されたの領域のローカル・ディスクに、定期的に書き出される。


Mapはメモリに保持=>Partition関数によってR個(Reduce個数)に分割されたDISKに保存される (※1)=>Reduce処理

※1 ・・ ここではMapが動作するローカルマシンに保存されるといわれていたが、Reduceが動作するリモートマシンに保存するのかもしれない。Mapがすべて完了するまでReduceは動作しないのでReduceのマシンまで転送してあげた方が効率的か?




SortはReduce側で行う。Reduceの最初の仕事。中間データ量が収まらなかったらDISKに書く。すべてのMap処理が終わらなければ開始されない。

Combinerは典型的には、reduceで実行されるコードと同じものである。Reduceに渡す前に可能な限りMap側でやっておく。reduce関数の出力は最終の出力となるが、combine関数の出力は、reduceに送られる中間出力に書き出される。

水曜日, 10月 01, 2008

【Reflex】 ドメインモデル貧血症、サービスと振る舞いについて このエントリーを含むはてなブックマーク


 自分の頭を整理するために、こちらの記事のように、敢えてReflexをドメインモデルに当てはめて考えてみたものの、案の定、ドメインモデルではない根拠を発見してしまった。Reflexはそのままではドメインモデル貧血症を起こすらしい。

ドメインモデル貧血症


ドメインモデル貧血症の基本的な症状は、一見、それが本物のドメインモデルに見えるという点です。オブジェクトがいくつかあり、それらはドメイン空間にある名詞から名前をつけられています。それから、オブジェクト同士がしっかりとしたリレーションで結びついており、本物のドメインモデルと同じような構造を持っているのです。ただし、オブジェクトの振る舞いを見れば違いが分かります。それらのオブジェクトにはわずかな振る舞いしかない、ということに気づくと思います。ドメインのロジックをドメインオブジェクトの中に入れないという設計ルールに従っているのでしょう。その代わり、すべてのドメインロジックを含むサービスオブジェクト群が存在しているのです。こういったサービスはドメインモデルの上位に居座り、データのためだけにドメインモデルを使うのです。

このアンチパターンが根本的に怖いのは、オブジェクト指向設計の基本概念(データと処理を一緒にする)の真逆だということです。ドメインモデル貧血症とは、単なる手続き型設計のことなのです。まさに、私(そしてEric)のようなオブジェクト信望者が、Smalltalkの初期からずーーーーーっと戦ってきたもの、そのものなのです。さらに困ったことに、貧血オブジェクト(Anemic Object) が本物のオブジェクトだと思っているひとがたくさんいます。つまり、オブジェクト指向設計が何たるかをまったく分かっていないということなんです。


 ここで説明されている「貧血症」とは、振る舞いがドメインに欠けている状態であると理解できる。たしかに、オブジェクトは「データ+振る舞い」であるから、Reflexの振る舞いをもたないResource層に位置するコンポーネント群などはオブジェクトとはいえない。

 しかし、Reflexはそもそもオブジェクトを前提としていないので、データと振る舞いをくっつけることができない。

詳しくは、「MVCモデルは進化する」を参照していただきたいが、Reflexでは「オブジェクト設計をしない」ことがスタート地点になっており「貧血症」というよりは「殻皮類」のようなもので「血」がない生物なのである。なので、「オブジェクト指向設計が何たるかを」全く知らないで開発しても貧血になって倒れたりしない。また、ある意味挑戦的で挑発的な、真の「Domain Model」推進者が知ったら顔を真っ赤にして怒るだろうアンチパターンを平気な顔してやっちゃおうという試みでもあるのだ。

MVCモデルは進化するの抜粋>

そこで、得た結論は、

否定の6.オブジェクト設計をしない


である。正確には、設計クラスのModelをオブジェクトにはしないで、オブジェクトで扱うデータに関心を集めようというもの。Modelとは、モデリングによってできた成果物(※)でありオブジェクトであるから、データとプログラムがくっついている状態。それからプログラムを切り離してデータのみに関心を集めて考える。データだけであればオブジェクトではないのでオブジェクト設計をしないことを意味する。とはいえ、分析クラスまでは設計して論理ビューを作る。論理ビューで定義したサブシステム内であれば、勝手に設計/実装して構わないという感じになる。
(※ Modelの定義は曖昧で様々な説明が存在する。私はこの説明が一番好きだ。)



 また振る舞いがどのように定義されるかについても触れておきたい。振る舞いは、BCEのC(Control)でフローという形で定義されるものである。そして、ControlからEntityが手続き型のように呼ばれる。これはトランザクションスクリプトに近いモデルである。

【IBM sMash】 マッシュアップはサーバでいいんですか。いいんですよ。

それから、sMashで最も重要だと思う点は、サーバサイド Mashupであり、BCEでいうところのControlに照準を当てているということ。Controlは、ビジネスロジックというと語弊があるが、ワークフローのロジック部分といえばしっくりくる。これまでワークフローとWebアプリは別物のようなもので、開発者の多くはイメージしにくいかと思う。また、この記事でも書いたように、ControlはこれまでModelに無理やり詰め込まれていて、あまり意識せずにWebを開発できた。これまで曖昧で意識もされなかったControlであるが、RESTfulな設計を推し進めることで、相対的にくっきりと浮かび上がってきた。resourceは自己完結した情報の集合として静的に扱われる一方、ControlはBoundaryの要求に応じて動的にresourceを編集する機能となる。このようにきれいに分けることで、いわゆる疎結合開発ができるようなる。従来のWeb設計開発では、画面、ビジネスロジック、データベースの3つに依存した密結合開発であったものを、 RESTful設計ではビジネスロジックを外だしにして画面も独立して開発できるようになるのだ。この結果、分業という大きなメリットを享受できるようになった。分業のメリットがいかに大きいかは、この記事で説明したとおりである。


 ちなみに、「サービス」と「振る舞い」は基本的に異なるものとしてReflexでは定義している。どちらもビジネスロジックを記述することには違いないが、振る舞いは「フローという形で定義できるもの」に対して、サービスは「I/Oを持たない揮発性の関数」としている。また、振る舞いはControlのMashup層だけに出現できるが、サービスはBCEのどのレイヤにも出現することができる。(Reflexではサービスはblogic()としている)

【EC開発体験記 -Model-】 2面性をもった掴み所がないオブジェクト

そして、convertに限らず、BlogicはすべてEntityを入れてEntityを返すとしてよさそうである。ただし、BlogicにI/Oを持たせてしまうと外部参照となってしまうため基本的にNGである。ResourceへのアクセスはEntityのCRUDメソッドだけが許されるものとし、さらにBlogicからはそれを呼ぶこともできないとする。EntityのCRUDメソッドを呼べるのはControlからだけだ。
Blogicで可能なことは、Entityを元に計算や変換処理を行って、Entityに詰めなおして返すだけ。なんとも制約の多いものだが、これがカプセル化として働くため、非常に安定したシステムとなる。(後ほど説明するがテストも楽になる)
したがって、Blogicの定義は次のようにする。

1.entity = blogic(entity)
2.Blogicは揮発性である(ステートレスでありデータを保持しない。また、外部リソースへのI/Oはない)


 ドメインモデルでいわれているような、手続き型を否定し、オブジェクトにすることがどれほどのメリットを生み出すかは正直分からない。一方のReflexは実際の私の開発経験から得たノウハウを元にした開発手法である。ドメインモデルの設計に近い部分がありながら敢えてオブジェクトにしない。そうすることでむしろ、オブジェクト設計の呪縛から解放されてシンプルに設計できる。オブジェクト化して「振る舞い」を混合させるのではなく静的なドメインだけに集中して扱う。これがReflexのドメインモデルであり、最も実践的で生産的な手法だと考えているものである。

 最初はこちらの記事のようにReflexをドメインモデルに当てはめても素直に解釈ができたのだが、あらためて考えてみると「振る舞いが記述されていない」との理由でReflexはドメインモデルではないという結論を得た。それはそれでいいと私は思うし、どちらが正しいかなどの議論はするつもりはない。また一見正しそうな結論が出たとしても、実際の開発を元にしない限り往々にして不毛に終わる。これ以上、机上の方法論に時間を費やしたくないのが本音である。
 
© 2006-2015 Virtual Technology
当サイトではGoogle Analyticsを使ってウェブサイトのトラフィック情報を収集しています。詳しくは、プライバシーポリシーを参照してください。