読者です 読者をやめる 読者になる 読者になる

mixi engineer blog

ミクシィ・グループで、実際に開発に携わっているエンジニア達が執筆している公式ブログです。様々なサービスの開発や運用を行っていく際に得た技術情報から採用情報まで、有益な情報を幅広く取り扱っています。

PyCon JP 2016 にダイヤモンドスポンサーとして参加してきました。

Hunza Django python recruiting

はじめまして、株式会社フンザの尾関と申します。

普段はチケットキャンプのサーバサイドをPython/Djangoで開発しています。
趣味はドローンでの空撮です。

エンジニアブログですが、技術的な話は特にありません。すみません。

 

9/21, 9/22の2日間、PyCon JP 2016という日本最大のPythonistaが集うカンファレンスに参加してきました。

 

当社では創業時からチケットキャンプのサーバサイドをDjangoで開発しており、我々のビジネスができているのも全てPythonという存在のおかげ!という思いもありまして、その恩返しとしてダイヤモンドスポンサーとして出資させていただきました。

 

個人的には、2013年と2015年に一般で参加したので雰囲気は分かっていましたが、今回はスポンサーとしてブースを出す!ということでまた違った視点から参加できました。

 

もちろん、ブースを出すからには、フンザという会社を知ってもらいたい!チケットキャンプを知ってもらいたい!いい人がいれば採用につなげたい!という目的があり、それを全面に打ち出すブースづくりを心がけました。

↓設営の様子

f:id:mixi_engineers:20160929190420j:plain

 

このあたりは、我々のようにイベント慣れしていない担当者が、初めてブースを出すことになった場合の参考に少しでもなればいいなと思って書いています。

と言っても、我々も反省点だらけでまだまだ改善の余地があるので、来年またスポンサーとして出展できるのであれば、もっと良い形にできるだろうと思っています。

ブースでやったこと 

f:id:mixi_engineers:20160929192200j:plain

話さなくても事業・社内の様子が分かるように

実際に開発者が使っている32インチ4Kのディスプレイを2台持ってきて、片方はTVCMの動画を流すことで事業の紹介と、もう片方は社内イベント・社内風景などの様子も流して、会社全体の雰囲気が伝わるように心がけました。

けっこう立ち止まって見てくれる方もいらっしゃったり、実際にお話したときに「楽しそうな職場ですね」と言って頂けたりしたのでこれは見る側としても良かったんじゃないかと思いました。

ブースに来てくれた方にプレゼント

これはやっぱりノベルティですね。今回は奮発してTシャツとステッカーを配りました。1日目に配ったものを2日目に着てくれていた方もいて、配っているこちら側も嬉しい気持ちになれました。

さらに、『積極採用中!』と記載された名刺サイズのカードも沿えて配りました。これは『よくある採用のチラシを配っても、正直あまり見られない』と親会社からアドバイスをうけて作りましたが、配る方も配りやすく、もらう方も負担にならないのでかなり良かったんじゃないかと思いました。

実際に渡したデザインがこちらです。必要なメッセージだけに絞っています。

f:id:mixi_engineers:20160930170054p:plain

キャラクターで認知してもらう

他の企業を見ていると、特に、モノタロウさんはすごく良く出来ていて、というかモノタロウ侍のマスコットだけで、参加者の心を鷲掴みにしていましたね。やっぱかわいいゆるキャラはみんな好きですよね。

去年のPyConでも人気者でしたし、当然今年もモノタロウ侍が会場に来ることは分かっていたので、我々も負けじとチケットキャンプのマスコットであるチケキャン犬というキャラクターでアピールしました。

 

モノタロウ侍とのコラボ。チケキャン犬の彼ももちろんエンジニアです。

現在はもう契約上、動画は載せられませんが、、実はこれ、小島瑠璃子さんがCMで実際に着ていた衣装です。なんだか台無しにしてしまった気もするので、ファンから怒られないか心配です。気になる方はググってください

PyConJP2016に参加されている方への印象

ありがたいことにそんなブースに足を止めてくださった方も多く、様々な方とお話させていただきましたが、今年は思った以上に学生さんが多い印象でした。

聞けば、大学の研究で機械学習を使っていて、それをPythonで書いているという方の多いこと多いこと!

去年参加した時も、機械学習系の方が多い印象でしたが、今年はさらに多く、また傾向としては『機械学習』がメインの研究テーマというよりも、何か別の研究テーマがあって、その精度を上げるために機械学習を用いているという方が多く、かなり実用的なところで使われているんだなぁと関心しました(小並感) 

一方、アプリケーションエンジニアとしてPythonを使っている企業というのは日本ではまだまだ少ないなぁという印象でした。

弊社の発表 

2日目にジョブフェアというセッションがあり、お昼ごはんを食べながら企業の話を聞く機会がありまして、そこで弊社CTOの酒徳もパネルディスカッションに参加しました。

f:id:mixi_engineers:20160930141548p:plain

企業のブースで直接話を聞くのは緊張するけど、企業側の話を聞きたいという方にとってはすごくいい機会になりますね。

 

また、弊社エンジニアの小松もLTに登壇しました。こちらは動画・資料も公開されています。 

www.youtube.com

 

2日目のLT終了後、プレゼントのコーナーがあり、受け取ると景品がもらえるカラーボールを弊社の小松 チケキャン犬くんが頑張ってたくさん投げていました。受け取れた方、おめでとうございます。 

f:id:mixi_engineers:20160930144544p:plain

まとめ&所感

Everyone's different, all are wonderful.「みんなちがって、みんないい」

今年は上記のテーマで開催されたPyConJPでしたが、実際に業務でPythonを使っている身としては、こういうコミュニティを通して知り合いを増やし、楽しく仕事や相談の出来る仲間が増えるといいなと思っていまして、その受け皿としてこのコミュニティはとても居心地がよく、今後もPyConJPに参加していきたいなと思った所存でございます。

 

最後に 

最後まで読んで頂き、ありがとうございました。

 

株式会社フンザはPythonエンジニアを大募集しています。

もし興味がありましたらご連絡ください!

 

ノハナ開発品質向上合宿を行いました

