レガシー分散システムからモダン分散システムへ
はじめに
Dockerは個人的には色々便利なんだけど、オンプレな本番環境に適用するメリットあるかな? とたまに思います。 Infrastructure as Codeは別な方法でも実現できますし。
Googleとかもコンテナは分散システムの基盤としてを重要視してるように感じるので、本番環境に適用する決め手はこっちかな、と思っています。
なので、今回は思考の整理に、近代的な分散システムってなんで要るんだっけ? というのをまとめてみました。
分散システムとは?
分散システムと聞くと何を思い浮かべますか? SparkやHadoopですか? それともUnixやダウンサイジングですか?
この記事を見る人の多くは前者を思い浮かべると思うのですが、Wikipedia的には後者の意味で記載されています。
前者は分散コンピューティングとして扱われてますね。英語でも同じかどうかは調べてないですが。
エンタープライズ系の人だと後者もなじみ深いと思うのですが、ようはメインフレームの対義語です。 単一のマシンですべての業務をこなすメインフレームに対して、複数のマシンでそれぞれの業務をこなすのがレガシーな意味での分散システムですね。 つまり、現在私たちが触るほとんどのシステムは「分散システム」となります。このような業務(アプリ)毎に専用のマシンを使うアプローチを「レガシー分散システム」と呼びましょう。
対して、SparkやHadoopのような巨大なワークロードを複数のマシンで分散して実行するアプローチや、 docker-swarmやk8sやmesosのような多様なワークロードを複数のマシンで分散して実行するようなアプローチも分散システムと呼ぶこともあると思います。 このような複数のコンピューターリソースを束ね、業務(アプリ)毎に振り分けるアプローチを「モダン分散システム」と呼ぶことにします。 ちなみに、巨大なワークロードも究極的には多様なワークロードの一種でしかないので、今回は分散コンピューティングの話はあまりしません。
最近、Dockerをはじめとして「コンテナ!」「コンテナ!」と言っていますが、開発環境と本番環境をポータブルに行き来できる、ということ以外には「モダン分散システム」の作りやすさがあります。 必要なCPU数やメモリをコンテナに割り当てて、それを実行するのに必要なリソースをスケジューラで確保して、実体はプールしたマシンのどこかしますがあたかも単一のOS上で動いてるように見せかけます。 GoogleのBorgやKubernetes、Apache Mesos、Apache Hadoop YARNはそのためのミドルウェアですし、IntelのRack-Scale-Design(旧Rack-Scale-Architecture)はそれを想定したハードウェアです。
なぜモダン分散システムが必要か?
なぜ、このような仕組みが必要になってきたかというと、CPUが十二分に速くなってきた事とCPUがこれ以上はあまり速くならない事です。
20年前、10年前にくらべてCPUはずいぶん速くなりました。1つのアプリケーションを走らせただけで通常はCPUが100%になることなどなく、ユーザからのリクエストや処理するデータがCPUに対して少なくてほとんど遊んでるマシンも珍しくありません。
また、フリーランチは終了しました。ムーアの法則は破れこれ以上CPUは単独では速くならないとも言われています。そのため、最近は1ソケットだろうとサーバ買えば少なくとも4コアは付いています。
シングルスレッドのアプリケーションだとOSが賢くスケジューリングしてくれるにしても効率的に稼働させるのは限度があります。
スマートな相乗り
こうした無駄なリソースを効率的に使うための方法があります。それは「相乗り」です。 1つのマシンで複数のアプリケーションを動かすことでサーバの利用効率を高め、マシン導入の手間も省く事ができるのでビジネス的にも大きなメリットがあります。
が、メリットがあるので使われてきましたが、相乗りは蛇蝎のごとく嫌われていました。曰く「片方のアプリケーションがリソースを使いすぎてもう片方も重くなる」「ポートが被る」「ファイルパスが被る」と運用上のリスクがたくさんあるからです。
これはすべて真実です。わたしも下記で書いてあるような作りこみをしない限りは「相乗り、ダメ、ゼッタイ」というスタンスです。
ただ、これは相乗りが悪いのじゃなくて、リソースが分離されてないからです。
例えば、ファイルパスやポートはjailでもかなりの部分綺麗に分離できます。テスト環境のような計算リソースの共有が許容されるレベルならこれで十分でしょう。
また、Dockerでも使われているcgroupsを使えばCPUやメモリも適切に隔離することができます。このような「スマートな相乗り」であれば、サーバリソースを効率的に使うための優れた方式です。
近年、vmwareとかの仮想化が流行っているのもこの「スマートな相乗り」を実現するための手法の一種だからです。
ワークロードの分散
一方で、これはまだ不十分です。アプリケーションで必要なリソースとタイミングはそれぞれ異なります。
CPUが2個ついたマシンが2台あったとして、何時にどのサーバでどのアプリケーションを動かすのが最適になるのかをJP1とかでスケジューリングできますか?
そういったことを考慮してジョブの依存を書くのは至難の業です。しかも、日によってワークロードが変わるかもしれません。
ひょっとすると今日はいつもよりサーバAで動かすジョブのデータが多くて、他のジョブはサーバBで動かしたほうが効率的かもしれません
ダイナミックな情報も必要なので、どのサーバで動かすのが適切かを人間が決めることは出来ません。なのでプーリングとスケジューラが必要です。
レガシー分散システムのように「業務Aを実行するサーバ」、あるいはそれに相乗りの要素を加えて「業務AとBを実行するサーバ」という概念を捨てます。
そうではなく「業務を実行するコンピュータリソースのプール」として管理します。例えば合計4個のvCPUプールとか。
あとは簡単ですね? vCPUの空き状況を見ながらタスクを振ればワークロードは分散されます。
こうすることで、サーバの使用率を最大化することが出来ます。これはサーバ費用と調達時間という2つのコストを削減できるのでビジネス的にもとても良いことです。
vmwareのような仮想化技術では「スマートな相乗り」までは実現できますが、仮想OSで動いてるシステムがレガシー分散システムだとワークロードの分散は出来ません。
でも、相乗りなんでしょ?
メリットは確かにありますが「相乗り」というリスクを犯してまで使うべきでしょうか?
もちろん「スマートな相乗り」であれば基本的に相乗りのデメリットは受けないのですが、そのスマートさを保証する機能自体のバグというリスクはあります。
私は使うべきだと思います。なぜなら、本質的にモダン分散システムは冗長構成だから。
1台のマシンで100個のリクエストを捌く構成より、10台のマシンで10リクエスト捌く方が機器障害やメンテナンス時のインパクトが小さいです。 まあ、これは前提として1台のハイスペックマシンだと意味がないので、ある程度ホストマシンも数をそろえておく必要はあるけど。
モダン分散システムへの移行は必須か?
モダン分散システムはサーバーの使用率を最大化することで、総体としてのサーバ費用と業務毎における調達時間を圧縮できるので、ビジネスメリットがあります。
でも、それだけなら移行する動機付けとしては弱くもあります。
まず、調達時間の圧縮は仮想で十分。サーバ費用に関しても仮想ならある程度割り当てるリソースの調整でベアメタルよりはマシになります。
なので、これが決定的な導入理由にはならないことも多そう。
ハードウェア費用ケチるより、利益を上げる作業をした方が儲かるビジネスモデルもあるしね。人のリソースは有限だから。
どちらかというと、Elasticにリソースをアプリケーションに割り当てれる運用性が価値になるかな。仮想だとOSの起動や停止から始まるのでトロいし。 この特性はバッチサーバ、特に並列処理とかに有用になりそう。SparkとDockerを同じリソーススケジューラで管理するとかが決め手かも。
あとは、昼と夜でリアルタイムとバッチ処理のワークロードが逆転するとかのケースにも使いやすいかな。これもOSの上げ下げとかしてると面倒だし。
運用面でも、OS単位じゃなくてアプリケーション単位でリソースがモニタリングしやすくなるので、慣れると楽そう。
いずれにしても、「移行」という観点では「今すぐ移行するべき!」と強い言葉を使うほどじゃないかな? はまりそうなユースケースでは使うべきだし、ゼロから設計するなら構築したいけど。
あと、当然だけどサーバーが大量にあってコストを圧迫してるなら検討するべき。
どちらかというと、こういうモダンなシステムを導入するにあたっての、運用や構成の見直しが一番のメリットになるといういつものパターンな気もする。
マイクロサービスとかCDとかもそうだけど、実現しようとするといろんな要素をクリアしなくちゃいけなくて、結果として前提条件をクリアすることで効果が出るというパターン。。。
まとめ
最近、もやもやっとすることをとりあえず文章にして形にしてみました。突込みや指摘をお待ちしております。
移行は必須か? のところが相当整理されてない感じがにじみ出てますが、実際どうだろうなー、というのが正直なところ。 まあ、結論が出せる程理解してないからこんな記事書いてるのだし。
ちなみにクラウドベンダーやGoogleのような巨大インフラを持ってる会社は 運用してるサーバの数が馬鹿にならないだろうから、こういうのに積極的なのだと思う。
参考
運開分離とDEVOPS
この記事は「システムエンジニア Advent Calendar 2016」の記事です。
さて、今日はクリスマス☆イブ。ITな香りがほんわかするポエムを書いてしまおうと思います。
システムエンジニア Advent Calendarってあったから、とりあえず登録しといたんですが、よく見ればSIerって書いてありますね!? ワタシ、ユーザ企業の人間なので社内SEとして内製とか運用とかしてる人間ですが、まあ、細かいことは良いよね? クリスマスだし!
今回は運用と開発を両方やってきた人間としてエンプラ系で思う「運開分離」と、どちらかというとWeb界隈から普及してきた「DEVOPS」に関して書いてみようと思います。
運開分離
会社がエンタープライズよりになると「運開分離」というキーワードが首をもたげてきます。
これは文字通り「開発」と「運用」の責務を明確に分離し、人や組織も分離するという思想です。
さて、何故そんなことをするのでしょうか?
色んな理由があります。
例えば資産化率の安定化。開発を新規案件、運用を保守やトラブル対応等の非資産化としてチームを構成することで、突発的なトラブルで予定していた開発が進まない、というのを防ぐことが出来ます。
この分け方の場合、開発と運用で求められるスキルセットはほぼ同じです。どちらもアプリとインフラ、業務とシステムを抑える必要があります。
一方、別の定義もあります。
本番環境の作業、すなわちリリース以降の工程を担うのが運用チームで、要求出しからリリースまでの担当をするのが開発チームだという区分です。
どちらかというと、こっちの方がエンプラ的には多いんじゃないでしょうか?
この場合、「運用」と「開発」では求められるスキルが違うことも多くなる印象です。「運開分離」という言葉を出すときには多くの場合、こちらの組織構造を念頭に置いていると思います。
そして、なぜこのような状態で運開分離が唱えられるのかというと、セキュリティです。
たとえば、「アプリケーション開発者が,本番環境のDBを操作できると,財務諸表にかかわるデータを修正できる可能性があったからだ」と説明される場合があります。
「運用」と「開発」を分離することで、このようなリスクを避ける事が出来ます。個人的んはそれって??? と思うんですが、それは後述するのでいったん置いときます。
運用と開発は仲が悪い
運用と開発が仲が悪いという話はよく聞きますね。「なれる!SE」でも、インフラ開発に当たるSE部とインフラ保守・運用に当るOS部は仲悪いですね。業界あるあるネタだということがここからもわかります。
この理由は組織によっていろいろ違います。たとえば、最初はミッションから来る対立だったものの、のちには人の代替わりなんかもあって対立だけが残り感情的な対立になるようなケースすらあります。
逆にやたら運用と仲の良い開発の人やその逆もあります。なぜこのような事態が起こるかというと、個人的な印象としてはKPIが異なるからです。
運用と開発のKPI
これは完全に組織依存ですが、良くありそうな運用のKPIは「システムを落とさないこと」、同じく開発のKPIは「新規機能を作って利益を上げる事」なのではないでしょうか?
この場合、「攻めの開発、守りの運用」と評されることがあるようにお互いのゴールが異なるため、しばしば意見が対立します。
しかし、良く考えてみましょう。本当に運用の最重要ミッションは「システムを落とさないこと」ですか? 開発の最重要ミッションは「新規機能を作る事」ですか?
違います。ほとんどの会社が真に掲げてる最重要ミッションは「利益を最大化すること」、つまり「会社が儲けること」です。もう少し綺麗な言葉で言えば、「お客さんの笑顔のため」ですね?
大事なのはこの基準を共通化することです。運用と開発だけではなく、ビジネスサイドも本質的には共有するべきです。
各組織毎に割り振られたKPIは、それを計測するたのめ1指標でしかないはずですが、多くの場合はそれが絶対化されて、ひいては開発と運用の意見の対立が生まれます。
本当は同じゴールを最終的には目指してるはずなので、一時的にどっちかが折れるのは妥当ですが、そこを理解しないとお互いの利益だけを主張することになるので。
DEVOPSは開発Tが運用をすること?
周りから、良く言われるのですがDEVOPSというムーブメントは「開発Tが運用をすること」ではありません。
なので、先ほどの運開分離の話とは本質的に矛盾しません。DEOPSはバズワード化してるので定義はあいまいですが、この記事の中では比較的古くからある定義として「開発担当者と運用担当者が連携して協力する開発手法」としましょう。
これは裏を返せば「協力するために同じ環境を見ている」ともいえます。
それこそがDEVOPSの本質です。たとえば統合監視ツールやKibanaなど可視化ツールをいれることで、今までは運用しか見れたかったシステム負荷を開発も簡単に見れるようになります。
逆に、運用からは見えづらかった開発の動きも分かりやすくなります。
CI/CDがあることで、開発チームから何がリリースされてるかを把握することが簡単になりました。このように仕組みを導入して運用と開発のKPIのギャップを小さくするのがDEVOPSが登場した背景の一つだと思っています。
運開分離はするべき?
個人的には運開分離はするべきではありません。少なくとも組織レベルでは。
いくつか理由があります
- 運用と開発の技量が乖離する
- 運用を知らない開発者にちゃんとした運用設計は出来ない
- 開発ができない運用は単なるパンチャーなのでChefやAnsibleで代用される
チームを分離した当初とかなら良いのですが、純粋培養な人たちが大多数を占めると「本番を知らない開発」と「中身が分からない運用」が大量に生まれます。
いずれのパターンもお互いの本業を担うのに十全な力がありません。例えばトラブル対応等でログ集計をしたことがある人間はログを出すタイミングやフォーマットにも非常に気を使います。
たとえば、以下のようなそれぞれのログがあります。
A. 2016-12-24 10ms Start Christmas B. 2016-12-24 10 ms Start Christmas C. Start Christmas 2016-12-24 10 ms
同じ情報量で単に表現を変えただけですが、あなたはどのログを選びますか? 運用経験者は「B」を選ぶ人が多いでしょう。
Aだとスペース区切りじゃないので単純にawk等の解析で人手間かかります。
Cだと複数のサーバで出力されたログを日付毎にソートするのが少し面倒です。
ちなみに、A,B,Cのいずれも情報量が同じなので「一手間」以上の違いはありませんが、選べるなら手間の無い方を選ぶはずです。この辺のログのフォーマット設計は運用をしてないとピンとこないと思います。
もうちょっというと、カンマ区切りやスペース区切りも課題があるので、TSVやLTSVを運用観点では選ぶでしょうね。
もちろん、これは一例で運用経験が無いと思いつかない設計というのはそれなりにあります。
開発を知らない運用はもっと深刻で、手順書の通りにしかできないなら人間がやる必要すらありません。
そうならないためにもアプリケーションを熟知し、どのような負荷をシステムに与える特性があるのか、いつが負荷が多いのかってのは作りを知らないとわからない部分です。
こういたスキルはとても高度で蓄積を必要とするものなので、外注に丸投げするものでは本来はありません。
また、CIなどの開発なんだか運用なんだか持ち分に困るツールの管理も運開分離を徹底した時には起こりがちです。
でもセキュリティが...
そもそも運開分離はセキュリティのために提唱されたといわれております。
でも、それって「運用は悪意が無い」という前提がないと意味ないですよね?
先ほどの「アプリケーション開発者が,本番環境のDBを操作できると云々」の話であれば、アプリケーション開発者が悪意を持ってデータ改ざんできるなら、運用担当者も改ざん意味ないのですよね。
なぜ、無条件にアプリケーション開発者がだめで運用担当者はOKになるのか理解ができません。
そうではなくて、例えばrootなどの特権の利用を制限するとか、監査ログをしっかりとるとか、運用担当者も不正が出来ないシステムにすることで、開発担当者も不正が出来ないようにするのが肝心です。
下手すると開発はガチガチに制限されてるけど、運用はrootで入り放題とかいう脆弱を生みかねないので、変な幻想は捨てるべきでしょう。
まとめ
エンプラの人たちが大好きな運開分離ですが、個人的には不要だと思います。
DEVOPSとは矛盾しないので必要な組織に入れたらいいと思いますが。
特に資産化工数の安定化はそれなりに重要なので、その観点で分けるのはありでしょう。
ただ、その場合でも技術と意識の乖離を防ぐために定期的には人をシャッフルすることが大事だと思います。
英語で萌えよう!
この記事は、 OIT Advent Calendar 2016の19日目の記事です。
OITでAdvent Calendarが書かれるのは感慨深いです。
自己紹介
2003年入学、2009年修士卒のOBです。HxSコンピューターサークルとF教授の研究室にいました。今は、某IT系企業でエンジニアをやっています。 Twitterでは@kodukiで活動しています。大学関係者はパスカルの方が分かる人多いかも?
大学時代は北山祭で餅ついて売ったり、バケツでプリン作ったり、コーラにメントス入れたり、 「何を言ってるかさっぱりわからない研究でも必ず質問をする」という謎のマイルールで6年間いろんな研究室の発表を見に行ってたらしまいにはメガネの魔王とか言われたのは良い思い出です。
学祭や卒研発表には今でも顔を出しに行くことが多いので、見かけたら声をかけてくださいー。
また、今年はKirika_K2氏と一緒に大学院の講義の「情報科学特別講義C 」を一つ受け持つこともしました。
今回はOITのアドベントカレンダーということなのでせっかくなので、学生の人たちに読んでもらいたいなー、と思う記事を書いてみることにしました。
この記事は特段技術系ではないので、技術系の記事読みたい人は他のアドベントカレンダーだけど下記あたりをどうぞ。
- WebVR/A-FrameとGearVRで始めるVR開発 - Qiita
- さあ、並列プログラミングをはじめよう - Qiita
- Heroku Container Registryで作るDocker時代のRails 5 入門 - Qiita
英語やってますか?
在学中、6年間LL教室に入り浸ってはいましたが、遊んでただけで特に英語の勉強をすることは無く、TOEICの点数も300点以下という悲惨な感じでしたが、 趣味の技術関係や研究に必要な技術資料は自分の英語力でもある程度読めるし問題ないかなーと思ってました。
でも、就職して思ったのは英語が出来るとやっぱ世界が広がんるんですね。
色んなソフトや技術を選ぶなかで「日本語でのサポートの有無」を前提にしなくて良くなりますし、
海外の会社だと身構えることなくいろんな人と直接コミュニケーション出来ますし、
イベントで発表して質問が英語だったり、そもそも会場が英語だったりでも対応できますし、
ある日突然明日から会社の公用語は英語ねって言われても困らないですし、
JavaやC++などどんな言語よりもエンジニアが覚えて損しない言語だと思っています。
別の会社に行った人やIT関係以外の人も含めても聞く限り、意外に学生時代に思ってるよりは「明日から英語ね」とか「ちょっと海外行って来て」と言われるケースは多いと思います。 飲食店やスーパーでさえその辺にいる外国人が店に来た時は対応してる店員よく見かけますし。私の想像力が足らなかっただけかもですが。
そんなわけで英語学習の話をしたいと思います。
どうやって英語を勉強するの?
「学べ、そして使え」これだけです。簡単でしょ? ...ええ、言うのは。
今は英語の勉強は一昔前より圧倒的に簡単です。 ネットで良質なネイティブの英語コンテンツ(TEDとかCNNとか)は無料で山ほど手に入りますし、英単語もスマホアプリ化されて学習がかなり効率化されてますし、Skype英会話で英会話だって格安で簡単に始めれます。
また、効果的な勉強の仕方も共有されていて、例えばTOEICとかも英語上達完全マップとかに書いてある事を丁寧に実践すれば確実に上がります。
実際、私や知り合いが英語のスコアを上げた勉強法もこのサイトに書いてある事かその延長法ですしね。
http://mutuno.o.oo7.jp/mutuno.o.oo7.jp
でも、英語学習はトレーニングです。タフなタスクなんです。強いモチベーションが必要です。ともすれば英語を嫌いになってしまいます。 もちろん私も勉強は嫌いです。なので、英語を嫌いにならないために自分の好きなものと組み合わせることにしました。そうだ、萌えよう、と。
萌え + 英語教材を使ってみる
まずは王道というか初歩。教材編です。
萌えを売りにした英語教材っていくつかありますよね? 例えば「もえたん」はその走りであり代表例です。
もえたん新装版 |
英語を勉強するには単語だけじゃなくて文法も必要です。中高時代にやったはずですが過去分詞とかみんな忘れましたよね? もえたんサブリーダーはそんなあなたに最適な本です。
もえたんサブリーダー |
もえたんの良いところは単に表紙が萌え萌えしてるだけじゃなくて、オタクならくすりっと笑えるその文章にあります。
コンテンツ自体にアニメネタを散りばめたのだと下記あたりもお勧めです。 英単語だけじゃなく英文法の解説やハルヒのやつみたいに小説仕立てになってるのもあるので、 ある程度長文が載ってるのもあるので精読->多読/速読と重ねて英語を読み慣れる教材としても使えたりするかもです。
- 涼宮ハルヒの憂鬱で英単語が面白いほど身につく本
- 「きんいろモザイク」と英語レッスン [ きんいろ英語レッスン受講生一同 ]
- 俺の妹がこんなに可愛いわけがないとやり直す中学英語 [ 明慶徹 ]
- ガンダムで英語を身につける本 [ ガンダムEnglish研究会 ]
- 『ジョジョの奇妙な冒険』で英語を学ぶッ! [ マーティ・フリードマン ]
直接的に既存のアニメと絡めてない教材としては下記の2つがお勧めです。
中学生の時の英語の教科書はなんでしたか? 私はNEW HORIZONです。
グリーン先生やパウロ・シルバー。ユミやケンが出てくる奴ですね。タイムマシンで未来に行ったりもしましたね。
「ミライ系NEW HORIZON」は、そんなNEW HORIZONから大人になったユミやケン、ケンのアメリカでの友達のルーシーを交えたSchool Daysもとい三角関係をラノベ仕立てでにした例文で進む英語教材です。
かなり読みやすいのですし、リスニングCDも付いてるのでお勧めです。ルーシーの声がかわいいので。とりあえずケンがいつか刺されると思う。音読やリスニング教材としても良いです。
「TOEICテストにでる単600語」の方は一見硬派なタイトルで、中身もたまにイラストに女の子が載ってるだけで例文も良くも悪くも普通です。むしろ普通のTOEIC本。
ただ、リスニングCDがすごい。すみっぺが日本語訳を話してくれます。
リスニングの疲れをすみっぺの声で癒されるという良いサイクルが出来ています。
割り切って英語はネイティブがしゃべってるのも良いですね。
ちなみに割とTOEIC界隈で有名な人が書いていて本当に超頻出単語が載ってるので普通に教材として出来が良い。
しかし、ロシア語の教材じゃないがいいんだろうか...
本以外だと、「鬼桃語り」というスマホアプリもあります。
英単語がメインで正直、iKnowやmikanに比べたら学習効率は落ちると思いますが、ふつうにソシャゲーみたいな感じなので息抜きにやるには最適ですね。
MANGAを読もう!
どんなに親しみやすくても「教科書はなーっ」てそんなあなた。うん。分かる。
なので、普通にMANGAを読みましょう。マンガじゃないですよMANGAです.つまり、英訳版ですね。 昔は、大きな書店に行かないと手に入りませんでしたが、今はKindleやKobo、それにBookWalkerで簡単に手に入ります。 一番簡単なのは専門サイトもあるBookWalkerですね。Kindleでは最近日本からは一部の本が買えないように制約が入ったみたいです。
ちなみに、私は最近はUQ HolderとかMushoku Tensei読んでます。
基本的にはローマ字やカタカナをそのまま英単語にすれば良いのですが、 「Is It Wrong to Try to Pick Up Girls in a Dungeon?(ダンジョンに出会いを求めるのはまちがっているだろうか?)」なんかはタイトルがちゃんと英訳されてるので、 日本人からすると逆に探しづらいでしょうから絵から頑張りましょう。
NOWAY(そんなのってないよ、馬鹿な、まじ?)とかDammit(ちくしょう)とか覚えておけば、あとは絵を見て何となくわかります。 絵が相当に理解を助けてくれるので英文をスムーズに読む、という習慣をつけるには悪く無い気はしています。
「Shinmei school Secret Technique!(神鳴流奥義!)」とか「Spirit Circuits(精霊回廊)」とか「Magical Girl(魔法少女)」とかいろんな語彙が増えます! TOEICにも英検にも出ることは無いでしょうけど。。。
ちなみにラノベの英語版もありますが、読むのに結構パワーを使うので最初はMANGAから始めたほうが気軽で良いと思います。
Animeを視よう
マンガよりアニメが良い! という人もいるでしょう。
じゃあ、アニメを見ましょう。いわゆる北米版アニメというやつですね。
去年までなら英語版のNetflixやHuluで簡単に見れたんですが、最近は規制が厳しくなったので日本からNetflixを見るのは難しそうです。
かといって、日本版のNetflixには英語版はほとんど登録されてないので、今後どうするかは難しいところ。
ちなみに、英語版のアニメを見るにあたって一番覚えておくべきことはDub/Dubbed(音声吹替え)とSub/Subbed(字幕)の違いです。
英語の勉強として使いたいならDubの方が断然いいですね。
また、Dubで字幕を付けることも当然可能なんですが、なぜか「言ってる事」と「書いてある事」が結構違うのが問題。
瀬戸の花嫁とかは結構ひどくて、主人公の呼び方が音声と字幕で異なっていたので、いっそのこと英語だけ聞いた方が分かりやすい、というケースもありました。
日本製じゃなくてRWBYみたいな海外製もあります。まあ、これはアニメというよりMMD動画見てる気分になりますがw
注意点として私を含めてほとんどの人が英語でAnimeを視てもリスニングというよりヒアリングレベルになることが多いでしょうから、慣れるまで息抜き以上の意味はないです。
でも、普通に視てて楽しめますし、ご飯食べながらでも良いし、自分のまだ見てないアニメを積極的に見る事でモチベーションにもなりやすいので「英語を嫌いにならない」って目的には一番あってるかもですね。
一応、英語のイントネーションや言い回し、音の強弱に慣れるって効果は多少はある気がします。
まどマギは英語版を何度も見たので 「It makes no sense at all!(分けが分からないよ)」とか明日から使える英語を覚えることもできました!
ラブライブは英語版しか見てないので、たまにニコ動とかで見つけて関西弁でしゃべられると「こんなしゃべり方だったの!?」とビビりますが、それもまた面白い体験ですね。
ちなみに、ガチでやりたい人はWelcome to Anime Transcripts@アニメで英語とか使いながら反復練習するのが良いと思います。
よろしい、ならばゲームだ!
ゲーム派のあなたにも朗報です。Steam使えば結構英語版でゲームを楽しめるんです。
「閃乱カグラ」や「シャドウバース」のようなゲームを英語テキストでやるもよし、 「CLANNAD」や「ひぐらしのなく頃に」「グリザイアの果実」「Shuffle!」なんかの往年のギャルゲーもあります。
なんか最近、Steamで出すのが流行ってるみたいなので、私が名前知らないだけで最近のゲームもある気はします。
「CLANNAD」とか普通に日本語でもクリアするのにGWを使った気がしますが、英語版にクリアした暁には人生について英語で語れるようになってるんじゃないかなー。
日本語で普通にやれるゲームだと英語でわざわざするモチベーション無い人もいるでしょう。
一応、Steam専用として最初から英語で作られている「Sakura Spirit」とか「Gaokao.Love.100Days」とか「Go! Go! Nippon! ~My First Trip to Japan~」もあります。
探せば他にもたくさんありそう。特に「Sakura Spirit」は日本をリスペクトした海外製ギャルゲーということでも有名ですね。続編というか同じメーカーからのSakuraシリーズは結構他にも出ています。
まとめ
英語に萌える方法、いくつか紹介してみましたが如何でしたでしょうか?
英語の勉強は大変ですが、何事も息抜きを入れることでもうちょっとだけ頑張れるかな、と思っています。
個人的には海外発の萌えコンテンツに興味があるので、誰か見つけたらコメントやTwitterで教えてください。
さて、みなさんモチベーション管理の準備はできましたか? ツラくなったらMANGAやANIMEを見る準備はOK?
ふつうのユニットテストのための7つのルール
最近、久しぶりにコードレビューをすることが増えたのですが、UnitTestのコードを見るとヒドイ部分が多く残念な気持ちになることもあります。
原因のひとつとして、プロダクトコードと違いテストの書き方をあまり書き方を明文化してなかったのが悪かったなと思い、とりあえず明文化してみました。
今回は、命名規則とかそのレベルまではいかず「ユニットテストかくあるべし」ってところまでをまとめます。正直、これ守ってくれたらあとは好みの世界もあるしね。
追記: テクニカルな部分も最低限ですがQiitaに記載しました。
追記: もうちょっと大上段の規約に関してもまとめてみました。
前提
ここではユニットテストを関数レベルのテストをJUnitのような自動テストツールで取り扱う場合に限定します。 また、Mavenでビルド時は常にテストを回すことを想定しているので、それを踏まえたルールだと思ってください。
ルール
ポータビリティを大事にする
CIサーバや他人のPCで動かないテストコードを書いてはいけません。他所で動かないコードは不要では無く害悪です。 後述のルールでも具体的に触れていきますが、まずこの大前提を忘れないでください。
プロジェクト配下のディレクトリのみを使う
本番環境の「/var/hogedata」や「D:\hogedata」みたいなパスを前提にしたテストを書いてはいけません。 gitから落としたら即座に利用できるようにsrcまたはtarget配下を前提として相対パスでテストデータの配置やファイル入出力を行ってください。
DBやネットワークといった外部環境への依存を無くす
日付やDBやネットワーク(WebAPIとか)といったものに依存するコードをユニットテストに書くべきではありません。ユニットテストはあくまでロジックの検証にとどめるためにMockやその他テストダブルを活用してください。 ネットワークの場合はBetamax、それ以外の場合はJMockit等を使うこともできます。 DIコンテナやフィールドをパッケージレベルにするとで依存性を注入できるようにするとなお良いです。
SQLそのものをテストしたい場合等の重たいテストはIntegration Testとして、mavenのテストフェーズではなくintegration-testフェーズ等で実行してください。
繰り返し実行できるように作る
上記、2つのルールと被るところもありますが、手動手順無く繰り返し実行できるように作る必要があります。 環境の初期化と後始末を含めてすべてをテスト内で表現してください。setUpとtearDownで初期化とクリーンアップを適切に実施してください
標準出力にログを出さない
printlnや各種Logger等でユニットテストのために標準出力にログを出してはいけません。テストの結果は人間が目視で確認するのではなく、すべてコード上のアサーションに表れているべきです。 結果としてユニットテスト向けに人間が見るためのログが出ることはノイズにしかならないので、原則出力するべきではありません。 特に「エラーが正常に出ることを確認する場合」にprintStacktraceをするのはログが汚染されて本当に困るのでやめてください。本当のビルドエラーを追うのが困難になります。
とはいえ、ユニットテストのデバックのためにログを出したいケースもあると思いますので、その場合は一時的に書いてちゃんと消すか、traceレベルのログを使ってください。
ひとつのテストケースにはひとつの観点しか検証しない
一つのテストケースでは一つの観点でしか検証をしてはいけません。テストがこけたときに原因の切り分けが出来なくなるからです。 手動で実行してる分けではないので、テストケースの圧縮を過度にする必要はありません。
もちろん、同じ観点でのパラメータ化テストや、一つの検証観点で複数の検証項目がある(例えばBeanの各プロパティをチェックとか)場合にassertをいくつも書くのは問題ないです。
問題なのはテストXを実行したときに「ロジックAの動作」と「ロジックBの動作」を同時に検証することです。たとえ、AとBが依存してても個別のテストケースに落とすべきです。
ユニットテストを見て何をしてるか分かるように書く
稀にユニットテストの中が「test001」から「test010」まで並んでいて、なにを検証してるのかが別で作られてるExcelのテスト仕様書をみないとサッパリわからないUTがあります。 テストケースはふるまいを確認するための重要なコードなので、きちんと名称等にも気を使って書くべきです。
日本語圏のエンジニアが中心ならテストケース名を日本語で書くのもありでしょうし、せめてコメントで記載されてるだけでもずいぶん違います。最悪でもそのテスト仕様書の場所をコード内に書いてください。
BDDテストツールを使えばそれがベストかもしれませんが、そのあたりは本題から外れるので割愛。
番外ルール
「-Dmaven.test.skip=true」ダメ、ゼッタイ!
ちょっと粒度が違うので番外ルールですが、気軽に「-Dmaven.test.skip=true」を使うのはダメダメです。
これは「CI上ですでにいろんなテストがパスしたことを確認したのちにリリース担当者がビルドするとき」とか、結構特殊なケースのみで使うべきものです。
「あれ? なんかビルド失敗する。テストか、とりあえずskipしよう」みたいな事考えだすと後からひどい目にあいます。
CI使ってもテストがこけるのは分かるようになりますが、例えば標準出力の汚染とかビルド時間の増加とかは分かんないので、みんなが日々ビルドしてることが大事ですね。
テストとコンパイルとパッケージを含めてこそのビルドです。
まとめ
さて、いくつかまとめてみましたが、あくまで個人的なポリシーなので異論については大いに議論したいなと思います。
このあたりを整備した後はもっと具体的な命名規則とかテストの種別によるJUnitや各テストツールの具体的な使い方をまとめた資料が必要になってる来ると思いますが、テクニカルなところは結構世の中にも良い資料がたくさんある気がするのでそっちにお任せ。
またMavenを前提に考えてますが、今ならDockerがローカルにもCI環境にもあることを前提にすれば、また違った考え方は出来そうですね。
それではHappy Hacking!
自動テスト関係のメモ
gitの良さは未だに分からないがPullRequestの良さはちょっとだけ分かるぞい
スマートニュース見てたらこんな記事が上がってました。
まあ、gitの良いところはそれなりにありますがローカルコミットを上手に使えるようになるまでの壁はとても高いですよね。
正直言えば私もrebaseとかなるべく打ちたくないし、使いこなせてるとは言い難い。
とはいえPR(本文中はマージリクエスト)がレビューを強制するので良くないとか、trunkに直接コミットすれば良くないとかはどうなん? と思ったり。
そもそも個人的にはSVNとgitで運用方式がさほど変わるとは思えないのですよ。実際変えなかったし。
というわけで、私が使ってるコード管理方式について語りたいと思います。タイトルはちょっと釣り... というかぞいぞい言いたかっただけです!
そもそもSVNでどう運用していたか?
たぶん、多くのサービスがそうであるようにSVNからGitに移行しました。もっと言うとさらに昔はCSVでした。
それも、色々な理由でSVNから短期間でgitの運用らしくないところもありますが、今は当時無理やりgit-flowとか入れなくて良かったなぁとは思ってます。
じゃあ、そもそもSVNでどんな運用してたのよ? という話になりますがおおむね下記のような運用でした。
- trunkは常に本番環境と一致。リリース時にはタグを打つ
- 開発時にはプロジェクト毎にtrunkから開発ブランチを作る。これが同時並行で大量にできる
- 検証環境向けのブランチに開発ブランチをマージしてテストする。検証期間/環境の都合でリリース日の異なる複数のプロジェクトがマージされる事がある
- 3の前後でtrunkと開発ブランチとの差分をとってReviewBoardとかでレビューする
- 3,4の完了したら開発ブランチをtrunkにマージ。タグ打ってリリース
実のところ結果としてGitHub Flowに結構近い運用だと思っています。違うところは3の検証ブランチでしょうけど、検証ブランチ自体はどこにもマージされないので大差は無いんじゃないかと。 まあ、この手のベストプラクティスは似通ってくるものなので不思議ではないですね。
なんで移行したのか?
移行した理由は2つあります。一つはSVNがあまりにとろく、特にマージやDiffが地獄のような重さでした。普通に数分から十数分オーダー。
これはおそらく大量のブランチを運用してたり、用意されていたインフラと管理していたリポジトリ規模がアンマッチだったことがあります。
当時の私はレビューアーとライブラリアンも担当してたので、gitに移行前からsvn-gitとかを使ってローカルリポジトリを運用してました。パフォーマンスマジ大事。
もう1点はPRですね。会社で共通基盤としてStashを導入することは知ってたので、上記のパフォーマンスの理由もあって協力に推進しました。
Gitでどのように運用しているのか?
では、本題のGitでの運用方式です。正直、パフォーマンスがダメダメなだけで運用プロセスには大きな不満があった分けではないので、ほぼそのまま移行しました。
- masterは常に本番環境と一致。リリース時にはタグを打つ
- 開発時にはプロジェクト毎にmasterから開発ブランチを作る。これが同時並行で大量にできる
- 検証環境向けのブランチに開発ブランチをマージしてテストする。検証期間/環境の都合でリリース日の異なる複数のプロジェクトがマージされる事がある
- 3の前後でmasterと開発ブランチとのPRでレビューする
- 3,4の完了したらPRをマージしてmasterにマージ。タグ打ってリリース
外部システムのReviewBoardがPRになり、マージ依頼と統合されました。なにこれ便利すぎる! と狂喜乱舞したのは私です。
それ以外は、まったくと言って良いほど同一プロセスです。gitの操作が独特だったり複雑ってのもTortoiseSVNからTortoiseGitに変わっただけなので、あまり大きな変化はありません。
まあ「Pushを忘れるな!」と徹底するくらいですかね。rebaseでコミットログを綺麗にしようとすると、ドキドキする運用がいっぱい待ってますが「そんなことしなくて良いんです」。
確かに残念なログは入り込みますしが、良くわかってないメンバーが使ってリポジトリがぶっ壊されるよりはマシです。
別に、コミットログが多少汚れてても、リリースのタグだけ適切に管理できてればそんなに困りません。clone/checkout/pull/merge/commit/pushくらい使えれば十分ですね。
なので、これ以外の操作をするときは権限を与えた特定メンバーに依頼しろという運用にしています。ちょっと窮屈だけど、窮屈だと思える程度にスキルがある人には権限与えれば良いですしね。
で、基本的にこれで運用してましたが、いきなり5の手順でmasterに取り込んでリリースをしてましたが、切り戻しが大変というリスクがありました。
特に、一日に何度もリリースする時に朝のリリースがこけると午後のリリースの準備がパーになるのでツラい。
なので、現在はリリースブランチを作って下記のように運用しています。
- masterは常に本番環境と一致。リリース時にはタグを打つ
- 開発時にはプロジェクト毎にmasterから開発ブランチを作る。これが同時並行で大量にできる
- 検証環境向けのブランチに開発ブランチをマージしてテストする。検証期間/環境の都合でリリース日の異なる複数のプロジェクトがマージされる事がある
- 3の前後でmasterと開発ブランチとのPRでレビューする
- 3,4の完了したらmasterからリリースブランチを作成して開発ブランチを取り込む。3のPRは破棄。
- リリースブランチをリリース。無事リリースされたらmasterにマージしてタグを打つ
この手順にすることで、リリース失敗時の切り戻しが簡単になる上に、リリース前にリリースブランチをリグレッションテストできるので品質面でも貢献できました。
ちなみにこの改良版の手順も含めてSVNでできないのはPRくらいでしょう。これもReviewBoardとかの外部ツールで代替はできますが。
PRによるレビューはなぜ重要なのか?
元記事ではさんざん言われてるPRによるコードレビューだけど、これは超重要だと思っています。「あなたがgitに移行するべきたった一つの理由」とか言うそれっぽい記事のタイトルにできそなほどに。
重要な理由は2点あります。
1. 保守性の担保
元記事では「採用ミスの尻ぬぐいだ!」と言わんばかりのコードレビューですが、確かに読んでバグ見つけるよりは動かして見つけた方がずっと早いし合理的です。
が、コードレビューはバグ発見より可読性や設計レベルの保守性を主にチェックする行為だと考えています。コードは読み物なので第三者が読んで読みづらいのはダメです。
これは私やおそらく元記事の方を含むほとんどのエンジニアに必要な行為で、当然ですが自分より優秀な人が書いたコードのレビュー指摘なんていくらでもしたことがあります。
静的解析で基本的な部分はかなり潰れるんですが、設計レベルに由来するところは人が見ないと分からないですがねー。
一応、高いスキルを持ったエンジニアがお互いのコンテキストを良く理解しあった上で開発すればレビューとかいらない気がしますが、 そんな事例1ケースしか私は聞いたことが無いのと、それこそハイスキルな行為ですね。
2. 適切なマージがされるかの確認
これはPR最大の利点ですね。なんとgitはPR出た差分の通りにマージされるんです! ライブラリアン的な作業をしないと気づきづらいかもしれませんが、マージってのは「コンフリクトもせずに開発者の意図とは違うマージになる」可能性があり得るんです 。 gitはsvnよりずいぶんマシとはいえ、しょせんテキストベースのマージですからね。同じコードの一番上と一番したに同じメソッドを追加しても追加したら両方正しく取り込まれますけど、コンパイルエラーになりますよね?
これを防ぐにはSemanticMergeみたいなもう少しインテリジェンスなツールを使う必要があります。
通常は同じ行を修正してれば正しくコンフリクトしますが、コンフリクトの解決を適当にされると稀に「マージの時系列」や「同じ行としての判定」が狂う可能性があります。
この場合、何が怖いってSVNとかの場合は「Diffツールで見た結果と実際のマージ結果が異なる可能性がある」ってことです。せっかくレビューしたのにマージ結果が異なるとかツラい。
そのためリリース時のマージではマージした後に想定したマージ内容になってるかを差分確認という二度手間になっていました。
PRであれば、そもそもマージ申請なので見た目の差分通りに取り込まれるので、初回のレビューしっかりやるだけで良いので簡単ですし、安心感がありますね!
GitではなくSVNに回帰するべきなのか?
正直、管理をしない側がGitとSVNでたいそうな差があるとは思えません。
プロジェクト規模や体制にもよるでしょうが50%から80%くらいの人はrabaseがどうの以前にlogコマンドすら打たないんじゃないかな?
なので、管理者/ヘビーユーザに都合が良いGitから回帰するメリットは特に無いのだけど、全員がrebaseを使うような複雑な運用プロセスはやめたほうが良い気がしますね。
少数精鋭チームなら問題ないかもだけど、大半が初心者なら入れるメリットのがデメリットを上回らない気がします。
あと、これは私が「システムの整合性を保つ唯一の機械的な方法はリポジトリである」という単一リポジトリ教に入ってるせいもありますが、
SVNのようにディレクトリ単位で落とせてもいいんじゃないかなー、とは思ったり。あとshallow cloneにcommitできるとか。
正直、10GB級の巨大リポジトリを運用しようとするとcloneがHTTP Proxyに切断されるとか、サーバの方でハングするとかツラい事象が...
その辺を考慮したツールが欲しいなぁ。
余談
>コードレビュー導入は終局的には「コードはできるだけ書かない」という境地に至る。
本題とは本当に関係ないのだけど、元記事の人と意見が真逆で面白かったのでピックアップ。
「コードはできるだけ書かない」はプログラマーが目指すべき一つの境地だと思ってます。ここだけの秘密ですがコードを書くとバグが発生する可能性が上がるんですよ?
まとめ
元記事で言う「中規模以上のプロジェクトのリリースを本格的に管理する側」を経験した人間なので、ちょっとカウンター記事を書いてみました。
正直、10個も20個もあるそんなに短くないプロジェクトを並行運用するのをみんなどうやってるんだろう? という疑問をずっと持ってたので、 とりあえず自分の現状を公開してあわよくばコメントをもらおうという算段もあったります。
というか、そういうツラい運用したくないからリリーススケジュールをシリアライズして並行稼働開発をしないのが正しい組織運用かもしれないデス。
それでは、Happy Hacking!