派遣で働くエンジニアのスキルアップを応援するサイト

PRODUCED BY RECRUIT

池澤あやかとはてな大西がリクルートマーケティングパートナーズの竹迫さんに「エンジニアの働きやすい職場って?」と聞いてみた。

f:id:blog-media:20151125104819j:plain

連載:池澤あやかとはてな大西の「エンジニアの働きやすい職場って?」

リクルートスタッフィングが新たにスタートするエンジニア向けメディアを、株式会社はてながお手伝い。女優でエンジニアとしても活躍されている池澤あやかさんと、はてな チーフエンジニアの大西康裕が、エンジニアの働く環境や開発の様子、エンジニアのキャリアパスなどについてインタビューする連載です。毎回、さまざまな企業を訪問し、エンジニアの理想の働く環境について考えていきます。

大西 連載「エンジニアの働きやすい職場って?」始まりました。はてな サービス開発本部長 チーフエンジニアの大西です。

池澤 池澤です。よろしくお願いします!

大西 記念すべき第1回は、ゼクシィ、カーセンサー、受験サプリ、料理サプリ、Quipperなど多岐にわたるサービスを展開する、リクルートマーケティングパートナーズ のオフィスにお邪魔します。

f:id:blog-media:20151125104820j:plain

立ってPCを触りたい人にも気分転換したい人にもうれしいスタンディングテーブル(しかもおしゃれ!)

大西 いきなり不思議な写真ですが、これは執務スペースの中にある、立ちながらちょっとした打ち合わせができるスペースのようですね。便利!

池澤 まずはオフィスを見学したいんですが、どなたか案内してくれる人はいませんかね?

大西 知り合いがいないか探してみましょう……あっ!

f:id:blog-media:20151125104821j:plain

大西 あそこにいるのは……!

f:id:blog-media:20151125104822j:plain

大西 最近、リクルートマーケティングパートナーズに入社された、TAKESAKOこと竹迫良範さんじゃないですか!

技術フェローのtakesakoです – PSYENCE:MEDIA

竹迫 こんにちは! 技術フェローの竹迫です。今日は私がご案内します。

池澤 ありがとうございます!

竹迫 まずはこちらにどうぞ。

f:id:blog-media:20151125104823j:plain

ミーティングスペース全景。広々とした空間に、さまざまなテーブルやいす、クッションが置かれている。

池澤 広い!

大西 ミーティングできるスペースですね。勉強会なんかもできそう。

竹迫 はい、ここでよくやっていますよ。あと、段差がついていますよね。これ、高さが変わることで、別のテーブルの声が届きにくくなる効果があるんです。

f:id:blog-media:20151125104824j:plain

テーブルとテーブルの間に段差が見える。モニターの取り付け位置も少しずつ違う。

池澤 端の方にはカウンターみたいな席もありますね。コンセントがいっぱい。

f:id:blog-media:20151125104825j:plain

ミーティングスペースのカウンター席。窓から執務スペースの様子を見ることができる。

池澤 執務スペースの中が見える! なんか葉っぱみたいなのが見えますね。

竹迫 葉っぱですね。頭上の照明がまぶしくならないように使っています。

大西 エンジニアのいるオフィスで、よく見る光景だ(笑)。葉っぱ、モニターに照明が映り込んでしまうのを防げるんですよね。はてなでも使っている人は結構います。

竹迫 会議室もご紹介しますね。

f:id:blog-media:20151125104826j:plain

池澤 おしゃれですね。カフェみたい。

竹迫 部屋によって違うソファが置いてあったりします。どうですか、座ってみませんか。

f:id:blog-media:20151125104827j:plain

竹迫 大西さんもどうぞ。

f:id:blog-media:20151125104828j:plain

大西 緊張した。

竹迫 次は廊下へどうぞ。廊下の壁は一面、ホワイトボードになっています。

池澤 すごい!

f:id:blog-media:20151125104829j:plain

f:id:blog-media:20151125104830j:plain