こんにちは、side_tana です。まずは画像を見ていただきたいのですが、こういった活動を行ってきました。

f:id:mixi_engineers:20160329123640j:plain

最高ですね。ノハナでは 3月16日から18日にかけて、湯河原温泉のおんやど恵さんで開発品質向上合宿を行ってきました。

開発品質向上合宿とは

ソフトウェア開発を行う中で様々な課題と向き合う必要があります。例えばテストが薄い箇所の改善や古くなったドキュメントの整理、短期的な課題解決のため少々強引に変更を加えられた箇所の修正といった課題です。しかしながら、これらの課題と並行して日々の運用や機能追加といった業務をこなす必要があり、多くの場合短期的に優先度の高い運用や開発業務が優先されることになります。その結果として、開発に関わる困難に取り組む時間は限られてきます。

そこでノハナでは、エンジニア開発品質向上合宿という形でそれらに集中できる場所と時間をつくってみました。

進行

f:id:mixi_engineers:20160329120135p:plain

会社で開発合宿を企画するのは意外と労力がかかります。企画における労力を圧縮するため、今回は

  • ミーティングはキックオフと合宿後の振り返りのみ
  • あとはSlack中心に進め、決まったことをtrelloでカードにし、担当者をアサインする

といったアプローチをとりました。とはいえ宿や施設の調整・経路の確保など、事前の作業が多いものは負荷が高くなりがちなので、そのあたりは今後改善が必要といえます。

宿決め

いくつかの宿をリストアップし検討したのですが、今回はおんやど恵さんを利用させていただきました。ポイントとしては

  • 開発合宿プランがある
  • 無線LANが利用できる
  • 机と椅子が利用できる
    • 座敷での長時間作業は結構つらい
  • 温泉が深夜まで利用できる

といったところになります。コンビニまでの距離(徒歩15分弱)が少し気にかかったのですが、おんやど恵さんの食事が非常に豪華だったため、間食などのためコンビニに行くということはほとんどなく、問題にはなりませんでした。

www.onyadomegumi.co.jp

様子

f:id:mixi_engineers:20160329123846j:plain
初日は新宿駅に集合

f:id:mixi_engineers:20160329123714j:plain
ロマンスカーで小田原まで移動中の様子

f:id:mixi_engineers:20160329123948j:plain
宿へ到着

f:id:mixi_engineers:20160329123718j:plain
作業スペースとしてお借りした会議室はこんな感じ

f:id:mixi_engineers:20160329123726j:plain
初日の夕食(これでも一部です!)

f:id:mixi_engineers:20160329123722j:plain
二日目の夜は懇親会をしました。エンジニアの懇親会ですからやることといったらLTです。

f:id:mixi_engineers:20160329124202j:plain
最終日はチェックアウト後、小田原駅まで戻り貸し会議室で作業を続けました。

まとめ

日々の業務から離れ、割り込み作業の発生しにくい環境をつくることにより、

  • リファクタリング
  • テストの拡充・CIの追加
  • 開発ツールの更新とそれに合わせた社内ライブラリのメンテ
  • ドキュメント整理

といった作業に集中して取り組むことができ、当初の目標だった「開発品質の向上」「継続的に改善をしていくための土台作り」に対して一定の成果を得ることができました!

おわりに

f:id:mixi_engineers:20160326164045j:plain
合宿での思い出はフォトブックに!

ノハナでは一組でも多くの家族に笑顔を届けるために困難に立ち向かうエンジニアを募集しています!

Android・iOSエンジニア【Android・iOSエンジニア】さらなる飛躍のための自社サービスのグロースハック、新規事業の創造に興味あるスマホアプリエンジニア募集!!

Apple IPv6審査対応 NAT64/DNS64環境構築について

ipv6 nat DNS iOS Android

こんにちは、arukasaです。

今回IPv6 (NAT64/DNS64) のWi-Fi環境構築という貴重な経験をしましたので、情報共有を兼ねて寄稿させて頂きます。

背景

Appleが、2016年1月以降はIPv6環境で動作しないアプリはリジェクトすると宣言しましたので、ミクシィ社内でもその検証環境が必要になりました。

現時点ではApple側も回線から上位はv4想定のようなので、検証環境もそれに倣いLAN側はIPv6、WAN側はIPv4の構成を取りました。

構成

f:id:mixi_engineers:20160106210856p:plain

ネットワーク

  • uplinkはIPv4 only
  • クライアントはIPv6 only
  • サーバとASA間のみv4&v6 併用

機器構成

  • ASA 5505 ( NAT64 )
  • Raspberry Pi
    • DNS64 (unbound 1.5以降)
    • RA (radvd)
  • Aruba (Wi-Fi)

実は構成が確定するまでが一番苦労した部分で、当初導入予定だったDHCPv6 (isc-dhcp-server)やASAでのRA送出、BINDには色々な制限が有り、期待した機能を満たしていない事が動かしてみて初めてわかりました。この辺りの経緯は最後の【ハマったこと】に纏めています。宜しければご参照ください。

※ 以下に記述する手順はインターネット上の情報を多数参考にしています。
※ 環境の違いによって意図しない動作をする可能性も有ります、ご了承ください。
※ 間違い・改善出来る部分など多々あるかと思いますのでご指摘頂けると非常に有りがたいです。

以下configです。

ASA

まずASAから設定します。

先述の通りRAのやり取りはRaspberry piのradvdで行いますので、必要最小限のアドレス設定と、NAT64の設定です。RAの送出も抑止しています。

outsideはキャリアのDHCPサーバーからグローバルのIPv4アドレスを受け取っています。

IP設定

interface Vlan214
nameif inside02
security-level 0
ip address 10.10.214.1
ipv6 address face::10:10:214:1/64
ipv6 enable
ipv6 nd prefix face::/64 no-autoconfig
ipv6 nd suppress-ra 0 

interface Vlan2999
nameif outside01
security-level 0
ip address dhcp setroute

NAT64

IPv6をoutsideのIPv4アドレスにNAT64しています。 またRaspberry PiがIPv4でDNSを聞きに行く為、IPv4アドレスもNATします。

object network REAL_IPv6
 subnet face::/64
