くらしのマーケット開発ブログ

猫のいる会社、みんなのマーケットの技術ブログ

Techのみんなが仕事中なんの音楽聴いているのか聞いてみた

はじめに

こんにちは。みんなのマーケットのテクノロジー本部でデザイナーをしているラミレスです。

私は音楽が好きで、前職でも音楽系のプロジェクトに携わっていました。
テクノロジー本部の他のメンバーも音楽好きがいて、音楽を聴きながら仕事をしている人がたくさんいます。

そこで今回、「テクノロジー本部のメンバーは、どんな音楽を聴いて仕事をしているの?」
というインタビューをしながら、メンバーの音楽の好みを探っていきたいと思います!

オフィスで音楽を聴いているテクノロジー本部のメンバーを探してみた

さっそく、音楽を聴いているメンバーに話を伺ってみましょう。
おっ、良いところに「Beats-X」のイヤホンをした新卒エンジニアの都築くんがいました。

1 tsuzuki

───都築くん、こんにちは!なんの音楽を聴いているんですか?

都築くん:乃木坂46です。

───へえ〜都築くんはアイドルが好きなんですか?

都築くん:否定はしません。ドルオタです。

───乃木坂46の誰が好きなんですか?

都築くん:衛藤美彩ちゃんです。

───え?

都築くん:あまり大きい声で言いたくないのでSlack(※)で送ります。
 ※Slack:社内チャットツールのこと。

───いやいや、自分で調べるからいいよ。笑 (調べてみる)ほ〜!すごく綺麗で可愛い方ですね!衛藤美彩ちゃんに会いに行ったりもするんですか?

都築くん:ライブで見ることはありますが、握手会には行きませんね。変なこだわりなんですが、会いに行ったら「アイドル」じゃなくなる気がするというか。あくまで、この距離感を大切にしたいんです。

───へえ・・・(よくわかんないな)。乃木坂46以外で好きなアイドルはいないんですか?

都築くん:けやき坂46も聴きますが、推しメンはいません。1人しか推したくないんで。衛藤美彩ちゃんは、かれこれ4年くらい推してますね。

───ほお〜都築くんは一途な男なんですね!衛藤美彩ちゃんのグッズとかを買ったりしないんですか?

都築くん:ライブでタオルなどのグッズを買うこともありますが、基本的には買わないですね、かさばるんで。CDはまあまあ持ってます。

───なるほど、なんだか都築くんらしい理由ですね。CDは毎回買うんですか?

都築くん:毎回ではないですけど、今回はA~Dまであるじゃないですか。それは全部買いました。

2 tsuzuki

───いや知らないけど・・・。というか、Dまであるんですね。それを全部買ったってのはすごい!毎回は買わないけど、買うときにはがっつり買うということですね!どういう基準でCDを買うか決めるんですか?

都築くん:特典ですね。好みのDVDが付いているかどうか、とかです。

───なるほど〜。購入したCDを仕事中に聴いているということですか?

都築くん:聴くのは乃木坂ですが、AppleMusicで聴いているのでCDは聴きません。

───えっ!?じゃあCDを買って、もう一度AppleMusicで購入するということでしょうか?

都築くん:そういうことですね。

───すごい・・・。乃木坂46の売り上げに貢献してますね・・・。

都築くん:そうですね、もはやCDは特典のために購入しているようなものです。家でCDを聴くこともありませんね。

───乃木坂のための浪費は厭わないということですね!アイドルオタク感があって良いです!都築くん、ありがとうございました!

CTO登場

次の方にインタビューをしてみましょう。
誰か音楽聴いている人はいないかな〜。

お!「Bose QuietControl 30 wireless headphones ワイヤレスノイズキャンセリングイヤホン」をした、CTOの戸澤さんがいました!

3 tozawa

───戸澤さん、こんにちは!インタビューさせてください!

戸澤さん:え、あ、はい。

───いま付けているイヤホン、ノイズキャンセリングが非常に良いとおっしゃってましたよね!デザインもとってもクールですね!いつもそちらを利用されているんですか?

戸澤さん:このイヤホンの他に、「sennheiser HD 25 ALUMINIUM」のヘッドフォンも利用しています。

───ゼンハイザーといえば、ギター音に強いイメージがあります!音楽関係者やDJの方で利用されている方も多い印象ですが、そのヘッドフォンで一体どんな音楽を聴かれるんですか?

戸澤さん:Perfumeです。

───おお!Perfumeといえば、ライブのクオリティーが非常に高いことで有名ですよね。ライブには行ったりするんですか?

戸澤さん:行きます。そもそもライブがそんなに頻繁には開催されないのですが、開催されるときには必ず抽選に応募します。地方開催もあるので、大阪に行ったこともあります。来月は長野、12月には横浜で開催されるライブに行きます。

───おお!アクティブに色々な所へ行くんですね!ライブはお休みの日に行くんですか?

戸澤さん:平日に開催されることもありますね。12月の横浜は平日に開催されるライブです。

───平日にライブに行く際は、仕事をお休みして行くんですか?

戸澤さん:仕事を早めに切り上げれば間に合うので、仕事後に行きますね。

───仕事後にライブへ行けるのは良いですね〜。これがフレックスの良いところ!ちなみに、Perfumeの中では誰が好きなんですか?

戸澤さん:それは内緒です。知ってる人は知ってますが。

───今後聞き出せるよう、戸澤さんとの距離を縮めて行きますね!ところで、それだけのライブ、よく当たりますね!チケットを当てるコツはあるんですか?