廊下に備え付けられたホワイトボードを使ってみる池澤さん。奥の方では実際に打ち合わせが行われていた。

大西 廊下で打ち合わせができますね。

竹迫 はい。窓側はすべて座れるように椅子になっているので、ちょっとした打ち合わせは廊下でもできます。

f:id:blog-media:20151125104831j:plain

先ほどミーティングスペースの窓から見ていた執務スペース。

竹迫 執務スペースの中はこんな感じです。

大西 執務スペースは、割と……普通の雰囲気ですね。

竹迫 そうですね(笑)。席は、なるべく同じチームが背中合わせになるように配置しています。

f:id:blog-media:20151125104832j:plain

竹迫 こちらはモニタールームです。別室でサービスやアプリを実際に使っていただいて、その様子を観察できます。ユーザーテストに使います。

池澤 モニターがたくさんあってかっこいいですね!

全社でリモートワークを推進中。仕事の質を高める取り組み

大西 ではこのあたりでオフィス見学は終了して、竹迫さんにお話を伺っていきたいと思います。

竹迫 よろしくお願いします。

f:id:blog-media:20151125104833j:plain

池澤 執務スペースが静かでしたねー。

竹迫 エンジニアやデザイナー、ディレクター、企画などがいま見てきた執務スペースにいて、営業さんなどは別フロアにいます。コミュニケーションにはSlackを使っていて、そちらでは盛り上がっていますよ。

その仕事、Slack で。 | Slack

大西 Slackを使っている会社は増えましたね。はてなもSlackを使っています。

池澤 私もSlack、使っています! そういえば、そもそもオフィスにいる人がちょっと少ないような?

竹迫 はい、リモート業務を推奨しているためです。月曜と金曜は出社している人がとても少なくて、水曜も少なめです。今日(編注:取材日)は水曜日なのでいつもより少ないですね。

池澤 ええー、お仕事できるんですか?

竹迫 普段からSlackで会話しているので、大丈夫ですよ。あとは、AtlassianのConfluence(企業向けのWiki/コラボレーションソフトウェア)やQiita(プログラマ向け技術情報共有サービス)を使っています。

Confluence - チーム コラボレーション ソフトウェア | アトラシアン
Qiita

f:id:blog-media:20151125104834j:plain

竹迫 リモート業務はエンジニアを中心として試験的に実施していましたが、2015年10月からは全社的な取り組みとして、全従業員がリモートワークできる状態になりました(※入社半年以内の新人は除くなど一部例外あり)。僕の部署ではリモート勤務を推奨していて、Google Hangoutsを使って映像を飛ばしながら、という感じが多いですね。

大西 はてなにも何人かリモート勤務のエンジニアがいますが、ひとりが猫を飼っていて、会議中に猫が入ってきて映り込むと、みんなかわいい~ってなります(笑)

竹迫 良いですね(笑)。弊社では自分のための時間と与えられた仕事をする時間のバランスをとるように、と社長から指示が出ています。時間をかけてだらだら仕事するのではなく、質を高めていこうという方針です。

池澤 ちなみに、外に行っての仕事はOKですか?

竹迫 業務内容によります。セキュリティレベルによって扱える仕事が決まっています。僕の場合は、外でもできるレベルですが、画面が外部の人に見られると良くないので、基本的に自宅で。ただ、レンタルオフィスを借りて、そこで仕事、というパターンもあります。

大西 社内で勉強会などは開催されているんですか?

竹迫 技術勉強会を2週間に1回、木曜の夜にやっていますね。あとは、社外の人も招いてのLT大会なんかもやっています。まさに、このスペースで。ピザとビールを頼んで!

大西 はてなも木曜夜に技術勉強会をやっています、似てますね(笑)。はてなでは寿司が出ます!

池澤 普段リモートで業務をしていると、勉強会で集まるのは大変そうな気がしますね。

f:id:blog-media:20151125104835j:plain

竹迫 むしろ仕事だけだとバラバラになっちゃうので、勉強会で顔を合わせて情報交換する、という効果がありますね。

