Septeni Engineer's Blog

セプテーニエンジニアが綴る技術ブログ

2017年セプテーニ・オリジナルの新人研修について

こんにちは。 昨年の8月に入社した嶽(だけ) @masayadk1229 です。

今回は私も携わらせて頂いている2017年のセプテーニ・オリジナルの新人研修についてご紹介したいと思います。 新人研修を担当されている方、新卒/中途問わず弊社に入社を考えている方などは少しでもご参考にして頂ければ嬉しいです。

※弊社では、新人のことをBN(Brand New)と呼んでいるので、これ以降はBNと記載致します。

全体的な流れとしては、以下の形でご紹介させて頂きます。

2017年BN研修チーム発足の経緯

弊社では、今までの新人研修は集合研修→配属チームでの研修→実戦に投入という形を取っていました。 具体的に昨年の研修の例をあげると、以下のような研修を実施していました。

2016年のBN研修について

  • 集合研修
    • JavaScript研修(自学)
      • プログラミング自体を学ぶ研修
    • JavaScript研修(講師あり)
      • Web界隈の最新状況の雰囲気をキャッチアップするための研修
    • Java研修(自学)
      • 習熟度に応じて渡される書籍は違うが、基本的にはJavaを学ぶ研修
    • Scala研修(講師あり)
      • 麻植さん(@oe_uia)に依頼する外部研修(14日連続で実施)
  • 配属チームでの研修
    • 掲示板研修(自由形式)
    • 掲示板研修(DDD)
      • DDDに従い、掲示板を作成

2016年のBN研修の課題

ただ、上記を実施したことで、BN配属後の現場では以下のような事象が発生していました。

  • 研修がプログラミング経験者向きになっており、初学者は研修を終えても十分に知識が身に付いていない
  • 配属チームごとに教育方針が違い、研修が長期化 or 研修が終わっても戦力化に時間がかかることがあった
  • 研修ではScala/Play/DDDを学ぶことになっているが、その他の土台となる知識を学ぶ機会が少ない

上記がチーム配属後の状況から課題として浮き彫りになりました。

よって、今年はBN研修チームを結成して、その課題を解消すべく動くことになりました。

BN研修チームで最初に決めたこと

BN研修チームのメンバーについては、弊社内で2017年1月前半に公募し、主導するマネージャー含めて6名のチームで動くことになりました。

第1回のMTGでは上記のチーム発足の経緯を鑑みて、まずは2017年のBN研修は何が達成できれば良いかをチームで考え、ゴールや研修に取り組む姿勢について設定しました。

BN研修のゴール

BN研修のゴールは「早期戦力化」。

戦力化というのは研修が終わってPJに入れたらゴールではなく、エンジニアとして自走(自ら学び、自ら走る)してチームに貢献できる状態を指す。

そのためにチームに参加したタイミングでも各チームへの負担を減らしつつ、BNもScalaに限らず一定程度の必要知識を習っている状態を目指す。

BN研修に取り組む姿勢

また、BNメンバーにおいても研修への姿勢として、以下のように取り組んで欲しい旨をお伝えしました。

BNそれぞれにスキル差があり進み具合もバラバラになる事が想定されるが、研修が終わるまではBN全員で一つのチームであるという意識を持ってほしい。

メンターや講師はもちろんフォローするが、それぞれの課題や研修内容についてお互いに話し合い、協力して理解を深めてくことが重要。

コードを書く力は勿論だが、話を聞く力、話を伝える力、協調性など様々なことを研修を通じて学びとってほしい。

BN研修内容を決定するまでの経緯

ゴールが決まったので、ここからは実際にどんな研修内容にするかについて話し合いました。

BN研修内容を決定するまでの流れ

大まかには、以下の流れで研修内容を決定しました。

どのようなスキルが必要かを考える
↓
どんな研修を実施すればそのスキルが身につくかを考える
↓
研修イメージの中身について深掘りをする
↓
外部に研修を依頼するか社内のエンジニアが講師を担当するかを検討
↓
BN研修チームとしてのたたき台を作成
↓
予算面/スケジュール面で経営陣に合意を取る
↓
研修内容の決定

弊社で必要となるスキルのブレスト結果

参考までにBN研修チームで、弊社で必要となるスキルは以下の通りに定義付けました。

BN研修の内容について

今回、BN研修チームとしては実際に実施した(実施している)研修内容をご紹介致します。

この研修内容は、課題にあったプログラミング初学者も考慮に入れて、作成しています。

BN研修のカリキュラム

