WordPressのWindowsクライアントを試してみた

お久しぶりです、10年振りの投稿です。10年前はWindows Live Writerを使ってブログを書いていましたが、今はブラウザ版Wordpressのエディタ機能がかなり進化しているので、昔のような画像が貼りにくいとか、タグを細かく編集したいとかで困ることはなくなりました。

どうしてもブラウザとは別のウィンドウで記事を書きたい人なので、Windows版クライアントを試してみました。

ダウンロードはこちら(https://apps.wordpress.com/ja/)から

仕組みは、Electronなのかな、Slackなどのようにブラウザ版とWindowsクライアント版とあるように機能に差はありません。(少し使ってみた感じ差はわからなかった)使い分けは好みの問題だと思います。

ブラウザ版のエディタが快適なので、Windowsクライアント版の需要がないためか、検索しても意外と引っかからないので、記事にしてみました。

Selenium Web Driverでスマホ用Webアプリのテスト(2)

今回はSelenium Web Driverを使用してChromeのUser-Agentをスマホ(iPhone, Android)に設定してWebブラウザを自動操作するC#のサンプルプログラムを紹介します。

1.ソリューションの作成

何はともあれ、まずはVisual Studioからソリューションを作成します。とりあえず「コンソールアプリケーション」として作成します。

2.Selenium Web Driverのインストール

Nugetから必要なモジュールをインストールします、[ツール] – [ライブラリパッケージマネージャー]-[パッケージマネージャーコンソール]から以下のコマンドを実行します。

Install-Package Selenium.WebDriver

3.Selenium Chrome Driverのインストール

Chrome DriverはNugetで公開されていないので、Webからダウンロードする必要があります。以下のURLで公開されているので、「selenium-dotnet-X.X.XX.zip」(2012/12/22時点で2.28.0)をダウンロードします。

http://code.google.com/p/selenium/downloads/list

4.chromedriver.exeをプロジェクトに配置

ダウンロードした「selenium-dotnet.X.X.XX.zip」を解凍すると「chromedriver.exe」が展開されるので、プロジェクトに含めます。そしてビルド時に出力ディレクトリにコピーされるようにします。

image

5.Chrome起動

Chromeを起動するプログラムを記述します。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using OpenQA.Selenium;

using OpenQA.Selenium.Chrome;

 

namespace SeleniumChromeSample

{

    class Program

    {

        static void Main(string[] args)

        {

            IWebDriver browser = new ChromeDriver();

            browser.Url = "http://www.google.co.jp";

        }

    }

}

ほぼ説明は不要だと思います。ChromeDriverのインスタンスを生成して、Urlプロパティに表示したいUrlをセットするだけです。ChromeDriverのインスタンス生成時にブラウザが起動し、Urlプロパティを変更した時点で画面遷移が行われます。

5.Chromeをスマホとして起動

最後に、ChromeのUser-Agent文字列をAndroidに設定して起動します。例としてGALAXY NEXUSとして起動させます。

static void Main(string[] args)

{

    var option = new ChromeOptions();

    option.AddArgument("–user-agent=\"Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\"");

 

    IWebDriver browser = new ChromeDriver(option);

    browser.Url = http://www.google.co.jp;

}

ChromeOptionクラスのAddArgumentにUser-Agent文字列を設定し、ChromeDriverのコンストラクタにChromeOptionを設定します。iPhoneの場合は以下の文字列を設定しします。

Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3

このプログラムを実行すると、以下のようにモバイルモードでGoogleトップページが表示されます。

image

今回作成したサンプルコードは、こちらで公開しています。次回はテキストの入力、オブジェクトのクリックなどの操作を行っていこうと思います。

今回のブログエントリの作成にあたって、Selenium Web Driverの情報は以下のサイトを参考にさせていただきました。

http://www.slideshare.net/odashinsuke/selenium-webdriver-12311228#btnNext

http://www.storklab.com/seleniumhq.org/docs/03_webdriver.html

http://d.hatena.ne.jp/suzukij/20110828/1314549996

Selenium Web Driverでスマホ用Webアプリのテスト(1)

この頃、ブラウザを自動操作したい需要が自分の中で高まりつつあります。ただ、スマートフォン向けのコンテンツなのでIEのようにUser-Agentを変更できないブラウザではためなんですよね。普段はChromeの[F12] – 右下の設定アイコンからブラウザのUser-Agent文字列を変更してテストをしています。

clip_image002

ブラウザを自動操作するといえば、自分の中ではWatin(http://watin.org/) なのですが、2年弱(最新Ver2.1のリリースが2011年4月)開発が止まっていたり、Chromeは正式に対応していなかったりと、ちょっと利用するにはためらう状況です。しかも、「Watin」で検索すると自分のブログが上位にヒットするという、悲しいほど日本語の情報がありません。

じゃ、どうするかということでいろいろと探した結果、Selenium Web Driverを使用することにしました。Selenium自体は、以前からWebアプリケーションの自動テストツールとして有名でしたが、Version2からは複数のプログラム言語、複数のブラウザに対応しています。

詳しくは、以下の@ITの記事が参考になると思います。

iPhone/Android含むブラウザ自動テストの最終兵器Selenium WebDriverとは (1/2)

基本情報をまとめると、以下の通りです。

  • プログラム言語:Java, C#, Ruby, Python
  • ブラウザ: IE, FireFox (ドライバのダウンロードが必要Chrome, Opera) (SDKのインストールが必要: Android, iOS)

次回は、Chrome Driverを使用してUser-AgentをiPhone/Androidに設定してスマートフォン向けコンテンツを自動操作する方法を紹介しようと思います。

Android4.0→Android4.1→Android4.2(3)

前回前々回とAndroid4.0~4.2に関するエントリーを書きました。最後は、Androidの抱える癌の部分である、断片化について紹介しようと思います。

機種依存

Androidアプリ開発者にとっての最大の悩みです、OSのバージョンが同じでも解像度が異なっていたり、同じOSのバージョンでもメーカーがカスタマイズをおこなっているため挙動が異なったりということはよく聞きます。仕事でWebアプリの開発をしていますが、同じOSのバージョンの標準ブラウザであっても描画や挙動が異なったりします。このようにAndroid向けの開発を終了する事例もあります。

「Androidはもうからない」――人気ゲームメーカーが開発終了を発表

同じAndroidでもいかに多様化しているかが、この記事からもわかると思います。

Android用アプリ開発が難しい原因が機種数の多さによる断片化であることがよくわかる図

ネットでいろんなサンプルコードが公開されているので、エミュレーター上で動作するAndroidアプリを作成することはそれほど難しいことではありません。ただ「多種多様なAndroid端末で動作するアプリ」を作ることが非常に困難になっています。

Androidのアップデート

スマートフォンはガラケーと異なり最新版にアップデートすることができるといわれていた時期がありましたが、Androidに関して言えばそれは幻想です。アップデートを受けられるのは最新機種とNexusシリーズのみです。

例としてdocomoがAndroid 2.3→4.0へのアップデート可能端末を公開しているので、それを例に見てみます。

【Android(TM)4.0 へのバージョンアップ】今後の提供時期および提供中の製品について

こうやって見るとたくさんの機種がアップデート可能なように見えますが、2011年夏モデル(SO-02C, SH-12C など)は軒並みアップデート対象外になっています。iPhone 3GSがiOS6に対応しているのとは非常に対照的です。つまり、Android 4.0リリース後に発売された機種しかアップデートを受けられないということになります。裏を返せば、

「最新端末で、古いバージョンのOSを搭載した機種であればアップデートを受けられる」

「最新バージョンのOSを搭載した機種であればアップデートを受けられない」

ということになります。確かに、まだ発表されていないOSにアップデートできる端末を世に出せるとは限らないというのが現実なのでしょうが、アップデートを受けるためには古いバージョンのOSを選択するというのは皮肉です。

最新OSの機種がリリースされない

Androidは最新バージョンのOSがリリースされてからメーカーが対応端末の開発を始める印象があります。そのため、Googleが最新OSを発表してから、端末がリリースされるまでに半年近いタイムラグが生まれます。これも発表と同時に最新バージョンのOSが利用できるiOSとは非常に対照的です。OSのリリースと、docomo端末のリリースのタイムラグは以下の通りです(たぶん)。

OS OSリリース 端末リリース アップデート
Android 2.2 2010年5月 2010年10月(GALAXY S) 2011年5月(T-01C)
Android 2.3 2010年12月 2011年3月(Xperia arc) 2011年6月(GALAXY S)
Android 4.0 2011年11月 2011年6月(SH-07D) 2012年8月(GALAXY SⅡ)

多種多様なバージョンが混在する

アップデートが絶望的で、なかなか最新OSの機種がリリースされないということは、さまざまなバージョンのAndroidが混在するという結果になります。2012年12月時点で、メジャーバージョンで2.1, 2.2, 2.3, 4.0と4つのバージョンのAndroidが存在することになります。しかも今後減ることはなく、4.1, 4.2 の端末がリリースされれば、世界に存在するAndroid端末のバージョンの種類はどんどん増えていきます。それが、Androidアプリ開発者の負担になっていきます。

リファレンスモデルが「例外」

日本で唯一正式に発売されているAndroidのリファレンスモデルであるGALAXY NEXUSは「例外」扱いです。アプリであったりサービスの対応機種に

「対象外機種: GALAXY NEXUS(SC-04D)」

とよく記載れています。

たとえば: 「AKB48ステージファイターの対象機種を教えてください」とか。

docomoの正式サービスまで対象外機種になってしまい、こんなブログ記事が書かれることも。

Galaxy Nexus(SC-04D)でしゃべってコンシェルを使う方法

挙句の果てには、悪名高いSPモードメールから、Gmail風のクラウドメールへ改めた「ドコモメール」のサービスを開始しますが、堂々と「GALAXY NEXUS SC-04Dは利用できない」と。

「spモードメール」がクラウド化し「ドコモメール」に改称

Googleが公開しているAndroidは「純正Android」ですが、キャリアのカスタマイズが入っていないためキャリアのサービスが受けられないという不思議な状況になってしまっています。

これまで話してきたAndroidの癌の部分を図にしてみるとこのようになります。この「機種依存」の先には、「アプリ開発者離れ」「Androidの魅力の低下」、「Androidの衰退」と続いていきます。

image

ただ、GoogleもこのカオスすぎるAndroidの状況をよくないと思っているらしく、Android 4.2 SDK にAndroidの断片化を生じるような行為を禁止しているようです。

グーグル、Android OS断片化の拡大防止のため、SDKに新たな利用条件を設定

ただし、何を禁止しているのかは明確ではなく、すでに断片化したAndroidの状況が解消するには3~4年は必要でしょうから、これからもGoogleと開発者はAndroidの断片化に悩まされることになるのでしょう。

 

Android4.0→Android4.1→Android4.2(2)

前回のエントリーでは、自分の端末のAndroidのバージョンアップを行った経緯について紹介しました。今回のエントリーは新しいバージョンのAndroidを使ってみた感想を書いてみたいと思います。

※ Androidの新機能を全部使っての感想ではなく、普通にスマートフォンとして使用した感想なので、それほどコアな情報は書けないと思いますが

Android 4.0 → Android 4.1

新機能の詳細については、こちらのサイトを参照してください

開発者が知らないと残念過ぎるAndroid 4.1の新機能36選

新機能は盛りだくさんなんですが、個人的にうれしかったのはAndroidそのもの(アプリも)の動作が非常に高速になったということです。はっきりと体感できるレベルで高速化しています、Android上で動作するアプリも確実に高速化しています。Android 4.0 + 1.2GHz(デュアルコア)でもサクサク動いていたんですが、Android 4.1にアップデートすると超サクサクです、アニメーションに頼らなくても鋭利な刃物のように

「シュッ!!」

と鋭く動作します。当時のライバルであるiPhone4Sよりも動作は高速ではないかと思うほどです。(iPhone持ってないので、店頭でホットモックを触った感想ですが) Androidと言えば過剰なハードウェアスペックでサクサクを実現していましたが、ソフトウェアがチューニングされたことでさらに高速な動作を実現しています。

あとは地味に通知バーからメールの返信、音楽の再生などのアクションをとることができるようになったのも地味に便利になりました。

Android 4.1 → Android 4.2

新機能の詳細については、こちらのサイトを参照してください

新タブレット時代を見据えるAndroid 4.2の新機能9選

誰得な新機能が多い気がするのは、自分がマジョリティではない証拠でしょうか。Android4.1で「超サクサク」になった動作が、「ヌルヌル」に変更されました。アプリの切り替えや、ホームボタンを押したときにはっきりとアニメーションを介して

「うにょ」

と動作するようになりました。iOSよりもアニメーションが濃いような気がします。4.1でソフトウェアのチューニングが行われて高速に動作するようになったのに、なぜあんなアニメーションを付けるようになったのか理解に苦しみます。自分はあのサクサクが好きだったんですが...

あと、ロック画面にウィジェットを置けるようになったのは地味に便利です。ロックを解除しなくてもGmailの新着メールの一部を見ることができるようになります。ただ、iOSの通知機能に比べると貧弱です、Androidに早くロック画面に表示される通知機能を...

同一端末で3バージョンのAndroidを使用していると、OSの進化を体感できて楽しいです。必ずしも自分にとってメリットが最大化される進化とは限りませんが。

Googleが公開しているファクトリーイメージを適用したデメリット

最後に、プリインストールされたAndroidからGoogleが公開したファクトリーイメージに入れ替えるといろいろデメリットがあります。基本的にdocomoのサービスの設定が消えるので、メール・留守電は0から設定が必要です。

そして、トラブルがあってdocomoショップに持って行ってもAndroidを入れ替えたことがばれるとサポートを受けられない可能性があります。自分はAndroid4.1にした後にガラケーから電話帳を移行しようとdocomoショップで電話帳移行ツールを使いましたが、うまく移行できませんでした。docomoショップのお姉さんにサポートを依頼すると、Androidを勝手にアップデートしたことがばれましたが、1件1件手動でコピーしてくれました。他のショップスタッフだと断られていたかもしれません。

あと、spモードのプッシュ受信ができなくなります、手動で受信すればいいんですが。「WAPPushManager.apk」を導入することでプッシュ受信ができるようになるみたいですが、自分の環境ではどうしてもできませんでした。なので、spモードは解約しました。

Android4.0→Android4.1→Android4.2(1)

自分の携帯はSC-04DことGalaxy Nexusです。2011年11月docomoが世界(ほぼ)初のAndroid4.0端末として渾身の力を込めて発表/発売したのに、一部のガジェットヲタクにしか売れなくて期末に信じられない価格で(機種変で1万切る)投げ売りした、docomoにとっての黒歴史端末です。

Nexusシリーズの端末ですから、新しいAndroidのバージョンがリリースされれば当然すぐにアップデートできると思っていました。2012年6月にAndroid4.1が発表され、7月半ばからOTAアップデートが開始されました。が、docomoの端末にはアップデートは提供されませんでした。Googleが新しいAndroidをリリースしても配信するかどうかはキャリアが判断するので、アップデートを受けることができませんでしたし、いつ受けられるのかの発表もありませんでした。

そんな時にビッグニュースが

Google、出荷状態に戻せるAndroid 4.1のファクトリーイメージを公開

GoogleがまっさらなAndroid4.1のイメージファイルを公開しました、docomoのアップデートが待てなかったのでOSを再インストールするような形でAndroid4.1をインストールしました。root化、イメージの移行は「Nexus Root Toolkit」を使用しました。

GALAXY NEXUS SC-04D Android 4.1.1を導入してみる

無事、Android 4.1の導入が完了しました。

Android4.1

11月にはAndroid4.2が発表され、Googleがアップデート用イメージを公開したので、手動でインストールしました。

Galaxy Nexus”takju”をAndroid 4.1.2(JZO54K)からAndroid 4.2(JOP40C)に手動でアップデートさせる方法

無事アップデート完了、Android4.2.1へ

というわけで、今はAndroid4.2.1を使用しています。

docomoは何をしていたかというと、11月にAndroid4.1へのアップデートを提供しています。Galaxy Nexusを黒歴史認定しているので、アップデートは提供されないと思っていたので意外でした。

GALAXY NEXUS SC-04Dの製品アップデート情報

次回は、Android 4.1, 4.2を使用してみての感想を書いてみようと思います。

クラウド環境で処理効率のいいプログラムを実行するということ

2011年5月ころから、1年近く個人的にWindows Azureを使ってきました。趣味プログラマ的な観点ですが、気付いたことを書きたいと思います。
自分が使っていたのはクラウドサービスのWebロール+TableStorageが中心で、作成したWebアプリをアップしていました。ローカルでデバッグした後にデプロイして思うことはいつも

遅い

です。何せXSインスタンスを使っていたので、スペックがあまりよくないんですよ。もちろん自分のプログラムが悪いこともあるんですが、ローカルに比べてハードウェアスペックに差がありすぎるので、明らかに遅いと感じてしまいます。ちなみにローカルとXSインスタンスの簡単なハードウェアスペックを記載しておきます。

ローカル
CPU: Core i5-520M 2.40GHz (2コア×2スレッド)
Memory: 8GB
SSD 128GB

Azure XSインスタンス
CPU: 1.0GHz(コア共有)
Memory: 768MB
ストレージ 20GB(I/Oパフォーマンス低)

ちょっと重めの処理をローカルで実行してそれなりのスピードがでて「何とかなるかな」と思ってデプロイすると、レスポンスが返ってくるまでに秒単位の時間がかかったりします。とくに、LinqでTableStorageにアクセスするときに遅延評価のことをすっかり忘れていて、ループの中で何度もTableStorageにアクセスしてしまうと遅くてイライラします。なので、Azureにアップするアプリは自分なりに効率性を考えてプログラミングをしていました。この時代にXSインスタンスのようなハードウェアスペックのサーバーで動作するプログラムを書くというのはいい経験になりました。とくに意識したのは以下の2点です。

Linqの実行タイミング
Linqは遅延実行されます、メソッドの行を通ったタイミングではなくIEnumerable<T>オブジェクト以外の結果が必要になった時に実行されます。
たとえば、以下のようなデータベースやストレージにアクセスするコードを書いたとします。
var hogeList = Db.HogeTable.Where(x => x.Code == code);

foreach(var h in hogeList)
{
    Console.WriteLine(h.Name);
}

ぱっと見、1回のアクセスを行っているように見えますが、ループの回数分アクセスが行われます。メモリ内のコレクションに対するアクセスであればそれほどパフォーマンスに差が出ませんが、外部ストレージ(SQL Azure/Table Storage)へのアクセスの場合一気にパフォーマンスが劣化します。自分が一番ハマったのもこのパターンです。アクセスを1回に抑えるためには、Whereメソッドの後にToListやToArrayなどで、データの型を確定させる必要があります。

Linqの細かいことはこちらの@ITの記事を参考にしてください。
LINQの仕組み&遅延評価の正しい基礎知識
http://www.atmarkit.co.jp/fdotnet/chushin/greatblogentry_06/greatblogentry_06_01.html

外部ストレージへのアクセスタイミング
1つめと関連する内容ですが、1回のアクセスで大量の件数のデータを取得する方が速いのか、1件のデータを複数回のアクセスで取得する方が速いのかです。具体的には
・1回のアクセスで多めにデータを取得し、ループではメモリにのみアクセスする
・ループの中で都度データを1づつ取得して処理を行う
のどちらが速いかということです。これはケースバイケースで、しかも実機でしか確認できないので、少し書き換えて何度もデプロイして確認していました。ローカルのSQLServerやストレージエミュレーターでは何度もアクセスした方が速いのに、実機ではネットワークアクセスが伴うので、1回のアクセスで多めのデータを取得したほうが速いことが多かったです。

あと、.NET4から導入されたParallelを使って並列処理を行うと大幅にパフォーマンスを改善できることがありました。特に、単純ループでデータを登録する処理は1ケタ速くなります。1コアのCPUでも並列処理は効果がありました。今見るといい加減なデータの取り方ですが、昨年TableStorageに並列アクセスして高速化に挑戦したブログを書いています。

Azure TableStorageの高速化(2) -処理の並列化-
https://david9142.wordpress.com/2011/10/26/azure-tablestorage%E3%81%AE%E9%AB%98%E9%80%9F%E5%8C%962-%E5%87%A6%E7%90%86%E3%81%AE%E4%B8%A6%E5%88%97%E5%8C%96/

AzureTableStorageの高速化(3) -打倒SQLAzure!!!-
https://david9142.wordpress.com/2011/10/26/azuretablestorage%E3%81%AE%E9%AB%98%E9%80%9F%E5%8C%963-%E6%89%93%E5%80%92sqlazure%EF%BC%81%EF%BC%81%EF%BC%81/

最新のハードウェアでは些細な、ほとんど気づかないパフォーマンス差であっても、低速なハードウェア環境では大きな差になることを身に染みて感じましたし、パフォーマンスを改善するのはなかなか楽しいものです。

最後にプログラムのパフォーマンスとクラウドの関係について考えてみます。オンプレミス環境ではリソース不足を防ぐために余裕をもってハードウェアスペックを調達することが多いです、想定される負荷に耐えられるスペックの1.3~1.5倍とか。そしてハードウェア調達後にプログラムを改修してパフォーマンスを改善して必要なサーバー台数が少なくなると、運がよければ感謝されるかもしれません。ただ、見えないところで

「なんで最初から速いプログラムにしなかったの?」

「誰がこんな余分なスペックを見積もったんだ!」

と揉めることになるかもしれません。そして誰かが責任を取ることになることになるかもしれません。ハードウェア購入費用は返ってきませんから。運用・サポート費用がそれほど変わることも稀ですし。パフォーマンスが悪くてハードウェアを追加購入して増強した後に、プログラムを改修してパフォーマンスが改善した場合はもう目も当てられません、パフォーマンスがよくなったこと自体はいいことなのですが、大惨事です。誰がハードウェア増強の判断をしたのか、もとのプログラムを作ったのは誰なのか、と犠牲者が増えていきます。

そういった経験をすると、別の機会では

「プログラムの改修は必要ない、ハード増強で対応する」

という判断になるのかもしれません。

クラウド環境であれば、必要なサーバー(インスタンス)数が少なくなれば、直接的に運用コストを下げることができます。クラウド環境のメリットにスケールアウトが挙げられることが多いのですが、個人的には一番のメリットはスケールインだと思っています。クラウドのプログラマにとってのメリットは、環境構築・サービスイン後にパフォーマンスを改善してもみんなが幸せになれることでしょう。サービスイン時点で完璧なプログラムを作るのって難しいです、あとから改善して幸せになれることが分かれば、改善しようと努力しますよね。今まで余裕を見てハードウェアスペックを見積もって、処理が非効率であってもハードウェアのパワーに頼って目を瞑ってきたプログラムは結構あると思います。購入後にそのハードウェアが不要になる状況は作りたくないので、あえてパフォーマンスの見直しを行わないプログラムも結構あると思います。

今後クラウド上で動作するプログラムが増えると、こういったプログラムを見直すメリットが増えてきます。また、処理効率のいいプログラムを書けるスキルは運用コストに直接響いてくるので、今まで以上に重要視されるかもしれません。

ASP.NET MVCのクラスの作り方を考えてみた(4)

前回のブログエントリーでUnityでのインターフェースと型のマッピングがC#には書けず、設定ファイルに書かなければならないという内容を書きましたが、実はC#にもマッピングの設定を記述することができます。あまりに自分が無知ですみません。このブログエントリーを見て気づきました。

IoCフレームワーク、クラスとConfigファイルの両方から設定する (miso_soup3さん)

設定方法は、UnityContainer.ResisterTypeでインターフェースと型を登録します。C#で設定を行うのでintellisenseが効いてタイプミスを防ぐことができます。Global.asax.csのApplication_Startにはこのように記述します。UnityContainer.LoadConfigurationをコメントアウトしているのは、設定ファイルを作成しているとこのメソッドを呼び出した際に設定が上書きされてしまうためです。

IUnityContainer container = new UnityContainer();

 

// Unity用マッピング設定

container.RegisterType<IHogeWorkerService, HogeWorkerService>();

container.RegisterType<IHogeDao, HogeDao>();

//container.LoadConfiguration();

 

IDependencyResolver resolver = new UnityDependencyResolver(container);

DependencyResolver.SetResolver(resolver);

 

C#でUnityのマッピング設定を行うことができることがわかったので、もう使わない手はないですね。DIなしで単体テストを行うなんて狂気の沙汰ですから。(単体テストを行わないなんてもっと 以下略) #if debugを使用すればテスト用とRelease用の設定も分けることが(たぶん)できるでしょうし。やっぱり個人的にはUnityを使う場合はC#でマッピングの設定を書きたいですね、設定ファイル地獄はC#の文化には合わないと思います。

今回はUnityをテーマに書きました。作成したソースはSkyDriveにアップしてあります。「MvcHogeApp_v4」をダウンロードしてください。サイズを抑えるため、アセンブリ類は削除してあるのでVisual Studio 2012 Express for Webがインストールされた環境で開いてください。

退職しました

7月31日をもって10年勤めた会社を退職しました。8月1日から新しい会社で働きます。

社員数2,000人超の中堅SIerを辞めて社員400人くらいの会社へ転職するので、いろんな方に「もったいない」と言われましたが、自分の中ではこの会社に継続して勤めることがもったいないと感じたので転職することにしました。

前の会社(部署)はゆるくてぬるくてMAXパワーの半分程度を出すと仕事が片付いてしまいます。10年戦士となるとサラリーマンとしての技術的なスキルはピークに達するので、他の人ではできなくても自分ではできることが多くなって評価があがります。あとは管理職になって腹八分目で仕事をしていけばある程度は昇進できるような未来が見えました。サラリーマンですからエンジニアの理想よりも、よりリスクを抑えて利益が大きくなる方法を考えていけばいいんです。新しい技術は趣味程度にさらっと追いかけていけばいいんです、客から言われなければ無理に導入する必要はないんです、必要になれば部下に「やれ!」って言えばいいんです。自分の仕事じゃないし、そのほうがリスクを抑えられる。そうやってあと30~35年サラリーマンをだらだら続けていけば、一応1部上場の企業なのでそれなりに給料がもらえる最後の世代だと思っています。自分たちは海外との競争から逃げ切れる最後の世代だと感じています。

その一方で、社外のエンジニアの方と知り合う、Twitterやブログで一方的に知る機会がこの2年くらいで一気に増えました。外には化け物のような(自分よりもはるかにすごいという意味で)人たちがゴロゴロいることを知りました。また、新しい技術(最近では、Windows Azureの新機能リリースやASP.NET MVC4が中心)に触れる機会が一気に増えました。ブログも自分なりに真面目に書くようになりましたし、勉強会などで発表させていただく機会が何度かありました。おぼろげにVBを書くことしかできませんでしたが、業務経験なしでもVBがすらすら書けるようになりましたし、C#も書けるようになりました。30を過ぎてから新しい技術に追随していくことがしんどくなるのではなく、昔よりも楽に新しい技術を追いかけることができるようになりました。

また、ゴミみたいな人たちを使って自分が最大できることの半分の成果をあげればいい仕事はつまらないということを再認識しました。そうなると人間欲が出てくるもので、こういう化け物みたいな人たちと新しい技術を使って一緒に仕事をしてみたい、と思うわけです。しかも、客から言われたことを濁目で淡々とこなすSIではない仕事を。ドラゴンボール的にいうとナメック星時代のクリリンレベルの自分が、ギニューさんやフリーザ様と一緒に仕事をしてみたいと考えてみたってことです。今の会社に対する不満は百万個や二百万個はあります、ただ、それは些細な話しで退職のきっかけになったわけではありません、些細なネガティブな理由で退職してもいいことはないでしょうから。それよりも、今の会社ではなくほかのSIではない会社を見てみたいということと、サラリーマン11年目の自分の評価を他の会社から聞いてみたいという思いで転職活動を始めました。

今年のGW前に転職エージェントに登録しました、たまたまGWがあったので履歴書・業務経歴書を書くまとまった時間があったのは非常にラッキーでした。GW明けに転職エージェントに合い、こちらの希望を伝えました。

  • PM・コンサルではなく、エンジニア職
  • SIerではない会社
  • C#, ASP.NET
  • Windows Azureとかあったらうれしいな

すると、この条件に合う求人はほとんどないんですよね。「SIerじゃない」という条件の時点で、求人条件はほぼLAMP系になります。思わずTwitterでつぶやきました

「ASP.NET / C# / Windows Azureの求人なんて存在しないze!」

「みんな!転職するならLAMPのスキルを身につけよう!!」

そしたらMSの中の人にDMでフォローされました(笑) 仕方がないので条件に完全に合致しない会社も応募しましたが、案の定、求めるスキルと職務経歴が合わない会社は書類選考で落ちました。面接は選考というよりもほぼ勧誘でした。これまでの業務経歴を簡単に説明することと、向こうからのいくつかの質問に答えるだけで勧誘が始まりますw これからこういうサービス/ビジネスをやっていくから、こういう仕事をして欲しいとか、「フレームワークのソース見る?」とか、採用面接に来ただけの人間(機密保持契約結んでない)にこんなことまで言っていいの?とこっちがドン引きになるくらいでした。自分くらいの年齢の人ってどの会社でも不足してるんですね、世代的には団塊Jrよりも下の世代なのでそんなに多くはないですけど、今の20代に比べれば少なくはないと思うんですが。みんなどこにいるんでしょうね。どの会社も20代後半~30代半ばくらいで指示しなくて黙っていても仕事ができる人って足りないし、欲しいんですね。ちなみに、履歴書・業務経歴書にはざっくりとこんな内容を書きました。

  • 経験年数10年(リーマソ11年目)
  • プロジェクトリーダーを担当することが当たり前ですが何か?
  • ASP.NET, C#できますけど?(たぶん...たぶんできると思う...)
  • 新しい技術好きです、個人的にはASP.NET MVCアツいです

一部経歴を詐称していますが...(だってC#の業務経歴ないんだもん(´・ω・`))できないことを「できる!」と言っているのではなく、できることを「できます!」といっているので(自分の中では)問題ないと思っています(`・ω・´)キリッ。いくつかの会社はとんでもないスピード感で採用を進めてきます、面接が終わって帰宅途中の電車の中で結果通知のメールが来ます。実際には転職エージェントを通じてメールが来るので、面接後すぐにエージェントへ結果を通知していることになります、あらかじめ結果を用意しておいたんじゃないかと思うようなスピード感です。しかも「明日、来れますか?最終面接になります」と。その上、最終面接も帰りの電車の中で結果通知メールが来ることがありました、内定通知書付でw もう、絶対面接前に用意していたとしか考えられませんw 現職(もう退職したので、正確には前職)の会社だったら何度も会議して決めるんでしょうねぇ(遠い目)、どの口が「ビジネスのスピード感を高める」とか言ってるんでしょう...おっと、すみません、愚痴になってしまいました。

転職活動を始めてみたら、2週間くらいで最初の内定がもらえて3週間で応募した会社の全ての面接が完了しました。2001年の新卒採用試験ではかろうじて1社からのみ内定をもらえたのですが、11年後には3週間で3社から内定が出ました。で、そのうち採用のスピード感が最も早い会社に決めました。ASP.NET+C#でのアプリ開発エンジニアという職種になります。

明日から

「わたしの戦闘力は530000です」

という人たちと仕事ができると思うと、本当、ドキがムネムネします。自分ドMなので、フリーザー様のように「このクズ野郎!」とか「この虫ケラが!」と言われるとうれしくなってしまいます。

そんなにたくさんの会社の中を知っているわけではありませんが、SIerって能力のある人にはしんどい環境だと思います。自分が転職することを決めたせいか、濁目・社畜自慢をしている人を見ると「会社辞めればいいのに」と思ってしまいます。会社のグチであったり、「オレはXXXXがやりたいんだ!」と主張する労力よりも採用面接を受ける労力のほうがよっぽど小さいですよ。経験や能力が本当にある人であれば、転職先を選べる環境にあると思います。

7月後半は毎日前の会社の送別会でした、毎日二日酔いで昼間も酔っ払った状態だったかもしれません。10年でいろんな部署をたらい廻しにされたため社内の知り合いが(辞める直前の部以外では)多く、直接会ってごあいさつできない方も何人かいらっしゃいました。送別会では絶対転職先の話題になります、転職先や職種について説明が面倒臭いので、転職先について

「Gで始まる(.NET界隈では)有名(だと思う、ソーシャルアプリを作っている)企業」

と説明して勘違いさせたり。

「次の会社でもSE?」とか訳の分からないことを聞く人もいるので

「次の会社ではピージーです。(`・ω・´)キリッ」

と適当に答えたこともありました。ごめんなさい。

// 自部署の送別会よりも常駐している顧客先での送別会のほうがたくさんの方が参加するのは、よくある話ですよね。

このブログについてですが、平日昼間に満たされない思いをぶつけて書いていました。今後、平日昼間にエンジニアとしての自分が満たされることがあればこのブログは更新されないかもしれません。

ASP.NET MVCのクラスの作り方を考えてみた(3)

何回シリーズになるか分かりませんが、「プログラミング ASP.NET MVC」を読んでASP.NET MVCのクラス構成について考えた記事を書いています。これまで2回書いており、内容は以下の通りです。

第3回目はpatterns&practicesのProject Silkで利用されているUnityを利用したDIについて書きます。Unityは制御の反転(IoC:Inversion of Control)を実現するためのフレームワークです。IoCとはDIの1つ上、抽象化された概念だと思ってください。IoCを実現するための実装の1つがDIになります。(用語や概念を厳密に説明できるほど理解が進んでいないです)詳しいことを知りたい方は、以下のページを良く読んでください。

制御の反転

Unity におけるポリシーの挿入

Project SilkやUnityについてはすでにブログで書いている方がいらっしゃるので、最大限参考にさせていていただきました。

ASP.NET MVC 3 と Unity の組み合わせを試し中 (shibayanさん)

Project SilkにならってUnityを使ってみる (miso_soup3さん)

今回は(2)で作成したソースをUnityに対応させたいと思います。まずはNugetでインストールします。

PM> Install-Package Unity
依存関係 ‘CommonServiceLocator (≥ 1.0)’ の解決を試みています。
‘CommonServiceLocator 1.0’ が正常にインストールされました。
Unity を Microsoft patterns & practices からダウンロードします。このライセンス条項は http://www.opensource.org/licenses/ms-pl で参照できます。固有のライセンス条項がある追加の依存関係がパッケージに含まれていないかどうかを確認してください。パッケージおよび依存関係を使用することで、該当するライセンス条項に同意したものとみなされます。ライセンス条項に同意しない場合は、関係のあるコンポーネントをデバイスから削除してください。
‘Unity 2.1.505.0’ が正常にインストールされました。
‘CommonServiceLocator 1.0’ が MvcHogeApp に正常に追加されました。
‘Unity 2.1.505.0’ が MvcHogeApp に正常に追加されました。

Web.configにインターフェースと実装クラスのマッピング設定を記述します。

<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <configSections>

    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>

  </configSections>

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">

    <namespace name="MvcHogeApp" />

    <namespace name="MvcHogeApp.WorkerService" />

    <namespace name="MvcHogeApp.Models" />

    <assembly name="MvcHogeApp" />

    <container>

      <register type="IHogeWorkerService" mapTo="HogeWorkerService" />

      <register type="IHogeDao" mapTo="HogeDao" />

    </container>

  </unity>

</configuration>

 

Project SilkではWeb.configではなく専用の設定ファイル(Unity.config)にマッピング情報を記載していました。また<register>タグで指定するマッピング情報では名前空間を省略せずに書いてありました。

次にリゾルバの設定です、なぜかIDependencyResolverインターフェースを実装した、欲しいインスタンスを取得するリゾルバが提供されていないので、自分でコードを書く必要があります。今回はProjet Silkで実装されている「UnityDependencyResolver.cs」をそのまま利用しました。このとき知ったのは、Unity関連のクラスはMicrosoft.Practices.Unity名前空間にあるんですね。Unityがルートじゃないんですね。

そしてリゾルバの設定です、Global.asax.csのApplication_Startに設定を行います。

protected void Application_Start()

{

    IUnityContainer container = new UnityContainer();

    container.LoadConfiguration();

 

    IDependencyResolver resolver = new UnityDependencyResolver(container);

    DependencyResolver.SetResolver(resolver);

}

 

こうすることで、引数なしのコンストラクタが不要になります。Web.configに記載したマッピングの設定にしたがってUnityがインスタンスを取得してくれるためです。コードはこうなります。(わかりやすくするために、以前のコードも残してあります)多少コードがすっきりしたことがわかると思います。

public class HogeWorkerService : IHogeWorkerService

{

    private IHogeDao Dao;

 

    // 通常のコンストラクタ

    //public HogeWorkerService()

    //{

    //    Dao = new HogeDao();

    //}

 

    // DI(コンストラクタインジェクション)コンストラクタ

    public HogeWorkerService(IHogeDao dao)

    {

        Dao = dao;

    }

 

    // コントローラーから呼び出されるメソッド

    public HogeViewModels MakeHoge()

    {

        // 省略

    }

 

今まで通り、引数付きのコンストラクタは単体テスト用に必要です。

Unityを使った感想ですが、それほどDIフレームワークを利用するメリットが思いつかないです。コードがややすっきりするのは確かですが、デフォルトコンストラクタがなくなるだけなので、それほど劇的に変わりません。逆に、設定ファイルに型・インターフェース名を文字列として記載するのでタイプミスでエラーが発生してハマるリスクのほうが大きい気が...(昔S2Containerのdiconファイルの記述でハマった悪夢が蘇りました)

ただ、Release/Debug用に設定ファイルを分けることで、取得するインスタンスを切り替えることができますし、単体テストプロジェクトにも設定ファイルを作成して、リゾルバを設定することで引数付きコンストラクタもなくすことができると思います。(Project Silkではそこまでやっていませんでしたが)使うのであれば、プロダクションコード、テストプロジェクトまで徹底的に使わないと、使い方を覚えるコストをペイできないんじゃないかなぁ、と思いました。手放しで「素晴らしい!」とは言えませんでした。う~ん。

Unityの単純な使い方ではなくて、シナリオがあってUnityを使うとこんなに素晴らしくなるという説明を誰かブログに書いてくれないですかねぇ。自分は書けませんでした。

今回はUnityをテーマに書きました。作成したソースはSkyDriveにアップしてあります。「MvcHogeApp_v3」をダウンロードしてください。サイズを抑えるため、アセンブリ類は削除してあるのでVisual Studio 12 Express for Webがインストールされた環境で開いてください。