2017年2月26日

ScalaMatsuri 2017に行ってきた

昨日と今日は、プログラミング言語Scalaのカンファレンスである「ScalaMatsuri 2017」に初参加してきました。

Scala自体は業務でも個人でもまだ使えていないのですが、前職で少し触る機会があったのと、一緒に行こうという事で勢いでチケットを買ってみた次第です。

1日目

事前に発表された講演内容で、自分のScalaレベルと興味のある分野からセッションを選択しました。

Readable Scala

少し触っていた頃に、"~>"とか今まで見たことない(そしてググりにくい)記号が多くて愕然としていたのを思い出したのですが、「”パラダイムやイディオムを知らないから可読性が低い”という主張は意味をなさない」というのは耳の痛いところでした。また、それらがコードをいかに読みやすくするかに主眼を置いて設計されている事がよく分かったセッションでした。
(そしてsprayが今はもうメンテナンスされていない事を今さら知る。。あとググりにくいのは”tilde greater than scala”みたいにすれば探せるのを知ってだいぶ改善された)

新サービスをゼロから開発してローンチするのに大切だった3つのこと

Twitterに新機能(新サービス)を追加した際の知見として、「まずは上から下までとにかくつないで動かす」「内部状態と変更の流れを管理する(一方向にする)」「ちゃんと名前をつけることが大切」があげられていました。個人的には、旧システムからの移行を一部のモデルから行うためにFutureを導入して解決していったくだりがFutureを理解する参考になりました。

Akkaで分散システムの障害に備える

本セッションでは、「障害を前提としたシステム(アンチフラジャイル)」「レジリエントなシステム」をAkkaでどう実現するかが語られましたが、システム障害に対する今までの考え方や備えを改めさせる可能性を感じました。

ゲームサーバのためのScala/Play

もともとPHPで開発していた自社ゲームタイトルのサーバーサイドをScala/Playで実装した事例として、規模感やインフラ周りのTips集などが語られたので、業種や経緯とかいろいろ思い出しながら聞かせて頂きましたが、Scalaの"better Java"としての事例は今後増えていって欲しいなと思いました。
(FPバリバリで書かれているのかもしれませんが。。)

DMMのAPI GatewayをAkka StreamsとAkka HTTPで作り込んでみた


こちらもPHPで作られた旧認証基盤を置き換えるというお話だったので、いろいろ思い出しながら聞かせて頂きました。プロダクションレベルでAkkaが導入された事例としても興味深かったです。


メタメタにしてやんよ。(メタプログラミングもしくは Shapeless のすすめ)

”入出力がデータではなくプログラム”であるマクロとして、Scalaマクロ(今は使ってはいけない)から、それに代わるScala.metaとshapelessの例をライブコーディングで見ることができました。

Scala & Sparkによるデータ・エンジニアリング 7大レシピ

組織でデータを集めて分析に使うために必要な7つの”レシピ”と、その解決方法を聞くことができましたが、前半のレシピにあったチームへの根回しやデータの品質を高める努力は海外でも同じだったのが意外でした。

ChatWorkのScala採用プロダクト “Falcon” リリースまでの失敗と成功の歴史

動いているサービスをScalaに置き換えるプロジェクトとしては国内有数の規模だったかと思われますが、それだけに苦労も多かった感じがひしひしと伝わる内容でした。

2日目

”アンカンファレンス”という、参加者の投票や参加者の中で発表したい(もしくは聞いてみたい)内容を当日決めるといった形式で行われました。

Ad Serving System on Finagle and Thrift

前日の講演でシリアライズライブラリーのThriftを多く見かけたので、使っている事例を聞こうと選択しました。シリアライズしたデータはMySQLのBLOBに入れる(=インデックス付きのKVS)ソリューションはおっと思いましたが、ScalaScriptをSQLのDML代わりに使う事で解決されたのが印象的でした。

採用担当者CTOぶっちゃけ座談会

各社の採用戦略や求められるエンジニア像が生々しく語られました。オフレコだったので詳しい内容は書けないものの、今回メモった量が一番多いセッションでしたw

Poorman’s Type Classes Revisited

Scala初学者が理解に苦しむ(らしい)implicitについて、なぜこれが導入されたのかをHaskellの例を交えて詳しく解説されました。実は1日目のReadable Scalaでもimplicitについては触れられてたのですが、その時は正直分からなかったのがこのセッションで何となく理解することができました。

JavaエンジニアのScalaの話が聞きたい

もともとJavaや他の言語で開発していた組織の中で、Scalaに変えるメリットや導入に関する悩みをざっくばらんにお話する(ちょっとだけ自分も混ぜてもらった)会でした。ScalaをFPで書くか"better Java"で書くかのさじ加減については、「ミッションクリティカルな部分はFP、(リリースの)速さを求められる部分は非FP」という回答が得られたのは個人的には収穫でした。

Lensの基本と基礎

最後のセッションは、「var使えばよくね?」という自分への戒めとして(笑)こちらを選択させて頂きました。”getter/setterを抽象化する”という例をライブコーディングを交えながらの講演で、こちらも理解できれば可能性が広がる感じがしました。
(LL言語のゆるふわなアクセスをカタい形で持ってくる理解、ではないんだろうな。。)