戸澤さん:Perfumeに関しては、お金を積めばチケットが当たりやすくなることはないです。運ですね。

───なるほど〜!どのくらいの倍率かわかりませんが、それだけライブに行けるというのは相当な強運の持ち主なのかもしれないですね!戸澤さん、ありがとうございました!

UK好き!デザイナーのみそさん

Bose SoundSport Free wireless」のイヤホンをしたデザイナーのみそさんを発見!
何かを聴いていますね。

4 miso

───こんにちは!インタビューしたいんですが良いですか?

みそさん:良いですよ!

5 miso

───ありがとうございます!あれ、てかそれ水着みたいですね!

みそさん:え、わかる?これ水着だよ!

───え!?本当に水着なんですか・・・。(すごい、この人、会社に水着で来てる)

みそさん:このまま水に入れるよ!

───(全然メリットに感じないけど)そうですね!水に入れますね!ところで、みそさん今何を聴いていたんですか?

みそさん:シャ乱Q

───(やばいどう掘り下げたら良いのかわからない)他にはどんなアーティストの曲を聴きますか?

みそさん:他には、中森明菜、玉木浩二、D.O、Michita、HeartsdalesYMO、Metronomyです!

───すごい振り幅!みそさんはUK好きというイメージがあります!先日もUKアーティストのライブに行った際の写真を見せてくれましたよね!

みそさん:Metronomyです!めちゃくちゃ好きなアーティストなんですよ。渋谷のイベントでMetronomyのジョセフがDJをすると聞き、行ってきました。その時は髪型もジョセフヘアにしてました!

7 miso

───なるほど!だから頭がくるくるだったんですね!オフィスのある五反田と渋谷は近いので、イベントの開催場所が渋谷だと嬉しいですね。そういえば、みそさんはロックバンドをやっているご友人がいると言っていましたね!その方のイベントにも行くんですか?

みそさん:たまに行きますね!渋谷で開催されるときには、仕事を早めに切り上げて行きます。

───おお、ここにもフレックスを活用してイベントに参加する方がいましたね。みそさん、ありがとうございました!水着は水の中で履いてくださいね!

アニメ好き!へいへい!

アニメが好きと噂のエンジニア、へいへいさんを発見したのでお仕事の邪魔をしてみましょう!

何かを真面目に考えているようですね。

あ、こっち見てくれた。

笑ってくれました!

───こんにちは!インタビューさせて頂いてもよろしいでしょうか!

へいへいさん:はい!大丈夫です。

───へいへいさんは、普段あまりイヤホンをしていないイメージがあります!

へいへいさん:いや、してますよ。最近は電話の開発をしていて、そのテストなどで耳を塞げない状況なので、以前と比べると音楽を聴いていないかもしれませんね。

───なるほど!今ちょうど、出店者(※)とお客様が電話できる機能を開発しているところですもんね!では、仕事中に音楽を聴くとき、どのような音楽を聴いているんですか?
 ※出店者:みんなのマーケットが運営するサービス「くらしのマーケット」で、ハウスクリーニングなどのサービスを提供する事業者のこと。

へいへいさん:YouTubeのトップページから見ていきましょうか。RadioheadSquarepusherを聴いているようですね。

───(自分の履歴なのに、まるで他人の履歴を見るかのような言い回し)なるほど!ロック、エレクトロ、ドラムンベースがお好きなんですね!わたしはトロピカルベースなどが好きなので、今度ベース系のイベントに一緒に行きましょう!
ところで、へいへいさんはアニメが好きとお聞きしていますが、アニソンは聴かないんですか?

へいへいさん:仕事中は聴かないですね。何かの拍子にイヤホンが外れ、アニソンが流れてしまったら恥ずかしいじゃないですか。

11 hey

───でも、Macはイヤホンが外れちゃっても自動で音が止まるので大丈夫だと思います!それに、アニソン聴いてても全然恥ずかしくないと思いますよ!

へいへいさん:では、今後は仕事中でもアニソンを聴くようにしますね。

12 hey

───ちなみに、アニメはどのようなアニメを見るんですか?

へいへいさん:週末はバトミントンアニメをひたすら見てました。

───バトミントンアニメ・・・!ピンと来なさすぎるのでスルーします!アニメ系のイベントって都内でよく開催されているイメージがありますが、イベントにも行くんですか?

へいへいさん:アニメ系のイベントには一度しか行ったことないです。同人誌イベントにはよく行きますよ。

───なるほど、へいへいさんは漫画・アニメ・本がお好きなんですね!

ここでSREの千代田さん登場!

───いいところに千代田さん!千代田さんのお好きな音楽についてもお聞きしたいのですが、よろしいでしょうか!

千代田さん:顔出しはNGでお願いします。

13 hiroki

───わかりました!千代田さんは普段どのような音楽を聴くんですか?

千代田さん:ジャンルは、EDM・ダブステップ・ハードコア系のロックが多いですね。アーティストだと洋楽であればアリセイナ、邦楽だとSKY-HIですかね。あと、小瀬村晶とかも聴きますね。

───ハードコアロックからピアノまで、千代田さんも幅広く音楽を聴くんですね。イベントには行かないんですか?

千代田さん:行かないです。基本的に家から出たくないので。

───なるほど!千代田さんらしいですね!ちなみにイヤホンにはこだわりとかありますか?