object network REAL_IPv4
 subnet 10.10.214.0 255.255.255.0
object network DNS64_range
 subnet cafe:ff9b::/96

nat (inside02,outside01) source dynamic REAL_IPv6 interface destination static DNS64_range any
nat (inside02,outside01) source dynamic REAL_IPv4 interface

ASAは以上です。あとは必要なセキュリティの設定と、物理インターフェースに各interface Vlanを割り当てます。

Raspberry Pi

unbound

unboundは1.5以降のバージョンからDNS64対応ですが、apt-getでは1.4系のパッケージしか無いため、ソースコードからインストールが必要です。ただし必要なパッケージが無いと多大な時間を浪費する事になります (当方はここでハマりました)。

raspberry-piの場合はlibssl-develが必須のようです。

他の手順は以下を参考にしました。

 

unbound.conf

server:
verbosity: 1
pidfile: "/var/run/unbound.pid"
use-syslog: yes
module-config: "dns64 iterator"
dns64-prefix: cafe:ff9b::/96
dns64-synthall: yes
interface: ::1
interface: face::10:10:214:235
access-control: ::0/0 allow 

forward-zone:
name: "."
forward-addr: 8.8.8.8
  • dns64-synthall: yesで、すべての問い合わせをDNS64変換するという実装になります。これをしないと、問い合わせた外部サイトがv6アドレスを持っていた場合、cafe:ff9bではなく生v6アドレスをクライアントに返してしまいます。BINDではここの実装がクリアできず、unboundに変更しました。
  • IPv6への移行という観点から言うとAAAAで接続出来るサイトにはv6通信出来た方が良いのかもしれませんが、今回はApple推奨環境と同様の動作をする環境構築が目的なので、あえてunboundを採用しています。
  • prefixをcafe:ff9b::/64にしているのは、ASAがwell-known-prefixを指定してNATできない仕様のためです。

以上でunboundは動作すると思います。

次はradvdでクライアントへIPv6アドレス、DNSサーバー、デフォルトゲートウェイを通知します。

radvd

こちらもapt-getできるバージョンが古い為、念のためソースから最新版をビルドします。以下を参考にしました。

Cross Compiling Radvd for ARM - BeyondLogic

radvd.conf

interface eth1 {
AdvSendAdvert on;
IgnoreIfMissing on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
AdvDefaultPreference high;
AdvHomeAgentFlag on;

#フラグの設定

AdvManagedFlag off;
AdvOtherConfigFlag off;

prefix face::/64
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
};

#DNSの通知

RDNSS face::10:10:214:235
{
AdvRDNSSPreference 8;
AdvRDNSSOpen off;
AdvRDNSSLifetime 30;
};
};
  • Raspberry PiのデフォルトゲートウェイはASAに向けてください。
  • ここで設定したフラグの値でクライアントはRAを参照するのかDHCPを参照するのかが決定されます。今回の場合は全てRAを参照させたいので、M flagとO flagを共にOFFにします。
    ただし先述の通り、この設定によりWindowsに自動設定させる事はできなくなりますので、Windows側でオープンソースのアドオンを入れるか、DNSサーバーの情報は手動設定してください。
    rdnssd-win32 download | SourceForge.net
  • iPhoneやAndroidを繋がず、Windows PCやMacだけで良い場合はOフラグをonにし、isc-dhcp-serverでDNSを通知すれば自動接続出来るようになります。 

Raspberry Piは以上です。

Aruba

今回ASAからArubaまで全て同一VLANのL2構成での使用の為、IPv4と比べて特別な設定は必要ありませんでしたが、いくつか注意が有ります。

  • ipv6 enable
    この設定が入っていないと無線側がL2構成であってもIPv6のFirewall Processが働かず、正常に通信出来ません。
  • Valid user (ACL)
    ここがホワイトリストのような役割を果たしており、導入したOSバージョンによっては一定の制限が掛かっています。通信させたいセグメントを許可するように設定変更してください。
  • RA-Guard
    クライアント側から意図しないRAが発せられた時に、それをブロックします。アクセスリストに以下の記述を組み込んでください。
    ip access-list session ra-guard
        ipv6 user any icmpv6 rtr-adv deny

あとはIPv4と同じようにSS-IDを作成すれば接続できるはずです。

 

これで以上です。以下は苦労した点やハマった点などを記載します。

ハマった事

NAT絡み

  • NAT64が上手くいかない → source addressだけでなくdestの改変も必要だった。
  • well-known-prefixをDNSマッピングに指定していたがASAではNATに指定できない仕様だった

DHCPv6(isc-dhcp-server)やRA絡み

  • ASAでDHCPさせようとしたが、そもそもDHCPv6対応していない(ipv6 dhcp relayのみ対応)
    → dhcpをrelayしてRasperry PiにDHCPv6させようとする(当初raspberry piとクライアントは別セグメントだった為)
    → isc-dhcp-serverがIPv6で起動できない
    → v6起動のオプションが必要
    sudo vi /etc/init.d/isc-dhcp-server
    OPTIONS="-6"
    → 起動したものの、Androidだけ接続出来ない
    → 調べるとIPv6アドレスは取れているが、v6のDNS情報が通知出来ていない様子
    → AndroidはDHCPv6非対応の為、RAでDNSサーバー情報を渡さなければならない
    Comparison of IPv6 support in operating systems - Wikipedia, the free encyclopedia
    → RAでDNS情報を通知する為にはRFC6106をサポートした製品が必要になり、まだ多くのネットワーク製品がサポートしていない。
    インターネット用語1分解説~RA (Router Advertisement; ルータ広告)とは~ - JPNIC
    Firewall IPv6 Capabilities: Cisco, Forti, Juniper, Palo
    → 今回はアドレス情報やDNS情報のやり取りはASAではなくRaspberry Piのradvdに任せて、ASAは出口のNAT専用機とする事に変更。

DNS絡み (BINDの問題)

  • 問い合わせた結果AAAAで返ってきたアドレスはDNS64変換されず生のAAAAレコードをクライアントに返してしまう
  • ASAのNATでDNS64レンジを宛先に指定する必要があるためNG
  • unboundなら "dns64-synthall" というオプションがあるようなのでunboundに変更

