Quantcast
Channel: A Day In The Boy's Life
Viewing all 287 articles
Browse latest View live

やる人はやるがやらない人はやらないという現実

$
0
0

確かに身も蓋も無い話ではあるが。


「できない人」にいくら教えても「できる人」にならないのか @ ITpro


突き詰めれば「できる人」というのは「やる人(やる気のある人)」であったりもします。

ただ、「やる人」であったとしても「できる人」であるとは限りません。

まぁ、仕事においては論外という扱いなのかもしれませんが、「できる人」を育てるよりも「やる人」を育てるという方がずっと厄介だったりもします。



みんなできる人にしようという幻想


やる気があるのに空回りするとか失敗ばかりするという人は周りにもいることでしょう。

しかし、本人のやる気がある分、こちらも教える気にもなりますし、どこかしら失敗ばかり繰り返すその姿に(たまにイラっとしながらも)どこか愛嬌を感じたりもします。


一方でやらない人は、自分の領域を作り何を言ってもそれ以上のことはせず、それ以下であることがしばしば目立ちます。

この記事にあるできる人の長年のカンというやつも、実はできない人も持ち合わせているのかもしれないんですが、そもそもやる気が無いためそのカンを働かそうとしません。

何れにせよやらないわけですから、周りから見れば「できない人」というレッテルを貼られることは違いありませんが。


「できない人」に教えることである程度のルーチンをこなせるようにはなるかもしれませんが、「やらない人」を動かすのは一苦労です。

「これは僕の仕事ではありません」とばりに自ら仕事の幅を広げようとしなかったりもするので、その殻を破るのは方法論の論理だけではどうにもならなかったりもしますから。


まぁ、持論としていってしまえば「できない人」全員を「できる人」にしようというのは幻想で、せいぜいその組織としての役割の一部を担えればよいという感じで、その人はその人のポジションが組織の中にはごろごろと空いてたりもしますからうまく割り当てていけばよい、という考えだったりもします。

もちろん人には得て不得手があるわけですから、何でもかんでも特別なポジションとしてやる気があって優秀な人を割り当てればよいというわけでもなく、その戦力の中から誰がどの役割を一番うまくこなせるのかをみて、その適応能力が高いところにひたすら当てはめていけばよいという考えです。


できない人(または凡庸)をできる人に仕立てなくてはならない、という風潮があったりして、ビジネス本とかでもそういった組織を作るにはどう人を育てればいいのか、何てこと書いてたりしますけどそんなことができたら苦労をしませんし、理想を追い求めた果ての現実として組織が崩壊するというのは過去の経験でも目にしていたりもします。

ですから、ある意味開き直ってやる気が無い人がいるってことを認め、その人に最低限の役割をこなしてもらうためにはどうすればよいのか、またはそのポジションとは何なのかってことを考えた方が健全な気がしています。

自分が社長で簡単に人を異動したり切ったりするのができるのであれば楽なんでしょうけど、こういった悩みを抱えているのは中間管理職の人やチームリーダーだったりもするので、今ある戦力でどう戦うのかってことを考えていった方がよいと思うわけです。



働きアリが働かないアリになる現実


働きアリの法則(パレートの法則)というのがあります。

働きアリというのはみんなが働いているわけではなく、2割が熱心に働き、残り8割が怠けているというものです(実際にはよく働くアリが2割、普通に働くアリが6割、怠けているアリが2割といった具合になるそうです)。

そして面白いのが、2割の働きアリを別の場所に移動すると、残りの8割から熱心に働くアリが2割出てくる、または逆に2割の熱心に働いていたアリの中からも8割が怠けだすというところです。


実際の組織の中でもこういった現象は起きているのではないでしょうか。

アリの世界でこのような現象が起きる理由は知る由もありませんが、組織の中において「やらない人」が出てくるのは見ていて想像がついたりもします。


1つは、やる気がでるポジションがないということです。
大抵の組織は人が多すぎるように思えます。
業務を遂行する上で実際には人が足りてなかったりするのですが、大人数の中で自分に与えられる役割というのは細分化された作業の一部であり、そこにモチベーションを見出すのは難しくなってきます
「君はこのモジュールを作る責任者だ」と言われたところで、それは途方もなく大きな機械の一歯車を作る作業であったりして、そこの責任者なりリーダーなり良いような名前のポジションを貰ったところで単に責任を押し付けられているだけのようにも感じたりします。


課長なり部長なりその組織の大きな責任を担うポジションであれば、その責任を全うするために否応なくやる気を出さざるを得ないという場合がありますけど、そんなポジションがごろごろあるわけではありません。
ですから、毎年毎年余計な組織が増えてはそこに割り当てるポジションを捻出するというようなことがされたりして、それを貰った人は良いにしても、その下で働く人はその人を割り当てるためだけの組織で働いているわけですから仕事の楽しさを見出せるはずもなかったりします。
もしかしたら、アリ自体も他の一生懸命働くアリを見たら「俺がやらなくても良いんじゃね?」って感づいてしまうのかもしれません。


もう1つは、効率化された環境になればなるほど、その人が担う役割が単純化されてしまうということです。
「みんな仕事大変だよね。だからもっと効率化してみんなの仕事を楽にしよう!」って意義で始まったPJも、その過程はみなで考え、やることも多いので充実するかもしれません。
しかし、出来上がった完璧な環境(絶対そうはなりませんけど)は、作業をひどく効率化した一方でそこでやる仕事は単純になりつまらくなってしまいます。


CASEツールを使って完全なプログラムが作れたとしたら、極論言えばシステム部門でなくてもプログラムを書けるわけで、そうなってくるとプログラマとしての面白みは失われていくでしょうし、変わりに与えられるのは上流工程だったりして、こういうことって昔から言われているんですが「今の仕事を効率化して空いた時間でより上のレベルの仕事をしてもらいたい」という言葉の「上のレベルの仕事」というのはたいていの場合、会社から見れば単価が高い仕事って意味だったりもするので、レベルが高いかどうか関係なかったりするわけです。



「やる人」を作る組織


これも身も蓋もない話ですが、みんなが「できる人」になるのは幻想と書いたようにみんなが「やる人」になるのもまた幻想だと思います。


先ほど書いたアリの世界と逆のことをすればうまくいくかもしれませんが、誰もがモチベーションを持てるポジションを作るというのは縦割りの世界をなくした完全フラットで誰もが重要なポジションにいる組織を作るということになり、その中で誰かに押し付けたいような仕事を自分でがんばるみたいなことを皆が思っているか、割り切って無駄ややりたくないことをアウトソースしてしまうというような割りきりが必要なんでしょうけど、コスト面で見合うかという問題も出てきたりします。

そして、効率化しない組織を作るというのは組織の成長としてあり得ないので、ひたすら成長し変改し続ける状態を保つにしてもそれってきつい状況でもあるわけですから、その人が忙殺される毎日に耐えれなくなったり、ふとした合間で燃え尽きてしまう可能性もあります。


小さな組織であればこれは少し見込みがあるわけですが、規模が大きくなり人が多くなればなるほど絶望的な状況になりかねません。
極論言えば「やる人はやるけどやらない人は幾ら言ってもやらない」ってことになるわけですけど、できない人をできるようにするよりも前に、やらない人をやる人に変えていくことをしないと成長もしないよ、と思ったりします。


で、やる人に少しでもやる気を持ってもらう方法としてですが、以前に読んだ「小さなチーム、大きな仕事 」の中に書かれているような組織作りのイメージを持っているのですが、これは組織としての常識を覆すものが多いので、なかなか今の組織の中に取り入れるというのは難しい場合が多いかもしれません。
組織としての急速な成長というものを捨て去る必要がありますし、そもそもができる人を育てるということすら考えていません。


組織がコンパクトであればあるほど、担う役割というのは大きくなります
そしてやることも当然多い分、その人にとっての充実感が増すことにはなるでしょう(一歩間違えればブラックですけど)。

結局のところ、会社という枠組みの中で、その企業のトップダウンとしてそういった文化を創れるのであればよいでしょうけど、大抵はそんなことはなく小さな組織として成り立たせても、会社の言い分と組織の言い分でのギャップができて板ばさみにあう組織長は心が折れてしまう気がします。


言ってしまえば、やる人を作るというのはその企業命題の中にどれだけ本気で従業員のやる気にさせる組み込めるかってことになり、それって売上犠牲にしてまでやるってことでいいんですよね?という質問にきちんと「はい」って答えられる人が運営しないと作れないと思うわけです。

ですので、アリと同じく8割が仕事をしていないという状況でも、2割で組織が持っているなら良いじゃんという究極的な答えが出てくるのだろうと思います。


ここで、「やる人」が育ったとしても「できる人」にするためには更なる変化が必要なわけで原点回帰して最初の問題に戻るわけですが、「やらない人」が多くいる環境では幾ら「できる人になれ」と言ったところで成長は見込めないと思うわけです。






PR: 振り込め詐欺 知っておきたい心がけ-政府ネットTV

$
0
0
最新の手口や、ご家族に伝えて欲しい普段の心がけ等について、警察担当者が詳しく解説

未だにシステム化さえすれば自動化されると思っている人は多い

$
0
0

「今の現場には人も足りていないし業務が非効率になっている。システム化することでこれが改善できるはずだからどうにかして欲しい」というような要望を受けることは未だによくあります。

未だにというのは、システム化をすれば状況が改善されて自分たちの仕事が格段に楽になるという状況を思い浮かべているということです。

しかし、実際には改善はされるかもしれませんが、自分たちの仕事が楽になるのかといったら必ずしもそうではなかったりします。



システム化すると自分たちの首を絞める現状


システム化ということに対して妙な期待感を抱くのもわかるのですが、必ずしもそうすることで幸せになるわけでもなかったりします。

ある申請の承認フローがアナログな紙の押印で回っていたとして、それが電子承認システムを入れたからといって実際のところ業務が効率化されるわけでも業務量が減るわけでもなかったりしますし、そこ実行コストに見合ったことができているのかといわれれば疑問がある点も多々出てきます。

紙がなくなるのでエコになる!とか、状況がリアルタイムに見れて便利!!とか、電子化ってカッコいい!!!ってレベルの話はあるのかもしれませんけどね。


が、紙のアナログな業務を見ていると「未だに紙で申請とかありえないよね」みたいな話がでるんですけど、システム化したところでやってることはむしろ退化してないか?って思ったりもするわけです。

例えば、紙の申請書に対してめくら判を押すのは昔からよくありますが、システム化された状況だと似たようなところで申請の一括承認機能なんてものがあったりして、それってボタン1つで行われる作業としてめくら判より酷いんじゃないかって思ったり、「LINEで既読無視されたー。ひどーい」とか言うのと「PCとイーモバ持って出張行ったのに申請の承認してくれなんてひどーい」って基本同義だとは思うんですよね。


話がいきなり飛んだわけですが、冒頭の会話に戻すとこういった幻想を抱く背景には、人手が足りない状況の中、今の業務の一部でも自動化することで自分たちの手を煩わせているものを取り除きたいという切実な想いがあるのでしょう。

しかし、よくよく考えたらわかるように単に今の業務をシステム化したところでその業務がなくなるわけではありません。

作業は効率化されるかもしれませんが、その仕事が根本的になくなるわけではないわけです。

むしろ手が空いたところで別の業務量が増えるかもしれませんし、サービスを始めることでよりよいものにブラッシュアップをしていく終わりなき運用が始まります。


冒頭での言葉の意味を深読みすると「自分たちの業務をシステム化してそれが全自動で回るように一緒に運用して欲しい」と聞こえてしまうわけで、それって単に自分たちの手を煩わせているものをシステム部門に押し付けたいという風にも受け取れてしまいます(卑屈に見えますけど)。

ビジネスプロセスの整備の一環でそれを受注することはあるかもしれませんが、システム部門にとっては厄介な運用が増えるだけですし、これをやりだすと全社の業務をシステム部門が担わなければならないわけで、本来はそういった目的の組織ではないでしょうから、しっかりとそのシステムの業務運用をしてもらう体制が必要になってきます。


ですから、システム化することで今の業務スタイルというものは大きく変わってきてそれは今までのアナログな世界から脱却させてくれ大きな進歩をもたらすかもしれませんが、そもそも仕事自体が無くなるわけではありませんし、その進歩ゆえに運用者を窮屈にすることもあるわけです。