千代田さん:会社ではSONYの6,000円くらいのイヤホンを使ってます。家では「SteelSeries Siberia v3 Prism Cool Grey」というヘッドフォンを使ってますが、ヘッドフォンを外でつけるのは抵抗があります。似合う人がつけてるならいいですけど、自分がつけるのは恥ずかしいですね。

へいへいさん:ヘッドフォンのブランディング的に悪い感じしますよね。笑

14 heyhiroki

───お二人とも謙虚ですね!絶対ヘッドフォン似合うのに!千代田さん、へいへいさん、ありがとうございました!

アプリのことなら俺に任せろ。ヤンヤン

次は、アプリ開発をしている中国出身のヤンさんが音楽を聴いているので、お話を聞いてみましょう!
ヤンさんはコーヒーがお好きなので、コーヒーを淹れながらお話しましょう!

15 yang

───普段、ヤンさんはどのような音楽を聴きますか?

ヤンさん:基本は雑食ですが、冷血系か熱血系です。

16 yang

───???!具体的に、好きなアーティストはいますか?

ヤンさん:冷血系でいえば●×△●・・ですね。

───????!(発音良すぎて聞き取れず)スペルをお願いします・・・!

ヤンさん:「Two steps from hell」です。絶対に皆さん聴いたことありますよ。

───初耳です!調べてみますね!(調べてみる) あ〜『ハリー・ポッター』、『パイレーツ・オブ・カリビアン』、『X-メン』など、映画のトラックを提供しているんですね!

ヤンさん:それは知らなかったです。笑

17 yang

───笑。 (Youtubeで聴いてみる)おお、めちゃかっこいいですね!ゲーム系の音楽って感じがしますねー!そのほかに聴く曲はありますか?

ヤンさん:アニメの曲なんですが、A/Z|aLIEz(アライズ)という曲です。このアニメを見たことはないのですが、中国ですごく人気の曲です。

───へえ!そういえばヤンさんはアニメがお好きですよね!どんなアニメがお好きなんですか?

ヤンさん:最近は「ペルソナ」シリーズを見てます。RPGのゲームがアニメになったものです。

(都築くん登場)

都築くん:「とある魔術の禁書目録」じゃないんですか?

18 tsuzuki

ヤンさん:科学の方が好きです。

───・・・!?

都築くん:「とある魔術の禁書目録」と「とある科学の超電磁砲」があるのですが、ヤンさんは「とある科学の超電磁砲」の方が好きと言ってます。

───都築くん解説ありがとうございます!そういうアニメがあるんですね!ところで、ヤンさんはコミケには行かないんですか?

ヤンさん:人が多いので行かないです。

都築くん:でも、機会があれば行きたいですよね!ぜひ一緒に行きましょう!

19 tsuzukiyang

───都築くんはコミケとかに行くんでしたっけ?

都築くん:行ったことあります。あれは一回行くとハマりますよ。ぜひヤンさんと行きたいですね。

───そうなんですね〜!今度、コミケの魅力についてもぜひ教えてください!都築くん、ヤンさん、ありがとうございました!

エレベーターでのりすけさんに会いました!

エレベーターでSREののりすけさんに会ったので、インタビューしてみました!アイスランドのシンガーソングライター、「ビョーク」のTシャツを着ているので、期待が膨らみますね!

───のりすけさん、こんにちは!突然ですが、仕事中はどんな音楽を聴いているんですか?

のりすけさん:最近は他の方と話をすることが多いので、あまり聴いていないです。聴くときはAppleMusicでオススメの曲とかを聴く感じですね。

───のりすけさんは他のエンジニアの方とお話をしていることが多く、周りから頼りにされていますもんね!
さすが、開発部門の父!のりすけさんといえば、音楽をやっているお友達が多いイメージがあります。イベントには行くんですか?

のりすけさん:最近は全然行かないですね。昔は電気グルーヴのイベントによく行っていました。あと、知人が出てるモッシュするような激しいイベントによく行っていましたが、もう年齢的に無理ですね。今は座って音楽を聴きたいです。

───すごいわかります!電気グルーヴのイベントは日本全国に行っていたんですか?

のりすけさん:それはないですね。追いかけたいとか、会いたいとかは別に思わないんですよ。

───都築くんもそんなようなこと言ってましたね。会ったらアイドルじゃなくなるって言ってました!

のりすけさん:その気持ちわかるかもしれないです。会ってみてイメージ崩れるのは嫌だなと思いますね。

───なんだか深いですね〜。多分アーティストのファンというよりは『音楽が好き』という部分が強いのかもしれないですね!のりすけさん、ありがとうございました!

さいごに

今回は、開発メンバーが普段どのような音楽を聴いてお仕事をしているのかを聞くことができ、知らないアーティストや普段聴かない音楽ジャンルについて知ることができました。皆さんから教えていただいた音楽を私も聴いてみたいと思います!

私たちテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています!

【本当に優秀な人はマネージャーが必要ない】という考え方のもと、各自、自分自身をマネジメントできるよう、フレックスタイム制やフレキシブルな休暇など、個人の裁量に働き方を委ねる様々な制度を導入しています。

「好きな音楽を聴きながら仕事をしたい!」
「仕事後に音楽イベントに行きたい!」
「アイドルイベントのために有給取りたい!」

