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

Laravelでサブシステム用のディレクトリを分離する

$
0
0

標準のLaravelのディレクトリ構成でも特に問題なくアプリケーションの構築は行えるわけですが、このフレームワーク上で多数のシステムを動かすとなった場合、ディレクトリの構成をサブシステムごとに分離できたほうがよい場合があります。

例えば、システム数が多くなるとコントローラの数が増えてくるので(設定ファイルやViewファイルなども同様ですが)どのコントローラが何の処理をしているのかわかりづらくなってきたりで、あるシステムで構成するファイル群がまとまっていた方がターゲットが明確になったり、システムを削除する際にもそれ以下をごっそり消せばいいといったことができたりとかでメリットがあったりもします。


Laravelではディレクトリ構成をある程度自由にカスタマイズできるのでこういったことも簡単にできたりします。

ここでは、Laravel4.2を対象にしています。



アプリケーション用のディレクトリを分離する


今回は、下記のようなディレクトリ構成にしたいと思います。


laravel  + app     + Sys        + Subsys           + controllers           + config           + lang           + models           + services           + views           + routes.php  + controllers  + config  + lang  + models  + views  + routes.php

Sysディレクトリ以下が新しく作ったディレクトリ構成で、Subsysディレクトリ下はapp直下にあるcontrollersやconfigなどオリジナルのディレクトリ構成と合わせています(サービスプロバイダ用ファイルを登録するservicesディレクトリは追加してます)。

サブシステムを追加したければSubsysディレクトリをさらにコピーしてあげれば幾つでも追加していけます。

$ cd /path/to/laravel/app$ mkdir -p Sys/Subsys$ cd Sys/Subsys/$ mkdir config controllers lang models services views

ここで作ったディレクトリはLaravelの基本セットです。

後述する設定によってどのファイルがどのディレクトリにあるのかを対応付けさせればよいので、名前などは自由に決めれますし例えばライブラリファイルとしてオリジナルのlibディレクトリを追加するといったこともできます。


次に、Laravelでアプリを作る際の基本となるcontollerファイルとviewファイルを作ります。

この作業はLaravelでアプリを作る際の作業と同じです。

コントローラーファイルは、Sys/Subsys/controllersディレクトリに配置します。