大西 リモートだと、例えばみんなで付箋を貼ったボードを見ながら議論……とかは難しいイメージですが。

竹迫 そうですね。スクラムを導入しているチームなどは、スプリント計画会などのミーティングの日は曜日を固定して、その日は必ず出社しましょう、というようにしています。

大西 スプリントの振り返りの日とかもですね。これも、はてなも同じです。あとリモートだと、誰も見てないので、むしろ頑張らなきゃ、という気持ちになりますよね。

竹迫 純粋に成果が求められますからね。

「技術フェロー」の仕事は、エンジニアのキャリアパス整備と技術の見立て

池澤 技術フェローとして、普段どんなことをされているんですか?

大西 今年(2015年)の9月に入社されたんですよね。

竹迫 はい。主な業務のひとつが、エンジニアのキャリアパスを整備していくことです。エンジニアがこの会社の中で成長できるようなキャリアを作っていくことを考える、ということですね。

池澤 入ったばかりでそんなことを!

竹迫 リクルートマーケティングパートナーズの設立は2012年なのですが、エンジニアを徐々に増やしていって、今は27人くらいです。来年には35人程度に増える予定です。新卒エンジニアも採用していますよ。

f:id:blog-media:20151125104836j:plain

大西 まだ入られたばかりだとは思いますが、具体的に導入した仕組みなどはありますか?

竹迫 そうですね、キャリアパスをエンジニアみんなと考えて作っていくというのをやり始めています。

大西 はてなのエンジニアも今ちょうど35人くらいなので、今度お酒でも飲みながら、エンジニアのキャリア制度について相談させてください(笑)

竹迫 良いですね(笑)。それから技術フェローとしては、プロダクトに使う技術の中長期的な見立てにも関わっています。「受験サプリ」や「料理サプリ」などのサプリシリーズは、それぞれ別の言語で作られているんですね。Rubyだったり、Scalaだったり。いま作っている新しいサービスはJavaだったり。

池澤 どうしてそれぞれ言語が違うんですか?

竹迫 各チームのエンジニアが使いやすい、使いたいものを使っていい、というふうにしてきたんです。ただ、あまりにも言語がバラバラだと、チーム間の人の異動や技術の共有がしづらくなっていくので、その辺りの全体最適のバランスを考えていくのも仕事です。

池澤 前職とは仕事内容、変わりましたか?

竹迫 前職でも採用まわり、育成まわりは担当していたので、実は大きく変わっていないんじゃないかなって思っています。

エンジニアがやりたい仕事を選べる仕組みづくり

池澤 1チーム、何人くらいで動いているんですか?

竹迫 サプリ系は1つのチームにエンジニアが4~8人くらい。あとはプロデューサーとプロダクトオーナー、スクラムマスター、デザイナーが2人とかで、全員で9~13人くらいですね。

大西 スクラムマスターは専門職なんですか? それともエンジニアが持ち回り?

竹迫 エンジニアがやる場合もありますが、ディレクターが勉強して担当したりもします。コーチをお呼びしたりもしていますよ。

大西 スクラムマスターになったエンジニアは、コードを書かなくなる?

竹迫 いいえ、コードは書きますね。

f:id:blog-media:20151125104837j:plain

大西 なるほど。エンジニアのキャリアパスについて、もう少し詳しく伺ってもよいでしょうか。

竹迫 現在は、大きく3つのパスを設けています。一つ目が、ミッションクリティカルな課金系のシステムや、しっかりしたインフラを作るエンジニアになる方向。二つ目が、技術に特化したテクニカルな方向で、新しい技術を導入したり、対外的な発表なども活発にするタイプ。三つ目が、ビジネスコミュニケーションに特化していって、コードも書きつつ他の部署とも調整して事業を推進するタイプです。

大西 なんとなくエンジニアだと二つ目に多く人が集まりそうなイメージですが、どうですか?