実はアナログなシステム運用の裏側


システムが全てを解決してくれることもあります。

ただし、金があれば。

これだけIT化が進み、インフラの維持コストが低下している状況でそんなに金をかけなくてもできるはずだという意見は正しいのですが、それでもできることは限定されます。

全てが綺麗に片付くわけではないということです。


昔、テレビ録画で芸能人の名前を入れておけばその人が出てくる番組を自動で予約してくれるという機能があって凄いと思ったのですが、その裏側はセンターで何百人もの人が全ての番組をチェックしてデータを流し込んでいると聞いたことがあります。

これまた昔の知り合いから聞いたサービスで、人物の写真をメールに添付して送るとその人の似顔絵が返送されるシステムを作ったと聞いてすげー!って思ったんですが、実は送られてきた写真をインド人が高速で似顔絵を描いていると聞いて爆笑した記憶があります。


あるシステムにおいてデータの登録・修正など補正する機能があるにも関わらず、そのデータ量があまりに多いがためにシステム部門にどうにか一括で登録できないかという依頼を受けることはよくあります。

まぁ、何で一括登録や補正機能を付けていないんだという話もあるんですが、要件聞いていたらそんな機能は初期登録時ぐらいしか想定されなくて、そういったところはシステム部門で何とかデータを流し込んだりするので、作るだけ無駄と判断されるわけです。

そういったところを記憶していたのかどうかはわかりませんが、機能外である大量のデータ補正などをシステム部門に頼まれたところで、実は大して手間はかからなかったりもするのです。

1件、1件データをコピーしながら登録していく作業に変わって、システム部門の人間がInsert/Update文を作ってたりもして、それって担当者がやるべき仕事を押し付けられていることに変わりは無かったりするわけです。


まぁ、全てがそうではないでしょうけどやっぱり何でもかんでもシステム化というのは難しく、やろうとしても莫大なお金がかかったりするので、人がまかなえるところはまかなうしかないというのが現状なわけです。

「人を使うのが一番安い」って言うブラックな発言を聞いたこともありますが、時と場合によってはそれは正解にはなってしまいます。
システム化の提案書を作るときはよく、松竹梅の案を作ったりするわけですが、たいていの場合は松のプランなんて選ぼうともしなかったりして、「そこは運用でカバーします」と言われたりして自身で「人を使うのが一番安い(自分でどうにかします)」ってことを暗に認めていたりもします。


こういったことってどんなシステムであれ必ず発生しますので、冒頭の全自動で仕事が楽になって助かるぞーという思いは満たされなかったりするわけです。



まとめ


現状ある業務サービスがシステム化されていようといまいと、それを運用していくという工数は最低限降りかかってきます。

それがなくなる魔法を作るには、それなりの投資を経てなるだけ自動化された目的のシステムを作るか、これまたお金のかかる話ではありますがアウトソースをするか、それが難しければ受け入れるかさもなくばそのサービスを捨て去るという判断が必要です。


皮肉にも、今の非効率な業務が嫌だからシステム化しようとしても、それがなくなるわけではなくむしろ逆で真っ向とその業務と向き合わざるを得ない状況に追い込まれたりもします。

ですから、そのシステム化されたサービスを継続して運用していく覚悟が当然必要になってくるわけです。


結局のところシステム化という施策は単に自動化するかどうかという話ではなく、そのサービスの質をあげよりよいものに改善していくためにあります。

そういったところが話しの中で見えてこないと、システム部門の人間としても少し斜に構えて話を聞いてしまうわけです。





イノベーション・オブ・ライフ ハーバード・ビジネススクールを巣立つ君たちへ

$
0
0

イノベーション・オブ・ライフ ハーバード・ビジネススクールを巣立つ君たちへ/クレイトン・M・クリステンセン

¥1,890
Amazon.co.jp


人生において幸せの感じ方は人それぞれでしょうが、その人生の幸せとは何かを考えさせてくれる本です。

今は幸せだからずっとこのままでよいと思っている人も、今の環境を変えたいと願い他人が持っている幸福をうらやましく思う人もそれが本当に正しいことかわかりません。

ずっとこのままで、というのは現在の環境をそのまま維持し続けるということになりますが、経済環境の変化だけでなくそもそも自分が年老いていくということに対して逆行することはできないのでそもそもが不可能です。

他人の幸せというのも、自分から見て華やかであって実際のところはどうなのかわかりません。

それが本当の成功なのか偽りの中で作られた成功なのか、偽りの場合はそこまでして自分はその環境を手に入れたいと思うだろうかとか。


この本では、過去の成功・失敗体験からどうすればよいとか、こうやって歩を進めていきなさいという予測ではなく、理論を元に人生や仕事のやり方というものをプランニングするように書かれています。

私たちが働く目的とは何なのか、新しい分野に進出するときにどう考えればいいのか、その計画がうまくいかなかったときにどう方向転換すべきなのかといったことだけでなく、家族との向き合い方から子育てで大切なことというのを単に筆者の経験則から出なく、実績から導かれた理論で解説しています。

そして、理論を持つということの大切さもこう書かれています。


あなたは人生の重要な決定を、過去の事例や他人の経験を参考にして下せばいいと思うかもしれない。
(中略)
だがそれでは、未来へ向けて船出するとき、その情報や助言を受け入れ、どれを聞き流すべきかという、根本的な問題の解決にはならない。これに対して、確かな理論を使ってこれから起きることを予測できれば、成功するチャンスを格段に高められる。

この本の面白いところは、家族や子育ての分野でもどうすべきかというところをかなりのページを裂いて解説しているところです。

自分には子供はいませんが、自分が親からしてもらったことと照らし合わせてみると納得することも多くありますし、理論を交えた子育て本というのはなかなか無いのではないでしょうか。

そんな仕事の考え方だけでなく、家族や子供との向かい方にも深く切り込んでいるので、何が人生において幸せなのかというのを深く考えさせられます。

成功というのは何なのか、それは1つしかないものでも他人の評価によって決まることでもなく、自分の中でそれを生み出しそして掴み取ることの大切さというものを考えさせれる本でした。



目次


第1部 幸せなキャリアを歩む
 第2講 私たちを動かすもの
 第3講 計算と幸運のバランス
 第4講 口で言っているだけでは戦略にならない

第2部 幸せな関係を築く
 第5講 時を刻み続ける時計
 第6講 そのミルクシェイクは何のために雇ったのか
 第7講 子どもたちをテセウスの船に乗せる
 第8講 経験の学校
 第9講 家庭内の見えざる手

第3部 罪人にならない
 第10講 この一度だけ・・・・・・



CakePHP2.x系でバッチプログラムを作る

$
0
0

コマンドライン処理をPHPで作りたい場合、わざわざCakePHPでバッチプログラムを作らなくても、っていうのはあるかもしれませんがWebをCakePHPで作っているのであれば、そこで作ったコンポーネントやモデルなどを再利用できるため何かと便利だったりします。



CakePHP2.xでバッチプログラムの作り方


CakePHPのバッチプログラムは、下記のパスに保存します。


/path/to/cakephp/app/Console/Command

バッチプログラム名は、指定したいプログラム名に「Shell.php」をつけて定義します。

プログラム名が長い場合、キャメルケースを使って定義している方がよいでしょう(理由は後述)。

そして、バッチプログラム本体は、同ディレクトリ内に存在するAppShellクラスのサブクラスとして定義します。


<?php

class HogeDataImportShell extends AppShell {

    /**
     * バッチ開始前の処理
      */
    public function startup()
    {
        parent::startup();
        $this->cleanup();
    }

    /**
     * バッチのメイン処理
      */
    public function main() {
        $thi->out("バッチ処理を開始します");
    }

    /**
     * 独自のデータを初期化する処理
     */
    public function cleanup() {
        $this->foo = NULL;
        $this->bar = array();
    }

必要なのは、main()のみでこちらはバッチ実行時に自動的に呼び出される関数です。

startup()は必須ではありませんが、バッチ実行前に呼び出したい処理があればここに書いておきます。

cleanupは単に独自関数でバッチの処理の中でも共通で使うものや切り出したい処理があればバッチ内に関数を定義していくこともできます。


バッチの実行は下記のように、cakeコマンドを通して実行します。


$ /path/to/cakephp/app/Console/cake HogeDataImport dry-run
Welcome to CakePHP v2.3.7 Console
---------------------------------------------------------------
App : app
Path: /var/www/cakephp/app/
---------------------------------------------------------------
バッチ処理を開始します

cakeコマンドの後にプログラム名(Shell.phpを除く)を指定し、引数を渡したい場合はその後にスペース区切りで指定していきます(上記の場合は「dry-run」が引数)

または、下記のようにcakePHPによって認識されるアプリケーション名を指定しても実行できます。


$ cake hoge_data_import

アプリケーション名は、キャメルケースで書かれたプログラムをアンダーバーで区切ったものとして認識されているようで、cakeコマンドだけを実行してみるとアプリケーション名がはっきりわかります。


$ /path/to/cakephp/app/Console/cake

Welcome to CakePHP v2.3.7 Console
---------------------------------------------------------------
App : app
Path: /var/www/cakephp/app/
---------------------------------------------------------------
Current Paths:

 -app: app
 -working: /var/www/cakephp/app
 -root: /var/www/cakephp
 -core: /var/www/cakephp/lib

Changing Paths:

Your working path should be the same as your application path. To change your path use the '-app' param.
Example: -app relative/path/to/myapp or -app /absolute/path/to/myapp

Available Shells:

[CORE] acl, api, bake, command_list, console, i18n, schema, server, test, testsuite, upgrade

[app] hoge_data_import, fuga_menu_import

To run an app or core command, type cake shell_name [args]
To run a plugin command, type cake Plugin.shell_name [args]
To get help on a specific command, type cake shell_name --help

上記の場合、hoge_data_import(プログラム名はHogeDataImport)とfuga_menu_import(プログラム名はFugaMenuImport)がCakePHPのバッチとして認識されています。



バッチプログラムを作るうえで覚えておくこと


これだけでバッチプログラムを作ることができるようになったわけですが、プログラムをより便利に作るために幾つか覚えておいた方がよいことがあります。


・ バッチで引数の受け取り方


まず、先ほどのバッチ実行時に指定した引数ですが、バッチプログラム内では下記のように引数を受け取ることができます。


if (preg_match("/^dry-run$/", $this->args[0]) === 1) {
    $this->dryRunMode = TRUE;
}


$this->args内に引数で指定した順番にデータが配列として格納されます。


・ バッチでモデルの使い方


Controllerで呼び出しているモデルを同様に使うことができます。

呼び出し方も同様です。


class HogeDataImportShell extends AppShell {
    public $uses = array('Foo', 'Bar');

    public function main() {
        $data = $this->Foo->find('first');
    }
}

メンバ変数として呼び出したいモデルを配列に格納しておきます。

使い方もControllerと同様ですね。


・ バッチでコンポーネントの使い方


Controllerの共通処理として定義しているコンポーネントをバッチからも呼び出せたら処理が統一できて非常に便利です。

幾つか呼び出し方はあるみたいですが、少し方法が複雑です。


App::uses('ComponentCollection', 'Controller');
App::uses('CommonComponent', 'Controller/Component');

class HogeDataImportShell extends AppShell {