無線絡み

  1. L2構成の場合ArubaのコントローラにIPv6アドレスを振らない為、IPv6を有効にする必要が無いと勘違いしていた。
  2. IPv6 enableを設定しないとFirewall(v6)も動作しない事を知らなかった。
  3. 運用中の実機のため、迂闊にIPv6 enableなどの設定変更が行えなかった。
  4. IPv6 enableを投入したものの、未だにACLに引っ掛かり通信出来ない
  5. valid userの設定変更が必要だと気づく

機器の実装の違い (最大の難関)

  • WindowsはDNS情報の通知にDHCPv6を使用しなければならないが、
  • AndroidはRAを使用しなければならない。
  • iPhoneはどちらでも構わないが、RAのやり取りが不安定で接続出来たり出来なかったりする。

以下まとめです。

  • Windows
    • RA(IP取得): OK
    • RA(DNS取得): NG (wikipediaより, 上記アドオンインストールで取得出来るようになるようです)
    • DHCPv6(DNS取得): OK
    • v6手動設定: OK
  • Android
    • RA(IP): OK
    • RA(DNS): OK
    • DHCPv6(DNS): NG
    • v6手動設定: 不可
  • iPhone (Mac OS X)
    • RA(IP): OK
    • RA(DNS): OK
    • DHCPv6(RA): OK
    • v6手動設定(DNSのみ): OK

上記よりWindows側が手動やアドオンなど頑張れる要素が多い事と、Appleの推奨環境もそういった構成を取っている為、それに倣いました。

情報の不足

海外サイト、国内サイトを含めて中々必要な情報が得られない状態でした。特に国内のサイトには一通りの情報をまとめているサイトが数える程しか無く、情報収集に苦労しました。

まとめ

Android・iOS・Windowsなどデバイス、OSによってサポート、非サポートな部分の違いが多数有る事がわかりました。本構成ではWindowsの標準機能でDNSサーバーを渡す事が出来ない点が、依然課題として残っています。(Windows側でアドオンをインストールするか、DNSのみ手動設定という手段で何とか接続させています。)

機器毎に実装が大幅に異なるIPv6が、本当にこのまま普及するのか疑問です。現状はappleが普及に向けた先導をしているように見えますが、Google, Microsoft等、業界大手が足並みを揃えなければ世界的な移行は難しいのでは無いかと思います。

謝辞

今回の構築にあたり加藤さん、吉野さんにはお忙しい中、多大なるご協力を頂きました。私一人では完成まで辿り着けなかったと思います。

本当にありがとうございました。

総行数57,000の巨大CSS群をLessに書き換えた軌跡

CSS CSSプリプロセッサ mixi LESS

こんにちは!フロントエンド闇祓いの Kuniwak です。
この投稿はmixiグループ Advent Calendar 2015の20日目の記事です。

今年の9月に、スマートフォン Web ブラウザ版 mixi「mixi Touch」の巨大 CSS を Less (CSS プリプロセッサー)でビルドする環境へと移行しました。 書き換えた CSS の行数は、なんと 56,725行 です。😵

ということで、今回は弊社の大規模 CSS → Less 移行事例についてお話しします。

背景

スマートフォン版 mixi は、2010年5月に始まりました。 この頃のスマートフォンは、iPhone 端末であれば iPhone 3GS、Android 端末であれば Nexus One という時期です。 また、スマートフォンの世界では、Webkit ベースのブラウザーが席巻していた時代ということになります。

そのため、当時の CSS は Webkit ベースのブラウザーのみを考慮した書き方が多く見られました。たとえば、次のような -webkit- プレフィックスを使った書き方です:

/* 非標準の CSS プロパティ fuga を使う場合の書き方 */
.hoge {
  -webkit-fuga: moge;
  fuga: hoge;
}

この -webkit- プレフィックスは非標準(または実験段階)の機能などを先行して利用するためのものです。 ただし、実験段階の機能ということだけあって、標準化される過程で CSS プロパティの名前が変わったり、別仕様に取り込まれてしまったりするリスクがあります。

そのため、-webkit- のようなベンダープレフィックスを使うためには、変更されたときの影響を小さくしたり、書き換えを楽にするような工夫が必要とされます。

しかし、当時の弊社の CSS では、次のような悪い書き方が散見されました:

/* 潜在的な問題を抱えたコード */
.something {
  -webkit-background-size: 8px 8px;
}

このコードは、当時のモバイルブラウザーであれば意図通り表示されることでしょう。 しかし、この書き方には3つの潜在的な問題があります。

  1. 非 Webkit ベースのブラウザーを考慮していない
  2. -webkit- つきのプロパティが標準になったときの書き換えが大変
  3. -webkit- つきのプロパティが非標準になったときの書き換えが大変

当時から問題は認識されていたものの、問題への対処は見送られていました。
そして、5年経った今になって、この3つの問題が顕在化したのです。

この問題の解決のために、HTML コーダー(マークアップエンジニア)2名 + 技術支援1名 + テスター1名の体制で対応作業を始めました。

問題1: 非 Webkit ベースのブラウザーを考慮していない

-webkit- プレフィックスをつけたプロパティは、非 Webkit ベースのモバイルブラウザー(Android 版 Firefox や Windows Phone の IE など)では解釈されません。 しかし、これらのシェアが小さいためか、-webkit- プレフィックスのみの CSS が世に溢れています。

そこで動き出したのが Mozilla です。 Mozilla には WebCompat Team なる部署があり、-webkit- のみの CSS を使っている Web サイトへの啓蒙活動をしているそうです(Mozilla の方による記事 WebCompat)。 mixi に対しても Mozilla からのコンタクトがありましたが、あまりの -webkit- プレフィックスの多さから見送られた、苦い記憶があります。😢

また、啓蒙活動とは別に、Firefox のコード側にも動きがありました。 それは、特定のドメインの CSS では、-webkit- プレフィックスを外して解釈するというものです。 つまり、ドメインによって CSS の解釈が変わることになります。 この動きについては Mozilla 側の対応チケットを見ると何がおこなわれたのかわかります。