竹迫 意外とそうでもないんですよ。「俺、そこまででもないし」っていう謙虚な人が多くて。エンジニアからプロダクトオーナーになる人もいますし、将来的には企画をして事業を作っていきたいという人もいます。あと、リクルートグループは、どの職種も他のグループ会社で仕事をしたいという希望を出して認められると、転籍できるという制度があるんですね。この制度、もともといた部署の上司には拒否権がないんです。

池澤 ええー!

大西 拒否権がないのはすごいですね。その制度は、利用者は結構いるんですか?

竹迫 はい。エンジニアの場合はプログラミングのテストなどをして、その結果で決まっていきます。グループを横断して、人と会社をマッチングする取り組みですね。そのほか、退職金制度も手厚いですし、それを元手に新しい会社を作るという人もいますね。

f:id:blog-media:20151125104838j:plain

竹迫 このように、エンジニアのモチベーションを大事にしています。その人がやりたいことを、いろんなところから探してくる努力を会社側でもしています。マネージャーは大変ですが(笑)

大西 すごく面白かったです。竹迫さんが入られたことで、さらに良くなっていくことを期待しています。

池澤 ありがとうございました!

§ § §

池澤 エンジニアが働きやすいような環境を目指して取り組まれている様子が伝わってきましたねー!

大西 竹迫さんが入られたことで、さらに加速していきそうですね。ところで、第1回ということでちょっと緊張していたのですが、取材がうまくいってホッとしています。次回以降もよろしくお願いします!

池澤 こちらこそ! それでは皆さん、また次回お会いしましょう!

写真:小高 雅也