おわりに

今回初めての参加で多少背伸びし過ぎた感はありましたが、ここ最近自己研鑽の時間を疎かにしがちだったので、いい刺激をもらうことができました。
また、今まではAdTech界隈での採用事例が多かったところに、ぽつぽつ他業界でもScalaが採用されつつあるのが印象的でした。
(特にFOLIOさんのようなFinTech系企業でのScala採用は、Javaの牙城にどれだけ食い込めるのか気になります)

2016年12月25日

vimを使ってファイル名を一括変更(リネーム)する

複数のファイル名を一括変更(リネーム)する時、どういった方法で行わているでしょうか?
専用のリネームツールを使うのも一つの手ですが、自分はもっぱらvimとコマンドプロンプトを使った方法で行っています。この方法のメリットとして、

  1. 普段使い慣れたvimコマンドで編集ができる
  2. リネーム操作を(ある程度)やり直すことができる
  3. Windowsに限らず、MacやLinuxでも似たような操作で実行できる

があげられます。
今回は、録画データのファイル名をリネームする方法を例に取って説明します。

リネーム元ファイルパスの取得

まず最初に、リネームしたいファイル一式が格納されているフォルダーをエクスプローラーで開きます。
そこでファイルを全て選択し、Shiftキーを押しながら右クリックを押すと、「パスのコピー」という項目が出てくるので、それを選択してファイルパスをクリップボードにコピーします。
次にvimを開いて、先ほどクリップボードにコピーしたファイルパスをエディター上に貼り付けます。
この際、場合によっては名前順に貼り付いていない事があるので、SHIFT+Vキーを押してこれら全てを行選択し、:sortと入力して選択範囲をソートしておきます。

フォルダーパスの除去(リネーム元ファイル名のみに編集)

貼り付けた文字列を見ると、行毎に両端がダブルクォーテーションでくくられており、ドライブ名から親フォルダーまでのフルパスが記載されています。
リネーム作業自体には影響ないのですが、事故防止のためControl+Vキーを押してドライブ名から親フォルダーまでの部分を矩形選択し、dキーを押して削除しておきます。
これで、ファイル名のみがダブルクォーテーションでくくられた状態になるはずです。
削除が不十分orし過ぎた場合は、慌てずuキーを押してアンドゥ(元に戻して)やり直します。

リネーム先ファイル名の準備

リネーム元ファイル名の準備ができたところで、今度はリネーム先ファイル名を準備します。
番組名には、タイトルや話数の他にサブタイトルなどの情報がありますが、それらをExcelなどの表形式であらかじめまとめておきます。もしくは、インターネット上に同じく表形式でまとまっている場合、それらをクリップボードにコピーしてvimに貼り付けます。
今回はWikipediaの源氏物語より、各帖と名前を話数とサブタイトルに見立ててリネーム先ファイル名とします。
上記表をブラウザーで開いたら、左端の列から右端まで13行分をマウスでドラッグして選択し、クリップボードにコピーしvimに貼り付けます。

リネーム先ファイル名の形式

貼り付けられた文字列をよく見ると、各項目がタブ文字<TAB>で区切られているかと思います。
このように、特定の区切り文字を挟んで行列(行方向は改行)の形になっている文字列を別の形に整形する場合は、正規表現のグループ化による一括置換が便利です。
なお、リネーム先ファイル名は、以下のフォーマットで整形します。

”タイトル<SP>第00話<SP>「サブタイトル」.mp4”
<SP>は半角スペース
00の部分は、話数の番号を2桁でゼロパディングしたもの
サブタイトルは、全角の括弧でくくられるようにする
末尾には拡張子.mp4を設定

リネーム先ファイル名の整形

では実際の整形作業を行ってみます。
まず、第1話~第9話の部分に矩形選択を使って"0"を挿入しておきます。
次に、話数とサブタイトルを行選択し、:キーを押した後に一括置換の正規表現パターンを入力します。

'<,'>s/^\(.\{-}\)<09>\(.\{-}\)<09>.*$/"リネームされた番組名 第\1話 「\2」.mp4"/

'<,'>の部分が「現在選択されている行」を表し、それに対して一括置換"s"をかける宣言を行い、置換元のパターンと置換先のパターンを"/"で区切って入力します。
置換元パターンに含まれるタブ文字<09>は、\tではなくControl+vキーを押した後にTABキーを押して制御文字として入力します。なお、\{-}は最短マッチ(.*?)になります。

リネームコマンドライン文字列の作成

ここまでできたら、リネーム先ファイル名をControl+vキーを押して矩形(ビジュアル)選択し、リネーム元ファイル名の右隣にペーストします。両端の間の空白はいくつあっても構いません。
最後に、先頭行にカーソルを移動してControl+vキーを押し、最下行までカーソルを移動したらShift+iキーを押して"ren "(スペース入力を忘れないこと)と入力し、リネームコマンドを完成させます。

リネームの実行