実は、この Mozilla 側での動きが、Less 化の強い動機になりました。 これは、弊社のステージング用の環境では専用のドメインが使われていることに起因します。 そのため、本番環境とステージング環境での CSS 解釈に差が出てしまうのです。 これではステージング環境の意味がありません。

つまり、非 Webkit なブラウザーに注意を払わなかった結果、ブラウザーベンダーがお怒りになり大変なことになったのでした。

問題2: -webkit- つきのプロパティが標準になったときの書き換えが大変

ベンダープレフィックスつきのプロパティは、そのまま標準化されることがあります。 この場合、-webkit- をつけたままのものは廃止予定(deprecated)になります。 そのため、「最後にプレフィックスなしのプロパティを付け加える」ことで、標準化されたものを優先的に利用する書き方が推奨されています。

.something {
  -webkit-background-size: 8px 8px;
  background-size: 8px 8px;
}

しかし、弊社の CSS には、プレフィックスなしのプロパティを併記しないものが多く見られました。 このような CSS がおよそ 57,000 行もあるのですから、推奨されている書き方に直すのも大変です。

つまり、推奨される書き方に従わないままコードが育っていった結果、推奨の状態に戻すことが困難になっていました。

問題3: -webkit- つきのプロパティが非標準になったときの書き換えが大変

ベンダープレフィックスつきの機能が標準化される過程で、CSS プロパティの指定方法が変わったり、機能自体が削除されることがあります。

たとえば、mixi の CSS には、相当前に非標準となった box 仕様のプロパティが使われていました。 この件は Mozilla でも問題になっていたらしく、「mixi.jp Mobile version is using the old-old CSS webkit flexbox syntax」というチケットがつくられており、個人的にはとても恥ずかしい気持ちでいっぱいでした。

このような機能は廃止予定になることが多く、何かの拍子に取り除かれてしまっても文句は言えません。 そのため、廃止予定になった時点で書き換える必要があります。 しかし、既に行数が膨らんでしまった CSS を仕様変更の都度に書き直すのは大変です。

まとめると、非標準な機能を多用すると、非標準の機能が消されることに怯える日々を過ごすことになることがあります。

問題への対処の軌跡

救世主 Autoprefixer

これらの問題に対処するために、Autoprefixer というツールを使うことにしました。 Autoprefixer は、指定した環境に合ったベンダープレフィックスを自動的につけてくれるツールです。