'); $backTopNav.appendTo($('.no-entry .entry-content')); } ////////////////////////////////////////////////////////// /* /* カテゴリ **/ function setLocalNav(){ // 右カラム:イベントレポートのナビ生成 var $reportNav = $('#js-report-nav'); if ( $reportNav.length > 0 ) { var reportCatParentIndex = 2; var reportCats = itseCategory[reportCatParentIndex][1]; $.each(reportCats,function(index, val) { $('
  • '+itseCategoryText[reportCatParentIndex][1][index]+'
  • ').appendTo($reportNav); }); } // 右カラム:コラム・連載のナビ生成 var $columnNav = $('#js-column-nav'); if ( $columnNav.length > 0 ) { var columnCatParentIndex = 1; var columnCats = itseCategory[columnCatParentIndex][1]; $.each(columnCats,function(index, val) { $('
  • '+itseCategoryText[columnCatParentIndex][1][index]+'
  • ').appendTo($columnNav); }); } } function setClassCategories(){ $('.categories a').each(function(){ if(!$(this).hasClass('.urllist-category-link')){ $(this).addClass('urllist-category-link category-'+$(this).text()); } }); } setLocalNav(); setClassCategories(); ////////////////////////////////////////////////////////// /* /* カレンダー **/ var eventData; var Calendar = function (elm) { this.$elm = elm; } Calendar.prototype.init = function () { this.$calendar = null; this.calendarDate = {}; this.settings = { year: 0, month: 0, weekValue: ['æ—¥', '月', '火', 'æ°´', '木', '金', '土'], areaClass: 'calendar', activeDateClass: 'active-date', prevNavClass: 'prev', nextNavClass: 'next', sunClass: 'sun', satClass: 'sat', todayClass: 'today', emptyClass: '', headerFormat: 'yå¹´m月', emptyValue: ' ' } var date = this.getDate(); this.calendarData = { year: date.year, month: date.month, date: date }; this.today = date.days; this.currentMonth = date.month; this.currentYear = date.year; this.setup(); } Calendar.prototype.getDate = function () { var date = new Date(); var toYear = date.getFullYear(); var toMonth = date.getMonth() + 1; var toDays = date.getDate(); var result = {}; result = { year: toYear, month: toMonth, days: toDays }; return result; }; Calendar.prototype.getPrevDate = function () { var result = { year: this.calendarData.year, month: this.calendarData.month }; if (result.month === 1) { result.year--; result.month = 12; } else { result.month--; } return result; }; Calendar.prototype.getNextDate = function () { var result = { year: this.calendarData.year, month: this.calendarData.month }; if (result.month === 12) { result.year++; result.month = 1; } else { result.month++; } return result; }; Calendar.prototype.zeroFormat = function (v, n) { var vl = String(v).length; if (n > vl) { return (new Array((n - vl) + 1).join(0)) + v; } else { return v; } }; Calendar.prototype.weekClass = function (weekNumber, targetDate) { var date = this.getDate(); var classArr = []; var classStr = ''; if (weekNumber === 0) { classArr.push(this.settings.sunClass); } else if (weekNumber === 6) { classArr.push(this.settings.satClass); } if (targetDate && targetDate === '' + date.year + this.zeroFormat(date.month, 2) + this.zeroFormat(date.days, 2)) { classArr.push(this.settings.todayClass); } if (classArr.length > 0) { classStr = ' class="' + classArr.join(' ') + '"'; } return classStr; }; Calendar.prototype.createBaseHTML = function () { var htmlStr = ''; htmlStr += '\n
    \n'; htmlStr += '
    \n'; htmlStr += '
    \n'; htmlStr += '
    \n'; htmlStr += '
    \n'; htmlStr += '
    \n'; htmlStr += '
    \n'; htmlStr += '
    \n'; htmlStr += '
    \n'; this.$calendar = $(htmlStr); this.$calendar.addClass(this.settings.areaClass); this.$calendar.find('.calendar-month').addClass(this.settings.activeDateClass); this.$calendar.find('.calendar-prev').addClass(this.settings.prevNavClass); this.$calendar.find('.calendar-next').addClass(this.settings.nextNavClass); }; Calendar.prototype.createBody = function () { var self = this; var year = this.calendarData.year; var month = this.calendarData.month; var lastdays = new Date(year, month, 0); var forDate = new Date(year, month - 1, 1); var emptyCell = '
  • ' + this.settings.emptyValue + '
  • \n'; var rowCount = 1; var htmlStr = ''; var i; var j; var len; htmlStr = '\n'; htmlStr += '\n'; htmlStr += '\n'; this.$calendar.find('.calendar-body').html(htmlStr); }; Calendar.prototype.setHeader = function () { var headerText = this.settings.headerFormat.replace('y', this.calendarData.year).replace('m', this.calendarData.month); this.$calendar.find('.calendar-month').html(headerText); }; Calendar.prototype.setup = function () { var self = this; this.createBaseHTML(); this.setHeader(); this.createBody(); // ヘッダー内、左右のリンクをクリックしたときの処理 this.$calendar.find('.js-change-month a').on('click', function () { var mode = $(this).attr('href').replace(/^#/, ''); if (mode === 'prev') { self.prevMonth(); } else if (mode === 'next') { self.nextMonth(); } return false; }); this.$elm.append(this.$calendar); }; Calendar.prototype.changeCalendar = function (year, month) { var date = this.getPrevDate(); if (year && month && String(year).match(/^[0-9]{4}$/) && String(month).match(/^[0-1]?[0-9]$/)) { this.calendarData.year = Number(year); this.calendarData.month = Number(month); this.setHeader(); this.createBody(); } }; Calendar.prototype.prevMonth = function () { var date = this.getPrevDate(); this.changeCalendar(date.year, date.month); }; Calendar.prototype.nextMonth = function () { var date = this.getNextDate(); this.changeCalendar(date.year, date.month); }; ////////////////////////////////////////////////////////// var getEventData = function () { var d = $.Deferred(); // dataを作る var data = {}; eventSchedule.forEach(function(v, i){ var date = new Date(v.date); var event = { category: v.category, year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate(), url: "http://www.itstaffing.jp" + v.url, title: v.title, }; data[i+1] = event; }); // ここまで d.resolve(data); return d.promise(); } if ($("#calendar").length > 0) { var getData = getEventData(); getData.then(function (data) { eventData = data; //console.log(eventData); var calendar = new Calendar($("#calendar")); calendar.init(); }); } //}; }); }();