と思った方、ぜひ一緒に働きましょう。ご応募お待ちしております!
(コーポレートサイト https://www.minma.jp/

次回は樹木に優しいエンジニア、へいへいさんの予定です!

Robot Frameworkを利用したUIテスト

こんにちは、新卒エンジニアのツヅキです。
今回はRobot Frameworkを使ったSPページのUIテストのお話です。
そもそもRobot Frameworkを使った”SPページのUIテスト”(以後、テスト)とはなんでしょうか?

スマートフォンのブラウザからあるサイトにアクセスし、特定の動作に対して機械的にテストをすること

ここでいくつかの疑問が生まれます。

  • なぜ、わざわざ機械的にテストするの?
  • なぜ、SPページでテストするの?
  • そもそもテストする必要ある?

などなど、では一つずつ考えていきましょう。
なぜ、わざわざ機械的にテストするの?
何度も同じテストを人が一回一回テストすると、とても時間がかかります。しかし、機械的にテストをすることによりテスト時間を大幅に短縮することができるので機械的にテストします。
なぜ、SPページでテストするの?
パソコンのブラウザより、スマートフォンのブラウザの方が多くの人に利用されているので、SPページでテストします。
そもそもテストする必要ある?
テストをすることによってテストケース内の動作は正常に動作できることは保障されるからです。

では、本題のRobot Frameworkのお話です。
Robot Frameworkは何かについて少しだけ説明させていただきます。

受け入れテストやテスト駆動開発 (ATDD) のための、オープンソースの汎用テスト自動化フレームワークです。 簡単に扱えるテーブル形式のテストデータ記述方法を備えていて、キーワード駆動型のテストアプローチに便利です。 テスト機能は Python や Java でテストライブラリを書いて拡張できます。 ユーザは既存のキーワードを使って新しい高水準キーワードを定義でき、それを使ってテストケースを書けます。[1]

どうやら、無料で簡単にテストを作ることができて、いい感じにカスタマイズできる素晴らしいシステムのようです。
今回のSPページのテストに利用するスマートフォンの種類としてiPhoneのシミュレーターを利用します。
大まかに必要なものを説明します。

必要なもの

  • Appium
  • Xcode
  • Python
  • iPhoneシミュレーター
  • 失敗してもめげない心

特に、一番下の失敗してもめげない心はとても重要です。MacがあればiPhoneシミュレータもAppiumもXcodeも簡単にインストールできますが、テスト環境を作ったりRobot Frameworkでテストを書いているとたまに心が折れそうになるのでしっかりと心の準備を整えてから挑んでください!

では早速インストールの話ですが、”brewでAppiumとMacAppStoreなどからXcodeをインストールし、XcodeでiPhoneシミュレーターを設定後、pipでRobot Frameworkをインストールしてみてください。”[2]ここで書くとこのブログを読んでくださる方も書いている私も心が折れそうなので割愛します。
(私がRobot Frameworkが正常に動作するようになる頃には、心のHPが85%くらい削られていました)

2018-08-23 20 32 38

まず最初に、Robot FrameworkからAppiumに対してどのようなものを使うかの設定を行います

Robot Frameworkの設定

*** Keywords ***
Initialize
    ${caps}=  create dictionary  browserName=Safari  platformName=iOS  platformVersion=11.4
    ...                          deviceName=iPhone 8  automationName=XCUITest  useNewWDA=true
    create webdriver  Remote  command_executor=localhost:3000  desired_capabilities=${caps}

こんな感じです。簡単に説明すると、

  • iPhone 8 のシミュレータを使います。
  • iOS11.4を使います
  • localhost:3000から操作を行います。

と書いてあります。 (Robot Frameworkに合わせてAppiumの設定を行う必要があります)

では次にRobot FrameworkでGoogleにアクセスして見ましょう

Webページへのアクセス

go to  https://www.google.com/

ここでのポイントは、go toの間のスペースは1つ~ to http://example.comtoとURLの間のスペースは2つというところです。

次は、特定の要素をクリックするという操作です。

要素の選択

click element  <XPATH>

この操作は特定のXPATHをもつ要素をクリックするという操作です。ここでも、click elementの間のスペースは1つ、element <XPATH>の間はスペース2つです。<XPATH>の部分には特定の要素を示すXPATHを示してあげてください。

次は、特定の要素に対して入力するという操作です。この操作のおかげで、ボックスなどに対して文字を入力することができます。

文字の入力

input text  <XPATH>  <入力したい文字列>

この操作は特定のXPATHに対して文字列を入力するという操作です。input textの間のスペースは1つ、text <XPATH> <入力したい文字列>の間はスペース2つです。<XPATH>の部分には特定の要素を示すXPATH、<入力したい文字列>の部分には入力したいテキストをそのまま入力してください。

次は、特定の要素が見つかるまで待つという操作です。この操作があるおかげで、読込みが早い時も、遅い時も、普通の時も要素のクリックや入力が正常にできるまで待ってくれます。

待機

wait until element is enabled  <XPATH>

この操作は特定のXPATHを読み込むまで待つという操作です。

2018-08-23 20 27 22

いかがでしたか?
今回は基本的な部分だけでしたが、他にもifforといった条件分岐や繰り返しを行うことができるので興味がある方は調べて見てください! 一緒に働いてみたいといった方もぜひお待ちしてます!

参考

[1] https://robotframework-ja.readthedocs.io/ja/latest/quickstart/QuickStart.html
[2] http://thinkami.hatenablog.com/entry/2017/09/15/222958

家賃を予測してみよう!

皆さん、こんにちは。エンジニアのトゥエンです。

あなたは家を探したことがありますか。私はもうすぐ引っ越しする予定です。 ですから、今日、「線形回帰」を使って、東京でシェアハウスの家賃を予測してみましょう。

f:id:curama-tech:20180820124309j:plain

問題

下記のような、部屋の家賃や面積、フロアについてのデータがあるとします。

面積(m²) フロア(F) 家賃(千円)
7 2 45
7.12 1 51
7.2 1 52
7.69 1 53
7.79 1 52.6
8 1 52
8.28 1 54
8.37 2 54.2
8.7 2 56
9.93 2 64
10.5 2 65
10.53 1 72
11 3 75
12.19 3 78.3
12.4 1 80

これを使って別の部屋の家賃を予測してみましょう。

少し数学について

線形回帰

上の問題は、「線形回帰」と呼ばれる、「教師あり学習」の一形態です。

線形回帰の公式は

{ \displaystyle 
        Y' \approx  Xw = Y 
    }
  • { \displaystyle Y' } : 予測の値
  • { \displaystyle Y } : 実際の値
  • { \displaystyle x } : インプットデータの値
  • { \displaystyle w } : ウェイト

損失関数

目標は実際の値(Y')と予測の値(Y)の差が最小です。ということは、関数の得る価値を最小するために { \displaystyle w } を見つける必要があります!

{ \displaystyle 
        L(w) = \frac{1}{2}\sum_{i=1}^{N}(Y'_{i}-Y_{i})^{2} = \frac{1}{2}\sum_{i=1}^{N}(Y'_{i}-X_{i}w)^{2} 
    }

問題の解決

損失関数の定義から、これが最適化問題であることがわかります。最適化問題を解決するために、一般的な方法の1つは、導関数を使用することです。

ちなみに、以前、凸最適化問題を紹介しました。よかったら、読んでください。

家賃予測

家賃は、次の式で計算されます。

家賃 = 面積 * { \displaystyle w_1 } + フロア * { \displaystyle w_2 }

家賃を予測するために、{ \displaystyle (w_1, w_2) }の適切な値を見つけなければなりません。

Pythonの scikit-learn ライブラリを使って、早く解決することができます。

import numpy as np
from sklearn import linear_model

X = np.array([
    [7, 7.12, 7.2, 7.69, 7.79, 8, 8.28, 8.37, 8.7, 9.93, 10.5, 10.53, 11, 12.19, 12.4],
    [2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 3, 3, 1]
]).T

Y = np.array([
    [45, 51, 52, 53, 52.6, 52, 54, 54.2, 56, 64, 65, 72, 75, 78.3, 80]
]).T

linear = linear_model.LinearRegression(fit_intercept=False)

linear.fit(X, Y)

print(linear.coef_)

結果:

[[ 6.74732924 -0.88385193]]

{ \displaystyle
    (w_1, w_2) = (6.74732924, -0.88385193)
}

ですから、3階にあり、面積8m²の部屋の家賃は約54700円です。

f:id:curama-tech:20180820124410p:plain

精度をテストしてみます。本例ではデータセット全体を 80:20 の割合でトレーニングデータとテストデータに分割します。

from sklearn.model_selection import train_test_split

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)

linear.fit(X_train, Y_train)

linearScore = linear.score(X_test, Y_test)

print(linearScore)

結果:

0.8280773078631194

1に近いほど精度は高くなります。

おわりに

我々みんなのマーケットテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています!興味がある方はぜひ気軽に連絡ください。

次回は、都築さんの予定です。

参考文献

[1] ウィキペディア

[2] Machine Learning is Fun! – Adam Geitgey

[3] Machine Learning co ban - Vu Huu Tiep, 2018

[4] scikit-learn

スタートアップの社内ネットワーク構築アンチパターン

こんにちは。みんなのマーケットでCTOをしております戸澤です。

この記事でわかること

スタートアップは、組織の急拡大のため年単位でオフィスの移転をすることがよくあります。 弊社も移転を繰り返し、その度に新しいオフィスの社内ネットワーク構築を行ってきました。

今回は、これまでの社内ネットワーク構築の経験をもとに、5,30,70名のそれぞれの規模のときに、どんな社内ネットワーク構成にしたかを紹介します。 また最後に、それらの経験から得られたアンチパターンをまとめますので、参考になればと思います。

f:id:curama-tech:20180809205438p:plain:w300

社内ネットワーク構築の歴史

弊社は2011年に創業したスタートアップで、東京と宮崎にオフィスがあります。東京オフィスは、これまでに7回の移転をしています。 このうち、最初の4回はシェアオフィスだったため、社内ネットワークの構築と管理は同居している他の会社の方がやってくれましたが、 5回目からは、自社のみのオフィスとなったため、自分たちで構築と管理をするようになりました。 5,6,7回目のそれぞれの移転で、人数が〜5名, 〜30名, 〜70名規模のオフィスとなったため、この組織規模別に社内ネットワークの構成を紹介していきます。

また、弊ブログの「Amazon Connect使ってみた!」の なぜ電話システム(IVR)が必要なのかでも触れていますが、 弊社には電話を多く使う業務があり、その電話はコンサル電話と呼ばれるブラウザ上から電話できるシステムを使って行われます。 tech.curama.jp

この電話の通信はWi-Fiを通して行われ、音声が途切れたり、相手の声が聞こえないなどのトラブルを何度も経験してきました。

電話というジッターやレイテンシ等の条件がある中で、持ち運びやすさのために有線LANの接続ではなくWi-Fi接続で安定させるための取り組みを行ってきましたので、その経験も参考になればと思います。

〜5名

当時、マンションの1LDK一室をオフィスにしていました。 この広さ、人数であれば、一般家庭でのネット利用と変わらず、家庭向けの機器や回線を選択することでコストも抑えられます。

なので、

  • ルーター(Wi-FiのAP付き): NECの家庭用のもの(Atermシリーズ)
  • 回線: フレッツ(マンションタイプ&最大1Gbps) + 個人向けISP(月800円ほど)

以上の構成で問題なく、ネットが利用できました。

〜30名

30名となると、広さはマンションの一室レベルではなくオフィスレベルになり、クライアント数も多くなるので、家庭用の機器では対応できません。 そのため、ルーターとアクセスポイント(AP)を業務用の機種から新しく導入しました。

ルータの選定は、他の方が書かれた記事を参考にしながら、YAMAHAで規模にあう機種を選びました。 YAMAHAのルーターを初めて導入するため、こちらの本も参考に構築を進めました。

ノンエンジニアのための社内ネットワーク施工・構築ガイド 20~40人規模のLAN環境を自分で作ろう (Do IT Yourself)

ノンエンジニアのための社内ネットワーク施工・構築ガイド 20~40人規模のLAN環境を自分で作ろう (Do IT Yourself)

また、回線もクライアント数の増加に対応できるよう、フレッツより大きい帯域幅が謳われているものを用意しました。

  • ルーター: YAHAMA RTX810
  • AP: Buffaloの業務用AP
  • 回線: フレッツのシェアドアクセス方式を利用した会社のもの

以上の構成で問題なく、ネットが利用できました。

〜70名(現在)

30名のオフィスでは、回線にフレッツより帯域幅の大きいシェアドアクセス方式のものを利用していました。 新オフィスでも継続利用を検討しましたが、移転工事にあたりフレッツよりも開通に時間を要するという説明を受け、 早くの移転を予定していたためそれに間に合うように、比較的開通までの時間が短いフレッツを利用することにしました。

当初、フレッツでは厳しいと考えていましたが、問題なく使えることがわかり現在も継続して使用しています。 NTTの収容局の混雑具合にもよりますが、70名規模でもフレッツで問題なく通信できていることから、〜30名でもファミリータイプであれば問題なく使えたと思っています。

ルーターはRTX810だとNATディスクリプターが近々枯渇することが予想できたので、より多くのNATディスクリプターをサポートしている上位機種のRTX1210を導入しました。

また、APもBuffalo1台のみでは対応できるクライアント数が厳しいので、今後YAMAHAでネットワーク機器を揃える方針でYAMAHAのAPを1台追加し、BuffaloとYAMAHAを併用しました。

  • ルーター: YAMAHA RTX1210
  • AP: Buffaloの業務用AP x1 + YAMAHAのAP x1
  • 回線: フレッツ(ファミリータイプ&最大1Gbps) + 個人用のISP

これでしばらく問題なく使えていたのですが、Windowsアップデートの日に回線が重くなり、パケットロスが多く発生しました。 弊社のWindows端末は数台だけで、社内のWindowsアップデートではなく、そのISPの利用者全体のアップデートに起因しているようでした。

ISP側もWindowsアップデートの日は重くなることを把握していて、毎月のWindowsアップデート日に発生する可能性があり業務に支障がでることが予想されるため、個人用ISPからIIJの法人向けISPに切り替えました。 IIJのISPはSLAがあり、今のところ、Windowsアップデート日やそれ以外でも重くなることは経験していません。

  • ルーター: YAMAHA RTX1210
  • AP: Buffaloの業務用AP x1 + YAMAHAのAP x1
  • 回線: フレッツ(ファミリータイプ&最大1Gbps) + IIJの法人向けISP

この構成で利用していきましたが、人数が60名くらいから稀にコンサル電話の音声が途切れるという問題が発生し始めます。 トラフィックを監視していると途切れが発生する直前に、大容量の通信(ISOファイルのダウンロードなど)が走ると、途切れが発生することがわかり、ルータとAPででQOSと端末ごとの速度制限を導入しました。 速度制限は250Mbpsといったかなり高速の通信をある時間以上すると、通信速度を不便にならない範囲で落とす仕組みです。これで途切れは減ったものの、まだ度々起きる状態でした。

電話トラブルの厄介なところは、原因がネット環境以外にも考えられることです。 ヘッドセットの調子、ブラウザ、電話システムのバグ、相手の通信状況など場合によっては、これらが原因のこともありました。

有線接続の場合は途切れが少ないとの声もあり、社内ネットワーク構築の会社の意見を聞いたところ、 現在の2台のAPでは台数が足りなく、メーカーも別でAP間の連携が取れないため端末分散ができないため、APで通信が詰まっている可能性があるという話になりました。 検証用のAPを導入し試験運用してみたところ、途切れがなくなったため、APの増設工事を依頼しました。

  • ルーター: YAMAHA RTX1210
  • AP: ArubaのAP x4
  • 回線: フレッツ(ファミリータイプ&最大1Gbps) + IIJの法人向けISP

現在は、この構成でネットを利用しています。 電話の途切れはなく、APのメーカーも統一されたことで管理が楽になりました。

これからこうしたい

クライアント数が増えること、トラブル時の損失のインパクトも大きいことを考えると、フレッツのベストエフォートのプランではなく、帯域保証のプランに変えるつもりです。

また、当初からの流れで私がメインとなって社内ネットワークの管理をしてきましたが、今後の規模を考えると次回からはエンジニアにメインの管理をお願いしたいと思っています。

アンチパターン

さて、社内ネットワーク構築の歴史をもとに、アンチパターンをまとめていきます。

機器間の連携が取れないAPを導入する

バラバラのメーカーのAPを導入すると、設定を変える際にmaster機で設定したものをslave機に自動反映することができず、個々に設定することになり管理がつらいです。 また、自動チャンネル変更もAP間で連携が取れなく、双方で永遠とチャンネル変更を繰り返してWi-Fiが何度も途切れることがありました。

現在は同じメーカーのAPを導入していて連携が取れるため、1台のAPにクライアントが集中しないように、AP間での端末分散もできるようになりました。

最初に複数台購入するときはもちろん揃えるとして、 途中でメーカーを変えたくなった場合でも、古いメーカーは使わずに、すべてのAPを新しく導入するメーカーで揃えることをおすすめします。

ジッターやレイテンシが通信要件に入っているのにWi-Fiを使う

専門の会社にAPの増設工事をしてもらい、Wi-Fiでの電話利用ができていますが、今後クライアント数が多くなった場合はどうなるかわかりません。

無線と有線は、トレードオフなところがあるので状況によるとは思いますが、トラブル時の対応工数を考えると有線LANを使うことをおすすめします。

また、ジッターやレイテンシ、パケットロスなどが通信要件に入っている場合、専門の会社に相談して設計や機種選定、キャパシティプランニングを行うことをおすすめします。

SLAのない個人向けISPで頑張る

問題なく使えていたという理由で個人用ISPを継続利用しましたが、ある日回線が遅くなる現象が起きました。

急ぎで導入したい場合は個人ISPの方が早いと思いますが、問題ないからといってそのまま継続するのではなく、 トラブル時の業務や売上へのインパクトを考えて、SLAや帯域保証があるISPに後に変えることをおすすめします。

今の人数だけに対応できる機種を導入する

30名から70名への移転する際、ルーターの買い替えをしました。 数年以内のオフィスの移転が見えているなら、最初から上位機種を購入した方が良かったと思います。

人数に対してオーバースペックにはなりますが、耐用年数は数年程度ではないので、今後の増員を見越して長く使えるものを導入することをおすすめします。

自分ですべて管理できると思う

トラブルが起きた際にネットワークに強いエンジニアの方であれば、問題ないのだとおもいますが、そうでない場合は対応工数が大きいです。 自分でやることで勉強になるという利点はあるのですが、特に電話の途切れトラブルでAPに起因する部分は早い段階で専門業者に相談するべきでした。

最近では、すべてマネージドでやってくれるサービスもあるようなので、社内メンバーがプロダクトに集中して、マネージドできるものはお願いするという選択は大いにありだと思います。

最後に

今回は組織の人数別に事例を紹介しましたが、実際は人数よりも接続するクライアントの数や利用状況への依存が大きいので、考慮した上で適用する必要があります。

最後に、みんなのマーケットに興味がありましたら、会社の雰囲気や事業を知っていただくための、ざっくばらんな面談もやってますので、ぜひ連絡ください。

次回は、Backendエンジニアのトゥエンさんがお送りします。

Swift: Memory leaks、 豊かな人々も泣く!

こんにちは、エンジニアのDuyです。

今日はSwiftのメモリリークについて、話そうと思います。

f:id:curama-tech:20180802152853p:plain:w262:h263

最近、技術が発展しているため、モバイルデバイスの容量も大きくなっているんですが、メモリを管理しないと、アプリが遅くなって、アプリの容量が大きすぎることによって、アプリがcrashする可能性もあります。お金持ちなのにお金を無駄遣いしたら、ある時点でお金がなくなってしまう。お金がなくなったら、豊かな人々も泣く!

そのため、メモリを管理するのが大切です。

つまり、メモリリークとは?

メモリリークはプログラムが確保したメモリの一部、または全部を解放するのを忘れ、確保したままになってしまうことを言う。そのメモリは参照されないので、開放できないし、利用もできない。

リークはいつ?どこから?

アプリを開発するとき、サードパーティのライブラリを使ったら、リークが発生する可能性があるし、CALayerやUILabelのようにAppleによって作成されたクラスからリークが発生する可能性もあります。さらに、デベロッパーのコードはリークがよく発生します。(残念なんですけど、それは本当のことです!)

ある朝、目を覚まして、綺麗な空を見ます。あなたは出社して、自分の席に座って、前日の困っていたことを突然スムーズに解決できますが、アプリを何回かテストしているうちに、だんだんと遅くなってしまいます。あなたがリークを作成しました。(実は寂しくてもうれしくても、リークを作成する可能性があります。)

どうやって、リークを避けることができるでしょうか? リークが発生したら、どうやって、リークを解決できるでしょう?

リークを避ける、あるいはリークを解決できるようにするため、Swiftのリークの原因をさがしましょう!

強参照サイクル (Strong Reference Cycles)

強参照は、参照が存在する限り参照が指すクラスインスタンスを割り当て解除できないことを意味します。下記の例を一緒に見ましょう!

(*) StaffとDeviceの例:

class Staff {
    let name: String
    init(name: String) {
    self.name = name 
    }
    var device: Device?
    
    deinit { 
        print("Staff \(name) is being deinitialized") 
    }
}

class Device {
    let name: String
    init(name: String) { 
        self.name = name 
    }
    var staff: Staff?
    deinit { 
        print("Device \(name) is being deinitialized") 
    }
}

Staffはnamedeviceという2つプロパティがあります。Staffは必ずdeviceがあるとは限らないので、deviceはオプショナルです。 類似、Deviceは2つプロパティがあります。nameとstaffです。

今、変数を定義します。下記の変数のイニシャル価はnilです。

var staff: Staff?
var device: Device?

次に、StaffとDeviceのインスタンスを上の変数にアサインします。

staff = Staff(name: "yamada hanako")
device = Device(name: "macbook")

2つのインスタンスをリンクします。

staff!.device = device
device!.staff = staff

リンクしたあとは、こういう感じになります。

f:id:curama-tech:20180802160844p:plain

変数をnilにします。

staff = nil
device = nil

staff及びdevice変数によって保持されている強参照は無くなりますがが、StaffDeviceのインスタンスはまだ強参照を残ります。それはメモリリークです。

他の例を一緒に見ましょう!

(*) Playerの例:

class Player {
    let name: String
    let age: Int

    lazy var detail: () -> String = {
        return "Name: \(self.name), age: \(self.age) "
    }
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    
    deinit {
        print("Deallocated!")
    }
}

var player: Player?
player = Player(name: "yamada", age: 20)

player?.detail()

player = nil

これから見ると、playerがnilに設定されている時にPlayerインスタンスが割り当て解除されないため、deinitのprintを実行されません。それもメモリリークです。

先程、リークを作りましたが、どうやって解決しますか?

弱参照(Weak Reference)

弱参照は、それが参照するインスタンスを強く保持しない参照です

弱参照は参照するインスタンスを強く保持しない参照であるため、ARCが参照インスタンスを破棄しないようにします。(オフィシャルドキュメント)

(*) StaffとDeviceの例をもう一回見ましょう!

もし、var staff: Staff?の行は weak var staff: Staff?にしたら、下記のスクリプトを実行して、

staff = nil
device = nil

結果は

Staff yamada hanako is being deinitialized
Device macbook is being deinitialized

というのは、StaffとDeviceのインスタンスを割り当て解除されました。リークを解決できました。

weakにはよくThe Delegation Patternを使います。例えば:

    
    open class UITableView : UIScrollView, NSCoding, UIDataSourceTranslating {

        public init(frame: CGRect, style: UITableViewStyle) // must specify style at creation. -initWithFrame: calls this with UITableViewStylePlain

        public init?(coder aDecoder: NSCoder)

        
        open var style: UITableViewStyle { get }

        
        weak open var dataSource: UITableViewDataSource?

        weak open var delegate: UITableViewDelegate?

[...]

または、

@IBOutlet private weak var label: UILabel?

これを見ると、weakはnilをセットできるので、定数にできません。

非所有参照 (Unowned Reference)

弱参照と同様に、非所有参照は、それが参照するインスタンスを強く保持しません。 ただし、弱参照とは異なり、他のインスタンスが同じ存続時間またはより長い存続時間を持つ場合、非所有参照が使用されます。(オフィシャルドキュメント)

例を見ましょう!

class Workspace {
    let name: String
    var channel: Channel?
    init(name: String) {
        self.name = name
    }
    deinit { 
        print("Workspace \(name) is being deinitialized") 
    }
}

class Channel {
    let name: String
    let workspace: Workspace
    init(name: String, workspace: Workspace) {
        self.name = name
        self.workspace = workspace
    }
    deinit { 
        print("Channel #\(number) is being deinitialized") 
    }
}

var workspace: Workspace?

workspace = Workspace(name: "slack")
workspace!.channel = Channel(name: "private", workspace: workspace!)

workspace = nil

Workspaceはchannelがあるかどうか決まっていないがChannelは必ずWorkspaceに属します。

この場合は、WorkspaceChannelのインスタンスは強参照があるので、deinitの関数を実行されません。

しかし、unownedをつかったら?

class Channel {
    let name: String
    unowned let workspace: Workspace // unowned を追加
    init(name: String, workspace: Workspace) {
        self.name = name
        self.workspace = workspace
    }
    deinit { 
        print("Channel #\(number) is being deinitialized") 
    }
}

こういう感じになります。

f:id:curama-tech:20180802160746p:plain

この行

workspace = nil

を実行すれば

Workspace slack is being deinitialized
Channel #private is being deinitialized

理由は、非所有参照のため、workspace変数が保持する強参照を解除すると、Workspaceインスタンスへの強参照はなくなります。メモリリークを解決できました。

キャプチャーリストを定義する(Capture List)

キャプチャリストは、weakまたはunownedキーワードをクラスインスタンス(selfなど)への参照や、値によって初期化された変数(delegate = self.delegate!など)とペアにしたものです。(オフィシャルドキュメント)

Playerの例をもう一回見ましょう!

lazy var detail: () -> String = {
        return "Name: \(self.name), age: \(self.age) "
    }

変更して、

lazy var detail: () -> String = { [unowned self] in // [unowned self] を追加
        return "Name: \(self.name), age: \(self.age) "
    }

もう一回実行したら、結果は

Deallocated!

というのはリークも解決できました。

最後に

私たちテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています。興味がある方は是非お気軽にご連絡ください (コーポレートサイト https://www.minma.jp/ )。