/* Autoprefixer 適用前 */
.example {
   background-image: linear-gradient(#e87451, #c42f02);
}
/* Autoprefixer 適用後 */
.example {
   background-image: -webkit-gradient(linear, left top, left bottom, from(#e87451), to(#c42f02));
   background-image: -webkit-linear-gradient(#e87451, #c42f02);
   background-image: -moz-linear-gradient(#e87451, #c42f02);
   background-image: linear-gradient(#e87451, #c42f02);
}

この Autoprefixer を使うと、問題の1と2を解消できます。 問題3についても、Autoprefixer が可能な限り標準の書き方へと変換してくれます。

ただし、Autoprefixer は既にベンダープレフィックスがついているプロパティに対しては何もしません。 そのため、前作業として CSS のベンダープレフィックスを外すように書き換える作業が必要になります。

CSS:fixme で Autporefixer の下ごしらえ

前述の通り、Autoprefixer の下ごしらえとして、既存の CSS からベンダープレフィックスを取り除く必要があります。

このために、CSS:fixme というツールを使いました。 このツールは Mozilla の方が開発しているオープンソースのツールで、ベンダープレフィックスつきの古い記法を、Autoprefixer にかけられるような記法へと変換してくれます。

ただし、巨大なファイルで作業するにはコマンドラインによる変換の方が便利だったため、魔改造をおこないました(魔改造後のコードは MPL ライセンスにしたがって公開しています)。

また、CSS:fixme で変換されないものもありました。 変換されない理由は、未標準だからか、変換対象から漏れていたかのどちらかです。 この部分は、マークアップエンジニアの方と細かく結果を確認しながら作業を進めました。

このベンダープレフィックスを外す作業が、全体のおおよそ半分を占めています。

Less 導入

さて、救世主 Autoprefixer を使うためには、CSS をビルドする必要が生じます。 そして、どうせビルドするならということで、CSS の表現力を補う CSS プリプロセッサー Less を導入しました。 つまり、Less 移行は、Autoprefixer 導入のついでという側面が強かったのです。😜

さて、CSS から Less へ移行すると変数が使えるようになります。 これによって、保守性を格段に向上させられます。

たとえば、カラーレギュレーションの色を変数にしておくだけでも、管理しやすいことは明らかです:

//- `@basicTextColor`: 基本のテキストカラー
@basicTextColor: #333;

//- `@subTextColor`: 基本よりすこし弱め
@subTextColor: #666;

// ...

カラーレギュレーション以外にも、アイコンフォントのコードポイントを変数によって集中管理しています。また、私個人としては z-index についても変数で管理することを目指しています。

さて、Less の他にも Sass という有名な CSS プリプロセッサーがあります。ここで Sass ではなく Less を採用した決め手は、それぞれの提供されているエコシステムにあります。 Sass は Ruby のエコシステムで提供されていますが、Less は Node.js のエコシステムで提供されています。 そして、Node.js の方が、Perl と同居させるのに都合がよかったのです。

-webkit-box との格闘

これで平和が訪れるかと思いきや、-webkit-box という厄介な問題が立ちはだかりました。

この -webkit-box は、横並び/縦並びの要素の表示制御に関する機能です。 これと同等の機能を実現するためには多大な労力が必要なため、非標準だった当時から重宝されていました。

ただし、この仕様は box(2009年)→ flexbox(2011年)→ flex(現在の最終草案の仕様)と 3 度大きく変更されました(仕様の変遷については flexboxの旧仕様、改定仕様、現行仕様の一覧 « LINE Engineers' Blog という素晴らしいまとめ記事があります)。 そして、-webkit-box はこのうち最も古い仕様で、Autoprefixer が適用できる状態にするには大幅な書き換えが必要です。

たとえば、CSS:fixme は可能な限り -webkit-box を最新の仕様である flex に書き換えてくれます。 しかし、display: -webkit-box があたっている要素の子要素の width に問題が生じます。

-webkit-box 仕様では、width が指定されていれば flex-basis 指定と同等の効果がありました。 しかし、flex を使う時には明示的に flex-basis を記述しなければなりません。

すると、CSS:fixme が width プロパティに遭遇したとき、これが flex-basis に相当するのか、それとも通常の width なのかを区別する必要があります。 このような書き換えは、セレクタの対象の親子関係を考慮できなければ実現できません。

/* ... */

.moge {
  /* 
   * この width の意味は、親要素に display: -webkit-box が
   * あたっているかどうかで変わってしまう
   */
  width: 10px;
}

/* ... */

つまり、BEM のような命名規則で CSS から親子関係を推測できない限り、機械的な検証は困難です。 この問題は、2人がかりでのコードレビューと、凄腕テスターによるステージング環境での動作確認で洗い出しました。

このような QC(品質管理)作業に、残り半分の作業時間が費やされています。 この甲斐あって、57,000 行に渡る書き換えにもかかわらず、不具合報告はきていません。

Less 化における QC への技術的支援

これまでの作業で、Autoprefixer による問題解決が実現できました。 しかし、このままでは、まだ Less の機能を活用できていません。 宝の持ち腐れの状態になっています。

そこで、次のフェーズとして、Less の機能を利用するようにリファクタするフェーズがはじまりました。

このフェーズでは、生成される CSS が変わらないことを期待できます。すると、CSS の AST(抽象構文木)による比較が可能になります。AST による比較では、CSS 内の改行位置や空白の取り方に左右されないため、よりブラウザーの CSS 解釈に近しい結果がえられます。この AST がリファクタ前後で変化していなければ、表示に差異がでないことが期待できます。

ただし、Less のような CSS プリプロセッサーを使えば、AST に差は出てしまうものです。 この AST の差で重要なのは、セレクタ・プロパティの過不足と、ルールの記述順序の2点です。

ここで重要なのは、この2点の深刻度に違いがあることです。 たとえば、セレクタ・プロパティの過不足は、記述漏れの可能性を強く示唆します。 これに対して、ルールの記述順序の差は、スタイルの上書きの可能性を示唆するものの、影響はごく軽微です。 この2つを混同してしまうと、深刻度の高い警告が深刻度の低い警告に埋もれてしまうといった問題が生じてしまいます。 ようするに、この2つは分解して観察することが重要なのです。

そして、既存の CSS の AST 比較ツールには、プロパティの過不足とルールの記述順序を分解して比較できるツールが存在しませんでした。 そこで、css-semdiff というツールを開発しました。

たとえば、css-semdiff を使うと、次のようにプロパティの過不足が発見できます。 このプロパティの過不足は、ルールの記述順序に影響されません。

$ css-astdiff a.css b.css --verbose
extra:
        #header ul {
          display: -webkit-box;
          display: -webkit-flex;
          display: -moz-box;
          display: flex;
        }

missing:
        #header ul {
          display: -webkit-box;
          display: -webkit-flex;
          display: flex;
        }
23 extra rules and 23 missing rules between a.css and b.css

また、ルールの記述順序の差異のみを発見することもできます:

$ css-orderdiff a.css b.css --verbose
order changed: #footDisplay
        become to be higher than:
                .error #mainDisplay,
                .webView01 #mainDisplay

order changed: .error #mainDisplay
        become to be lower than:
                #footDisplay

このフェーズでは css-semdiff を活用した結果、複数の不具合を未然に防止できました。 この css-semdiff は、MIT ライセンスで公開しています。 ぜひ、QC 作業にお役立てください!

後日談

この話は、私が新卒だったころに諦めた Firefox 対応を、1年越しに達成した話でもあります。それだけに、個人的にも思い入れの深い仕事です。

ちなみに、この作業を終えたところ、Mozilla の方からお礼のお返事 をいただきました。

This is fixed. \o/
Thanks to Mixi team and their hard work.

With a lot of love from Mozilla.

この仕事に携われてよかったと思えた瞬間です。😝

まとめ

弊社のスマートフォンページでは次の3つの問題が生じていました。

  1. 非 Webkit ベースのブラウザーを考慮していない
  2. -webkit- つきのプロパティが標準になったときの書き換えが大変
  3. -webkit- つきのプロパティが非標準になったときの書き換えが大変

そして、これらの問題を次のようなツール/活動で解決したという話でした。

  1. Autoprefixer
  2. CSS:fixme
  3. コードレビューなどの QC 活動
  4. css-semdiff

次は esugita さんの「Find Job!っていう求人メディアに関わってるので、採用とかとか。」です。

宣伝

ミクシィでは、技術を駆使して負債に立ち向かう闇祓いエンジニアをいつでも歓迎します! 闇祓いスキルをつけておくと、光環境/闇環境を選ばない技術力がつくことでしょう。

ともに闇祓い、してみませんか?

#師弟登壇2015 でミクシィの新卒研修について発表してきました

education

side_tana です。年の瀬も押し迫ってまいりましたが、みなさまいかがお過ごしでしょうか。

さて、12月6日に行われたGMOペパボさん主催の勉強会、師弟登壇2015でミクシィの新卒研修について発表をしてきましたので、本日はそのご報告です。
pepabo.connpass.com

師弟登壇という名の通り、講師側と新卒側の人間が二人一組となって発表する勉強会です。弊社からは 師匠 kuniwak とその弟子 side_tana というコンビで発表を行いました。

発表では、ミクシィの新卒技術研修の方針である「現場がおしえる・自分でそだつ」を軸として、

  • 新卒研修全体のフロー
  • 技術研修に対する考え方
  • ミクシィの公開している教材の作成過程・教材を公開する意義
  • 研修を受けてみて感じたこと

といったテーマについて話しました。

speakerdeck.com


speakerdeck.com


参加してみての感想ですが、各社の新卒研修の内容から、それぞれの会社の特色や、新卒採用に対する考え方の違いなども透けて見えるようで非常に面白かったです。

ところで弊社では2017年度の新卒採用活動をスタートさせております。ミクシィならではの研修を準備するつもりですので、弊社に興味のある方は以下からエントリーしていただければと思います。

mixi.co.jp

See Also

発表資料中で紹介している資料と、資料公開時のブログポストです。

alpha.mixi.co.jp

alpha.mixi.co.jp

また、githubのmixi-incではその他の教材や、先日行ったgit challengeの問題の一部も公開していますので、ぜひご覧ください!

github.com

第1回git challengeの出題内容を一部公開します

git seminar

2015年11月15日、ミクシィ渋谷オフィスで git challengeという学生向け技術イベントの第1回を開催しました。#mixi_git

この git challenge とは、問題がおきている Git リポジトリを、次のようなお題に沿って解決していく競技です。

  • うまく merge してください
  • バグが埋め込まれた場所を特定してください
  • push できない原因を特定してください
  • ...…

第1回の当日は、このような問題が18問出題され、4時間の競技時間でどこまで解けるかを競いました。ここで出題された問題の難易度は、以下の4段階に設定されています。

  • EASY: 調べなくても解ける
  • NORMAL: 調べれば解ける
  • HARD: 調べた上で考えれば解ける
  • VERY HARD: 考え尽くした上で最善の手を選び続ければ解ける

この記事では、このうち実際に出題された問題を 2問 (EASY, NORMAL) 公開します。

ぜひ、チャレンジしてみてください。

f:id:mixi_engineers:20151119181238j:plain

問題

なぜか新しいファイルを追加できないリポジトリ(難易度: EASY)

続きを読む

学生向けイベント「git challenge」のご案内

git seminar recruiting

第3回git challengeを開催します!

2016/8/21に、第3回git challengeを開催します!
参加エントリーはこちらからどうぞ!


f:id:mixi_engineers:20160307143957j:plain

f:id:mixi_engineers:20160307144002j:plain

f:id:mixi_engineers:20160307144006j:plain

今回の開催においても、チームごとに問題数だけ必要なprivate repos, およびノベルティをGitHub Japanさまにご提供いただいています。ご協賛ありがとうございます!

はじめに

人事 & イノベーション・センター 森本です。

株式会社ミクシィ (ミクシィグループ) では、皆さんにおもしろいスキル体験をしていただくため、そして意欲やスキル・センスある学生さんたちとの出会いのために、さまざまな学生向けイベントを企画・実施しています。

セキュリティ・バグをわざと入れたSNS mixiを攻略していただく「Scrap Challenge」や、スクラム・アジャイルのフレームワークであるインセプション・デッキを体験いただく「Inception Challenge」、あるいはUI改善のデザインプロセスを学べる「Prototype Challenge」など、エンジニア志望、総合職志望、デザイナー志望といったさまざまなスキル志向の学生さんたちに、面白く価値ある体験を提供しようと、取り組んでいます。

そして、来たる11月、また新たな「チャレンジ」イベントを開催します。
git challenge (ぎっと・ちゃれんじ) です。

f:id:mixi_engineers:20151015214311p:plain

#mixi_git

gitのテクを体験し競えるイベント

git (ぎっと) は、世界中で広く使われている分散型バージョン管理システムです。技術系の方であれば既にgitが手に馴染んでいるかたも多いと思いますが、あらためてgitについて簡単に振り返ってみます。

複数人でデジタル作業を行う場合、作業結果のすり合わせは常に重要です。

「せっかく編集したファイルを同僚に上書きされちゃった」
「人の作業を待たず、別の編集もとっととやりたい」
「先週のバージョンに戻りたいけど、もう戻れない……」

こんなの嫌ですよね。

そんな、現場の込み入ったコラボワークを助けてくれるのがファイルのバージョン管理システム(Version Control System)です。古くからさまざまなVCSがありますが、その中で最も強力で、性能や実績、普及度でも優れるのがgitです。いわゆるプログラム開発だけでなく、電子書籍の共同執筆校正など、一般的なデジタルコンテンツの共同作業にも、いまや広く使われています。

もちろんミクシィでも、モンスターストライクSNS mixi、ほか各種サービスやアプリの開発でgitを大規模に活用しています。高品質なプログラムやコンテンツを大人数で速やかに手がけていく現場では、gitの使いこなしも一段と本格的。時には、込み入ったバージョン分岐や後戻り、マージを解決しなければならないこともあります。そんな、今の現場ならではの解決スキルをうまくチャレンジ課題としてイベントし、みなさんに体験して学んでいただき、そしていつか一緒に課題解決できる仲間として出会いたい。

git challengeは、そんな1 dayの技術体験イベントです。

応募要項

開催日: 2015.11.15(日) 11:00-19:00
会場: 株式会社ミクシィ本社(東京・渋谷)
〒150-0011 東京都渋谷区東1-2-20 住友不動産渋谷ファーストタワー7F
http://mixi.co.jp/company/#access

ほか詳しい情報、そしてエントリーは、ミクシィグループ新卒採用サイト から
「【1 day技術イベント】git challenge」をご覧ください。

応募締め切りは2015.11.4(水) 23:59 JSTです。
興味お持ちのかたは、ぜひお誘い合わせのうえどうぞ!

git challengeの舞台裏

Scrap Challenge, Inception Challenge, Prototype Challengeと、ミクシィのワークショップイベントは、企画も実施も手づくりです。そのほうが、ミクシィならではの技術やノウハウをユニークにお伝えでき、体験していただけると思っているからです。このgit challengeも、若手エンジニアが「何かおもしろいyet another foobar challengeはないかな……」と考えて産み出してくれたものです。

そんな彼らはというと。

おっ、先日オープンしたばかりの、ミクシィの新たなコラボスペースの奥にある通称「ファミレステーブル」で、ちょうど彼らがお昼休みに、git challengeの設問についてコミュニケーションしているところではありませんか(棒)。

 

f:id:mixi_engineers:20151015215248j:plain

 

今回、git challengeの企画発想から、設問やシステム構築に至るまで技術的立ち上げのコア部分を担当してくれているのが、彼ら3名のコアメンバー。全員2014年の新卒入社です。

森本 (github.com/mrmt): おつかれさまです。まず、簡単な自己紹介から教えてください。

村山 (github.com/oppai): 2014年新卒入社の村山です。仕事は、モンスターストライクのサーバまわりの新機能の開発や、運用まわりを担当しています。

菊池 (github.com/kikuchy): 同じく2014年新卒入社です。いまは株式会社Diverseに出向して、YYCのAndroid版クライアントの開発をしています。

国分 (github.com/Kuniwak): 2014年新卒入社です。仕事は、SNS mixiのフロントエンドの闇払いをしています(笑)

mrmt: 闇払いとは……

Kuniwak: たとえば、mixi.jpでは生で直接CSSを書くのをやめてLESSに移行したんですが、対象コードサイズが6万行だったりしました。あとは例えば, gulp.jsのビルド時間が2分かかっていたのを10秒に短縮したりしました。基本的にはincremental buildを作るんですが、加えて自分でplug-inを作ったり。

mrmt: 仕事人感ある…… ありがとうございます。

 

f:id:mixi_engineers:20151015220312j:plain

 

mrmt: そもそも皆さんには、「次の新たなチャレンジ・イベントを創ろうよ」というレベルから相談に乗っていただいていて嬉しい限りです。このgit challengeのアイディアが降りてきたのって、どんなタイミングでした?

Kuniwak: ちょうどその一ヶ月ぐらい前、gitで死ぬほど苦労した覚えがあって、「あっ、これ問題作れるレベルだな」と思ったのがきっかけかも。

oppai: 業務で共同開発していくと、Kuniwakくんが言っていたように、やっぱりいろんな(バージョン管理の)課題にぶつかります。このレベルの課題は学生の頃は体験できなかったので、ならばgithubやCIを組み合わせて、攻略型のイベントに仕立てたら面白いんじゃないかと。

kikuchy: 学生のうちに、ここまで体験したり教えてもらえたら嬉しかったな…… というのはありますね。

mrmt: なるほど。では、git challengeの仕掛けを作り始めてみて気づいた難しさは?

kikuchy: そうですね…… まず問題を作って、その問題が果たして自分の意図したレベルで解けるものになっているかな…… という難しさがひとつ。
次に、それ(問題となるようなgitのややこしい状態)を再現するために自分で手を動かして作るのが大変で、ただ、それを自動化しようと思うと、それもなかなか大変。改めて、他のVCSと比べるとgitのマージ性能の高さはまさに圧倒的。日頃使っているツールのメリットについても再発見できました。

 

f:id:mixi_engineers:20151015220526j:plain

 

Kuniwak: 問題を作っている本人ですら、今が(git的に)どんな状態なのかよく分からなくなるような難しい問題を作り出してしまったり。これも、実際に問題を作ってみてわかった難しさですね。

mrmt: 問題の難易度を調整するチューニングにもかなり苦心してらっしゃる……

Kuniwak: 苦心してますね。すぐに分かる問題にしちゃうと面白くないので、ひとひねり加えたりとか。

oppai: 参加者には「gitの困難」に立ち向かってみてほしいので、例えば特定のプラットフォームや言語に依存したプログラムやスクリプトといったものは課題としていません。

mrmt: 実際、入社前にもgitやgithubは使ってました?

kikuchy: いちおう使ってはいました。が、一応commitができて, mergeができて, remote repositoryにpushができる。という程度の技能しか持っていなかったので、reflogを見たり、refspecいじったりとか、そういうことまでは学生当時はやらなかったです。

oppai: 僕はアルバイトでsvnをずっと使ってて, gitは個人開発でしか使ってなかったです。subversionはどうしてもcommitの粒度が大きくなるので、そのぶんtrunkを常にきれいに保とうというインセンティブが働きます。その点、gitは分散VCSなので、commit粒度は仮に細かくてもpullやmergeの大きさが違うなど、文化の違いも感じました。

 

f:id:mixi_engineers:20151015220920j:plain

 

Kuniwak: 学生のころ、大学のゼミで、論文のテンプレートをみんなで管理したくて、githubへの移行を呼びかけたんですが、結局自分ひとりで使っていたという……

mrmt: 「みんなに使ってもらう」ところが一番難しいんですよね…… わかります。

ラスボスのキャラ

mrmt: では、その後に入社して、職場で出会ったgitやVCSの難しさにはどんなものが?

一同: それは…… そのへんのエッセンスが今回の問題になっているので、ネタバレが…… (笑)

Kuniwak: 恐らく、git challengeの中で一番むずかしい問題は、自分が体験した、その1ヶ月前の体験です。

mrmt: 最後の、ラスボス的な……

Kuniwak: ラスボス的なやつですね(笑) 詳細は明かせませんが、「過去に雑なことをすると、あとで面倒なことになる」というのが、最終問のテーマです。

mrmt: なるほど。それを解いて体験することで、git共同作業での良き考え方や姿勢も身につくぞと。

Kuniwak: そういうことです。

commitlogを解き明かせ

mrmt: git challengeには、どんなかたに来て欲しいですか?

Kuniwak: 個人で使うだけではわからないgitの難しさがあります。複数人で作業を重ねていくとどうなるか。それを体験できます。

kikuchy: 仕事として働く際のgitの実活用を知りたい人かな? 今回の課題まわりをちょっと知っただけで、ぐんとgitを扱いやすくなる。

oppai: ほかにもCI連携や、Slackに通知させたりとか、そんなチーム環境も学んで体験できると思います。

Kuniwak: このgit challengeの参加者にとって、またgit上級者にとって最も重要な資質は、gitを知っていることではなく、gitのcommitlogを解き明かすこと。この部分について、とても実力がつくと思います。

 

f:id:mixi_engineers:20151015221051j:plain

 

git challengeの開催は2015.11.15(日)です。現場から生まれたgit問題を解き明かしていくことで、本場のgit力 (ぎっとりょく)が身に付く体験を、ぜひ楽しんでください!
エントリーはミクシィグループ 新卒採用からどうぞ。

再掲

git challenge 第2回を2016/3/5(土)に開催します!
詳細と応募はこちらをごらんください!

では、会場の渋谷ミクシィでお会いしましょう!