※ タイトルの後の括弧内は研修期間。

  • ソフトスキル研修(半日)
  • Macを使おう(数時間)
    • Mac初心者が多いため、ターミナルを使った基本的な操作などを教育する。
  • Web基礎研修(2日)
    • インターネットやシステムなど、Webに関わる基礎部分を書籍を参考に講義し、理解を促進する事で自分たちがこれから取り組む業務の基礎理解を促進する。
  • Scala研修準備(10日)
    • Scala研修の前段階として、最低限学んでおいたほうがいいと言われた書籍を参考にフォローを行う。
    • プログラミング(とできればJava)の基本用語・概念(クラス、インスタンス、メソッド、オブジェクト、戻り値、引数…) についてある程度理解している、ぐらいの理解度を目指す。
    • 参考書籍: Java言語プログラミングレッスン 第3版(上)(下)」
  • Scala研修(半日×14日)
    • コップ本をベースにScalaについて学ぶ
    • 麻植さん( @oe_uia)に依頼する外部研修(週2回で合計14回実施)
    • 参考書籍: Scalaスケーラブルプログラミング第3版」
  • サーバ構築講習(1日)
    • 自分たちが書いたアプリケーションを実行するサーバを最低限構築する技術を教育する。
  • データベース基礎(2日)
    • アプリケーションに必要不可欠なデータベースについての基礎を書籍を参考に教育する。
    • 参考書籍: 「SQL 第2版 ゼロからはじめるデータベース操作」、「Webエンジニアのための データベース技術[実践]入門」
  • 設計(アルゴリズム)基礎(半日)
    • プログラミングをする際に知識としてあったほうがよい一般的なアルゴリズムについての講義をする。
    • 参考書籍: 「アルゴリズムの絵本-プログラミングが好きになる9つの扉」
  • TDD研修(半日)
    • 弊社全体で行なっている研修を用いて、テスト駆動開発について講義をする。
  • スクラム基礎研修(半日)
    • チーム開発で弊社が採用しているスクラムについての概要を講義する。
  • チーム開発準備(半日)
    • チームで開発をする上で必要な情報をインプットする。
    • 具体的には、弊社が採用しているGit、 Atlassian製品の使い方(JIRA、Bitbucket、Confluence)の説明、活用方法を講義する。
  • DDD研修(1日)
    • 弊社が採用しているDDDについて、講義を行う。
  • チーム開発(実施日数未定/期限あり)
    • BNで研修の仕上げとしてチームを組んでECサイトの開発を行う。

上記をBN研修チーム外の方にも研修の担当講師としてご協力いただき、大方実施を終えました。

残りの研修は現在実施中のチーム開発とDDD研修が残っております。

今回に関しては外部研修は麻植さん(@oe_uia)のScala研修のみでした。

チーム開発研修

今年の目玉は他社でもよく実施するであろうチーム開発研修で、 チームで協力して何かを作り上げるということを経験してもらう内容になっています。

具体的には擬似的な顧客(プロダクトオーナー)を立てて、要件が曖昧な中で基本は丸投げしてECサイトの完成を目指してもらうものになっております。

こちら、以下の目的で研修を設定しました。

  • チーム開発を経験してもらう
  • 要件の掘り下げのフェーズから経験してもらう
  • 失敗を経験してもらう

こちら以外の研修は基本的に座学や自習が多く、こちらから与えるような研修ですが、チーム開発研修のみ自分たちでどのように動いて成功させるかの自発性も問われるものになっています。

あえて、ここまで扱わなかったWebアプリを作成するという課題を設定し、プロダクトオーナーとのやりとりも自分たちで進めるものとなっています。

また、どのように進めるかをこちらから提示せず、丸投げでスタートさせたのは一旦失敗を経験してもらいたかったという意図もあります。

ここでいう失敗とは、極端な例で言えばバージョン管理システムを使わなければ競合が起こる、チームで話したことをドキュメントに残さないと仕様認識の齟齬が起きるなどを身を持って経験して欲しいかったからです。

このような失敗の経験をすることで開発プロセスやツール、開発手法などに関しても"なぜ採用しているのか"ということを考える機会を提供できると考えたからです。

BN研修を実施してみて

今回、弊社内で初の試みということで、様々なことがありましたが、問題が発生した中で抜粋していくつか紹介したいと思います。

研修運営の課題

研修を担当してくださった講師の方は資料作成など負担が大きいものになりました。 負担が大きくなった理由はいくつかありますが、個人的には以下のいずれかに該当するかなと思っています。(あくまでも個人の見解です)

  • 資料作成の時間を確保できていない
  • 資料にお手製の図などを入れたりして、見た目の作り込みだけでも時間がかかった
  • 参考書籍をうまく活用できなかった