    public function startup() {
        $collection = new ComponentCollection();
        $this->Common = new CommonComponent($collection);
    {
    public function main() {
        $this->Common->getData();
    }
}

上記のようにComponentCollectionを生成した上で、呼び出したいコンポーネント(CommonComponent)のオブジェクトを生成します。

オブジェクトが生成できれば使い方はControllerでの使い方と同様です。


・ サイレンとモードでの実行


これはおまけ的なものですが、CakePHPのバッチを実行すると最初にヘッダが出力されて少し煩わしいことがあります。


$ cake hoge
Welcome to CakePHP v2.3.7 Console
---------------------------------------------------------------
App : app
Path: /var/www/cakephp/app/
---------------------------------------------------------------

これの消し方として、「-q」のオプションを指定する方法があります。


$ cake -q hoge

ただし、この方法はバッチプログラム内で標準出力している($this->out)ものも出力されなくなってしまいますが・・・。

または、バッチプログラム内でstartup関数をオーバーライドして消す(parent::startup()を呼び出さない)という方法でも出力を抑制できたりします。





開発チームと運用チームの戦い

$
0
0

むかしむかし、組織がそしてシステムが小さな頃は開発や保守、運用という区切りは存在せず、みんなが全てを担当し、一丸となって運営を行っていました。

しかし、システムが複雑になるにつれ、組織も大きくなり、何時しかそれらの作業は1人1人のキャパでは回しきれなくなっていきました。

そこで困った組織長はチームを二分し、開発(・保守)と運用という役割に分けることにします。

チームの役割をはっきりさせることによって組織運営を円滑にするための措置でしたが、それによってチーム同士の戦いが始まることになりました。



開発と運用という縦割りと横割りの隊形


今ではシステム運営のイロハが世に出回っていますから、こんなストリーのように最初から非効率な状態で開始されるということはないかもしれませんが、それでも組織自体が小さかったり、要員が少ないという場合はどうしてもこのように非効率な状態から開始せざるを得ないというのはあるでしょう。

サービスを作り上げた当初、開発・運用の体制が数人というケースはよくあるでしょうし、そういった場合は書いたように全員が開発・運用を担っていくというような組織作りにせざるを得なかったりします。


私もこういった組織体制の変遷を辿ってきたりしましたが、最初はサービスやシステム単位でチームが組まれていきます。

あるシステムはこのチームが運営していく、別のシステムは別のチームが、というように組織が縦割りになって構成されます。

しかし、個々の規模が大きくなってくると各組織で同じような課題が出てきてそれを解決するための施策が立ち上がったりしてきますし、情報が共有されずに非効率な組織運営となっていきます。


それらを解決するために、どのシステムも横串で面倒を見れる開発チームや運用チームという横割りの組織体制に変わっていったりするわけですが、それでも情報共有がされないという課題は同じように出てきたり、横割り故に自分の作業に大きく弊害が出る問題が発生したりします。


縦割りの組織では、「よそはよそ、うちはうち」という割りきりができますが、横割りの組織の場合、業務上でお互いが通さなくてはならないフローを邪魔することがおき始めたりします。

開発には開発のルール、運用には運用のルールというものが出来上がるので、それはお互いのチームの中でよく吟味され、効率化やリスクを低減させるためのものだったりするわけですが、他のチームから見たらその良さは良さや理由が伝わってなくて面倒に思えてきたりします。

「なんでそんな面倒なことをするの?」「そんなの言わなくてもわかるでしょ?」という具合に、早くして欲しいのに遅々として進まない状況に苛立ちを覚えたりもするわけです。



運用チームの苛立ち、開発チームのジレンマ


運用チームから見れば開発の状況が見えないというのは苛立ちの一つでもあったりします。

もちろん進捗を確認する打ち合わせなどで開発担当者からの定期的な報告は聞いているんでしょうけど、何でそういう進捗になっているのかとか、そういった構成をとることになるのか、それを何故リリース後に運用が担当しないといけないのかなどなど、細かいところはなかなか共有されなかったりもします。


開発というのは一定の期間で終わることが多いですが、運用というのはそのサービスやシステムがある限り面倒を見なくてはならない業務です。

それ故に最初が肝心というのを運用の担当者は身にしみて覚えていたりします。

「最初は運用で回避して。後でシステム化するから」といったところで他の案件で開発要員の手が取られて一向に改善が進まないばかりか、そういったシステムが次々と回されてきて現場はパンク寸前なんてことがあったりするからでしょう。


一方で開発チームが受けるジレンマは、運用の細かなルールに縛られるところがあったりします。

「バグです」なら開発が悪いって事になりますが、サービスが止まった(止まりかけた)ってなると運用が責められますし、ユーザーとのやり取りの矢面に立つのが運用だったりもするので品質の維持に人一倍シビアに考えていたりもするからでしょう。

そのために多くのマニュアルが備えられ、ミスを防止するための細かいルールが整備されたりしますが、開発側から見ればそれは酷くまどろっこしいものだったりもするわけです。

ちょっとした機能をリリースしたり、サービスへの影響が無いメンテナンスをするためにも所定の手続きが必要だったりして、「そんなのこっちの責任でやらせてよ」って思ったりもします。


自分はどちらかというと開発側の経験の方が長かったりもするんですが、一番面倒に思えるのがサービスの維持のために必要なサービス監視だったりして、直接影響が無い作業でも監視引っかかったりするとアラートがあがって、運用の担当者に「何かやりましたか?」って都度都度状況を説明しないといけなかったりします。

もちろん監視自体は重要なものとわかっているのですが、そのちょっとしたことがすぐにできないジレンマがあったりするわけです。

「監視システムは5分おきにポーリングしているから、そのログから次の5分までに作業をすればばれないぞ!」みたいな変なノウハウを教わったりもします。



チームを一つにするための大義名分


開発と運用という組織が分かれた場合、その組織長が分かれたりしていて互いに仲が悪かったりする場合は困りものだったりするのですが、結局のところはその運営していくサービスをよりよくするためのことを考えていたりするわけです。

ただ、互いの領分を守ろうとするあまりに相手の言い分が聞こえないような状況に陥ってしまっているわけで、その目的達成のために自分たちの手法やルールが必要だと言い合っているだけだったりします。

こういった状況を打破するためにも、もう一度しっかりと互いの共通目的はなんなのかというチームを束ねるための大義名分が必要だと思います。

こういうのって結構シンプルなものでよくって、「このサービスをよりよくしてお客さんに喜んでもらいたい」とか、「世の中を良くするためのものを作ろう」とか、お互いにそういったことのためにしているんだけど忘れがちになっている部分をちゃんと互いに再認識しておくのって結構大事なんだなって思ったりします。


まぁ、こういうことをいえるのは互いの組織をさらに束ねる長がしっかりと示すべきでしょうけど、そういうのが期待できない場合は、相手の仕事を理解するためのチーム間のローテーションなども必要になってくるでしょう。

互いのチームのやっていることというものが見えればその理由というのもおのずと理解できますし、こういった情報が必要だろうとか、ここは運用とネゴしておこうとか、相手への気遣いというもの生まれて運営が円滑になったりもします。

何よりも互いのチームを回すための業務の知識というものは結構異なってきたりもしますし、システムの運用をするのにプログラムに理解が無いというのは結構開発視点でも運用視点でも辛かったりもします。
運用側の課題を解決するために自分たちでどうにかできないというのは、開発はサービスやアプリの開発に注力して運用の課題を解決するための施策に手を回す時間が取れなかったりもしますから、運用側は運用側で自分たちで運用ツールを構築していくといったことをしていかないと何時まで経っても仕事が降ってきて要員はパンク寸前という状況が打破できません。


あとは、何よりもチームが分かれているけど、互いにとって必要な存在ではあるわけですから、しっかりと情報を共有したり、言いたいことを言っておく場というのも大事になってきます。
色んなシステムの面倒を見ていて大変というのはあるんですけど、開発側も運用側もそれぞれの苦労があるわけで、互いの言い分だけでなくちゃんと理由を伝えることだったり、自分も運用側にいてその苦労がわかるからそれを回避するためにやってあげた方がいいことっていう気遣いをちゃんと示しておくとわかってくれたりもするものです。

そして、お互い何のためのこの仕事をしているのか?ってことの原点をちゃんと確認しておくべきじゃないかと思うわけです。





情報システム部門でクリエイティブな仕事ができるのか?

$
0
0

という話題が周りで出たりして少し考えさせられたりしました。

クリエイティブという言葉は非情に魅力的に聞こえたりするのですが、社内のシステム保守・開発・運用をする部門に当てはめるには縁遠い言葉のようにも聞こえたりしたわけです。



創造的ではなく真似事と現状維持の仕事をする現実


社内の情報システム部門に与えられる役割は企業によって様々でしょうけど、その中の人で「我々はクリエイティブな仕事をしているぞ!」というのはどれぐらいいるのでしょうか。

自分の予測ではほぼいないような気がします。


クリエイティブという言葉は創造的といった意味にはなりますが、その意味以上に何か新しいもの、世の中に無いものを作り出すといったイメージが含まれていてワクワクさせられるわけですけど、そういったクリエイティブな領域が情報システム部門の中にあるかというとあまり見当たりません

今のうちのこの業務領域が非効率で改善したいとか、社員同士のコミュニケーションインフラを改革したいといったプロジェクトが立ち上がったとしても、それは他所でやっていることや世の中のトレンドを反映しようとしたものになります。

単純に言えば、「今SNSが流行っているようだからうちでも導入して社員のコミュニケーションを円滑にしよう」といった具合に。


ただ、これをクリエイティブと呼ぶかといったらそうではないでしょう。

ありものを持ってこようとしているわけで、それを設計する側としても「Facebookみたいに「いいね」ボタンをつけようぜ」みたいに真似事のシステムを作ろうとするわけです。

結果的にそれが功を奏して社内の業務改善につながるかもしれません。

ただ、それでクリエイティブな仕事をしてたと言えるのかと言えば個人的に違うんじゃないかと思うわけです。

悪く言えば流行を取り入れた真似事のサービスを実装しようとも言えなくもありません。


また、そういった業務改善をすることで新規に何かサービスやシステムを作り出そうというプロジェクトならまだ何かを生み出しているという感覚に包まれるのでよいかもしれませんが、そういったプロジェクトよりも既存のシステム保守・運用といった仕事の方が多かったりします。

サーバーやソフトウェアのEOSに始まったリプレイス施策やインフラ・システムの拡張といったことは、今あるものをベースに考えられたりするので、何か新しいものを作るというよりは単純に現状通りになんとか延命していこうという施策ばかりでは「クリエイティブな仕事がしたい」と思う人がいるのも無理は無いかもしれません。



情報システム部門の中にクリエイティブな仕事の領域があるのか


というのは、情報システム部門にクリエイティブな領域が求められているかどうかということになりますが、例えばラボのようなものがシステム部門の中にあるのであれば、そこは世の中のトレンドをウォッチしつつ社内や社外向けのサービスの種となるような実験的なことをやれたりもするかもしれませんが、こういったラボがシステム部門としてあるところも少ないと思います。

サービス系の部門の一組織として存在していたり、または世の中のトレンドを見るというところも調査部や企画部といった組織に役割が与えられていたりして、情報システム部門としてそういった領域も含めて組織構成されているところはどれだけあるのでしょうか。


つまり、悲しいかな大抵の情報システム部門においてクリエイティブな領域というのは求められたりしていないと思うわけです。

いや、現実的には「もっとクリエイティブな仕事をしていこう」とか言われたりもするのですが、それが実現可能なレベルで実行できるかといえば、踏み込む領域も要員も予算もなかったりするので何をどうやって生み出していけばいいんだ、という気持ちにもなります。


言ってしまえばクリエイティブな仕事をしたければシステム部門ではなく、そういったことをするためのサービス系の部門か、研究をする役割を与えられた組織に配属を希望する方が手っ取り早そうです。

現状のシステムやインフラを維持するという役割がある以上、クリエイティブなことに割く時間というのはおのずと短くなってしまいます

そういったことを避けるために、保守・運用をアウトソースしたりクラウドを利用するといったことが考えられたりもしていますが、それを推し進める過程で創造的であるための基礎を失うことにもなって、結局何も生み出せない抜け殻の組織が出来上がってしまうリスクもあったりします。


もう1つ、社内でのクリエイティブな仕事が難しい理由は、そもそも世の中に出てくる独創的なサービスや製品でも受け入れられるのがなかなか難しいものだったりする中、それを社員向けに使うわけですから、大体がついてこれないでしょうしそういった提案をしたところで「うちの社員には使えこなせそうに無いので今と同じように・・・」といった返答が返ってきたりもします。

この提案は全然クリエイティブではなかったりしますが、今の流行のスタイルというものを提案してもこういった状況なので、それ以上に独創的となると当然受け入れられるわけはないよなぁ、って思ったりします。

対外向けサービスの試作として社内に先行展開するというならまだ理解は得やすいかもしれませんし、それは仕事として扱うので拒否反応も薄いかもしれませんけど。


先進的なサービスを作って受け入れてくれるアーリーアダプターは、世の中的な母数から見ればそれなりの数が出てくるかもしれませんが、それが社内のってことになると皆無という状況にもなったりするわけで、そこからどう広めていくかということになると社員の多くが流行に敏感であったり、文化としてそれが受け入れられる土壌も必要になってくるのではないでしょうか。



まとめ


自分で書いていてなんだか悲しい気持ちにもなってきたりはしたのですが、それでも自分としてもクリエイティブな仕事をしたいという気持ちはあります。

広義に何かを作り出すということとして捉えればまだそういった仕事もあるわけで、システム部門の役割や求められる価値としてどんどん薄くなっていっている現状、そういった生み出す仕事というものをしていかないと本当に存在価値ない部門となっていってしまいます。


生み出す力が弱くなっていったのは、社内に導入していくシステムの数が増えて現状維持で手一杯になる一方で企業として求めるシステム基盤の要件を満たす人材が不足して、低コストで実現できるという名目の外部への委託に走った結果というのもあると思いますけど、それは自分たちがそんな現状に忙しいと甘んじていたというのも理由の一つになるでしょう。


ということで、クリエイティブな領域に踏み込む余地というのは少ないものの、そこに向けて食い込む努力をして勝ち取っていかないとやりたいこともできない状況にますますなっていくのではないかと感じています。

言葉の魔力だけを鵜呑みにするのではなく、与えられた役割をこなしつつ独創的なものを作り出していく、というのは簡単にいえるようで想像以上に難しいことだと感じています。





yumによる多数のサーバーへのパッチ適用を自動化する

$
0
0

サーバーの台数が増えてくると個々のサーバーへのパッチの適用作業というのは結構手間になってきたりもします。
しかも、パッチを適用することでそれらのパッケージを利用したプログラムとかに影響が出たりして、十分に検証期間を取った上で本番環境に適用したいというニーズが出てきたりもします。


というわけで、単純なyum関連のコマンド(yum、yumdownloader、createrepo)を利用してパッチの適用作業を自動化する方法について書いてみたいと思います。
なお、環境はRedHat5系をベースにして書いています。



社内配布用のリポジトリサーバーを構築する


まず、システム構成のイメージとしては下記のようになります。


A Day In The Boy&#39;s Life
社内用のリポジトリ兼検証用サーバーは通常通り外部のリポジトリから最新パッチを適用していき、その影響調査および本番サーバーに配布するためのリポジトリサーバーという役割を担います。
詳しくは後述しますが、もう少し本番適用までを慎重にしたいとか、複数のサーバーで影響調査をしたいという場合は、リポジトリサーバーをもう1台増やしたりして、1台目は最新を常に当てる、2台目は検証が取れた本番適用予定のパッチだけがリポジトリに登録されている、というような構成も取れたりします。


まず最初に、検証用サーバーでは通常通りyum updateで最新のパッチを適用していきます。


# yum update -y

この辺もCronに設定しておけば自動化できるでしょう。
当てたくないパッチなどがある場合は、yum.confのexcludeに適用対象外のパッケージ名を指定しておきます。


exclude=kernel*

次に、検証用サーバーに適用したパッケージをダウンロードしてリポジトリを生成します。
このリポジトリを本番サーバーが参照します。
以下のようなバッチを作成して、検証用サーバーに適用しているパッケージのソースをダウンロードします。


#!/bin/sh
DESTDIR=/path/to/htdocs/rpm/rhel-x86_64-server-5/dev/
rpm -qa | xargs rpm -q --qf '%{NAME}\n' | sort | uniq | xargs yumdownloader --destdir=$DESTDIR
createrepo -q --update $DESTDIR

yumdownloader(createrepoやreposyncコマンドも同様)は、yum-utilsに含まれますので環境に存在しない場合はyum経由でインストールしておきましょう。
後述するreposyncコマンドを使って、外部リポジトリ(rhelやrpmforgeなど)を丸ごとコピーしてもよいですが、かなり容量も大きくなりますし不要なものも多いので、サーバーに適用しているパッケージだけをダウンロードするようにしています。
パッケージダウンロード後は、createrepoコマンドでリポジトリを生成しています。
リポジトリのディレクトリは別のサーバーからHTTP経由でアクセスするため、ドキュメントルート以下にしておきます。


yum update後に上記のバッチによってパッケージをダウンロードしておけば、検証環境に適用しているパッケージとリポジトリに登録しているパッケージのバージョンをそろえることができます



本番環境のリポジトリ参照先を変更


社内配布用のリポジトリができたので、次は本番サーバーがこのリポジトリを参照するように設定変更します。
yum-fastestmirrorを導入している場合、参照先のリポジトリが自動的に選択されるので、まずはこれらのプラグインを動かさないようにしておきます。


[main]
enabled = 0
gpgcheck = 1

enabledを0にしてプラグインの読み込みを禁止します。
次に、検証用のリポジトリを参照するようにyumの設定ファイルを追加します。


[dev]
name = RHEL $releasever - www.example.com -
baseurl = http://192.168.0.100/rpm/rhel-x86_64-server-5/dev/
enabled = 1
protect = 0
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag
gpgcheck = 0

baseurlには、検証用のサーバーのリポジトリのURIを指定します。
設定後は、yumコマンドでリポジトリの参照先が検証用サーバーを向いているか確認しておきましょう。


# yum check-update
Loaded plugins: security
Excluding Packages in global exclude list
Finished
Skipping security plugin, no data

httpd.x86_64                2.2.3-83.el5_10           dev
httpd-devel.i386            2.2.3-83.el5_10           dev
httpd-devel.x86_64          2.2.3-83.el5_10           dev
httpd-manual.x86_64         2.2.3-83.el5_10           dev

右端に参照しているリポジトリ名(dev)が表示されます。
あとは、任意のタイミングでyum updateを本番サーバーで動かすようにCronにでも登録しておけばパッチが適用されていきます。

この仕組みでは、検証用サーバーのリポジトリを更新しない限り、本番サーバーへ勝手にパッチが当たることがありません
検証用サーバーで十分に検証期間を取った上で本番に適用していきたいということであれば、この辺は運用の組み立て方の話でありますが、


1. 検証用サーバーのパッチ適用は手動で行う(毎週月曜日とか。その週は検証期間としておく)

2. 検証期間で問題なければ日曜日の深夜に検証用サーバーのリポジトリを自動更新する

3. 毎週月曜日の早朝にCronでパッチを自動適用する

4. 以下、次の最新パッチを検証用サーバーにあてていく


というような動かし方ができます。
要は2.を実行しない限り、3.のパッチの本番適用は空振りします(その前に全てのパッチが当たっているはずなので)。
1.2.にどれだけの期間をおくのか、全部自動化してしまうのか、心配だから2.までを手動で行うのか、といった調整でどうにかなるんじゃないでしょうか。


予断にはなりますが、社内リポジトリサーバーを複数たてる(ステージング用のサーバーを作るとか)場合ですが、リポジトリ間の同期が必要です。
その場合は、reposyncコマンドを使ってリポジトリのコピーを作成することができます。
こちらも下記のようなバッチを作っておけば便利です。


#!/bin/sh
DESTDIR=/path/to/htdocs/rpm/rhel-x86_64-server-5/
reposync -p $DESTDIR
createrepo -q --update $DESTDIR/dev/

検証用サーバーでは、外部のリポジトリを参照してパッチを全て当てておき、適用したパッチも含めた最新のリポジトリを作成する。
ステージングサーバーでは、検証用サーバーのリポジトリを上記のバッチで複製しておく(複製のタイミングは少しずらしておく)。
本番サーバーのリポジトリはステージングサーバーのリポジトリを参照する。


といったことをしておけば、万が一検証用サーバーに変なパッチが当たってもそのパッチの本番適用を防ぐことはできると思います。


yum updateだけで対処しようとすると、適用するタイミングでパッチの種類やバージョンが変わったりするので、社内向けにリポジトリサーバーを立てるだけでも結構この辺の作業は楽になるんじゃないかと思います。






エンジニアが考えるお金と胡散臭さと偏見のお話

$
0
0

セカイカメラ終了のお知らせ……開発元・頓智ドット「目指した思想は諦めていない」 @ TechCrunch


このサービスが発表されたときの盛り上がりは、当時のニュースサイトで大きく取り上げられていて凄く印象に残っています。

ただ、私自身がセカイカメラを使ったことがあるわけでもなく、またどういうビジネスモデルで収益を得ようとしていたのかという点もよくわかっていないので、このニュース自体を題材について語ることはできないのですけど、今回のニュースのコメントを見るとそのビジネスモデルの作り方という点に言及したものや、エンジニアの集団としてのお金儲けの仕方について触れているところが多かったりして、エンジニアが作りたいサービスとそこからどう利益の出して成長させていくのかという点においては結構、考えるところがあったりします。



お金儲けに染まりたくないという心情


というのは自分もあったりして、流石にこの歳になって家庭を持ったりするとそんな奇麗事ばかり並べてはいられないぞ、というところはあるんですけど我武者羅に開発とかしてたころはお金儲けの仕組みを作るってこと自体に興味がありませんでしたし、凄いものを作れば周りもついてきてくれるという気持ちさえ持っていたりしました。

別に欲しくないというわけではないのです。

それが一番になりたくないという気持ちが強かったんだと思います。


ただ、世の中には色んな職業や考え方を持つ人もいて、それを中心に考える人もいるわけです。

当然、ビジネスの世界で事業を継続するためには資金が要るわけですし、成長させるためにはなおその元金が必要になってきます。

お金儲けを中心に考え出すと、サービスを作るということ自体が乱暴に言ってしまえばどうでもよいものと化す可能性があります。

その寿命や世間の目を気にしなければ人気のサービスのパクリであったって言い訳でなんですけど、エンジニアとしてそれを作りたいか?と問われればそんなものを作りたくて技術磨いているわけではない、って思うエンジニアは多いでしょう。

そんなこんなで偏見だったりする部分もあるんですけどコンサルやっている人を酷く毛嫌いしている時期がありました。


お金儲けを中心に考えると曲げない(捨てないと)といけなくなるところが多々出てきます

これは日常の仕事の中でもそうなんですけど、新しい技術や保守性を保つよりも取りあえずスピードが求められたり、使いたくも無いパッケージを使う羽目になったり、入れたくも無い広告をでかでかと入れる必要性に迫られたりします。

日本人特有のお金は汚いものっていう感性が相まってか、そういう世界で精神を削られるよりは好きな開発に注力したいという心情も理解できたりします。


なので、そのサービスを作る意義や思想というものが大事になってくるのではないかと思うわけです。

まぁ平たく言えば、結局はお金儲けをする道具を作っているに過ぎないのですが、それをしていると感じさせてくれれない気持ちをそちらに向けさせないキャッチフレーズ的なものって結構好かれてるんじゃないかなと思います。



お金を稼ぐってことで割り切られる効果


そんな若かりし頃の感情もまだ残りつつも、自分もプライベートではとあるサービスを作るのにエンジニアとして参加していたりするのですが、そんな話を持ちかけられたときもやはりお金の話って切っても切れなかったりします。

当然、ボランティアでやるわけではないので(少なくともその話はそういった内容のものではないので)、プライベートな時間を削る分の対価を得たいと思うわけです。


ただ、じゃあ月幾らでとか、このサービスを作ってこんなビジネスモデルで集計を立てて、売上目標は幾らでとかいう話をされたらビジネスとしては当たり前のことなんでしょうけど途端に胡散臭ささえ感じられたりします。

エンジニアって営業とかに比べたらお金の話と遠い位置にあったりして、自分が作ったソフトウェアやサービスが幾らで売れたとしてもあまり身近に感じずに単に数値として定量的に見てしまっているところがあるのではないかと思ったりします。

ですので、エンジニア兼営業的なことをやるとその金額が途端に生々しく感じられたり、あまり現実味の無い話に聞こえたりします。


自分がそういったお金に対する抵抗が少し解けて実際に何かサービスを作っていくうえでは、そのサービスをどう成長させていくのかとかどうやって収益を立てていく必要があるのかという視点って凄く大事なことなんだなと思うようになったいう点ではこの話を受けてよかったなと思っているところです。

それは当然仕事をしていく上でも当たり前のように考えられていることですし、対価に対してやる範囲が決められたり、優先順位がそれによって変わってきたりもします。

もちろん、プライベートとは言え仕事の流儀に沿ってやってたりするわけですから割り切るところは割り切らないといけなくなってくるわけなんですけど、完全にプライベートであればそんな難しいことはあまり考えないでしょう。


もう1つ思うのは、そのサービスを成長させるビジネスモデルを作るということは、行き当たりばったりではないことの表れであったり作りたいものをはっきりさせる効果があったりします。

まぁ、やってみないとわからないところはありますし世の中のニーズに沿っているのか、とか考えたらそれだけできていればよいというわけではないのですが、少なくともプライベートで作るものにあまりそういった考えを持ってたりはしません。

取りあえず自分が作りたいものを作ろうという。

ただ、そういったものって長続きさせるには相当なモチベーションが要るわけですから、ある意味仕事のような割り切りができたほうがやりやすい面はあるのではないでしょうか。


そして、そういった成長路線を描くには様々な分析が必要になってくるわけで、自分自身が完全にそうなんですけど「プライベートでは何を作っていいのかわからない」という状況がクリアになってきます。

仕事での役割分担も完全にそうですけど、PJに参加するメンバーごとにロールが異なるわけで、作りたいものがあるけど作れない人と作れるけど作りたいものがわからない人、というのがうまく合致しないとなかなか一人で二役をこなすのは難しいものだと強く思ったりするわけです。


それを作りたいか?と言われればそうでもないんだけどお金もらえるし、その為にはそのサービスを成長させていく手段を考えていかないといけないって割りきりができる分、気分的に楽になるところがあるのではないでしょうか。

それによって得られる環境というのもありますし、やりたい事も広がってくる部分もあるので、それが目的になると道を外れる可能性はありますけど、あるに越したことはないレベルで考えてみるのは良いのではないかと思うこのごろです。





新しいモノやサービスがもたらすものと豊かさについて

$
0
0

少し遅くなりましたが、あけましておめでとうございます。

本年も当ブログをよろしくお願いします。

去年はあまりブログかけてない印象だったので、今年は無理はしないでももう少しペースをあげていけたらいいなと思っているこの頃です。


さて、お正月はというと帰省していたりして、戻ってくる際に東京駅付近で発生した火事の影響をもろにくらってしまい、帰りの新幹線が大変なことになったりしていたんですが、この件についてTwitterでの発言なんかが話題になっていたりもしました。

巻き込まれた身としては余裕の帰宅のはずが家に着いたのが深夜になって疲れはしたんですが、あんまり深く考えなくてのんびり変えれば良いや的に思ってたりもしたんですけど、やっぱり当たり前に動くものと思っていたものが想定からずれて新幹線のホームは大混乱でしたし、そのことに苛立ったりしている人を何人も見かけたりして、高度に進んだ技術やサービスというのが、人の豊かさに対して必ずしもプラスになっているのではないんじゃないかって考えさせられたりもしました。



技術の発展と豊かさ


1つ思ったのは技術の発展というのが必ずしも人々を豊かにしているわけではないんだな、という点です。

確かに新幹線や飛行機は高速に遠隔地に運んでくれますが、それによって緩和される時間のロスや旅行の苦労とは引き換えに、特に時間なんかは自由度と引き換えに追われるデメリットも出てきたりします。

整備された交通網のおかげで移動の時間が短縮される代わりに、せわしない旅行日程が組まれたり(現に詰め込みすぎなんじゃないかって印象を受ける旅行雑誌の日程表なんかもありますし)、発展した情報機器によって大量の情報にさらされ目の前にあるものの印象よりもネットの向こう側の情報に気を取られたりします。


現代人というのは常に何かに追われています。

イベントに出れば写真を撮って共有しないという観念に駆られたりする人も多いのではないでしょうか。

余談ですけど、写真を撮ったりすると目の前に起きている事への印象が薄れたりするそうです。


写真の撮り過ぎ、思い出薄れる? 心理学研究 @ AFPBB News


写真の共有というのもTwitterやらFacebookやらで常に誰かと比べられる・比べたい状況に身をおいているのが引き金になっていたりもするわけですけど、常にそんな周りを気にしないといけない状況になってSNS疲れを起すなんて要因になるのもなんとなくわかったりもします。

欲求の満たし方がより高次のものへと昇華し、多くの人の承認欲求が強くなっているのかわかりませんが、相手に伝えたいことは本当はそんなことではないでしょうしその温度間も自分と他人とで全然違うはずで、会えば身内ネタで済まされるようなことが炎上のネタになったりと、その欲求の満たし方の掛け違いによってブーメランのようにダメージが跳ね返ってきます。


今の時代、思い出を切り取ったりそのまま保存するということが容易になったことで人々が感動するレベルというのは一昔の人と比べて全然違うものになっているんだろうなとか思ったりしますが、忙しい我々にとってはただ1つのことに力を注ぐよりもより多くのものを見聞きしたいと考えるのは当たり前のことかもしれません。

ただ、後で見ることは無いのにビデオカメラを差し向け、何故か家ではYoutubeにアップされた他人のビデオを見ていたりします。

新幹線や飛行機は驚くべきスピードで遠くに連れて行ってくれますが、それでもなおその間にじっと座っている人は少なく、携帯やスマートフォンを触っています。

自分も目の前に人がいて喋っている一方でネットの向こう側の情報が気になってチェックしたりしますし、それなのに1人になると人恋しくてLINEなどしてみたりするわけです。

常に時間の隙間を埋めないといけないような病気にかかっているのかもしれません。


1つのことに集中できる時間を持つということは贅沢になってきていますし、常に短時間で並列の処理を求められている現状では相手もそれを求めてきたりします。

自分が豊かになる一方で求められる事、やらないといけない事も増えてそれによって窮屈さを感じてしまうのではないでしょうか。



テクノロジーの取捨選択


以前に読んだ「ワーク・シフト ― 孤独と貧困から自由になる働き方の未来図〈2025〉 」という本の中で近未来(2025年)の人々の働き方というのを描いてたりしてますが、ここでも人々がより多忙でより多くの情報にさらわれる未来を予測しています。

大体10年後の世界なわけですが、10年前と今とを比べると劇的に変化している状況と技術革新が加速度的に起こっている状況を見れば当たらず遠からずというような印象を受けたりします。


これと近い将来で2020年には東京オリンピックがあるわけですけど、今の親たちが子供たちに間近でトップアスリートの姿を見せてあげたいと思っていても、その子供たちが見るのは例え現場にいたとしてもカメラやスマートフォンを通してほとんどの光景を見ているのではないだろうかと思ったりします。

まぁ、当の親も同じことをしてそうな気がするんですが、思いは何だか裏腹だなぁとも感じたりするのですが。


きっとこれからも世の中に出てくる新しいテクノロジーによって本来やりたかったことでも好奇心をくすぐるものが多すぎて捨てざるを得ないことって多々出てくると思います。

幾ら並列処理に慣れているとはいえ限度がありますし、常に頭を動かすそんな状況だと平穏もあったものではないでしょう。

ある意味、可能性が広がっているわけですし進む道筋の選択肢も自由度を増すわけですが、よっぽど変化に慣れていたり乗りこなせる人ではない限りその全てを渡り歩いていくのは難しいのではないでしょうか。


常に大量の情報にさらされ、世の中に無作為に放り込まれる数々のテクノロジーと向き合っていくというのは、これからの現代人の生き方と宿命にはなるんでしょうけど、周りがそうだからといってからといって必ずしもあわせる必要もありません。

自分のペースに合わせて世の中にあるサービスや製品を選んでいけばいいと思いますし、選択肢の1つには「どれも選ばない」という選択もあるはずです。

結局のところ、豊かさを得るためのテクノロジーが自分の首を絞めることもありえているわけで、自分に使いこなせるのかどうかも含め、それを道具としてどう使っていくのかということを考えないと、得られるのは豊かさではなく蝕まれる結果になるのではないかと思うのです。




CakePHPでHtmlHelperを使って開いているページのURLを取得する

$
0
0

純粋なPHPで書く場合の$_SERVER['REQUEST_URI']と同じように、CakePHPで自分自身のページのURLを取得したいということがあります。

まぁ、REQUEST_URIでいいじゃん、って言う意見もあると思いますが、CakePHPを使っているならそっちのお作法に倣いたいとか、REQUEST_URIを使う場合、ドメインまでは返って来ないので、


$url = http://' . htmlspecialchars($_SERVER["HTTP_HOST"] . $_SERVER['REQUEST_URI']);

みたいなことをするのが面倒だという場合に便利かもしれません。



CakePHPで自分自身のURLを取得する


結論から書けばテンプレートの中でHtmlHelperを使って


<?php echo $this->Html->url('', true); ?>

のような書き方をすれば自分自身のURLが取得可能です。

元々、HtmlHelper::url()は、引数からURLを生成してくれるモジュールなんですが、第1引数を空で渡せば今開いているページのURLを返してくれます。

第2引数はドメイン名を付けて返すかどうかのオプションです。


// $this->Html->url('', true)の場合
http://www.example.com/search/category/123

// $this->Html->url()の場合
/search/category/123

のような違いです。


第1引数に配列でURLの構成情報を渡すことでそのURLを生成してくれます。


echo $this->Html->url(array(
    "controller" => "foo",
    "action" => "bar",
    "fuga" => "hoge"
));

まぁ、リンクのURLを作りたいという場合は、HtmlHelper::link()を使った方が早いと思いますが。

詳細は、マニュアル も参照してみてください。


少し本件からは話がずれますが、Controller内でURLを取得したいまたはURLを生成したいという場合は、下記のように書くことで取得ができます。


$url = Router::url(array('controller' => 'foo', 'action' => 'bar', 'hoge', 'fuga'), true);

使い方はHtmlHelperと同じです。

ロジックに応じて使い分けができるので便利ですね。





PR: DYNAMITE 6 CAMPAIGN

Apache Solrにおける特殊文字の意味と扱い方

$
0
0

Apache Solrにはクエリ内に使う際に注意が必要な特殊文字が幾つかあります。


Apache Lucene - Query Parser Syntax


上記マニュアルによれば、下記の文字列が特殊文字に該当するようです。


+ - && || ! ( ) { } [ ] ^ " ~ * ? : \

管理ツール上のQuery機能を使って特殊文字をそのまま入れて検索してみてもSolrがエラーを返してきます。


org.apache.solr.search.SyntaxError: Cannot parse '&&': Encountered " <AND> "&& "" at line 1, column 0.

ということで、この辺の特殊文字の意味とこれらをクエリに使いたい場合の回避方法のまとめです。



Apache Solrの特殊文字


・ 丸括弧()


Solrで丸括弧(小括弧)の文字はグルーピングを意味します。
例えば、「Apache Solrのデモ環境を作ってみる 」で使った郵便番号データの場合、下記のような検索が行えます。


(prefecture:東京) AND 杉並

東京都の中の杉並という地名を探すという検索です。

ちなみに、普通に杉並だけで探すと北海道に杉並町というのがあるらしくそのデータもヒットします。

都道府県に東京を指定するという条件のグルーピングを()で指定しているわけです。


・ 角括弧[]


Solrで角括弧(大括弧)の文字はレンジを意味します。
先ほどの郵便番号データの例で言えば下記のように書くことで郵便番号が指定の範囲にあるデータを検索できます。


zip:[0100000 TO 0200000]

郵便番号が「0100000」から「0200000」の範囲にあるデータを検索するというものです。
細かいところですが開始(0100000)と終了(0200000)の値も範囲に含まれます(以上、以下)。
後述しますが、アスタリスクを使って「zip:01*」というような検索でも似たようなことはできたりするのですが、きちんと範囲を指定したい場合は[]を使った範囲指定のほうがクエリもわかりやすいでしょう。


・ 波括弧{}


Solrで波括弧(中括弧)の文字は角括弧と同じレンジを意味しますが、若干角括弧と仕様が異なります。
角括弧は指定した開始と終了の値も含みますが、波括弧はその値を含みません(より大きい、未満)


zip:{0100000 TO 0200000}

この場合「0100000」と「0200000」の郵便番号を持つデータはヒットしません。


・ アンパサンド(&&)


これはプログラムでよくある構文と同じでAND条件を指定するものです。
先ほどの例の


(prefecture:東京) AND 杉並
(prefecture:東京) && 杉並

上記は同じ意味となります。


・ バーティカルバー(||)


こちらもプログラムの構文と同じでOR条件を指定するものです。


(prefecture:東京) OR 杉並
(prefecture:東京) || 杉並

上記は同じ意味となります。


・ 感嘆符(!)


感嘆符はNOTを意味し、その条件を含まないという動作をします。


(prefecture:東京) !杉並

上記は、東京都で「杉並」という言葉を含まない地名を検索します。


もちろんNOTの言葉のままでも使えます。


(prefecture:東京) NOT 杉並

・ プラス(+)


プラスはその言葉が必ず含まれるという条件になります。


(prefecture:東京) +杉並

上記の場合、必ず「杉並」ということが含まれる条件で検索します。


・ マイナス(-)


マイナスはプラスの逆でその言葉を含まないという条件になります。


(prefecture:東京) -杉並

どうもこの結果はNOTと同じみたいです。


In Solr, what is the difference between the NOT and - (minus) operators? @ stackoverflow


・ ワイルドカード(* ?)


Apache Solrの検索であいまい検索をしたい場合、ワイルドカードを指定することで柔軟な検索ができます。


town:*新宿*

アスタリスクを指定した場合、その文字が含まれる(前方一致や後方一致、中間一致)データを検索します。
例の場合、西新宿や新宿町などがヒットします。

アスタリスクはその間に0個以上の文字があるものにヒットしますが、特定の1文字に限定したければ疑問符を指定します。


town:?新宿

・ あいまい検索(~)


ワイルドカードの指定でもあいまい検索ができるのですが、Solrお任せのあいまい検索も可能です。
単語の最後にチルダを指定すると、その単語に近いキーワードを持つデータを検索してくれます。


town:杉並~

例えば、上記の検索だと「日並」や「杉津」といった地名もヒットします。
これが近いか、といわれると微妙なのですがその言葉に近い(1文字違いなど)言葉を検索してくれるようです。

どこまで使えるか不明なのですが、チルダの値の間に数字を指定してあいまいさの調整ができるようです。


town:杉並~0.8

数字は0から1の間で指定するようでデフォルトは0.5だそうです。


・ キャレット(^)


検索キーワードのあとにキャレットをつけるとその文字を重要性を強調させることができます。
こちらの例はマニュアルから参照しますが、


jakarta^4 apache

というクエリを投げた場合、Apacheよりjakartaという文字が含まれるデータのほうが重視されます。


・ ダブルコーテーション(")


ダブルコーテーションは文章を指定できます。
特にスペースで区切られた文字列を検索したい場合などに有効です。


"jakarta apache" OR "Apache Lucene"

といった感じで、単語単語ではなくその言葉で検索したい場合に指定します。


・ その他


「:」はそもそも条件の区切りに指定する特殊文字になります。
また、「\」は後述もしますが、これらの特殊文字をエスケープするために指定する文字です。



Apache Solrの特殊文字をエスケープする


マニュアルにも記載があるのですが、前述した特殊文字をクエリ内で使いたい場合はエスケープする必要があります。
エスケープは\マークをその特殊文字の前に指定します。


\(1\+1\)\:2

「(1+1):2」という文字を検索したい場合は、上記のようにエスケープしてクエリに投げます。

最後にPHPでこれらSolrの特殊文字をエスケープする処理が下記サイトにまとめられていました。


Escaping Characters in a Solr Query / Solr URL @ Mats Lindh


ただ、これだとstr_replace()使うんじゃなくてaddcslashes()を使ってもいいんじゃないかと思ったりして、そのパターンの例も載せておきます。


static public function escapeSolrValue($string)
{
    $string = addcslashes($string, "\\+-&|!(){}[]^~*?:\";");
    return $string;
}


検索機能を提供する場合、これら特殊文字をユーザーに指定させるというような使い方はさせないと思いますので、しっかりとこの辺の文字を処理しておかないとクエリがエラーとなって問題が起きることになりそうです。





CakePHPのデータをサニタイズする

$
0
0

サニタイズ言うなーという議論はさておいて、CakePHPにはSanitizeというクラスが存在します。

その名の通り、CakePHPで扱うデータから不正な文字を消してくれたりエスケープしてくれたりSQLセーフなデータとして返してくれたりします。

CakePHPでユーザーから送られてくるリクエストデータなどは取りあえずこれ通しとけってものなので、ぜひ覚えて使いたいクラスとなっています。



Sanitizeクラスの概要と使いかた


使い方も非常にシンプルで以下のようにしてSanitizeクラスの呼び込みとcleanメソッドを使えばデータを綺麗にしてくれます。


<?php
App::uses('Sanitize', 'Utility');

class FooController extends AppController {
    public function index($param) {
        $param = Sanitize::clean($param);
    }
}

サニタイズしたいデータが入った変数をcleanメソッドの引数として渡すだけでその変数を浄化してくれます。

配列にも対応していますので、その場合は再帰的に処理をしてくれます。

cleanメソッドはデータを浄化する一連の処理をしてくれるもので、個別の処理を呼び出すことも可能です。


Sanitizeクラスは、CakePHPのユーティリティとして、以下のパスに定義されています。


/path/to/cakephp/lib/Cake/Utility/Sanitize.php

それほど難しい処理をしていないので、中身を見ればどのような処理をしてくれるか理解できるかと思いますが、clean以外にも下記のメソッドが定義されています。


メソッド 用途
paranoid 半角英数字以外の文字を除去する(第2引数であえて許可したい文字を指定することができる)
escape SQLセーフなデータとして返す(エスケープ処理をする)
html データに含まれるHTMLタグを変換する(htmlentitiesとほぼ同義)。第2引数にremoveオプションを付けるとHTMLタグそのものを削除する
stripWhitespace 不要な改行コードやスペースを削除する
stripImages データに含まれるIMGタグを削除する
stripScripts データに含まれるSCRIPTタグを削除する
stripAll stripWhitespace、stripImages、stripScripts全ての処理を通す
stripTags データから特定のHTMLタグを除去する
clean 一連のサニタイズ処理を行う(オプション指定に付いては後述)

それぞれ、Sanitize::html($param)のように単体で呼び出すこともできます。

cleanメソッドは第2引数のオプションによって細かくサニタイズの処理を指定することができます。
オプションの配列に指定できるキーとそのデフォルト値は、プログラム内で以下のように定義されています。


$options = array_merge(array(
    'connection' => 'default',
    'odd_spaces' => true,
    'remove_html' => false,
    'encode' => true,
    'dollar' => true,
    'carriage' => true,
    'unicode' => true,
    'escape' => true,
    'backslash' => true
), $options);


それぞれのキーの意味は下記の通りです。


オプション 用途
connection DB接続名(app/Config/database.phpで指定している変数名)
odd_spaces 「0xCA」を含むおかしなスペースを標準的な半角スペースに置換する
remove_html HTMLタグを除去するかどうか(encodeオプションをTRUEにしないと動作しない)
encode HTMLタグを変換するかどうか
dollar ドルマークをエスケープするかどうか
carriage キャリッジリターンを削除するかどうか
unicode HTMLエンティティ化してしまったUnicodeの数値文字参照を正しいものに置き換えるかどうか
escape 内部のescapeメソッドを通すかどうか
backslash ユーザが入力したバックスラッシュを信頼できるバックスラッシュに置き換えるかどうか

デフォルトのオプションと照らし合わせて見ればわかりますが、データからHTMLタグの除去(remove_html)以外は全て処理をしてくれます。

一旦、Sanitize::clean()を通してしまい、必要の応じてアプリケーションごとの独自処理としてその他のデータの加工等をしていくのがよさそうです。

仕様の詳細は、マニュアル の方も確認してみてください。


ただ、サニタイズできたからデータが安全になったというわけではなく、やはりロジックの作りによりますので注意は当然必要です。

例えば、clean()によってSQLセーフなデータになったからといって下記のように直接SQLにユーザーから送られてくるパラメータを閉じ込めていいわけではありません。


$id = Sanitize::clean($id);
$data = $this->Foo->query("select name from foo where id = $id");

escape()によって余計な\マークをエスケープ処理してはくれますが、当然それだけでは上記のSQLインジェクションの問題を解決するわけではありません。

バインド変数を使うなど、適切な処理が必要です。


CakePHP内のデータをクリーンな状態にしたいという場合は、不正なデータの除去やHTMLエンティティの変換を自動でやってくれたりもするので、便利に使えるのではないでしょうか。





不透明な時代を見抜く「統計思考力」

$
0
0

不透明な時代を見抜く「統計思考力」/ディスカヴァー・トゥエンティワン
¥1,680
Amazon.co.jp

自分、理系なわけですが高校のときに確率・統計という授業がありまして、これがまた苦手だったんですよ。

ただ、社会人になってから一番ちゃんと勉強しておけばよかったなと後悔したのがこの統計だったりするんですよね。


社会人になって色んな提案資料を書くときにその元データを整理して並べたりするわけですが、よく質問されたのが「これって実績ベースの数値?それとも君の感覚値?」とか言われたりして、やっぱり感覚値だと信憑性が無いわけですから提案が通らないわけです。

エンジニアとしてインフラの増強を提案しようとしても、システムの利用者が増えてきているとか、機能数の増加とかそういうことも実績データを分析した結果をきちんと示さないといけないわけで。

そういったときに数値のまとめ方とか効果的に相手にインプットできる図の作り方とかだけでなく、そもそもの原因の分析の仕方というところに着目できるように統計思考力って改めて大事だったんだなとこの本を読んで改めて思ったりしました。


ただ、やっぱり本格的な統計の勉強をしようとすると色んな数式や手法が出てきて敬遠しがちなんですが、この本はあまりそういったところに突っ込むというよりは、手法の概要は解説しつつも統計を使って世の中の問題を取り上げていて、副題に「小泉改革派格差を拡大したのか?」っていうことであったり、「若者の読書離れはほんとうか?」といったことが分析されていて、新聞やニュースで取り上げられる話題を鵜呑みにするのではなく、自分なりの分析や検証の大切さが説かれていたりもします。

実績ベースの数値を集めることも大事なのですが、それは始めの第一歩なわけで単純にそれを図示して納得しているだけでは場合によっては数値に自分自身がだまされることになったりもします。

その検証をするための手法を知ることで数字の裏にある事実を知ることができますし、逆に世の中にある数字や自分に持ちかけられた提案に対してだまされずに済むんだなと感じたりもします。


そして、統計結果というのは過去のデータを元に並べたものですが、その結果の規則性などから未来を予測するのにも役立ったりもするわけです。

不透明な時代を見抜くという本のタイトルは、統計というものが単に過去の事実を明らかにするだけでなく、その結果からこれからの未来予測に応用ができるんだなということを気づかされたりした本でもあります。



目次


第1章 基礎編 データを見る
 1. 生データを入手する
 2. データを図にする
 3. 専門外のデータはこう読もう

第2章 中級編 データを読む
 1. 基本をおさえる - 平均と分散
 2. 足したらでてくる正規分布
 3. 一を聞いて十を知る - 大数の法則
 4. 分けて考えるべき分布
 5. 因果関係と間違えるな - 相関

第3章 上級編 データを利用する
 1. 未来を予測する
 2. 思考を練磨する - オープンコラボレーション
 3. 自力で考えることの最大の敵




Apache Tikaを使ってドキュメントの中身を取り出すPHPプログラム

$
0
0

PHPというよりはSolrネタではあるのですが、Apache SolrにはApache Tikaというドキュメントのメタデータを抽出するソフトウェアが同梱されています。

Apache Tikaを使えば、WordやPowerPoint、PDFなど様々なドキュメントの本文を取り出し、それをApache Solrへ取り込んで検索対象にするといったことが可能になります。

利用イメージは下記のような感じで、今回のプログラムは赤枠の部分をするためのものです。


Apache Tikaを使ってSolrへインポート


今回利用しているApache Solrのバージョンは4.6.1、PHPは5.3系を使っています。



Apache Tikaからドキュメントのメタデータを抽出するPHPプログラム


Apache Solrの中にあるApache TikaへのアクセスはRESTなAPIが提供されているため、ここに示すPHPでなくても簡単なプログラムで利用可能です。

CURL関数を使って書いていますので、それこそ同様の処理をシェルスクリプトからとかでも作れたりします。


<?php

// Apache Solrが使うポート番号
$solrPort = "8983";

// Solrのコア名
$solrCore = "collection1";

// 実行ホストのドメイン
$domain = "localhost";

// Apache Solr(Tika)のURL
$solrUrl = "http://" . $domain . ":" . $solrPort . "/solr/" . $solrCore . "/update/extract?extractOnly=true";

if (empty($argv[1]) || !file_exists($argv[1])) {
    echo "ディレクトリが存在しません" . PHP_EOL;
    exit;
} else {
    $dir = $argv[1];
}

// cURL初期化、ヘッダ設定
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $solrUrl);
curl_setopt($curl, CURLOPT_BINARYTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);

if (is_dir($dir) && $dh = opendir($dir)) {
    while (($file = readdir($dh)) !== FALSE) {
        if ($file === "." || $file === "..") {
            continue;
        }
        // 読み込み対象ファイル
        $targetFile = $dir . $file;

        $data = array('name' => $targetFile, 'file' => '@' . $targetFile);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

        $result = curl_exec($curl);
        if (curl_errno($curl)) {
            $info = curl_getinfo($curl);
            if (empty($info['code'])) {
                $code = "ホストに通信できません";
            } else {
                $code = "HTTP Code:" . $info['code'];
            }
            $msg = "通信エラー: " . $code . " url:" . $info['url'];
            echo $msg . PHP_EOL;
            exit;
        }

        // 解析結果のXMLをパース
        $xml = simplexml_load_string($result);

        $body = strip_tags($xml->str);
        echo $targetFile . PHP_EOL;
        var_dump($body);
    }
    closedir($dh);
}


コマンドラインで動かす想定にしているため、第一引数にドキュメントが格納されているディレクトリを指定すればその中にあるファイルを拾ってApache Tikaへ投げ、解析結果を受け取るというような流れで動きます。

Solrのポート番号やコア名などは必要に応じて変更してください。


$ php import.php /path/to/docdata/

結果はXML形式で受け取っていますが(パラメータ無しの場合のデフォルト)Apache Solrの検索と同様にパラメータをつける事でJSON形式やCSVなどで受け取ることができたりします。


// Apache Solr(Tika)のURL
$solrUrl = "http://" . $domain . ":" . $solrPort . "/solr/" . $solrCore . "/update/extract?extractOnly=true&wt=json";

上記はJSON形式で結果を受け取りたい場合で、wtパラメータに所定の形式をセットしてAPIに問合せます。

受け取ったメタデータをその後、どう加工したいかで必要に応じて変えてみるのがよいのではないでしょうか。


ということで、Apache TikaへのAPIに対して、送信に必要な設定の上で抽出したいドキュメントデータをPOSTしてあげるだけで結果が受け取れます。

ドキュメントデータにパスワードがかけられているものもあったりしますので、そういう場合はHTTPステータスコードが500で返ってきたりしますので必要に応じてエラーハンドリングしておくのがよいでしょう。


PDFやWordなどオフィス系のファイルの中身を取り出してDBに格納したいとか、表示したいという場合に簡単に抽出ができるのでApache Tikaの利用を検討してみてもよいかもしれません。





Solrの形態素解析で使えるフィルタあれこれ

$
0
0

Apache Solrのschema.xmlを読み解く 」にて少し書いたことですが、Apache Solrの設定ファイル(schema.xml)には様々なフィルタが設定可能で、それによって検索結果が大きく異なってきます。

フィルタの数は多数あって、利用用途やトークナイザーによって変わってきますのでここで書いているのは一部なんですが、こんな検索にヒットさせたいといった場合にフィルタの使い方次第で検索精度を高められたりするので、どういったフィルタがあるのか知っておけば用途に応じて使い分けられて便利です。


ここではApache Solrはバージョン4.6.1を使ってフィルタの検証をしています。



filterとcharFilter要素の違い


フィルタ(filter)要素はschema.xmlファイルのfieldType要素内に定義していきますが、charFilterという要素もあったりして少し混同したりします。

charFilterは、文章を解析する前処理としてデータの加工をするためのフィルタを指定する要素で、文字を置換するためのルールを定義しそれに従って変換するsolr.MappingCharFilterFactory、正規表現でパターンを指定しそれに従って変換するsolr.PatternReplaceCharFilterFactory、HTMLタグを取り除き中の文章だけを抜き取るsolr.HTMLStripCharFilterFactoryなどが標準であります。


HTMLStripCharFilterFactoryはSolrへのデータ投入前にデータ加工しておけばよいのではと思ったり、PatternReplaceCharFilterFactoryは正規表現を使うということでパフォーマンスに影響が出るって記事も見たりするので実質手軽に使えそうなのがMappingCharFilterFactoryぐらいなのかなと思ったりしますが。

MappingCharFilterFactoryの使い方は、


<charFilter class="solr.MappingCharFilterFactory" mapping="mapping.txt"/>

というようにマッピング用の定義ファイル(mapping.txt)を指定します。

mapping.txtは、下記のように変換ルールを定義します。


"0" => "0"
"1" => "1"
"2" => "2"
"3" => "3"
"4" => "4"
"5" => "5"
"6" => "6"
"7" => "7"
"8" => "8"
"9" => "9"

上記の例は、全角の数字を半角に変換するルールを書いています。

これにより、全角数字でも半角数字でも同じ検索結果を返せるようになったりします。

もう1つの効用として、トークナイザに形態素解析(solr.JapaneseTokenizerFactory)を使っている場合、下図のように全角数字はトークンを1つ1つに分解してしまうようで、事前に半角数字に変換することでトークナイザーに対して正しいトークンとして認識させることができたりします。


SolrAnylyze-1


charFilterはこのように文章をトークンに分割する際のルールを定義するもののため、tokenizer要素より前に指定する必要があります。
fiter要素とあわせるとその指定できる順序は、charFilter → tokenizer → filterという順番になります。


<fieldType name="text_ja" class="solr.TextField">
<analyzer type="index">
<charFilter class="solr.MappingCharFilterFactory" mapping="mapping.txt"/>
<tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms_index.txt" ignoreCase="true" expand="true"/>
</analyzer>
</fieldType>


フィルタの種類とその用途


本題のSolrのフィルタの種類ですが、下記のようなものがあります(一部です)。

先に書いたように、フィルタはトークナイザの種類によって使えるものと使えないものがあったりして、ここで列挙しているのは形態素解析(solr.JapaneseTokenizerFactory)を使っている場合に使えるフィルタですので注意してください。

あまり情報が無かったりして検証結果で書いている部分もあるので適当なところがあるかもしれません。


・ solr.SynonymFilterFactory


類語を登録できるフィルタです。


<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>

元々サンプルファイルがあるのでその中を見ればわかりやすいのですが、


aaafoo => aaabar
GB,gib,gigabyte,gigabytes

というように、「aaafoo」という単語を「aaabar」に置換したり、「GB」と「gigabyte」を同じ意味になるように定義しています。


SolrAnalyze-2


上記のようにSF(SynonymFilter)でaaafooがaaabarに置き換えられていることがわかります。

同義語や略語を登録したいという場合に便利だったりします。

ただ、英語の場合は一綴りで書いた単語はトークンが1つと認識してくれるのでよいですが、日本語を扱う場合は注意が必要でトークナイザがトークンに分割する際に同義語に定義した単語がそもそもきちんと認識してくれないケースがあったりします。


情報システム部,情シス

というような定義をしていてもトークナイザが下記のようなトークンに分割してしまい、「情報システム部」の同義語を登録していても正しく認識されません(「情シス」という単語も同様)。


SolrAnalyze-3


こういった場合は、事前に辞書データ(lang/userdict_ja.txt)にこれらの単語を登録してSolrに認知させる必要があります。


・ solr.JapaneseBaseFormFilterFactory


動詞とかを基本形に直してくれるフィルタです。


<filter class="solr.JapaneseBaseFormFilterFactory"/>

例えば「動いた」を解析してみると


SolrAnalyze-4


のような結果が返ってきます。

まぁ、取りあえず日本語使う場合は使っておけって言うフィルタですかね。


・ solr.JapanesePartOfSpeechStopFilterFactory


余計な品詞を検索対象にしないためのフィルタです。


<filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt" enablePositionIncrements="true"/>

設定ファイルを見てみると助詞や記号などを除外するようにしているみたいです。


・ solr.CJKWidthFilterFactory


全角の英字を半角にしたり、半角カタカナを全角にするフィルタです。

全角の数字は対象になっていないようで、先に書いたMappingCharFilterFactoryを事前に通すといった処理が必要です。


<filter class="solr.CJKWidthFilterFactory"/>

Solrの管理機能で解析してみると半角カナの場合は確かに全角に変換されてヒットしている表示になるのですが、全角大文字の英字になると半角に変換されているようですがヒットしているようには表示されません(全角でも小文字の英字だとヒットしているように表示される)。

ただ、その他のフィルタの文字を見るときちんと半角に変換された英字が対象になっているので、機能としてはきちんと働いており単に表示の不備なのかもしれません。


・ solr.StopFilterFactory


名前の通り、インデックスさせたくない単語を登録できるフィルタです。

「て」「に」「を」「は」といった助詞や、「によって」「において」「に関して」など要は検索する上では邪魔になる単語を排除してくれます。


<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt" />


オプションのignoreCaseは英字の大文字小文字を区別するかどうかというものになります。

このフィルタは、もちろん検索されたくない、インデックスさせたくないといったNGワードを登録することもできます。

例えば、「itboy」をNGワードとして登録しておき、「itboyさんは素敵です」の検索結果は下記のようになります。


SolrAnalyze-5


見事に消されているのがわかります。


・ solr.JapaneseKatakanaStemFilterFactory


カタカナの長音(ー)を消してくれるフィルタです。

「コンピューター」と「コンピュータ」など人によって使い方が違ってくる言葉を統一してくれます。


<filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>

オプションのminimumLengthは対象とする最大文字数を指定するもので、上記の場合4文字以上が対象となるため、「ソニー」が「ソニ」になることはありません。


SolrAnalyze-6


・ solr.JapaneseReadingFormFilterFactory


日本語の読みを検索対象にするためのフィルタです。

例えば、「日本」に対して「にっぽん」でも「ニッポン」でも読み方に対してヒットさせることができたりします。

(「日本」は「ニッポン」で登録されているため、キーワードが「ニホン」ではヒットしません。これをヒットさせたい場合、SynonymFilterFactoryにて類語登録をしておけばヒットさせることができます)


<filter class="solr.JapaneseReadingFormFilterFactory" useRomaji="false"/>

オプションのuseRomajiはローマ字も読みの対象にするか指定するもので先の例で言えば、「nippon」でもヒットさせることができるようになります。


・ solr.ICUTransformFilterFactory


カタカナを平仮名に変換できたりするフィルタですが、先ほどのJapaneseReadingFormFilterFactoryでも同じようなことができるのであまり詳しく調べてません。


<filter class="solr.ICUTransformFilterFactory" id="Katakana-Hiragana"/>

ちなみにこのフィルタはそのままだと使えないので、下記のようにライブラリをSolrへ事前にロードさせる必要があります。


まず、使いたいSolrコアのディレクトリ以下にlibディレクトリを作っておきます。

次に、そのlibディレクトリに下記のjarファイルをコピーします。


$ cp /path/to/solr/contrib/analysis-extras/lib/icu4j-49.1.jar /path/to/solr/example/solr/coreName/lib/
$ cp /path/to/solr/contrib/analysis-extras/lucene-libs/lucene-analyzers-icu-4.6.1.jar /path/to/solr/example/solr/coreName/lib/

最後にSolrを再起動します。


・ solr.LowerCaseFilterFactory


こちらは、英字を小文字にすることで大文字・小文字を使い分けた表記ゆれを統一することができるフィルタです。


<filter class="solr.LowerCaseFilterFactory"/>

「solr」でも「SOLR」でも「Solr」でもヒットさせることができるようになります。



フィルタは結構数が多いですし、Javaが書けたら自作もできるようですので色んな有識者が作成したものが公開されていたりします。

検索の用途や精度に応じて色々試してみたら実現したい検索システムを手早く作れるかもしれません。





エンジニアをイラっとさせない仕事術

$
0
0

エンジニアが色んな人と仕事をしていく中で、エンジニア泣かせのことを言われたり、「わかってくれよ」と思う場面に出くわすことはよくあります。

こういうのはその立場ごとに考え方が違うので、当然エンジニアと仕事をしていたらこういうところにイラっとくると思うことはあるんでしょうけど、ここではエンジニア視点で非エンジニアと仕事をするときにこういうところに気を回して欲しいと思うことをまとめてみたいと思います。



技術的なことを任せっきりにしない


技術的なプロとしてエンジニアを見てもらうことは結構ですが、その全てを押し付けられるとモチベーションが下がることはあったりします。

技術的な詳細は、非エンジニアの人にとっては未知なところもあるんでしょうけど、あまりにそれを任せっきりにされ「あとはいいようにしといて。細かいところは空気読んで作って」という雰囲気が出ていたりして、エスパーでもない我々にとっては頭が痛くなることばかりです。


例えば、テストであっても単体・結合テストレベルであればエンジニアしか対応できませんが、運用・受け入れテストにもろくに参加せず、リリース直前または直後にシステムを見て意見を言われたりすると「その機会はあったんだからもっと先に言ってよ」ということになるでしょう。

そういったフィードバックというのはおおかた当初に決めた仕様とは異なる意見であったりして、そもそもが仕様と違うこと言ってるじゃねぇかという気分にもなりますし、プロジェクト参加者の権威によって一気に覆ったりする(現場でまとめた仕様をPJリーダーが覆し、PJリーダーが言ったことを部長が覆し、それを役員が覆すとか)から収拾がつかなくなるケースもあったりします。


また、開発というのは結構孤独であったり重圧を受けることもあります。

上流工程が終わればあとは開発を待つだけとエンジニアだけが取り残されたりしますし(そしてお上は終わった気分になってたり)、納期のプレッシャーだけでなく技術的に実装可能かという課題にも苛まれます。

よくありがちなのが、「このサイトと同じような機能を作って」というもので、よくあるものだったらいいのですが、技術的にどう実装しているのかよくわからない場合であったり、何を使えば作れるのかがわかってもそのライブラリやツールを使った経験が無いことから納期内にうまくそれを取り込めるかやってみないとわからないということも多々あります。


このサイトと同じという「このサイト」がGoogleだったりして、これを作れるのはGoogleのエンジニアの能力や規模感や資金があるからできるわけであって、うちのこの小さなチーム(または個人)でそれをやるのにどんだけの工数かかると思ってるんだと、そのサラッと言われたことにイラっときたりするわけです。



プロジェクトの運営までを押し付けない


いざ開発が始まっても、それにどれだけの工数がかかり何時ぐらいに何ができるかというスケジュール(そして、それが可能かどうか)はエンジニア側の言い分によってある程度決まってきたりします。

ただ、そのスケジュールというのはあくまで仕様どおりの構築をするための線表であって、こちらとしては作る側で手一杯の状態であるのに、プロジェクト運営の課題やリリース前後の運用にまで仕事を回されることがあったりします。


例えば、構築するシステムに対する運用の組み立てができてなかったり(それによって仕様の変更に影響する恐れがあったり)、マイルストンがブレブレであったり(フェーズをわける考えが無くて全てをリリース時に盛り込もうとしたり)、現場への説得や説明にまわされたり(それによってタスクには含まれない成果物を求められたり)。


確かに技術的な要素については不明点も多いのかもしれませんが、そもそも作りたいと提案してきた側が明らかにそれをコントロールするイメージをもてておらず、想定のシステムができたら全てがうまく回ると思っていたりして、こちらとしてはそれをどう使っていくのかというその後が全く想定できていない現状を垣間見ると不安と心配が錯綜し、余計なところまで手を出さざるを得ない状況になったりします。

まぁ、こういうことはプロマネであったりプロジェクト運用担当者の能力に依存する部分なんでしょうけど、明らかにエンジニアとしての仕事ではない部分まで対応する羽目になったりするとイラっときたりするわけです。



エンジニアの美学を尊重する


こういうのは個人差があったりそもそもそういったことにこだわらない人もいるのですが、エンジニア独自の美学というのを持っている人もいたりして、それを否定することを嫌う人も多かったりします。


例えば、保守性を高めようとコードを綺麗に書いたりリファクタリングすることを理解できずに時間の無駄と捉えられたり、十分なテストをクリアしていないものをリリースさせたくないと思っているエンジニアもいる中で納期優先で「とりあえずリリースして」といってくる人もいたりします。

やはり目に見える画面だけでなくその裏のロジックもきっちりしたいと思っているエンジニアもいますし、取りあえずで作ったものが本格運用され規模が大きくなるにつれて手を加えることが難しくなり果てには自分たちを苦しめる結果になることをよく知っている人もいますし、品質が保証されてないものをリリースしバグが出ることで自分たちの能力を計られたりその改修で多くの工数を保守で費やす羽目になることを経験している人たちもいます。


自分はB型の割りに結構まめな方かなと思ったりしているんですが、結構システムの構成要素の作る順番とか決めているのを崩されたりするのが嫌だったり(もちろんそのマイルストンは事前に承諾を貰っているのに度外視されたり飛込みだったりして)、先に書いた取りあえずリリースしてと言われるのが嫌だったり(スモールスタートという意味ではなく取りあえず使いたいという意見だったり)、そもそも自分たちで物づくりすることに否定的だったりする(外注頼り)意見を言われるのが嫌だったりします。

まぁ、何れにせよエンジニア視点でよいものにしたいという考えがあるわけで、それを否定されることがあったら身構えちゃうわけです。


そういったものへの防衛本能や、コードそのものをある種芸術作品のように捉えているエンジニアもいて、自分が納得するまで妥協したくないと思っている人もいる中でそれを否定されるとイラっときたりするわけです。



まとめ


最初に書いたように逆の立場からエンジニアに言いたいことも多々あるでしょうから、双方で考え方の歩みよりは必要なのでしょう。

ただ、エンジニア独自の考えに配慮することでプロジェクト運営もスムーズに運べるようにはなるのではないかと思ったりするわけです。


エンジニアへのプレッシャーや役割への理解やそもそも言い分として矛盾している点がないかとか、よく考えるとエンジニア云々の話でもない点も多々あるわけで、やっぱり参加する人をきちんと見てその人に応じた対処や配慮をすることは大事なんじゃないかなと思うわけです。






Solrのインデックスデータを他のサイトへレプリケーションする

$
0
0

Solrのデータの取り込み・インデックス作成は実行コストがかなり大きく、実行中に検索サービスが正常に提供できないことがあったりします。

そういった事態を避けるために、Solrのデータ管理を分散し、マスターにてデータ更新を行い、その反映データをスレーブにすばやく反映するためのレプリケーション機能がSolrには標準で用意されています。


Solrが差分の更新をうまくしてくれるので、データの取り込みをするよりレプリケーション機能を使った方がかなり高速にデータの反映が行えます。



Apache Solrでレプリケーションを利用する(マスターサイト設定)


ここではまず、レプリケーション機能を使うために2つのサイトを用意します。

1つ目がマスターサイトでデータの更新管理を行うサーバーになります。

もう一方がスレーブサイトで、基本的にマスターサイトからの更新データを受け取って反映するだけのサイトにはなりますが、サービス提供はスレーブ側で行います。

データの流れは常にマスターからスレーブに行うので、スレーブサイトでのデータ更新は行わず、ある意味Read Onlyで運用するイメージとなります。


まずは、マスターサイトでSolrの設定ファイル(solrconfig.xml)にて、レプリケーション時の挙動やレプリケーション対象の各種ファイルを設定します。

該当箇所は初期値ではコメントアウトされているのでコメントアウトを解除し、適宜編集します。


<requestHandler name="/replication" class="solr.ReplicationHandler" >
  <!--
     To enable simple master/slave replication, uncomment one of the
     sections below, depending on whether this solr instance should be
     the "master" or a "slave".  If this instance is a "slave" you will
     also need to fill in the masterUrl to point to a real machine.
  -->
     <lst name="master">
       <str name="replicateAfter">commit</str>
       <str name="replicateAfter">startup</str>
       <str name="replicateAfter">optimize</str>
       <str name="confFiles">schema.xml,stopwords.txt,mapping.txt,synonyms_index.txt,synonyms_query.txt,lang/userdict_ja.txt</str>
     </lst>
</requestHandler>

replicateAfterの設定は、レプリケーションを行うタイミングを指定します。

それぞれ、コミット時、Solr起動時、最適化実行時にレプリケーションが行われます。

ただし、レプリケーションをキックするのはスレーブ側で、そのレプリケーションタイミングはチェックする間隔を指定できるので、そのタイミングが来たときにマスター側で設定したレプリケーションすべきかどうかの判断基準を元に実行されるようです(後述)。


confFilesの設定は、インデックスデータのレプリケーションと一緒に同期する設定ファイルを記述しておきます。

これにより、マスター側でスキーマ情報(schema.xml)が変わったり、辞書データ(userdict_ja.txt)を変更してもスレーブ側に同時に反映させることが可能です。



Apache Solrでレプリケーションを利用する(スレーブサイト設定)


マスター側の設定が終わったら次はスレーブ側の設定です。

スレーブ側のSolrからマスターのデータを取りに行くので実質スレーブは幾つでも作ることができます。

スレーブ側の設定ファイルもマスターと同様にsolrconfig.xmlを編集します。


<requestHandler name="/replication" class="solr.ReplicationHandler" >
  <!--
     To enable simple master/slave replication, uncomment one of the
     sections below, depending on whether this solr instance should be
     the "master" or a "slave".  If this instance is a "slave" you will
     also need to fill in the masterUrl to point to a real machine.
  -->
     <lst name="slave">
       <str name="masterUrl">http://master.example.com:8983/solr/collection</str>
       <str name="pollInterval">08:00:00</str>
     </lst>
</requestHandler>

masterUrlにて、マスター側のSolrのコレクションへのURLを指定します。

pollIntervalは同期をキックする時間間隔です。

この場合、8時間ごとにマスターサイトに変更があるかチェックし、変更がある場合は同期が開始されます。


もし、マスター側のSolrにBasic認証をかけている場合は、上記に


<str name="httpBasicAuthUser">Username</str>
<str name="httpBasicAuthPassword">Password</str>

を追加します。

セキュリティのためのApache Solrアクセス制限あれこれ 」に書いたようにマスターとスレーブ側で接続を許可するIPアドレスを追加して互いに信頼関係を設定しておいた方がよいかもしれませんが。



マスターとスレーブのデータを同期する


設定が完了したら早速レプリケーションを実行してみます。

まずは、マスター側のSolr管理サイトから設定が正しくできているか確認してみます。

管理サイトへアクセスし、左メニューからコレクションを選択してReplicatonメニューを開きます。


SolrReplication-1


レプリケーションのタイミングや同期する設定ファイルなど、設定した内容が正しく表示されていれば問題ありません。

次に、スレーブ側の管理サイトを開きます(同じReplicationメニューです)


SolrReplication-2


スレーブ側では、設定内容だけでなくレプリケーションの状況なども表示されます。

レプリケーションは、スレーブ側で設定した同期の間隔(pollInterval)でチェックされ、マスター側に変更が加わっていた場合(で、replicateAfterの要件が満たされている)に同期されます。

同期の間隔は左上に「Next Run」としてカウントダウン表示されていますので、次の同期のタイミングもわかります。

すぐに同期したい場合は、その下の「Replicate now」ボタンをクリックすると同期がすぐに開始されます。

ただ、どうも指定の時間にレプリケーションを実行するという機能は無いみたいです。

ですので、例えばサービスに影響が少ない深夜3時にレプリケーションをしたいという場合は、その時間帯に管理サイトから手動でレプリケーションを実行するか、同期間隔をうまいこと3時に実行するように調整して、その後に実行間隔を24時間ごとに変更するといった工夫が必要そうです。


同期のステータスは一番上の「Iterations」の項目に表示され、展開するとレプリケーションを何時実行し、それが成功したのか失敗したのかがわかります。

または、その下にマスターとスレーブのVersionやGen、Sizeの項目の数字が一致していればデータも揃っているという確認になります。


初回の同期は、全てのデータが転送されるためそれなりに時間がかかりますが、次回以降は差分での更新になるため、かなり高速にデータが同期されます(もちろん、マスター側でデータの全消し・全投入のようなことをした場合は、レプリケーションに時間がかかることになってしまうでしょうけど)。


設定もかなり簡単に行えますし、ユーザーへのサービス提供とデータ更新の管理作業を分散できるので、バックアップの意味だけでなく、レプリケーション機能を活用した方がサービスを提供しやすいかと思います。





PR: 野鳥撮影の旅なら【JTB】バードデスク

$
0
0
『世界最後の楽園』パプアニューギニアで野鳥ガイドと極楽鳥やカワセミ撮影三昧!
Viewing all 287 articles
Browse latest View live