リネーム元ファイル名とリネーム先ファイル名が一致している事を確認できたら、いよいよリネームコマンドを実行します。
リネーム元ファイル名が格納されているフォルダーを右クリックすると、メニューに「コマンドウィンドウをここで開く」という項目が出てくるので、それを選択してコマンドプロンプトを開きます。
コマンドプロンプトが開いたら、リネーム元ファイルが存在することを確認し、先ほど作成したリネームコマンドライン文字列を貼り付けてリネーム処理を実行します。

リネームに失敗した場合

万が一リネームに失敗していた場合でも、コマンドに誤りがない限りはファイルが消えたりすることはありません。
念のため話数とファイル名が一致している事を確認し、リネーム作業を最初からやり直せばOKです。

2015年11月15日

実家に格安SIM+Rasberry Pi+NUC録画機を設置した話


半年以上前の話になるのですが、この前の実家への帰省の際に地元のTVやラジオをいつでも視聴できるよう設置してきました。
(上の写真はその時参加したサイクリング大会のやつです)

構成

  • Pocket WiFi LTE GL06P
    • インターネットへ接続するルーター
    • ヤフオクで買ったやつ
    • 電源はコンセントから常時供給しておく
  • OCNモバイルONE
    • ルーターに入れる格安SIM
    • この価格帯でグローバルIPが振られるSIMはこれしかなさそうだった
  • Intel DC3217BY
    • TVやラジオ視聴を処理するNUC
    • 地デジ録画(SKNet Monster TV HDUSを接続)
    • FMラジオ受信(RTL2832Uチップ搭載のUSBワンセグチューナーを接続)
    • リモートから電源を入れられる対応を実施済み
  • Raspberry Pi 1 Model B
  • TENVIS JPT3815W
    • ネットワークカメラ
    • 両親の様子を、、じゃなくて単純に外の風景を撮影
    • DDNS更新をONにしてRasPiがDNS更新に失敗した時のバックアップも


帰省前の準備


普段使いのサーバーとかであれば自分で赴いてメンテナンスできるのですが、実家に設置となると気軽にそういう事はできませんので、いろいろな対策を考える必要がありました。
  • 問題が起こった際の復帰手段と予防策
    • SSH -R(autossh)などで、こちらから接続できない場合の別ルートの確保
    • 定期的な死活監視と週次での自動再起動
  • 両親のPCリテラシーは高くないので、細かい操作は期待できない
    • 電話口で機器の様子を見てもらったり、電源入れ直してもらったりする程度
  • 実家に負担がかからないようにする
    • 通信費→帯域やレイテンシー的に固定回線を引きたいけど格安SIMで代替
    • 電気代→サーバーは常時起動ではなく必要な時のみ電源を入れる/落とせる
これらのうち、事前にプログラミングや工作が必要だったものは自宅で行い、最終的な動作テストののち帰省数日前に梱包して送付しました。気分的には火星探査機を開発している気分です(笑)

設置後のトラブル


準備段階で気をつけていたつもりだったのですが、やはり完璧とはいかずさまざまなトラブルに見舞われました。
  • 無線LANの設定が自宅の設定のままになっている
    • 実家を出る数時間前に発覚
    • 急いで近くの家電量販店にキーボードとHDMIケーブルを買いに行って修正
      • 最近のTVはPCモニター代わりになって便利
  • ネットワークカメラの設置場所が不安定
    • 窓を開ける取っ手が邪魔、高さが足りず撮影できない
    • ホームセンターで板切れを買って棚を作り対応
  • ルーターの電源が落ちる
    • 自宅に戻って設定をいじってたら突然接続断
    • 仕方ないので実家に電話して見てもらったら”充電中”になってた
      • 通信し続けると充電を中断してバッテリー駆動になる?
一番致命的なのは最後のルーター周りで、録画データは一括送信できないのでsplitコマンドで50MBくらいに分割し、cronで間欠的に送信するようにしました。おかげで1時間番組を録画してもこっちで視聴できるまでに3日ぐらいかかります。。

また、レイテンシーの遅さも予想以上で、通信の少なそうな深夜帯でも500msくらいかかるので、リアルタイムに視聴する系はほぼ諦めてます。。

あとトラブルというわけではないのですが、実家の両親に火事の心配をされました。確かに機器は常時電源接続されており、特にルーターはリチウムイオン電池も入っているのでその辺の配慮が足りなかったのは反省点です。

おわりに

いろいろ問題はありましたが、なんとか最低限の目標は達成できました。ネットワークカメラも当初は固定で一場面の撮影のみでしたが、パンチルトを操作するAPIを使って二場面を撮影できるようにし、温度/湿度センサーの値を画像に合成するようにしました。
(「なんかカメラが定期的に首振るんだけど!」と実家から電話がかかってきましたがw)

来年の帰省の際は、グローバルIPを諦めてもっと安いSIMに乗り換える(IIJ系SIMはIPv6が使えるらしいけど。。)、RasPi側に録画視聴を集約する(RasPi2化する)あたりを検討中です。最近IoTが話題ですが、それらを考えるきっかけとしてもオススメです。