研修運営の課題に関しての次回以降のアクション

今回はこのような課題が出ましたが、個人の見解としては上記の課題に関しては以下のアクションを起こせると思います。

  • 会社として業務時間の何割かは使って良いと許可を頂いてはいるので、開始時期さえ早めれば十分に時間は確保出来るので、着手を早める
  • 講師はBNメンバーに配布する課題書籍を頂けるのですが、その書籍を電子書籍などにして頂ければ、画面キャプチャーなどを使い、図の作成を短縮できる
  • 参考書籍に関しての検討は一度手元に届いてから内容を確認して、講師側と認識をすり合わせるようにする

上記の見解は個人のものですが、今回は研修講師の方々にそれぞれ振り返りページを作って頂きました。 振り返りページを元に、来年以降の研修は改善していきたいと思います。

カリキュラムの課題

今年のBNは3人全員プログラミング経験者でした。

その情報を踏まえたうえでプログラミング初学者も考慮した今回の研修の実施を行なったわけですが、以下のような事象が発生しました。

  • Scala研修準備を10日間前後で設定したが、当初の想定より時間が余った
  • Scala経験者がScala研修の前半に時間を少し持て余してしまった
  • インフラ系のカリキュラムの順序が悪く、知識を繋げて伝えられなくて効率が悪かった

カリキュラムの課題に関しての次回以降のアクション

今回は、こんなに早く全員がカリキュラムを終えることを想定していなかったため、以下のカリキュラムを追加しました。

  • アルゴリズム系の問題の演習を行なってもらった
    • 参考書籍: 「世界で闘うプログラミング力を鍛える150問 」
  • Vimの操作やLinuxについて知識について学んでもらった
    • 参考書籍: LPIC Level1の教科書」
  • SQLの基礎について学んでもらった
    • 参考書籍: 「ゼロからはじめるデータベース操作」

次回以降は、自習系のカリキュラムの場合は早く終わった人には何をやってもらうかをBN研修チーム内であらかじめ決めておくべきだと思いました。

終わりに

弊社では手探りではございますが、BN研修をこのような形で刷新を行いました。

個人的にはほぼゼロベースから、手探りながらもチームで研修を作っていけたのはとてもやりがいがありました。

今年のBNが現場に入ってから少しでも活躍できるように尽力はしましたが、私自身も資料作成が遅れるなど至らなかったところがたくさんありました。

自分自身が前職で新人研修を手厚くして頂き、周りの方から教育して頂いたことで今の自分があると思っているので、恩送りという意味でも来年以降もBN研修には協力していきたいと思っています。

また、弊社では中途入社の方へも平均して1〜2ヶ月程度の研修が用意されています。

詳細は…別の機会に紹介させて頂くとして、こちらも刷新に向けて動き始めているようです。

ご興味を持って頂いた方は入社して頂き、一緒に研修を作り、会社の未来も作りましょう!

XcodeでInterfaceBuilderの型を消し去ってみると色々得られて少し失った

こんにちは。

GANMA! チームで開発をしている、寺坂です。

GANMA!のiOSアプリでは、
XcodeInterfaceBuilder を活用してUI開発をしています。

今回は、InterfaceBuilderをより活用できようになる、かもしれない内容を書いていきます。

モチベーション

UITableViewのdalegateやdataSourceのように
自分で作ったViewのdelegateもInterfaceBulder(以下、IB)上で Outlet接続したい。

続きを読む

スマフォを捨てて、1ヶ月が経ちました。

0. 前置き

どうも、初めての方ははじめまして、お久しぶりですの方はお久しぶりです。エンジニアの原田です。
ネタとして温めていたたわけでも無いんですが、個人端末についてでもお話しようかと思います。
結果、この持ち方が最高とか、賞賛するわけではないのですが、読み物的に楽しんでもらえれば幸いです。

1. なぜスマフォを捨てたのか?

どうしてスマフォを捨てようと考えたのかについてです。
スマフォに対して大きな不満はなかったのですが、決めてになった変更理由についてです。

続きを読む

scikit-learnを使ってみた

こんにちは、佐野です。

先日、機械学習を勉強する機会があり、手元でちょっと検証するときにscikit-learnを使ってみたのですが、とても使いやすく便利だったため、有名なライブラリですが紹介したいと思います。

scikit-learnとはPythonオープンソースライブラリで、クラス分類、回帰分析、クラスタリングなどのための様々なアルゴリズムを備えた機械学習ライブラリです。