<?phpclass BarController extends Controller{    public function anyIndex()    {        // viewを生成        return View::make('subsys::bar');    }}

ビューファイルは、Sys/Subsys/viewsディレクトリに配置します。


<!doctype html><html lang="ja"><head>    <meta charset="UTF-8">    <title>hello world</title></head><body>hello world</body></html>

次は、ルーティングの設定です。

URLで/barにアクセスしたら先ほどのBarControllerを呼び出すようにしてみます。

routes.phpファイルはSubsysディレクトリ直下に配置します。


<?php// barシステム用Route::any('bar', 'BarController@anyIndex');

次は、サービスプロバイダーファイルの作成です。

ここでは新しく追加したディレクトリを定義したり、プレフィックスを定義することでコントローラ内から簡易的な呼び出し方ができるようにセットしておきます。

サービスプロバイダーファイルはservicesディレクトリに配置します。


<?phpnamespace Sys\Subsys\services; use Illuminate\Support\ServiceProvider;class BarServiceProvider extends ServiceProvider{    public function register()    {    // IoCコンテナ登録のみ行うことが推奨されています    }    public function boot()    {    // Laravel用クラスローダーの登録    \ClassLoader::addDirectories( array(    // 独自で設定したフォルダを記載        __DIR__.'/../controllers',        __DIR__.'/../models',    ));    // ビュー、言語、設定の名前空間(プレフィックス)設定    // 独自で設定したフォルダを記載    \View::addNamespace( 'subsys', __DIR__.'/../views' );    \Lang::addNamespace( 'subsys', __DIR__.'/../lang' );    \Config::addNamespace( 'subsys', __DIR__.'/../config' );    // ルート定義の読み込み    require __DIR__.'/../routes.php';   }}

addDirectories()によって、独自のcontollersやmodelsディレクトリを使うように宣言したり、subsysプレフィックスを追加することで、先ほどのBarController.php内での


return View::make('subsys::bar');

という呼び出し方が可能なように定義しています。

subsysプレフィックスを付けるとviews、lang、configディレクトリからファイルを探してくれます。

設定ファイルも


$const = Config::get('subsys::foo.bar');

のような呼び出し方ができたりします。

次にこのサービスプロバイダをLaravel本体に認識させます。

これは、laravel/app/config/app.phpの中にprovidersという設定項目があるのでその中に追加します。


    'providers' => array(        'Illuminate\Foundation\Providers\ArtisanServiceProvider',        'Illuminate\Auth\AuthServiceProvider',        'Illuminate\Cache\CacheServiceProvider',        'Illuminate\Session\CommandsServiceProvider',        'Illuminate\Foundation\Providers\ConsoleSupportServiceProvider',        'Illuminate\Routing\ControllerServiceProvider',        'Illuminate\Cookie\CookieServiceProvider',        'Illuminate\Database\DatabaseServiceProvider',        'Illuminate\Encryption\EncryptionServiceProvider',        'Illuminate\Filesystem\FilesystemServiceProvider',        'Illuminate\Hashing\HashServiceProvider',        'Illuminate\Html\HtmlServiceProvider',        'Illuminate\Log\LogServiceProvider',        'Illuminate\Mail\MailServiceProvider',        'Illuminate\Database\MigrationServiceProvider',        'Illuminate\Pagination\PaginationServiceProvider',        'Illuminate\Queue\QueueServiceProvider',        'Illuminate\Redis\RedisServiceProvider',        'Illuminate\Remote\RemoteServiceProvider',        'Illuminate\Auth\Reminders\ReminderServiceProvider',        'Illuminate\Database\SeedServiceProvider',        'Illuminate\Session\SessionServiceProvider',        'Illuminate\Translation\TranslationServiceProvider',        'Illuminate\Validation\ValidationServiceProvider',        'Illuminate\View\ViewServiceProvider',        'Illuminate\Workbench\WorkbenchServiceProvider',        'Sys\Subsys\services\BarServiceProvider',    ),

最後に、追加したディレクトリをcomposerに認識させ、オートロードできるようにします。

laravel/composer.jsonに下記のpsr-0の項目を追加します(classmapはLaravelインストール時のデフォルトの設定です)。


    "autoload": {        "classmap": [            "app/commands",            "app/controllers",            "app/models",            "app/database/migrations",            "app/database/seeds",            "app/tests/TestCase.php"        ],        "psr-0": {            "Sys": "app/"        }    },

修正が終わったら


$ composer dump-autoload

を実行します。


初期設定は多少面倒ではありますが、これでサブディレクトリ内で幾つものLaravelのアプリを動かすことができます。

色々な設定をしていますが、app.php内のサービスプロバイダの中からサブシステム用のサービスプロバイダ(BarServiceProvider.php)が呼び出され(呼び出す際にはcomposerによりオートロード)、サービスプロバイダからルーティングファイルやコントローラやビューファイルの場所をLaravelに認識させているといった流れです。

ここで書いたのは例ですのでうまくサービスプロバイダの中身を書き換えればディレクトリ構成はもっと自由に定義できたりします。


新しいサブシステムを追加したい場合は、


・ Sysディレクトリ以下にサブシステム用ディレクトリを新たに作る

・ サービスプロバイダファイルを作成する

・ laravel/app/config/app.phpに追加したサービスプロバイダを追加する


という対応だけでどんどん増やしていくことができます。






開発スタイルと組織の向き不向きに関する考察

$
0
0

自分のところではプロジェクト管理としてRedmineを使って、各自担当するタスクや不具合、課題、要望などを管理するようにしているのですが、こうした開発スタイルをとっていく中で当然よい側面と悪い側面が出てきたりします。

簡単に言ってしまえば、タスクが明確化される一方で、与えられたタスクだけをやればよいという風に受け取られてしまうということがあるといった点です。


当然、それぞれのエンジニアの働き方にも大きく依存する問題なのでこうしたツールや開発スタイルというのは良いようにも悪いようにも受け取られたりします。



機械的な形式と機械的な仕事


自分のところではチケット駆動開発と呼ばれるほど厳密なルールを作ってやっているわけではありませんが、タスクや課題、バグからユーザーからの要望などなど雑多なものを拾い上げて適当な開発・改修の粒度に分けてチケットを管理していたりします。

別にこれはRedmineというBTSツールに頼らずとも、規模が小さなチームやプロジェクトであればExcelなんかで管理するというものでも全然かまわないんでしょうけど、要するに何らかのやらないといけない仕事がデータ化され保存されているというわけです。


これにより仕事の見える化が進むわけですけど、それにより最初に書いたような弊害が生まれたりもします。

担当者が決められ割り当てられるというのは、自分がやらないといけないタスクというものがはっきりしますので、いってしまえばそれをこなしていけばよいという機械的な仕事の形式にもなります

これが、そのタスクだけを自分が担当すればよいという思い込みにもつながったりすると最悪で、そっちは担当ではないから関係ないという思い込みとか、関連するタスクの状況を確認していかなかったために後々トラブルが起きたりとかします。


ここで積極的なエンジニアは他のチケットの状況を確認してコメントしたり、担当者が付いていないチケットでも進んで担当者になっていくというようなことが期待できるのですが、まぁこういう自主的に動いてくれるエンジニアは稀ではないでしょうか(仕事が増えるわけですから心理的には当たり前かもしれませんけど)。

エンジニアの中には自分の力量とタスクの難易度を鑑みて打算的に動く人もいますから、このチケットの難易度は高いから止めておこうとか、このモジュールはAさんが過去に対応していたから自分が受け取るのはやめておこう見たいな事にもなって特定のチケットが放置されたり、システムの分野やカテゴリによっては担当者が偏って負担が大きくなったりもします。


これは、その一部のエンジニアしか積極的にチケット管理ツールを使わないということにもなってきて、本来タスクの見える化や権限のフラット化やチームの活性化というものに結びつかなかったりもします。

個人的には、チケットの総量や担当者の動きというものが全て把握できたりもするので、誰が仕事をしていて誰がしていないか(または積極的ではないのか)ということがわかったりするので、結構残酷なツールだなと思ったりもします。



組織における向き不向き


チーム内でやらないといけないタスクというのは、誰がと言うわけではなく各々が見つけて提言していくのが理想的です。

バグにしろ、ユーザーから言われた改修の要望にしろ、それが特定のマネージャーを通らないとあがってこないという状況ではそこがボトルネックになりかねません。


先ほど書いたように積極的なエンジニアがどれだけチーム内にいるかという話にもなりますが、Wikipediaの記事を書く人と読む人のどちらが多いのかを比較すれば明らかですけど、かなり多く見積もって1割のエンジニアが積極的に動いてくれたとしても、100名のチームならそれなりのタスクの流動性を持たせられるでしょうが10名以下の小規模なチームとかになると1名とかになるのでタスクが自主的に動いていく数がかなり低くなってきます。

タスクが活発に動いている状況はチームが活発に動いている状況でもあるので、そのような状況に無い場合はそもそもその開発スタイルがチームにあっていないということにもなります。


別にこれはコミュニケーションスキルに優れたエンジニアがいるかいないかという話ではなく、BTSを使った場合のコミュニケーション手段は基本テキストになるので、バグの報告とかシステムの仕様をWikiにまとめるといったことは、話すのが苦手といったエンジニアの方が返って向いてたりもします。

逆に話し好きなエンジニアの方が打ち合わせで問題点や方針を決めたりして、それがチケットにあがってこないという状況にもなったりするのでこのスタイルに向いてないかもしれません。


また、チケット(タスク)の総量が減ってきたりするとエンジニアが仕事を持て余すようにもなってきたりします。

つまりは、受身なエンジニアが多い状況ではそのチームやプロジェクトのマネージャーがチケット(タスク)を作り出して割り当てていくということをしていかないと全然仕事が進んでいかないという状況に陥ります。

このスタイルを割り切ってしまえば、マネージャーの負担が大きくなるにしろ機械的にタスクをこなすことでチームを回す事はできるかもしれませんが、それに慣れてしまった場合に何も考えが及ばないようなエンジニアが育ってしまったりして怖いなとも思うわけです。


何れにせよ、数多ある開発スタイルというものは、マネジメントの観点だけで良し悪しが決まるものでもなく、そもそも組織やチームの文化やそこにいるエンジニアの能力や人柄なんかにも左右されるので、無理に当てはめてもすぐに効果が出るものでもなく、長い時間をかけて特性に合うエンジニアを育てていくということも大事なんだと思います。





政治的な理由で持ち込まれた製品の末路

$
0
0

自分たちでシステムを作る場合、何らかのツテがあるベンダーに入ってもらって提案してもらったり、または過去の導入実績からその新しい製品を見積もってもらったりといった感じでこちらが導入に際して主導権を握りますが、中にはそうではない厄介なものがあったりします。


それは、自社と取引のあるお客さんから「そっちの製品/サービスを買ってんだからうちのも買ってよ」という感じで持ちかけられたものたちです。

悪い例では、自分たちで構成を決め、見積もりを取り、設計をしている段階で営業部門とかから商談のネタとするために他の製品の導入を強引に持ち込んできたりもします。



使い道の無いものの使い道


こういった話の面倒なところは、販売元が取引先であるために無下に断れないことや、そもそも話が来た頃には勝手に導入することが決定されているような状態で来ることです。

しかも、自社のサービスのライン側もそういったものが必要で買うわけではないので使い道も無く、システム部門で使ってよということで話が来るわけですけど、当然こちらとしても使い道なんて無いわけですよ。


いや、使い道はあることはあるかもしれませんけど、そもそもシステム部門としても年間の大きなシステム投資計画や施策というものは決まっていて動いているわけですから、例えそれが今あるシステム部門の課題を解決してくれるものだとしても、当初の予定に無いものをやるには体制面や運用面や関連するシステムやユーザーへの影響などを考慮しなくてはならないわけで、言ってしまえば余計な仕事が増えるわけです。


まだ、これが遠い将来でも「それは課題だからいつかやらないとね」という認識のものであれば計画を変更してやりましょうということで落ち着けられるかもしれませんけど、そうではないケースも多々あります。

例えば、


・ その製品と同じ機能を持つものを去年導入したばかり(課題は解決済み)

・ 社内のデファクトスタンダードなもの(標準で使っているソフトウェアとか)を一変させなくてはならない

・ そもそもその製品が解決する課題が社内には見当たらない

・ オーバースペック過ぎる(超巨大なアプライアンス製品とか)

・ 機能がしょぼすぎる(使いものにならない)


といった感じのもの。

こういったものの末路というのは「とりあえず言われたから買うだけ買う」という状態になり、遊休資産として倉庫やサーバールームの奥深くに眠らせることになったりします。

巨大なアプライアンス製品を導入しなくてはならないときは、サーバールームでの耐荷重がオーバーしていたため(ただ単にそこに置くためだけに)床下の補強工事をする羽目になったり、塔が立ったように場所を占有して誰しもが作業に邪魔と思うような結果になったこともあります。

あと、電気代がもったいないから火を入れることすらしないとか、「○○のシステム作るのにサーバーが足りないんだよね」という話が出たときに「あのアプライアンス使えばいいじゃん」と揶揄されるだけの品になったりします。


まぁ、もうひたすら遊休資産として保管しておき誰もが早く償却しないかなとか考えるようになったりするわけです。

置いておくだけでいいなら別にいいのでは?とか思われるかもしれませんけど、現物としてある限りその資産を管理しないといけなかったり、アプライアンスだけでなくついでにその中のソフトウェアやH/Wに関する保守契約とか結ばされたりするので、その契約管理とか更新処理とか結構手間はかかってくるので早く消えて欲しいと願わざるを得なくなります。


また、ソフトウェアなら邪魔にならなくていいというわけでもなく、そういうのって導入のコンサルとセットになってたりして、そうなった場合は何らかの形で導入して使う算段を立てないといけないのでもっと面倒なことになったりします。

使い道が無いものに無理やり口実をつけないといけなくなったり、運用の手間が増えたり、導入までにやる気が全く沸いてこない打ち合わせに何回も付き合わないといけなかったり。

今の環境を変えることなく低コスト・短納期で導入が可能ですとかいわれても、作るときについでに入れろと言われるならまだしも実際には既存のシステムとの連携や組み込みがネックになって色々と構成を捻じ曲げないといけないようなことになったりして、手間だけでなくほかのところの弊害が幾つも出てきたりするわけです。


正直、買った体にしてお金だけ上げるからそっとしておいて見たいな事すら思えるレベルなんですが、政治レイヤーで勝手に決められることで振り回されるのは本当に勘弁して欲しいと思う今日この頃です。





情報を捨てるセンス選ぶ技術

$
0
0

情報を捨てるセンス 選ぶ技術/講談社
¥1,944
Amazon.co.jp


タイトルに惹かれて買った本なんですけど、今の時代の生きかたと言うものを捉えている本じゃないかなと思います。

どういったことを書いている本なのかというのは冒頭に以下のように書かれています。


本書の目的は、みなさんにより自信を持って、他人に依存せず、自分の頭で考え、賢明な意思決定ができる力を身につけてもらうことだ。他人の指示をやみくもに受け入れず、自分自身の直感や最初に抱いた考えさえもつねに疑うことのできる人になってもらうこと。つまり、大きく目を見開いて、自分の力で賢明な選択と決断のできる人になってもらうことなのだ。

今やネットで何でも探せる時代となっているわけですが、その利便性とは裏腹に情報量が多すぎて時には情報に踊らされたり傷つけられたりします。

そんな中で何を信じればいいのか、どうすれば釣られないのかというような情報ソースの追い方や検証の仕方なんかがTwitterやFacebookなどを中心にして実際に起きた事件や事象を絡めて書かれていたりしますので比較的とっつきやすい内容の本ではないでしょうか。


Twitterなんかを見てても嘘の情報というのはかなり多く流れてきますし、それを作り出した人に悪意があろうが無かろうが拡散する善意によって自体が悪化していくというようなケースもよく見ますし、何故それを本当かろくに調べもせずに鵜呑みにするんだろうという疑問を持つこともあったりするわけです。

また、ソーシャルの中で一定の権威を持つ人も含め、著名人とつながりやすくなったことでその行動や言葉に知らず知らずのうちに同調していくようなことがあったりします。


話題になっていることが必ずしも本当とは限らず、専門家の意見が常に正しいとも限らず、みんなの判断が必ずしも正しい結果になるとも限らないわけです。

当たり前のことなんですけど、圧倒的な情報量の前では考えることを止めてしまったり、知らず知らずのうちに自分の考えや行動が操られてしまうという危険性もあるわけで、こんな時代だからこそ情報に流されず考えて選択していく力というものが必要なんだと改めて思ったりします。


目次


Chapter1 選択と決断が人生を変えるStep1 めまぐるしく変化する世界とどう取り組むか?Chapter2 目を見開いて世界を見るStep2 正しい情報を見落としていないか?Step3 言葉の力にあやつられていないか?Chapter3 真実の管理人になるStep4 専門家に服従していないか?Step5 素人専門家を見逃していないか?Chapter4 デジタル情報の海に溺れないStep6 誰でも市民ジャーナリストになり得るのか?Step7 なりすましとやらせを選別するChapter5 情報を選ぶ技術を磨くStep8 数学から逃げていないか?Step9 ”自分という受信機”をチェックしているか?Chapter6 いまこそ変革を起こすStep10 ”みんなの判断”に同調していないか? 




udevを使ってデバイス名の固定する

$
0
0

Linux環境上に何らかのデバイスを接続した場合、/devディレクトリ以下に/dev/sdXといったデバイス名が表示されますが、運用の中でデバイスが追加・削除されたりすると名前が変わったりしてシステム上良くないことが起きる場合があります。

特にストレージ領域をマウントしているといった場合、その接続デバイスの名前が変わることで正しくマウントできなくなったり、OS上で動かしているソフトウェアによってはデバイス名を指定しているようなものもあったりして、それが変わるというのは動作に支障が出るケースもあります。


今回は、以前に書いた「iSCSI経由でExt4環境のボリュームをマウントする 」のようにiSCSI経由でストレージに接続している環境下で、接続したストレージボリュームのデバイス名を固定化するというやり方を書いてます。

この中でもデバイス名を固定化するやり方は簡単に書いているのですが、ボリューム内にパーティションをきっていた場合、そのパーティション領域のデバイス名がうまく固定化できなかったことから、改めてまとめてます。


なお、ここで動作確認しているOSはCentOS6.6となってます。

udevのバージョンによって設定方法が結構違うみたいなのでOSのバージョンによっては設定内容が異なるかもしれないので注意してください。



udevを使ってパーティション領域のデバイス名を固定化する


というのが今回の趣旨ではあるんですけど、まず最初にOS上でiSCSI経由で接続されているデバイスの一覧をみてみます。


# ls -l /dev/disk/by-path/合計 0lrwxrwxrwx 1 root root  9  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0 -> ../../sdclrwxrwxrwx 1 root root 10  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0-part1 -> ../../sdc1lrwxrwxrwx 1 root root  9  8月  7 10:35 2015 pci-0000:00:07.1-scsi-1:0:0:0 -> ../../sr0lrwxrwxrwx 1 root root  9  8月  7 10:35 2015 pci-0000:00:10.0-scsi-0:0:0:0 -> ../../sdalrwxrwxrwx 1 root root 10  8月  7 10:35 2015 pci-0000:00:10.0-scsi-0:0:0:0-part1 -> ../../sda1lrwxrwxrwx 1 root root 10  8月  7 10:35 2015 pci-0000:00:10.0-scsi-0:0:0:0-part2 -> ../../sda2lrwxrwxrwx 1 root root 10  8月  7 10:35 2015 pci-0000:00:10.0-scsi-0:0:0:0-part3 -> ../../sda3

先頭の2つがiSCSIでつなげているデバイスで、下記のようにlun-0(sdc)がブロックデバイス、lun-0-part1(sdc1)がパーティションの構成となっています。


# lsblkNAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTsr0     11:0    1 1024M  0 romsda      8:0    0   16G  0 disk├sda1   8:1    0  500M  0 part /boot├sda2   8:2    0 11.6G  0 part /└sda3   8:3    0  3.9G  0 partsdc      8:32   0  105G  0 disk└sdc1   8:33   0  105G  0 part

このsdcおよびsdc1というデバイス名を固定化する方法ですが、「iSCSI経由でExt4環境のボリュームをマウントする 」で書いた下記のようなudevのルールファイルを作成するとブロックデバイスに対してはデバイス名を固定化できるのですが、パーティション領域に関してはうまく動作してくれません。


KERNEL=="sd*", BUS=="scsi", PROGRAM="/lib/udev/scsi_id -g /dev/%k", RESULT=="36019cbd1a29432cc821b157e1600f0f1", NAME="bar%n", OWNER:="fuga", GROUP:="hoge", MODE:="0660"

このルールを適用すると下記のようにブロックデバイスとその中のパーティションとではデバイス名が変わってしまいます。


# ls -l /dev/disk/by-path/合計 0lrwxrwxrwx 1 root root  9  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0 -> ../../barlrwxrwxrwx 1 root root 10  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0-part1 -> ../../sdc1

想定としてはパーティションの領域はbar1というデバイス名になってほしいところが元もとのsdc1のままになってます。

実際にデータがおかれているパーティション領域はOS上でマウントする際に/etc/fstabとかに書いたりするのでこのデバイス名も固定化しておきたいところです。


先ほどのルールで何が問題なのかというのは、このファイルでやっていることはPROGRAMで指定したコマンドを叩いてRESULTの結果が一致したら、NAMEに指定しているデバイス名を付けろというものですが、そもそもscsi_idコマンドはブロックデバイスに対してしかSCSI ID(デバイス固有の一意な識別子)を返してくれないみたいです。

ってことで、ルールを下記のように変更します。

ファイルは、/etc/udev/rules.d/80-scsi.rulesという名前で保存しています。


SUBSYSTEM=="block", ENV{ID_BUS}=="scsi", ENV{ID_SERIAL}=="36019cbd1a29432cc821b157e1600f0f1", NAME="bar%n", OWNER:="fuga", GROUP:="hoge", MODE:="0660"

ENV{ID_SERIAL}によって、デバイスのプロパティが指定のSCSI IDと一致した場合にデバイス名をbar%n(%nは順番に振られるデバイス番号)にしろというルールに変更しています。

このID_SERIALは下記のコマンドで確認できます。


# udevadm info --query=all --name=/dev/barP: /devices/platform/host17/session15/target17:0:0/17:0:0:0/block/sdcN: bar- snip -E: UDEV_LOG=3E: DEVPATH=/devices/platform/host17/session15/target17:0:0/17:0:0:0/block/sdc- snip -E: ID_REVISION=6.0E: ID_TYPE=diskE: ID_SERIAL_RAW=36019cbd1a29432cc821b157e1600f0f1E: ID_SERIAL=36019cbd1a29432cc821b157e1600f0f1- snip -

このID_SERIALはブロックデバイスに対してもパーティション領域に対しても同じ結果がセットされているため、ルールファイルの中でうまく マッチングさせることができます。

ルールファイルの表記に関する説明は下記に詳しく書かれています。


udevルールを処理するカーネルデバイスイベントへの影響 @ Novell


設定変更後は、udevを再起動します。


# start_udevudev を起動中: [  OK  ]

これでもう一度、デバイス名を確認していると想定しているとおりbarやbar1のデバイス名になりました。


# ls -l /dev/disk/by-path/合計 0lrwxrwxrwx 1 root root  9  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0 -> ../../barlrwxrwxrwx 1 root root 10  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0-part1 -> ../../bar1

ちなみに、ルールファイルが正しく読み込まれていたり適用されているか確認したい場合は、下記のコマンドでテストをすることができます。

引数に渡しているパスは、先ほどのudevadm infoコマンドの結果の中でDEVPATHに表示されているパスです。


# udevadm test /devices/platform/host17/session15/target17:0:0/17:0:0:0/block/sdcrun_command: calling: testudevadm_test: version 147This program is for debugging only, it does not run any program,specified by a RUN key. It may show incorrect results, becausesome values may be different, or not available at a simulation run.- snip -parse_file: reading '/etc/udev/rules.d/80-scsi.rules' as rules file- snip -udev_rules_apply_to_event: OWNER 502 /etc/udev/rules.d/80-scsi.rules:1udev_rules_apply_to_event: GROUP 502 /etc/udev/rules.d/80-scsi.rules:1udev_rules_apply_to_event: MODE 0660 /etc/udev/rules.d/80-scsi.rules:1udev_rules_apply_to_event: NAME 'bar' /etc/udev/rules.d/80-scsi.rules:1- snip -

かなり大量に情報が出てきますけど、最初のほうにルールファイルを読み込んでいるか、後半のほうにルールファイルに指定された名前などが適用されているかの情報で正しいかどうか読み取れます。


あと、CentOS5とかだとこのルールファイルは20-scsi.rulesのように若い番号で定義していたんですけど、適用する順番が変わったのかこのままだとうまく動作せず、80-scsi.rulesという後半の番号で定義するようにしました。

理由はよくわからないのですが、udevのデフォルトルールファイルが/lib/udev/rules.d/にあったりして、この辺のファイルが先に名前をつけてしまっているからなんじゃないかなと思ったりしてます。





マニュアルってそもそもITサービスに向いてないんじゃないかって話

$
0
0

特に業務系のシステムの場合、そのサービスを利用するにあって何十ページもあるような分厚いマニュアルが作られたりもするんですけど、最初はユーザーのためにもマニュアルは必要と思ってたりもしてましたけど、最近はそもそもITサービスにマニュアル自体が向いてないんじゃないかと思ったりしてます。



マニュアルがあるせいで進化できないサービス


一つはマニュアルがITサービスの進化の過程で足かせになっているケースが多く見受けられることです。

マニュアルにはスクリーンショットと一緒に説明を入れたりするものが多いですが、そのせいで画面自体を変えることに抵抗されることがあったりします。

単にボタンの配置や色、表示されているメッセージを少し変えるにしても「マニュアルを差し替えないといけないからダメだ」(または時間をくれ)といわれることもあって、よりよい方向に変えるにもかなりの労力を費やす羽目になったりします。


また、そもそもITサービスの進化のスピードとマニュアルを整備したり教育したり、周知したりといった運用のスピードにかなりの差があったりして、一昔前ならこれは逆だったんでしょうけど今やシステムの進化や変化の方が早く、運用側がそれについてこれないといったこともあげられます。

もちろん、仕事が遅いというわけではないのですけど、教育したりそれを提供している客に連絡して現場で混乱しないようにするといったことは人間が介在する分、かなりスピード感がでなくなってきます。

システム開発のスピードは向上するものの、マニュアルなどは相変わらずオフィスソフトを使ってドキュメントを修正したり、メールやユーザーにお知らせする機能を使って情報を拡散するといった物理的な時間の制約が伴うものが多く、サービスの変化についてこれない状況になってきたりしています。


今やサービスの変化というのはよっぽど大きな変更は除いてユーザーに告知することなく(実際には告知はしているものの多くのユーザーはそれを知らなかったり)変わっている事が多々あったりします。

ソフトウェアを立ち上げるごとにバージョンのチェックが入って日々細々としたマイナーバージョンのものへとアップグレードが繰り返されてたりしますし、急にサービスメニューが増えたり変更となったりしていて不満を持ちつつも、使っている以上はそれに追随しなければならないわけです。

こういったことが当たり前の世界になりつつありますし、ユーザーもそれに慣れてきてたりもするので、そういったサービスの非情に短いサイクルでの変化の中でマニュアルの存在意義というのはますます薄れていっているのではないかと思います。



マニュアルがないと困るものはあるか


じゃあ、マニュアル自体は一切要らないのか、といわれたら個人的に困ることも多かったりして、例えば開発する上で必要なメソッドやAPIの仕様の説明、開発規則や設計書などはないと仕事にならなかったりするんですけど、こういったものでも最新リリースされたバージョンのAPIなどにきちんと付いていけているドキュメントとか少なかったりします。

まぁ、OSS系とかは有志によるものだったりしますので当然そういったドキュメントの整備とかはコミットされているわけではないですし、開発の第一人者やコミッタによって公開されている情報である程度概要がわかったり、そもそもOSS利用するなら自分でソース読めとか動作確認しろというのは当たり前だったりもするので文句はいえないところではあります。


結局のところ、ITサービスの進化についていくにはある程度自分で情報を追いかけていく努力が必要となるんでしょうけど、一般的なITサービスを使ってみても、初見で全く使い方がわからないといったものはほぼ無く(あったらたぶんそれ以上使わない)、そのマニュアルはUIの説明をするというよりは、仕様的な説明をするものに置き換わっており、これはマニュアルと呼ぶよりもどちらかというとFAQやQ&A的な使い方をしているものが多かったりします。


要は旧来のマニュアルといったものは役目を終えつつありますし、そういったものが無くてもわかるものが求められていたりしています。
数年前までガラケーだらけだったのに今やスマホだらけで、その過程で一定の不便さを感じることはありつつも、使い方が全くわからなかったという苦労をした人はあんまりいなかったんではないでしょうか。

現に、70歳を超える親にiPad渡してもすぐに使えていましたし、当時3歳の姪っ子も普通にYoutubeとか自分で見たりしているわけです。


まぁ、ユーザーによってはサービスや機器を使っていく中で結構細かいことを突っ込んでくる人もいたりしますし、特に機械系とかなら思わぬ使い方をして怪我をしたとかいった場合に訴えられても困りますからこういうことはしないでくださいって注意喚起をマニュアルに盛り込むようにもしたり、データが消えたとか保障する・しないとかの話も盛りこんだりということしているとかなり分厚いマニュアルができあがるわけですけど、こういったものはどちらかというとマニュアル自体が自己防衛の目的が強かったりします。

こういったものは利用規約などに吸収されてたりもするんですけど。


ということで、結局のところ分厚いマニュアルなんてユーザーは細かく読まないですし、マニュアルがなくて利用できるサービスというものがよいですし、同業他社のサービスに負けないためにも進化のスピードが求められてきますし、それを実現するためにも足枷になるようなものは作るに見合わないのではないかと思ったりします。





Laravelで独自に作ったライブラリファイルへのパスの通し方

$
0
0

コントローラーファイルにごりごりとビジネスロジックを書いていくようなやり方もありますが、コントローラー間の共通処理など別ファイルにロジックを分離したいということはよくあることです。

ってことで、Laravelでライブラリを定義する方法のまとめです。

ここでは、Laravel4.2をベースに書いています。



Laravelでライブラリを読み込む方法


基本的にLaravelはファイルやディレクトリの構成の制約をうけません。

どこに何のファイルを置いているのかを定義しておけば素直に読み込んでくれます。

ということで、まずはライブラリ用のディレクトリ(lib)を今回の例ではlaravel/app以下に作成するとします。


$ cd /path/to/laravel/app$ mkdir lib

この下にライブラリファイルを作っていくわけですが、このディレクトリへのパスの通し方は幾つか方法があります。


まずは、composerを使う方法。

composerで読み込む場合は、laravel/composer.jsonにオートロードするように記載します。


    "autoload": {        "classmap": [            "app/commands",            "app/controllers",            "app/models",            "app/database/migrations",            "app/database/seeds",            "app/tests/TestCase.php",            "app/lib",        ]    },

composer.jsonを編集した後は


$ composer dump-autoload

を実行する必要があります。

composerの使い方の詳細は「[Composer] プログラムのオートロードはComposerにお任せ 」を参照。

composerを使うとそっちに依存したり、ディレクトリが増えるたびにdump-autoloadするのが面倒だったりもするというデメリットもあったりします。


次に、app/start/global.phpに対象ディレクトリを書いてしまう方法です。


/*|--------------------------------------------------------------------------| Laravelクラスローダーの登録|--------------------------------------------------------------------------|| Composerを使用することに加え、コントローラーとモデルをロードするために| Laravelのクラスローダーを使用することもできます。Composerを更新しなくても| 「グローバル」な名前空間にあなたのクラスを設置しておくのに便利です。|*/ClassLoader::addDirectories(array(    app_path().'/commands',    app_path().'/controllers',    app_path().'/models',    app_path().'/database/seeds',    app_path().'/lib',));

最後に、laravel/libへのパスを追加しています。

こちらは、ファイルを編集するとすぐに読み込んでくれるためシステムの構成に柔軟に対応させることができるので一番手っ取り早い方法かもしれません。

ただし、Laravel内の全システムで共通となるため、全てで使う共有ライブラリを作りたいといった場合はよいですが、システム(やコントローラ)ごとのライブラリを作りたいといった場合は多少構成が煩雑になる可能性があります。


最後は、サービスプロバイダを使うやり方です。

こちらは、「Laravelでサブシステム用のディレクトリを分離する 」に書いたようにシステムごとにディレクトリを分離したいといった場合に便利なやり方ですが、少し設定が面倒です。


最初に、サービスプロバイダ用のファイル(CommonServiceProvider.php )を配置します。

今回は、laravel/app/Myproviders/Servicesに置くとします(実際にディレクトリやファイル名はどこでも大丈夫です)。

サービスプロバイダ用のファイルは下記のようなものとなります。


<?phpnamespace Myproviders\Services;use Illuminate\Support\ServiceProvider;class CommonServiceProvider extends ServiceProvider{    public function boot()    {        \ClassLoader::addDirectories(array(            __DIR__ . '/../../lib',        ));    }    /**     * Iocコンテナの登録.     *     * 事前に登録したいクラスがある場合はここで設定する.     *     * @return void     */    public function register()    {    }}

あとで、composerのオートロードにも登録するため名前空間を定義しています。

そして、boot()内にライブラリ用のディレクトリパスを定義しています(サービスプロバイダファイルからみたディレクトリパスを指定します) 。

次に、laravel/app/config/app.phpを編集し、先ほど作ったサービスプロバイダを登録します。


    /*    |--------------------------------------------------------------------------    | オートロードサービスプロバイダー    |--------------------------------------------------------------------------    |    | ここにリストしたサービスプロバイダーはアプリケーションのリクエストに対し    | 自動的にロードされます。アプリケーションの機能を拡張するため、この配列へ    | 自由に自分のサービスを付け加えてください。    |    */    'providers'=> array(        'Illuminate\Foundation\Providers\ArtisanServiceProvider',        'Illuminate\Auth\AuthServiceProvider',        'Illuminate\Cache\CacheServiceProvider',- snip -        'Myproviders\Services\CommonServiceProvider'    ),

指定方法は、PSR-0のオートロードに準拠した名前空間で指定します。

最後に、laravel/composer.jsonにサービスプロバイダを置いたディレクトリを登録しておきます。


    "autoload": {        "classmap": [            "app/commands",            "app/controllers",            "app/models",            "app/database/migrations",            "app/database/seeds",            "app/tests/TestCase.php"        ],        "psr-0": {            "Myproviders": "app/"        }    },

編集後は、dump-autoloadしておきます。

こちらも編集ファイルが多かったり、composerを使わないといけないといったデメリットはあるんですけど、「Laravelでサブシステム用のディレクトリを分離する 」に書いたようにシステムを分離したいといった場合に便利な方法かもしれません。



Laravelのライブラリを作成する


これでライブラリが読み込める環境となったわけですが、ライブラリファイル自体は一般的なクラスファイルとして定義すればよいだけです(モデルやバリデータを作りたいといった場合は継承するクラスがありますが今回は割愛します) 。

<?phpclass Tools{    function foo() {        return true;    }}

呼び出し方は、コントローラから


    public function bar()    {        $obj = App::make('Tools');        $obj->foo();    }

とするだけで呼び出せます。

余談ですが、サービスプロバイダを作っておくと独自のプレフィックスを定義できたりもして便利です。

先ほどのサービスプロバイダのboot()に


    public function boot()    {        \ClassLoader::addDirectories(array(            __DIR__ . '/../../lib',        ));        \View::addNamespace('Common', __DIR__ . '/../../views');        \Config::addNamespace('Common', __DIR__ . '/../../config');    }

このように「Common」というプレフィックスを定義しておくことで、


// 設定ファイルの読み込み$env = Config::get('Common::const.MY_ENV');// Viewファイルを読み込みreturn View::make('Common::top');

のようなことができて設定ファイルやViewファイルを分離、明示することができたりもします。





Laravelでバリデーションを定義する

$
0
0

Laravelで入力フォームのエラーチェックをしたいといった場合に、標準のバリデーションを利用すれば独自にロジックを組み込むことなく容易に実装することが可能です。

ってことでLaravel標準のバリデータの使い方のまとめです。

ここでは、Laravel4.2をベースに書いています。



Laravel標準のバリデータを利用する


どういったバリデータが標準で用意されているのかを知りたければ、エラーの際に出力されるメッセージの一覧の定義ファイルを見るのが早 いかもしれません。


<?phpreturn array(    /*    |--------------------------------------------------------------------------    | バリデーション言語行    |--------------------------------------------------------------------------    |    | 以下の言語行はバリデタークラスにより使用されるデフォルトのエラー    | メッセージです。サイズルールのようにいくつかのバリデーションを    | 持っているものもあります。メッセージはご自由に調整してください。    |    */    "accepted"             => ":attributeを承認してください。",    "active_url"           => ":attributeが有効なURLではありません。",    "after"                => ":attributeには、:date以降の日付を指定してください。",    "alpha"                => ":attributeはアルファベッドのみがご利用できます。",    "alpha_dash"           => ":attributeは英数字とダッシュ(-)及び下線(_)がご利用できます。",    "alpha_num"            => ":attributeは英数字がご利用できます。.",    "array"                => ":attributeは配列でなくてはなりません。",    "before"               => ":attributeには、:date以前の日付をご利用ください。",    "between"              => array(        "numeric" => ":attributeは、:minから:maxの間で指定してください。",        "file"    => ":attributeは、:min kBから、:max kBの間で指定してください。",        "string"  => ":attributeは、:min文字から、:max文字の間で指定してください。",        "array"   => ":attributeは、:min個から:max個の間で指定してください。",    ),    "boolean"              => ":attributeには、trueかfalseを指定してください。",    "confirmed"            => ":attributeと、確認フィールドとが、一致していません。",    "date"                 => ":attributeには有効な日付を指定してください。",- snip -

配列のキーがバリデーションのルールとなっており、ルールに違反した場合は配列の値に格納されているメッセージが出力されます。

例えば、入力項目がアルファベットのみであるかのチェックや指定の日付の正当性のチェックなどのルールが含まれています。

まぁ、boolean型かどうかのチェックでエラーを出すかなど、使うのかどうか疑問なルールもあるわけですが、取りあえず標準としては一般的に使いそうなバリデーションが定義されています。


また、これは日本語化された定義ファイルになりますが、laravel/app/lang/enディレクトリの中にも英語がベースとなっているメッセージ定義ファイルがあります。

この使い分けは、laravel/app/config/app.php内のロケールの定義に依存します。


    /*    |--------------------------------------------------------------------------    | アプリケーションローカル設定    |--------------------------------------------------------------------------    |    | アプリケーションローカルは翻訳サービスプロバイダーにより使用される    | デフォルトローカルを指定します。アプリケーションで提供するローカルを    | 自由に設定してください。    |    */    'locale' => 'ja',    /*    |--------------------------------------------------------------------------    | アプリケーションフォールバック言語    |--------------------------------------------------------------------------    |    | フォールバック言語は現在のローカルが使用できない場合に、    | 代替として使われます。アプリケーション全体に対して用意されている    | 言語フォルダーに対応するコードであればどれでも使用可能です。    |    */    'fallback_locale' => 'en',

上記のように設定することで標準はja(日本語)のロケールが設定され、それが存在しない場合にen(英語)が呼び出されます。

他の言語にローカライズしたい場合は、新たなロケールとメッセージファイルを用意します。


で、具体的なバリデーションの実装方法ですが、まずはバリデーション用のファイルを作りそれを読み込むようにします。

バリデーションファイルへのパスの通し方は「Laravelで独自に作ったライブラリファイルへのパスの通し方 」を参照。


class MyValidator{    public function validate (array $params)    {        $validator = Validator::make($params, ['id' => 'required|max:10', 'passwd' => 'required_if:flg,1|alpha_num']);        // バリデーションチェック        if (!$validator->passes()) {            $this->errors = $validator->messages();            return false;        }        return true;    }    public function errors()    {        return $this->errors;    }}

バリデーションの作り方はValidator::make()で作成し、チェック対象の引数とその配列内のキーにそれぞれバリデーションのルールを渡します(複数のルールを適用したければパイプで区切ります)。

例えば、idのパラメータは必須(required)でかつ最大10文字(max:10)であるかをチェックしています。

passwdパラメータでチェックしているrequired_ifは特殊でflgが1の場合に必須かどうかをチェックするというものです。

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


このバリデーションを元に実際にチェックしてみたいと思います。

コントローラファイルから先ほど作ったバリデーションを呼び出してエラーがあるかどうかをチェックします。


public function foo(){    $obj = App::make('MyValidator');    // リクエストパラメータを取得    $params = Input::all();    // バリデータにパラメータを渡してチェック    if (! $obj->validate($params)) {        // エラーがある場合は何がしかのエラー画面を出力        return View::make('Common::Error.index')->withErrors($obj->errors());    }    return View::make('hello');}

エラーがある(validate()からfalseが返ってくる)場合は専用のエラー画面を出力していますが、この辺はお好みで。



バリデーションをカスタマイズする


当然、デフォルトで用意しているバリデーションだけではアプリケーションの要件を満たさない場合がありますし、もっと複雑なバリデーシ ョンを作りたいという場合があります。

この場合、バリデーションルールを独自に作ることができます。

例えば、先ほどのvalidate()に独自のルールを追加してIDのチェック用にDBのマスタ上に存在するかといった処理を加えたルールを追加して みます。


public function validate (array $params){    // バリデータのルールを定義    Validator::extend('idCheck', function ($attribute, $value, $parameters, $validator) {        // IDが存在するかどうか        $db = App::make('DbMaster');        if (!$db->checkMember($value)) {            return false;        }        // 全パラメータを取得        $data = $validator->getData();        // flgが1の場合のみの処理を何か        if ($data['flg'] === "1" && $db->checkSomething($value)) {            return false;        }        return true;    });    // エラーメッセージ    $messages = array(        'id_check' => ':attributeが存在しません'    );    // 項目名    $attributes = array(        'id' => 'ログインID'    );    $validator = Validator::make($params, [        'id' => 'required|max:10|id_check',        'passwd' => 'required_if:flg,1|alpha_num'        ], $messages);    $validator->setAttributeNames($attributes);    // バリデーションチェック    if (!$validator->passes()) {        $this->errors = $validator->messages();        return false;    }    return true;}

バリデーションルールの拡張はValidator::extend()で行い、第1引数にルール名(idCheck)を指定します。

第2引数は無名関数として定義しており、中身に詳細なバリデーションロジックを記述します。

単純な話、何らかの処理をして最終的に正しければtrueを、誤りがある場合はfalseを返せばよいだけです。


その他のパラメターと複合的にチェックしたい場合、無名関数の第4引数にある$validatorのgetData()メソッドでその他のパラメータを受け 取れたりします。


// 全パラメータを取得$data = $validator->getData();

拡張したルールは、それに対応するエラーメッセージや項目名を定義する必要があります。

エラーメッセージはルール名をスネークケース(idCheckをid_checkにする)にしたキーを元に配列に格納します。


// エラーメッセージ$messages = array(    'id_check' => ':attributeが存在しません');

項目名は、エラーメッセージ内の項目名に何を入れるかを定義します。

この際の項目名は、チェックするパラメータ名をキーにしておきます。


// 項目名$attributes = array(    'id' => 'ログインID');

要は、このバリデーションに引っかかった場合は「ログインIDが存在しません」というエラーメッセージを受け取ることができます。


最後に、定義したルールを適用します。


$validator = Validator::make($params, [    'id' => 'required|max:10|id_check',    'passwd' => 'required_if:flg,1|alpha_num'    ], $messages);$validator->setAttributeNames($attributes);

最初のバリデーションとは異なり、idのパラメータに適用するバリデーションとしてid_checkが追加されています。

エラーメッセージの設定は、Validator::make()の第3引数に渡し、項目名はsetAttributeNames()によってセットします。


バリデーションのカスタマイズは標準のValidatorそのものを拡張するやり方もあったりするのですが、長くなったので別途まとめたいと思います。






PHPをソースからインストールするときにopcacheを有効にできない

$
0
0

PHPのコードキャッシュとしてOPcacheがPHP5.5以降バンドルされているのですが、CentOS6系のサーバー上でPHPをソースからインストールする際に、--enable-opcacheオプションをつけてコンパイルすると下記のエラーが出てうまくインストールできずにはまりました。


$ ./configure --enable-opcache- snip -checking "whether flock struct is linux ordered"... "no"checking "whether flock struct is BSD ordered"... "no"configure: error: Don't know how to define struct flock on this system, set --enable-opcache=no

まぁ、メッセージのとおり--enable-opcache=noオプションをつければコンパイルは通るわけですけど、コードキャッシュ使ったほうがパフォーマンスも良くなりますし、APCとかコードキャッシュしてくれなくなったりしてますんでOPcacheを使いたいわけですよ。

で、解決方法は共有ライブラリのパスを定義している/etc/ld.so.confに/usr以下のライブラリのディレクトリを追加したら解決しました。


include ld.so.conf.d/*.conf/usr/local/lib/usr/lib64

追加した後は、ldconfigで設定を反映します。


# ldconfig

その後、もう一度PHPのconfigureをしたら通ったので、そのままmake、make installします。

インストール完了後は、OPcacheを有効にするためにphp.iniを編集。


[opcache]zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20131226/opcache.soopcache.enable=1opcache.memory_consumption=128opcache.interned_strings_buffer=8opcache.max_accelerated_files=4000opcache.revalidate_freq=30opcache.fast_shutdown=1opcache.enable_cli=1

余談ですけど、Xdebugと一緒に使う場合はXdebugの設定より前に上記を書いておかないといけないらしいです(詳細はマニュアル 参照)。

最後に、Apacheを再起動してOPcacheが使えているかを確認。


# php -vPHP 5.6.13 (cli) (built: Sep 28 2015 11:18:05) Copyright (c) 1997-2015 The PHP GroupZend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies

OPcacheの詳しい使い方は以前に書いた、「PHPコードキャッシュにOPcacheを使ってみる 」も参考にしてみてください。





環境を固定化するリスク

$
0
0

一つの会社なり組織に長いこと属していると周りの環境が固定化されてしまい、それによって色々弊害が出てくることがあります。

実際のところその弊害というのは直感しづらいものであったりするのでなかなかピンとこなかったりもするのですが、いざ違う環境に身をおいたときに自分が浦島太郎状態であったことを痛感するのはよくあるパターンです。



同調によって見えなくなる危険性


1つは、その環境におけるメンバーが固定化すると話題などがある程度決まっていて考え方も同調するようになってしまうことです。

これは、その環境に自分が身を置くきっかけになった場合もあったりするので、ある意味自分が望んでいたり快適と思っていたりする部分はあります。

例えば、趣味が合う仲間といた方が話が弾むとか、思考や思想が似ているから結束感が生まれりして、逆に合わない仲間といるのは苦痛だったりもしますから、特に人間関係は自分が居心地のいい場所を探しがちなんだと思います。


ただ、その環境に身をおくと周りが見えなくなりがちだったりそれ以外の話題に触れることが少ないためかその環境の外で起きている変化に気づかなかったり、気づいたとしても自分の環境においては周りが騒がないから大丈夫だろうという変な安心感も生まれたりするわけです。

まぁ、学生時代に周りが遊んでいるから自分も遊んでても大丈夫だろうとか、「テスト全然できなかったよ~」とか言う会話を聞いて変に安心感が得られた記憶もあったりするのですけど、そんな感じでしょうか。


会社や組織において人が入れ替えられたり、新しく外部の人を受け入れるのを歓迎するのは、そういった固定化された考えに変化が求められたりするためだったりもするんでしょうけど、企業文化や風土によってはなかなかそこにメスが入りづらかったり、組織構造が変わりづらい部門とかではメンバーに変化が無い場合もあったりします。

こういう環境に身をおき続けると環境変化の耐性が失われていって、変えることへの嫌悪感や考え方が偏屈になったりしてなかなか異なる意見を受け入れにくくなったりもするんですけど、そういう意味ではそれを改善するために転職して環境をガラッと変えてしまうのはその手っ取り早い方法なのかもしれませんが。



今の環境が永続するという幻想


組織間の変な政治的な軋轢に巻き込まれたり、意見が合わない人たちと長期的に仕事をするというのは本業に色々影響が出てくることも多いのでできれば避けたいところです。

ですので、環境の中における安心感を得るのは大事なことではあると思いますが、長期的に環境の変化が起きづらいところでは、居心地がいいあまり当人たちがその環境があたかも永続的にあるように思い込んでしまったりもします。


酷くなってくるとその環境が永遠に続けばいいのにと思い込んだりもしますが、当然そんなことはありえません。

何時までも優しい先輩がいてくれるとも限りませんし、好きな仕事だけをしていられるとも限りませんし、今ある地位や権限があり続けるとも限りません。

何時までも今の環境が続いていくのではという錯覚に陥ってしまうと、実際に環境の変化が起きてしまった場合に付いていけないんじゃないかと心配になったりもします。


このことは結構バランスが難しいもので、環境としてはなるべく安定していた方が自分が注力したいことに集中できたりもするのですが、環境に依存しすぎたりはまりすぎたりすると周りで起きている変化や自分の環境が変わったときに耐性が無いあまりに何もできなくなるというようなリスクも出てくるわけです。
ですので、定期的な環境が変化する場に身をおくことというのは悪いことではないと思うわけですが、やはり何処かしら安定志向が頭にあるとガラッと環境を変えることへのリスクも頭をよぎったりして、よくある企業CMのように自分たちは変わる、改革するといったキャッチフレーズだけとなり、中身は何も変わっていないという状況になります。


実際にその環境の中に身を置く人、与えられた役割や仕事というものに大きな変化が無い中で環境そのものをガラッと変えるのはかなり難しいことです。

何処かしら今の安定した状態を保とうという意識が誰しも働きますし、それはある種の成功事例になっているわけなのでできるだけ崩したくないという思いが出てきたりします。

これもある意味、知らず知らずのうちに今ある環境を長く続けたいという考えが頭に根付いているのが原因であったりして、それは長らく凝り固まった環境に依存しすぎた一つの弊害なのかもしれません。





エンジニアの想像力を活かす環境、殺す環境

$
0
0

システムを作り上げていく中で、要件が曖昧な部分というのが出てきたり、設計書でも全てが完璧に書かれているものというのはまずないので行間を読まないといけない場合があったりして、そういった際に想像力を働かせないといけないことがよくあったりします。

こういうシーンでエンジニアの想像力というのが試されるわけなんですけど、変な解釈をしてあらぬ方向に進みだしたり、それが間違っているだろうと思っていても書かれている通りにしか実装しないというようなことをしていくと後々トラブルや面倒なことになったりしてきて、この想像する力というのは結構重要になってくるなと、最近強く感じてたりもします。



想像力の限界


物作りをするに当たって想像する力っていうのはコミュニケーションをとる上で相手の意図を汲み取ったり、文章の行間を読み取ったり、目的を遂行する上での理解の助けとなったりもします。

生粋のエンジニアの中にはコミュニケーションをとるのが苦手という人もいたりして、なかなか仕様がきちんと伝わらないことで何度も打ち合わせを繰り返したり大量の資料を用意しないといけなかったり、勝手な解釈によって実装が進んでしまって手戻りが必要になったりすることがあります。

こういうのは文化が違うオフショアとかでも良く起きる問題でそもそも互いが求める当たり前のレベルが違うためにコミュニケーションミスが発生しやすくもなります。


結構面倒な事に発展しやすいのは、伝えたことや書いてあることを何の疑問も持たずにそのまま鵜呑みにしてしまうケースで、もちろんこれは伝えた方や書いた方にほぼ瑕疵があるわけなんですけど、その裏にある背景や実装の中にある矛盾などを考慮していないというのは問題があると思ってたりもするわけです。

酷い場合には、それを知っていたり気が付いていたりするのに、そう書いてあるからとそのまま突き進んでしまったり。

そのエンジニアに与えた担当や役割によっては受け取る情報や権限などによってどうしても視野が狭くなってしまうことはあるわけですけど、だからこそ担当や役割にこだわらず幅広い視点というものが求められてくると感じたりもします。


もちろん、同じ人間同士とはいえ完璧な意思疎通ができるというのは極めて稀なため、どんなに想像力が豊かだったり、付き合いが長いことで働く勘があったとしてもミスが起きるのはよくあることです。

結局のところ、想像力というのは自分ひとりで働かせるのには限界があって、コミュニケーションの中で相手の意思や拾い集めた情報によってより確実なものへ高めていく必要があるわけで、クイズをしてるんじゃないんで当たるかどうか不確実なもので進んでいくのは困るわけです。



想像力を封じ込める環境


色々な疑問がエンジニアの想像力によって出てきたとしても、それを良しとしない環境もあったりします。

役割や権限が厳格化されていたり、仕様の通りに実装すればよいという雰囲気を出されては、その疑問もなかなかぶつけることもできません。


最近のシステム開発は役割が細分化されていたりもするので、全体の情報が集めにくかったり、担当が曖昧になりがちでお互いが相手がやるもんだと思っていたり、担当外のところに口を出しづらいなんてことも起きたりします。

客先に常駐している中で、相手の会社の業務フローや文化を理解した上で実装を進めるなんてのはかなり難易度が高いわけですし、上位の権限者によっては疑問をぶつけることもままならない雰囲気もあったりします。
なので、こういう自身の考えが言えない現場やエンジニアを単に実装の担当者とだけ決め付けているようなところでは、エンジニア自身の想像力を働かせる機会も失われ、先に書いたようなトラブルも起こるべくして起こる状況になってきます。


エンジニア自身が想像力を働かせることで生産性も大きく変わってきます。

これはエンジニアの経験値にも大きく左右されたりもしますが、設計書の中には一般的であったり当たり前と思われる要件が暗に含まれていたりもするのですが、それをどう読み解くかで効率化されたり、はたまた不具合が内在する結果になったりと変わってくるからです。

もちろん、そこで曖昧な部分は勝手な想像力を働かせずに緊密に情報共有しあうことでより手戻りが少なく済むことにもなるでしょう。


開発プロジェクトの中では非エンジニアがプロジェクトに携わる割合も多くなってきて、色々なアイデアが飛び交うわけですけど、エンジニアにはエンジニア独自の視点があるわけで、そういった観点での想像力というものが必要になる場面も多々あると思っています。

それは、システムの構成でもアーキテクチャ上の話でもなく、作るサービスそのものの話でエンジニア独自の観点から実装論が出てきたり、そのアイデアによってよりよいものへ変わっていくこともあるわけです。

ですから、エンジニア自身にも想像力を働かせるのは重要なことですし、またエンジニア自身の役割を決め付けてその意見を聞かないというのもまた貴重な機会を逃すことにもなるんじゃないかと思ったりします。





Surface Pro4を買いました

$
0
0
以前使っていたPCがかなり古くなったので久しぶりにPCを買い換えました。
自宅のPCでやることといえば、ネットを見たりブログを書いたりといったぐらいなんで、そんなにスペックとかにはこだわりはなかったのですけど、電気屋でSurfaceを見てたらついついほしくなり・・・。
まぁ、買ったのは電気屋からではなくMicrosoft Storeからだったりするんですけど。


タブレットとPCを兼用できるデバイス


買ったモデルは、Core i5+ SSD256GB+メモリ8GB のものなんですけど、自分的にはオーバースペック過ぎたかもとか今更思ってます。
モデルを結構細かく選べるのはうれしいところなんですけど、メモリは8GBぐらいほしいなと思いつつも、特にPC内に大きなデータを保存したりもしないので、ディスクは128GBでも十分でしょとか思うわけですけど、そこまで細かく選べないのが少し残念かもしれません。
ディスクが足りないということになってもUSBポートやmicroSDのスロットがついているので、何とかなりそうな気もしますし、OneDriveへのデータ転送サービスもあるっぽいです(使ってないけど)。

第一印象としては、そのウリの通りタブレットとPCのどちらでも使えるデバイスといった感じです。
USB使えて、microSDつなげることができて、Display Portがあって、いつものWindowsが使えるiPadみたいなもんです。
今こうしてブログを書いているのは後部のスタンドを立ててタイプカバーに接続して書いているわけですけど、寝る前にネットを見るときはタイプカバーを外してSurface本体だけで操作するように使い分けたりできるわけです。
まぁ、今のご時世はタブレットが主流になってますし、そうは言いつつもこうやって文章を書くときとかはキーボードあったほうが便利だよなぁ、というのがあるのでその両立ができるのは自分のニーズとぴったり合った感じです。

まさにそんな恰好で書いているわけですけど、ベッドの上であぐらかきながらSurfaceを膝の上にのせて操作するのも苦にはなりません。
以前のPCは長時間使っているとかなり熱を持ってきて同じ格好で使っていると色々心配になることがあったんですけど、タイプカバー(キーボード)部分は熱を持つ要素がほぼないですし、本体部分もほとんど熱くはなりません。
タイプカバーのキータッチは人それぞれ好みがあるので何とも言えないですけど、タッチパッドは正直使いづらい感じがあります(クリック部分がないように見えて、どうやって左右のクリックするんだとかとまどいましたけど)。
あと、高級なキーボードだなぁという印象。

ディスプレイサイズは以前のPCはいわゆるネットブックと言われていたもので画面自体がかなり小さかったので、Surfaceの画面サイズでも特に不満はありませんでした。
タブレットとして持ち運ぶことを考えるとこれぐらいのサイズが限度のような気もします(Surface3は少し小さいなとか思いましたけど)
一番の不満は結局のところバッテリーでしょうか。
9時間持続すると書いているとはいえ、電源ケーブルにつなげずにスリープモードで放置したりするといつの間にか充電がなくなってたりもします。
この辺はあらゆるタブレット製品の課題ではあるんでしょうけど。


なんだかんだでOSが肝


デバイスとしての大きな不満はまだ見当たらないんですけど、なんだかんだでWindows10の不慣れが一番大きな不満となってたりもします。
会社ではWindows7使ってたりもするんですけど、操作性とかは大きく違うので不慣れと言っていいのかわかりづらさ満載な感じですし、タブレットとして使う上で洗練されていない部分も多く見受けられたりします。
特にソフトウェアキーボードの反応が悪かったり。
入力項目をタッチしてもソフトウェアキーボードが表示されないことが多々あるので、自分でソフトウェアキーボードを表示させる操作をするのが結構ストレスだったりもします。

あとはWindows10への不満があちこちにネットで散見されるのでOSとしてまだ安定しない状態であることは確かなようで、この辺はiOSのほうがかなり洗練されているなと思うところです。
アプリにしても、iOSやAndoroidに比べてすごく興味があるものがあるわけではないので、結局のところ従来のPCとしてのOSという領域を逸脱できていない感じはします。
子供にYoutube見せたりできるしタブレットして使えるデバイスがあればいいなぁと思って購入したわけですけど、子供が操作するには難しすぎる部分もあるので、そういう意味ではより簡単に操作できるiPadとかのほうが向いているかもしれません。
まぁ、ここまで高価なデバイスを子供に「はい、使っていいよ」と気軽に渡す勇気はでないわけですけど。



Laravelで常時HTTPSでページ遷移をする方法

$
0
0

※ この記事はLaravel4.2を対象にしています。


Laravelのコントローラからリダイレクトをかけたり、Viewにて特定のURLへリンクしたりということは良くありますが、Laravelは現在の通信の状況をみてアクセス先の URLスキームを決めているようです。

つまり、HTTPで通信していた場合、デフォルトではリダイレクト先やリンク先もHTTPとみなされたりします。

まぁ、これはもちろんオプションが用意されているのでSSLでPOSTやGETするといったことをオプションによって区別させることができます。

例えばBladeの中で、form内の遷移先のURLを指定する際にURL::toメソッドを使う場合に第3引数をtrueとすることでHTTPSのURLを指定することができます。


{{ Form::open(array('url' => URL::to('/path/to/next', array(), true), 'name'=>'formName', 'id'=>'formId')) }}-snip-{{ Form::close() }}

実は、URL::toをSSL通信に特化させたければ


URL::secure('/path/to/next', array())

なんてメソッドもあるみたいなんですけど、書き方が統一されていなければ保守性が落ちそうです。

(link_to()ヘルパーをSSLに強制させるlink_to_secure()なんてヘルパーもあるみたいですけど)

ってことで、いまどきのサービスだと全通信をSSL化するみたいなのが当たり前になっていますし、アプリケーション側でオプションをつけるようなやり方をしているとミ スったと気に穴がでそうなので、統一する方法がないかなと調べてたどり着いた答えが下記です。


URL::forceSchema('https');

アプリケーション起動時に呼び出されるstart.phpの設定ファイル上にURL::forceSchema()にてhttpsを指定しています。

これでURL::toやlink_to()などのヘルパー関数も含めてリンク先のスキームがHTTPSとなります。

リンク先がHTTP/HTTPSでばらけるという場合はヘルパーなどは使わずに直接リンクタグとか書いたほうが便利かもしれません。





Google CodeにホストしていたJavaScriptをBitbucketに移行する

$
0
0

アナウンスされているとおり、Google Code が今月の2016年1月でサービスを停止するようです。

このブログではAmebloのフリープラグインのJavaScriptをGoogle codeにホストしたよ に書いたように、ソースコードを整形して表示してくれるSyntaxHighlighterや、Twitterなどのシェアボタンの設置をするためのJavaScriptのコードをGoogle Codeにホストしていたのですが、サービス終了に伴い別のホスティングサービスに移行する必要が出てきました。


まぁ、ホスティングサービスと言っても、Google CodeのSVNの公開リポジトリ上のソースのパスを読み込ませていただけなので、同様のことができるサービスがないかを探していてBitbucket というサービスを使ってみることにしました。
今時、ソース管理するならGitHubでしょってのはあるのですけれども、GitHubはプライベートリポジトリが無料だと持てないのと、特にほかに公開しているソースとかもないのでBitbucketで十分かなと思い選択してみました。



Google CodeのソースをBitbucketにインポートする


とりあえずBitbucketにアカウントを作成したら、リポジトリのインポートメニューからGoogle CodeのソースをBitbucket上のリポジトリへインポートします。


Bitbucket-menu

インポート対象となるソースの選択肢にGoogle Codeがあるのでインポート自体は難しくはありません。

Google Codeのプロジェクト名を指定して、リポジトリのタイプ(自分の場合はSubversionで管理してたので)を選択し、リポジトリのインポートボタンから取り込めます。


bitbucket-import


ポイントはリポジトリ名(Repository name)に「ユーザー名.bitbucket.org」と指定することです。
こうすることで、このリポジトリ名がそのまま公開されるURLとしてホストしている各ファイルへアクセスすることが可能となります。


ただ、そのままやると下記のようにインポート時にエラーが出てしまいました。


-snip-17:10:39 Subversion checkout successful17:10:39 Creating new git repository...17:10:39 Initialized empty Git repository in itboy/itboy/bb_tmp/.git/17:10:40 Done17:10:42 Done17:10:42 fatal: No existing author found with 'itboy (itboy)'17:10:42 Unable to convert svn checkout to git17:10:42 Svn checkout failed: <class 'bitbucket.apps.async.tasks.ImportException'>: Command failed. Return value: 128

理由は、Gitへのインポート時にauthorの情報が正しくないというもので、しばらくはまりましたがBitbucket上のプロファイルを下記のように編集することでうまくインポートできるようになります。

(プロファイルの編集は、右上の人のアイコンからSettingsを選択)


bitbucket-settings
要は、姓名の欄にユーザー名とメールアドレスを指定してGitのauthorの形式に合わせてあげることでうまくインポートすることができます。


リポジトリへのインポートが完了すれば、先ほどのリポジトリ名で指定したURLでアクセスが可能となります。

例えば、foo.jsをリポジトリに登録した場合は、


http://itboy.bitbucket.org/foo.js


というURLで公開されますので、後はこのJSファイルをブログに読み込ませるということで完了です。



Laravelでバッチプログラムを作成する

$
0
0

Laravelではartisanコマンドを通してコマンドラインから様々な処理を実行することができます。

アプリケーションを作成した場合、全てがWebインターフェースで実装するということは難しい場合もあるので、コマンドラインから実行できるバッチファイルを用意した ほうが便利なことが多かったりします。

ということで、Laravel4.2をベースにしたLaravel上でコマンドを作成する手順のまとめです。



コマンドのテンプレートを作成する


artisanコマンドはlaravelディレクトリの直下に存在し、色んな処理を実行することができます。


$ php artisan listLaravel Framework version 4.2.18Usage:  [options] command [arguments]Options:  --help           -h Display this help message  --quiet          -q Do not output any message  --verbose        -v|vv|vvv Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug  --version        -V Display this application version  --ansi              Force ANSI output  --no-ansi           Disable ANSI output  --no-interaction -n Do not ask any interactive question  --env               The environment the command should run under.Available commands:  changes                     Display the framework change list  clear-compiled              Remove the compiled class file  down                        Put the application into maintenance mode  dump-autoload               Regenerate framework autoload files  env                         Display the current framework environment  help                        Displays help for a command  list                        Lists commands  migrate                     Run the database migrations  optimize                    Optimize the framework for better performance  routes                      List all registered routes  serve                       Serve the application on the PHP development server  tail                        Tail a log file on a remote server  tinker                      Interact with your application  up                          Bring the application out of maintenance mode  workbench                   Create a new package workbenchasset  asset:publish               Publish a package's assets to the public directoryauth  auth:clear-reminders        Flush expired reminders.  auth:reminders-controller   Create a stub password reminder controller  auth:reminders-table        Create a migration for the password reminders tablecache  cache:clear                 Flush the application cache  cache:table                 Create a migration for the cache database tablecommand  command:make                Create a new Artisan command- snip -

この中に自作したコマンドを追加しオプションを指定することでバッチ処理を実行できたりします。

まずは、コマンドファイルを作ることからスタートなのですが、一からコマンドファイルを作成するのも手間なので、そのテンプレートファイルをartisanコマンドを通し て作成することができます。


$ php artisan command:make FooCommand

上記のように実行することでFooCommandファイルを作成することができます。

正常に実行されると、laravel/app/commandsディレクトリ以下に作成されます。


<?phpuse Illuminate\Console\Command;use Symfony\Component\Console\Input\InputOption;use Symfony\Component\Console\Input\InputArgument;class FooCommand extends Command {    /**     * The console command name.     *     * @var string     */    protected $name = 'command:name';    /**     * The console command description.     *     * @var string     */    protected $description = 'Command description.';    /**     * Create a new command instance.     *     * @return void     */    public function __construct()    {        parent::__construct();    }    /**     * Execute the console command.     *     * @return mixed     */    public function fire()    {        //    }    /**     * Get the console command arguments.     *     * @return array     */    protected function getArguments()    {        return array(            array('example', InputArgument::REQUIRED, 'An example argument.'),        );    }    /**     * Get the console command options.     *     * @return array     */    protected function getOptions()    {        return array(            array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null),        );    }}


コマンドを作成する


作成したテンプレートファイルを元に中身を編集していきます。

プロパティの$nameはコマンド名、$descriptionはコマンドの概要を記載しておきます。

この内容はartsanコマンド実行時に表示されるのでコマンドの中身がわかるように編集しておきましょう。

バッチ処理の具体的な中身はfire()メソッドの中に定義します。


public function fire(){    $obj = App::make('SomeClass');    echo "hello" . PHP_EOL;}

基本的にLaravelと同様の文法が使えるので、パスが通っていれば上記のようにSomeClassのオブジェクトを生成するというようなこともできます。

バッチ処理が書けたらコマンドをartisanコマンドから実行できるように登録します。

登録するには、laravel/app/start/artisan.phpに下記のように追加します。


<?phpArtisan::add(new FooCommand);

これで、再度artisanコマンドを実行してみると


$ php artisan-snip-Foo  Foo:echoHello               hello出力バッチ  changes                     Display the framework change list  clear-compiled              Remove the compiled class file-snip-

というようにコマンドが登録されています。

余談にはなりますが、「Laravelでサブシステム用のディレクトリを分離する 」に書いたような独自のディレクトリ構成をとった場合は、サービスプロバイダー用 のファイルからコマンドを追加することも出来ます。


public function boot(){    \ClassLoader::addDirectories(array(        __DIR__ . '/../Commands',    ));    require __DIR__ . '/../routes.php';}public function register(){    $this->commands('FooCommand');}

コマンドを実行するには


$ php artisan Foo:echoHellohello

というように実行できます。

コマンドには引数とオプションを指定できます。

それぞれ、コマンドファイルのgetArguments()、getOptions()にて指定でき必須の引数などを指定できます。


protected function getArguments(){    return array(        array('name', InputArgument::REQUIRED, 'your name'),    );}protected function getOptions(){    return array(        array('test', 't', InputOption::VALUE_OPTIONAL, 'run test mode', 'false'),    );}

上記の場合、引数の名前を必須とし、オプションとしてtestを用意しています。

fire()を少し変更してみます。


public function fire(){    if ($this->option('test') === 'true') {        echo "run test mode" . PHP_EOL;    }    echo "hello " . $this->argument('name') . PHP_EOL;}

オプションにtestが指定された場合はテストモードでの実行であることを表示し、引数nameに指定された名前を結合して出力するようにしています。

これで、下記のように実行してみると


$ php artisan Foo:echoHello itboy --test=true                                  run test modehello itboy

のような結果が出力されます。

この状態では引数が必須(REQUIRED)となっているため、引数を指定しない場合は下記のようなエラーがでます。


$ php artisan Foo:echoHello  [RuntimeException]  Not enough arguments.Foo:echoHello [--test[="..."]] name

引数を任意にしたい場合は


array('name', InputArgument::OPTIONAL, 'your name'),

とします。

オプションは動かし方に好みがあったりするのですが、オプション自体に値を指定したくない場合(--testでテストモード扱いにしたい)は、値を受け取らないこともできます。


array('test', 't', InputOption::VALUE_NONE, 'run test mode', null),

この場合、fire()の中では


if ($this->option('test') === TRUE) {    echo "run test mode" . PHP_EOL;}

のようにすることでオプションが指定されたかどうかだけで判別ができるようになります。

また、getOptions()で戻している配列の第2引数は短縮系を表すのでシンプルに


$ php artisan Foo:echoHello -t

というような実行も出来ます(--testまたは-tの両方が利用可能)。

あとは、コマンド実行スクリプトをCronなりジョブ管理ツールなどに登録するなりで定期的に実行すればいいかもしれません。






システムエンジニアを悩ますネタのようで実際に起きるトラブル

$
0
0

システム担当者なら誰しも巻き込まれるシステムトラブルですが、なんでこんなことにと悩ますような怪現象に巻き込まれることがしばしばあったりします。

例えばこんな・・・。



システム入れ替え前に現システムのトラブルが頻発する


数年ごとにシステムをリプレイすることがあったりしますけど、その直前に現在稼働しているシステムにトラブルが頻発することがあります。
エンジニア側から見れば、「もう少しでリプレイスするんだからそれまで我慢してくれよ」と思うわけですけど、「私なんてもう必要ないんでしょ!」とばりに今のシステムが機嫌を損ねてくるわけです。


で、こういう場合にエンジニアとしてはあんまり本気で対策を取りたくないわけです。
もうすぐ新しい環境に入れ替えるわけですから捨てるシステムにそれほど多くの労力を費やしたくないわけですし、そもそもリプレイスの作業のスケジュールが差し迫っている中、そちらに割く時間も多くは取れないわけです。
暫定的な対策で機嫌をごまかしつつこの日まで何とか持ってくれと祈るような気持ちで見守るもやもやした日々がリリース日まで続いたりします。

これはある程度システムやハードの寿命というのが間が悪く訪れる現象だとは思うのですが。



担当者不在の時に限ってトラブる


自分がそのシステムに一番詳しい場合、よりによって休んだ時に大きなトラブルが発生し、同僚とかからの電話に出る羽目になりせっかくの休みが台無しになることがよくあります。
また、他の担当者の場合でもトラブルが発生した時に事前の変更作業が共有されていなかったり、いつもは静かなのにその日に限ってやたらと問い合わせが入って詳細な仕様がわからずに多くの時間を調査に割かれることになったりします。

まぁ、この辺は保守・運用の問題でもあるわけですけど、多くのシステムを抱えていたりするとあの人が一番詳しいというのは出てきたりするわけで、そういう部分をついたトラブルや問い合わせや調査の依頼などが来て頭を悩ませることがあったりします。

休んでるだけならまだ連絡のつけようがあるのでいいんですけど、リリース前にエンジニアが辞めるなんてこともあったりして、その場合はなお悲惨な状況になるわけです。



何もしていないのにトラブルが直る


トラブルが発生して様々な調査にかなりの時間を費やしたにもかかわらず、原因が特定できずに途方に暮れている中で、特にシステムに変更を加えたわけでもないのに突然問題が解決するということがあったりします。
結局何をしたのが原因か、どこに問題が起きたのかわからず担当者はみな狐につままれた気持ちになるわけですが、調査も行き詰まりを見せると「タイミングの問題かね」なんてわけのわからない言葉でトラブルを闇に葬り去ろうとしたりします。

まぁ、逆のパターンの「何もしていないのにトラブる」というのは大体何かをしている場合で、まずいことを起こしたユーザーはたいてい「何もしていない」ととぼけられたりするわけですけど、ログとか追っていると明らかに何かしている痕跡がでてくるわけで、そういった無駄な調査に多くの時間を取られて疲労感いっぱいになったりもするわけです。



トラブルは連続して起きる


一つのシステムトラブルでいっぱいいっぱいになっている最中、別のトラブルに巻き込まれるといこともよくあり、なんで今日に限ってこれが起きるのかという気持ちになったりします。

こういうのはシステム間で全く無関係のように見えて実は関連性があるものであったりもするのですが、連続して全く別物のハードウェアが相次いでお亡くなりになるということもあったりして、凄惨を極める一日になったりすることがあります。

まぁ、炎上しているプロジェクトの場合で課題が次々と発生するのと同じことではあるんですけど、連続してトラブルが起きると担当が不足することもあり、関係ないシステムトラブルの対応に巻き込まれたりしてエンジニアが相次いで倒れる状況に陥ったり。



帰る頃にトラブる


さて、そろそろ帰るかと思ってたらシステムトラブルに関するアラートメールが発砲されてきたり、ユーザーから電話がかかってきたりすることもよくあることです。

24h/365dなサービスが多くなる中でシステムトラブルの時間を選ぶことなんてもちろんできないわけですけど、対応する側としては日中帯に起きてくれれば多くの時間が取れたのにという気分にもなったりします。

これがハードウェアの問題になってくると保守業者へ連絡して対応を待ったり、遠隔地に機材がある場合はそこへの移動を考えなくてはならなくなり、終電のことが頭をよぎったりしてどこまでを今日中にやるかという時間との別の戦いも始まります。

トラブルが起きたのがよりによって平日日中帯のサポートしか受けれない保守契約だったりして途方に暮れることもしばしばあります。



まとめ


まぁ、要は間が悪いときに限ってトラブルが起きるというものなんですけど、中の人にとっては結構なんでこのタイミングでその問題が起きるの?って気持ちになるわけです。

どこまでリスクヘッジをしておくかということでもあるわけですけど、可能性としては低いであろうことが当然のように起きたりします。

まぁ、そのリスクヘッジにかけるコストも当然捻出できなかったりして余計に頭を悩ませることになったりするんですけどね。





ヘルプデスクという組織運営に関する考察

$
0
0

情報システム部門として社内の様々なサービスに対して社員から問い合わせ対応を行うようないわゆるヘルプデスク業務というのは欠かせないものとなっています。

自分はヘルプデスクというのはそんなに経験があるわけではないですけど、同じシステム部門に存在するものとして、また第三者視点でヘルプデスクを見ているとこういう風にしたらいいのにな、と思うことはよくあります。



ヘルプデスク業務は現場に委任したほうがいい


ヘルプデスクというのは、現場の人から何か不明点や困ったことへの問い合わせに対して応じるもので、そのサービスへの知識や理解もさることながらコミュニケーション能力というものが高く求められたりします。


ただ、このコミュニケーションというのは結構厄介なもので、ヘルプデスク側の人間もいろんな人がいるわけですから、当然品質は一定はしませんしやり取りする情報の中で傍目から見ていたらものすごく気になる細かい点がいっぱい出てくるわけです。

ここで、マネジメントする側がそのやり取りに介入して一つ一つ指示を与えるようなことをするケースが見受けられたりするんですけど、こうなってくるとマネジメント側がかなりボトルネックになってきますし、そんなことやるぐらいなら最初から自分でヘルプデスクやればいいのに、となったりします。

こうなると現場への介入ばかりしだして、マネジメント側が本来やるべき組織運営がおざなりになり、いつまでも現場は苦しい運用を続けなければなりませんし、メンバーのモチベーションも上がることはないのだろうと思ったりします。


もう1点、その品質を担保するために細かなマニュアルを作成して現場に配るようなケースもあったりするのですが、サービスは日々変化していくのでそのうちマニュアルが陳腐化していきますし、そもそもマニュアルを見ないと対応できないような人員ばかりが育ってしまい、後々組織として成り立たなくなることもありえます。

マニュアルなんか作らなくてよいというわけではないのですが、そういうものに注力するよりはヘルプデスクとしての指針を共有したり定期的な勉強会などを開いてメンバーのスキルアップを図っていったほうが長い目で見て効果がでてくるのでは、と思ったりします。



ヘルプデスクはエンジニアがやらないほうがいい


極端な言い方をすれば、ヘルプデスクにくる問い合わせというのはトラブル系を除けば、何らかのサービスに問題があるというものになります。

使い方がわからない、マニュアル通りにしてもうまくいかない、次に何をすればいいのかわからない、(サービスの仕様により)使えなくなってしまった、などなどサービス側でそれらがすぐにわかるのであればユーザー側もわざわざしたくもない問い合わせをする必要性もなくなります。

ですので、それらの意見・問題点を集約することでサービスの品質改善につなげていかなくては永遠にヘルプデスクへの問い合わせは減りません。


システム部門にヘルプデスクが必要な理由はユーザーを助けるという名目よりも、サービス品質向上に向けての位置づけでなくてはならないと考えています。

システム部門としては、サービスにおける問題点を集約するというよりは、それを解決することに注力しなければならないわけで、こうなってくるとヘルプデスクという存在自体をシステム部門で抱える意味が薄くなってきます。


ヘルプデスク業務をアウトソースするほど予算もないし、そもそもそんなに規模も大きくないから、という理由でシステム部門で開発者自身がヘルプデスクを兼任するようなケースというのは少なくないと思いますけど、こうなってくるとサービスと密接になっているため、適切な判断が取れない場合があります。

要は問い合わせというのはある種クレームというのも内包されているため、自身が運営するサービスにたいして意見をされるのは気に障るエンジニアとかも多いですし、進捗している案件に時間が取られるためにヘルプデスク対応に億劫になるケースがあります。


しかし、ヘルプデスクというのはサービス品質向上に向けて貴重な意見を集約できる組織体でもあるわけですから、エンジニアとの体制をうまく構築することで、その意見をサービス向上につなげるスキームを作ることもできます。

ですから、そのユーザーからの意見をエンジニアがダイレクトに受けるよりは、ヘルプデスクというクッションを挟むことで、サービスの良しあしが客観的にわかるようにもなるわけです。



まとめ


簡単に言ってしまえば、ヘルプデスク自体を現場主導としたチームで運営し、そこで集約したユーザーからの意見や現場でのノウハウというものをうまくサービス改善につなげていくような体制作りが必要なんだなと感じているわけですけど、実際のところはクレーム処理を押し付けられていたりと、ヘルプデスクの現場にもユーザーにも運用回避する手段を押し付けているようなのが現状だったりもします。


組織の上の人たちも、このヘルプデスクという業務の必要性は理解しているものの、その存在価値や活用方法というのはあまりわかってないのではないでしょうか。

問い合わせの件数というのは定量的に推し量ることが簡単ではあるのですが、それがサービス改善にどう結び付いたのかという効果を推し量るのはなかなか難しいことで、実際にヘルプデスクの現場から生まれた改善であることを明確化したり、その効果を測定する仕組みを用意することで組織としての存在価値を認めてもらう必要性があると感じたりしています。





PHPで簡単に日付操作ができるライブラリCarbon

$
0
0

アプリケーション上、日付を扱うことというのはかなり多いと思いますが、日付の比較やN日後の取得などその操作は結構面倒だったりもします。

Carbon はそういった日付操作を容易に行うことができるライブラリとなっており、導入もcomposer経由で簡単にできます。



Carbonを使ってみる


導入は、公式サイトに記載のとおりcomposerコマンドからインストールすることができます。

composerの使い方などは「[Composer] PHPのパッケージ管理にComposerを使う 」を参照。

Carbon自体はPHPのDateTimeクラス を継承する形で作られています。


<?phpnamespace Carbon;use Closure;use DateTime;use DateTimeZone;use DateInterval;use DatePeriod;use InvalidArgumentException;- snip -class Carbon extends DateTime{- snip -

Carbonクラスはその中に定義されているstaticなメソッドやアクセサを使って操作します。


<?phprequire 'vendor/autoload.php'; use Carbon\Carbon;// 2016/03/03のオブジェクトを生成$cb = Carbon::parse('2016-03-03 12:30:45');// 2016年03月03日 12時30分45秒を出力// フォーマットの書式はPHPのdate()と同じecho $cb->format('Y年m月d日 H時i分s秒');// 個別に年月日時間を出力したい場合echo $cb->year . "/" . $cb->month . "/" . $cb->day . " " . $cb->hour . ":" . $cb->minute . ":" . $cb->second;// 1日後を表示(2016/03/04)echo $cb->addDays(1)->format('Y/m/d');// (この時点で2016/03/04となっているため注意)1週間前を表示(2016/02/26)echo $cb->addDays(-7)->format('Y/m/d');// (この時点で2016/02/26となっているため注意)1ヶ月後を表示(2016/03/26)echo $cb->addMonths(1)->format('Y/m/d');

Carbon::parseにて、引数にセットしたい日付(引数無しの場合は今現在)を渡します。

表示したい場合は、formatで整形して出力といった具合です。

addDaysやaddMonthsなど(addYearsもある)でN日前後、Nヶ月前後を取得することが出来たりします。

Carbon::createにてクラスオブジェクトを生成することもできますが、こちらは引数に年月日を個別に渡すやり方になります。


$cb = Carbon::create(2016, 3, 3, 12, 30, 45);echo $cb->format('Y/m/d H:i:s');

DBから取得した値をCarbonに渡すといった場合は、Carbon::parseのほうが便利かもしれません。

特徴的なのは、日付の比較などが簡単に行えることです。


// 2016/03/12の日付$cb1 = Carbon::create(2016, 3, 12, 0, 0, 0);// 今現在の日付$cb2 = Carbon::today();// 現在のコピー$cb3 = $cb2->copy();if ($cb1->eq($cb2)) {    echo "日付は今日です";} elseif ($cb1->lt($cb2)) {    echo "日付は過去です";} else {    echo "日付は未来です";}// 1週間以内の日付かをチェックするif ($cb1->between($cb2->addDays(-7), $cb3->addDays(1))) {    echo "日付は1週間以内です";}// 1週間前からの日付差(7)を取得echo Carbon::now()->diffInDays($cb2) . "日間の差があります";

eq(同一かどうか)、ne(同一ではないか)、lt(より小さいか)、gt(より大きいか)といった日時の比較や、betweenで指定の期間内かをチェックしています。

その外に、diffInDaysで日付差、diffInHoursで時間差を取得するといったことも出来ます。


また、その外に大きな特徴としてシステムの時刻を特定の日付にしてしまうということが出来ます。

これは例えば、未来の出来事でその処理が正常に行われるかのテストをしたいといった場合にとても便利です。


// 今日(2016/03/16)を表示echo Carbon::now();// 未来の日付(2020/04/01)をテスト的にセットCarbon::setTestNow(Carbon::createFromDate(2020, 4, 1));// 2020/04/01となっているecho Carbon::now();$cb = Carbon::today();// 2020/05/01を取得できるecho $cb->addMonths(1)->format('Y/m/d');

日付操作を全てCarbonに統一しておけば、設定の切替だけでテストが行えそうです。


このように、日付や時間を簡単に扱うことができるので、煩わしい日付操作をCarbonに任せてしまっても良いのではないでしょうか。

その他にも便利なメソッドも用意されているので、マニュアル も参照してください。





慣れの問題という問題

$
0
0

新しくなったアプリケーションに触れたときにたいていの人は「使いづらくなった」という言葉を口にするわけですが、確かに使いづらくなっているというパターンも存在するものの、普段使っている操作から変わってしまったことへの不満からきている場合も多かったりします。

またあれこれ操作方法を覚えないといけないとか、あの機能を使うにはどこへ行けばいいのかわからないといったマイナスの印象が大きく出てしまうわけですけど、つまりは慣れてしまえば気にならなくはなるというものであったりもするわけです。

この慣れの問題というのは結構厄介で、ユーザーが受け取る第一印象によって必ず出てしまう不満の一つでもあります。



欠落してしまう客観的評価


もし、初めて使うアプリケーションやデバイスなどを評価してほしいといった場合、ユーザーは冷静に幾つかの対象を比較することはできると思います。

A案とB案のUIのどちらがよいか、製品Xと製品Yはどちらが優れているかなど、客観的意見をもって判断を下すことができるわけですけど、普段使っているものを大きく変えるとなると、たとえそれがより良いものになっているとしても、大抵は反発が起きたりします。


それは、よりよいものになった印象よりも、自分的にベストにカスタマイズしている、または長い時間をかけて覚えたスキルや知識を台無しにされてしまうということへの嫌悪感があるからかもしれません。

だから、大きなバージョンアップの直後は不満が続出したりもするのですけど、こういった慣れれば済む問題というのはユーザーに向けてそれを声を大にしていえるものでもなく、時間をかけて浸透を待つしかないわけですけど、その過程で最初の不満の多くは忘れられていったりもします。

ただそれが良いわけでもなく、本来評価してほしいところを冷静に判断してもらえず、ユーザーが内心を思っている確実に悪くなっている点も同様に忘れられてしまうのが厄介な問題だったりします。


つまりは、サービス改善後のユーザーの意見というのは、単に変わってしまったことへの不満が大きいだけの場合もあったりして、どの点が前回より評価として低くなったのかということを集約しづらく、またサービス改善から一定の時間が経過してしまうと、前の状態や操作性を細かく覚えているユーザーも少なくなり、これまた評価を得にくい状況になってしまうということです。


また、ユーザーがサービスや操作性に慣れるその習得スピードとサービスの改善スピードが比例しない場合も多く、大きなサービスであれば機能改善というのは小さな変更を積み重ねて徐々に変化させて行ったりもするわけですけど、それがどこかで限界を迎え大胆な改善に踏み切り、ユーザーの不満を買ってしまうというニュースなどで話題になったりします。

この辺りはサービスの流行りなどもあって、新規ユーザーの獲得と既存ユーザーの満足度の向上などが相容れない関係になってしまう例でもあります。



意図しないところで慣れてしまうユーザー


サービスの使い方というのは人それぞれではあるのですが、運営側が「こういう風に使ってほしい」という意図と実際にユーザーが使っている実情というのは結構乖離しているケースがあったり、良くも悪くも本来の使い方とば別のところで盛り上がりを見せたりもあるんですけど、それによってはサービスを改善する妨げになったりすることもあったりします。

ユーザーも悪知恵が働くというか、本質をきちんと理解している人がいて、運営側が「こういう使い方はされないであろう」と思っていても、ユーザーからすれば「やってみたらできたからそういう使い方をしてました」って人は結構いたりするわけです。


こうしてユーザーのサービスの使い方がデファクトスタンダードになって慣れてしまい、ただ運営側が意図しないところであったり本来それは認めていないという理由でそのサービスの使い方を突然禁止とかするとかなり大きな反発を呼ぶことにもなります。

まぁ、これは運営側がそれを予想できてなかったところに非はあるわけなんですけど、社内システムとかにおいてはいろんな禁止事項を掲げる中で、それがシステムの制約として反映できているものとルールで縛るものとがあったりして、ただ後者のものはやれば実際にできてしまうところから、一部のユーザーではその使い方が常態化してしまうケースがあったりします。


また、アプリケーション上の操作というのは最もベーシックな機能から、知っていれば便利というものまで幅広く用意されていたりするわけですけど、最終的に使う機能が同じであろうともそのたどり方や使い方というのはユーザーによって異なってきます。

これにより、ユーザーがある機能を使う際にどういった操作に慣れているのかというのはかなり細分化されてしまうので、特定の機能の改善によって不満を持ってしまうユーザーも多少なりとも必ず出てきてしまいます。

この辺はユーザーのアクセスログなどから統計が取れるのでどういった操作が最も一般的なのかを洗い出して改善における影響度を調査していけばいいわけですけど、意図しない使われ方が定常化してしまうと、ユーザーの慣れが邪魔してそれを受け入れがたくしてしまったり機能を変えることが難しくなることになってしまいます。



まとめ


ユーザーが慣れているというのは、それだけよくサービスを利用してくれているという裏返しでもありますから、それを変える場合はかなり慎重にやっていかないと不満を持つ人も増えてしまいます。

また、不満が出た際にその本質の不満を掘り起こす作業というのは結構根気がいる作業となり、単に機能が変わったから使いづらいという意見だけでなく、なぜ今の機能じゃダメなのかを探っていく必要が出てきます。

逆にその不満を放置してしまい、しばらくたつとユーザーが何も言ってこなくなったから「これでよかったんだ」という盲目的になってしまうのも怖いところではあるんですけどね。





強いカラダ・ココロ・アタマをつくる はたらく人のコンディショニング事典

$
0
0

強いカラダ・ココロ・アタマをつくる はたらく人のコンディショニング事典 (ビジネスライフ)/著者不明
¥1,598
Amazon.co.jp


昔は健康のことなんてこれっぽっちも考えていなかったんですけど、歳を取ってくるとやはりそうもいかないわけで、別に健康志向というわけではないんですけど「なんか体が重い」とか「体調が悪くなることが多くなった」というようなことが実体験として出てくるのでどうしても考えたくもなったりもします。


この本では体調管理のための食事や体の鍛え方に加えて頭の鍛え方として記憶力や能力を最大限引き出すための生活習慣、メンタルの鍛え方やポジティブ思考の作り方などにも触れられています。

食事やダイエット、睡眠のことなどにも触れられているので悩んでたり興味を持つ人は多いんではないかなと思います。

「あーそれ聞いたことあるわ」ってこともあるんですけど、科学的な解説もきちんとされていて理由もわかって納得しならが読めるのではないかと思います。


やはり歳を重ねると若いころのような勢いで一日を押し切ることも難しかったりしますし、その日の体調が仕事のパフォーマンスに与える影響ってかなり大きくなってきたりもします。

ただ、健康って歳のせいというよりはそれまでの不摂生や健康に対して正しい知識を持っていないことの積み重ねが体にのしかかってきて発生するんだなとか思ったりもします。

ってことで、正しい知識をもって生活習慣を改めて見直してみて自分のパフォーマンスを高いところで維持し続けられたらなと読み終わって感じています。



目次


第1章 カラダを鍛える37のヒント1 疲れはどこからやってくる?2 目の疲れをとる3 休日の寝だめに効果はあるのか4 いったい何時間睡眠がよいのか5 睡眠の質を上げる方法6 徹夜明けや睡眠不足な1日の乗り越え方7 あなたは朝方体質?それとも夜型体質?8 日の光を浴び、体内時計をリセットする9 美容・健康・快眠に重要なメラトニン10 気持ち良く眠りにつくには11 体温をコントロールして眠りを操作する12 寝不足は肥満のもと13 ビタミンB1をとって疲労回復14 二日酔いにならない飲み方15 二日酔いになってしまったときの対処方法16 夏バテ対策17 夜遅い食事は肥満と疲れのもと18 早食いの人は肥満になりやすい19 水はたくさん飲めば飲むほど体にいい?20 胚芽米でかしこく栄養をとる21 「ローフード」をとり入れてみる22 日本食には健康的な欠点がある23 「食物不耐症」を知る24 禁煙ができない人は・・・25 簡単栄養バランスチェック26 忙しいビジネスパーソンの外食メニュー27 「歳のせいかな」と考えてしまいがちなこと28 コーヒーは身体にいい29 ファーストフードは食べ過ぎない30 油について正しい知識を持っておく31 いくら食べても太らない体になりたい32 鍛えていく体の順番33 上半身を鍛える34 美しい姿勢をキープするには35 「超回復」を利用する36 つらい腰痛解消方法37 肩こり解消法第2章 アタマを鍛える21のヒント1 前向きな考えが脳を活性化する2 イメージトレーニングのすすめ3 良い恋愛・付き合いは脳の処理能力を上げる4 「ながら活動」は脳を疲れさせる5 感謝の気持ちが脳機能を上げる6 アウトプットで記憶力が増す7 家事で脳を鍛える8 直観力を磨くには9 身の回りを整理することで、脳を整理する10 情報のインプットと記憶の定着11 脳の疲れを取り、眠気をなくす12 上手な仮眠のとり方13 睡魔に打ち勝つ14 睡眠不足がイライラをつくる15 短時間睡眠を続けると・・・16 午前中の仕事能率は朝食で決まる17 理想の朝食メニュー18 アミノ酸でやる気と集中力を高める19 自分の身体や気持ちの状態に気づく20 身体疲労と脳疲労の違い21 脳はいくつになっても成長できる第3章 ココロを鍛える16のヒント1 感情の整理には香りが効く2 歌うことには心の浄化作用がある3 気晴らしや快楽とは適度な距離で付き合う4 笑顔が感情を整える5 緊張状態を和らげる6 深い呼吸で心を落ち着かせる7 自律訓練法8 筋弛緩法9 ABCDE理論10 「いい人」をやめてみる11 責任感も他人からの評価も7割くらいがちょうどいい12 「メンター」と「ウィーク・タイズ」に相談をする13 やる気を出す目標の立て方14 やる気物質、ドーパミン15 最も効果的なストレス発散法16 イライラやクヨクヨがなくなる方法


Viewing all 287 articles
Browse latest View live