Pythonを今まで書いたことがなかったし、機械学習も薄っぺらい知識しかなかった僕でもインターフェースがとてもシンプルな作りになっていたのですぐ馴染むことができました。

続きを読む

ITS健康保険の保養施設に行ってきました

こんにちは、池田です。

セプテーニ・オリジナルは2016年7月より関東ITソフトウェア健康保険組合(以下、ITS健康保険)という健康保険に編入しました。

先日この健康保険で使える保養施設「トスラブ箱根ビオーレ」に行ってきまして、

大変良かったので簡単にご紹介したいと思います。

f:id:taketor:20170707033526j:plain:w500

▲ 宿泊した洋室

続きを読む

scala.concurrent.blocking()

こんにちは。3月にセプテーニ・オリジナルに入社した河内です。 新しい環境でフレッシュな気持ちで業務に取り組んでおります。

さて scala.concurrent.blocking() は全く新しくない話ですが、あまり知られていないのかな、と感じるので書いておきます。 scala.concurrent.blocking()ブロッキング処理をマークするのに使います。

実行中のスレッドに関連付けられた *1 BlockContext によっていい感じに取り扱われます。 デフォルトの BlockContext は渡された引数を単に評価するだけです*2

BlockContext.withBlockContext() を使うと、指定した BlockContext を使ってブロッキング処理を扱うことができます。 次の例では blocking 前に log を出す BlockContext を作って利用しています。withBlockContext() で指定することで blocking() で囲まれた処理を実行する前に log が出力されます。

    val logContext = new BlockContext {
      override def blockOn[T](thunk: => T)(implicit permission: CanAwait): T = {
        println("Start blocking")
        thunk
      }
    }

    BlockContext.withBlockContext(logContext) {
      blocking {
        println("Blocking code")
      }
    }

withBlockContext() を使って BlockContext を自分で指定することは少ないと思います。おそらく最もよく出てくる場面は ExecutionContext.Implicits.global (以下 global) の上で Future を走らせるときではないでしょうか。

globaljava.util.concurrent.ForkJoinPool を用いて実装されています。ForkJoinPool は限られたスレッドを使ってCPUを効率的に利用する仕組みですが、ブロッキング処理が混ざるとCPUを効率的に利用できません。そこで登場するのが ForkJoinPool.ManagedBlocker です。この中でブロッキング処理を実行すると、専用のスレッドが起動されるため、元々の限られたスレッドは別の計算を行うために引き続き利用できます。

blocking() を使わずに global 上でブロッキング処理を行うと、CPUを効率的に利用できません。 global 上で blocking() を実行すると ForkJoinPool.ManagedBlocker を利用して内部の処理を行います。 これにより global 上でも CPU を効率的に利用できる環境が保てます。

デフォルトではそのまま実行され、global などの環境では専用スレッドを起こしてくれるので、ブロッキング処理は blocking() で囲みましょう。。。

で、話が終わればいいのですが、 Scala 2.11 以前では気をつけなければならない事項があります。

まず、できるだけ blocking() の中で blocking() を呼ばないこと。 global では blocking() を呼び出したときにスレッド (Thread1) が作られ、その中で再度 blocking() を呼び出すと別のスレッド (Thread2) が作られます。 Thread2 上での処理が完了するまで Thread1 は遊んだ状態になります。 なるべく下の層で blocking() を使うのが良いでしょう。

次に、blocking() を並列にたくさん呼びすぎないこと。 ブロッキング処理用に作られるスレッド数には事実上制限がないため、一時に多くの blocking() を呼び出すと作ることができるスレッドの限度を超え、 OutOfMemory エラーが発生します*3

Scala 2.12 では上記二点が改善されています。 ネストした blocking() 呼び出しにより余計にスレッドが作られてしまうことはありません。 スレッド数は 256 が最大に設定されており、 scala.concurrent.context.maxExtraThreads システムプロパティで変更できます*4

接続先ごとに ExecutionContext を利用するのがベストプラクティスだと思いますが、小さい単位の関数を書いていると、実行時に使われる ExecutionContext (BlockContext) が限定できないという状況があると思います。 ブロッキングしなければならないとき*5には blocking() を使うと、global を使った場合でも全スレッドをブロックしてしまう事象が置きづらく、良いと思います。

*1:ThreadLocal や Thread.currentThread が参照されます。詳しくは BlockContext.current を参照。

*2:BlockContext.DefaultBlockContext、Scala 2.12 では BlockContext.defaultBlockContext を参照

*3:参考: blockingとOOM

*4:参考: Futures in Scala 2.12 (part 7)

*5:避けられる限りブロッキングしないようにしましょう