データサイエンティストの「開発の苦労」を解消! 開発合宿で得た重要な学びについて

 

■ はじめに

みなさん、こんにちは。

データ・AIソリューション本部データサイエンス部のデータサイエンティストの山内です。

部内の若手データサイエンティストが業務において開発に苦労することが多いということで、その課題を解消するべくデータサイエンティストの開発技術向上を目指した開発合宿という初の試みが行われました。

本記事では、その「データサイエンティスト向け開発合宿」の様子をレポートします。

 

■ 目次

 

■ 概要

開発技術向上のための今回の取り組みは「事前課題」とその総仕上げとなる「合宿」で構成されています。

エンジニアとしての就業経験を持つ先輩アナリストがこの企画を主催し、各カリキュラムの準備や参加者へのコードレビューを担いました。

 

  • 事前課題

    • カリキュラム

      • 課題1(関数設計) 各自で取り組み

      • 課題2(機能追加) 各自で取り組み

      • 課題3(Webアプリケーションの設計・実装) チームで取り組み

    • 形式:オンライン
      • 日々の業務の合間に各自課題に取り組む
      • 主催者が各参加者へレビューを行う
  • 合宿
    • 日時:2025/09/10 ~ 2025/09/11 (1泊2日)
    • 形式:オフライン (関東近郊の研修施設)
    • 参加者:6名
    • 内容:課題3で作成したWebアプリのデプロイと発表会
    • 社内の合宿支援制度を利用

 

背景/目的 

「データサイエンティスト向け開発合宿」の詳細を語る前に、この取り組みの背景と目的を簡単に確認しておきましょう。

  • 背景

    • 部内のデータサイエンティストから、「開発で苦労している」という声が多数あがっている

      • 「設計がよく分からず、行き当たりばったりなコードを書いてしまう。そのせいでコードの可読性や再利用性が低下し、機能の追加や修正をする際に無駄に手間がかかってしまっている。」など
  • 目的

    • 設計・コーディング能力の向上
       

■  各課題の概要と学び・感想

課題1 関数設計

概要

「FizzBuzz問題を解くコードを書いてみよう!」

 

第1の課題は「関数レベルの設計」です。

ここでは、例としてFizzBuzz問題を解く関数の設計・実装を行いました。

 

FizzBuzz問題とは、数字が3の倍数なら「Fizz」、5の倍数なら「Buzz」、両方の倍数(15の倍数)なら「Fizz Buzz」、いずれでもなければその数字をそのまま出力するという課題のことです。プログラミングの初歩的な課題としてよく使われています。

 

課題1_FizzBuzz

上記の画像のようにget_fizzbuzzという関数と、その引数、例外、戻り値が与えられます。

この通り動作するように、get_fizzbuzz関数の中身を設計・実装するという課題です。

期待通りの挙動になっているかチェックするためのテストコードは事前に用意されています。

テストがすべて通るように例外処理とFizzBuzzルールの処理を設計・実装していきます。

今回は「設計の練習」という趣旨なので、「コードを書く前にまず日本語で実装したい処理の内容を記述する」というルールがありました。

 

学んだこと

私がこの課題を通じて学んだことをまとめると以下の通りです。

  • コードを書き始める前に、実装したい処理を言葉で記述し設計を考えること
    • VS Codeの拡張機能「Todo Tree」を活用すると良い
  • 「見やすい/見づらい」という感覚を大事にすること
    • 機能ごとに処理を切り分けると良い
    • 条件分岐ではbool変数を活用すると良い

 

実際に自分の書いたコードと模範解答のコードを見比べながら詳しく見ていきましょう。

まず山内の書いたコードがこちらです。

課題1_山内解答

例外処理とFizzBuzzのメインの処理を1つの条件分岐構造の中に詰め込んでしまっているので、elifがいくつも続いて見づらいですね。

今回は簡単な処理の短い関数なのでこの書き方でも読めますが、複雑な処理が必要なコードで同じことをやってしまったら可読性が低くなることは容易に想像できます。

 

では、レビュー時にいただいた模範解答も見てみましょう。

 

課題1_模範解答

先ほどの山内のコードとは違い、例外処理とFizzBuzzのメイン処理を分けているのでスッキリして見やすいですね。

 

また、条件分岐ではbool変数が活用されています。

「iが3で割り切れる」、「iが5で割り切れる」という条件式をjudge3、judge5というbool変数にすることでif文がスッキリして見やすくなるとともに、条件式の再利用もできます。

 

レビュー・模範解答をふまえて「コードを書く前に実装したい処理の内容を言葉で記述せよ」という指示について改めて考えてみると、単に「TODOを言葉で残すことで対応漏れをなくすため」「コメントを残し意図を伝えるため」というだけではなく、「処理を書き出すことで、どこを切り分けどこを共通化すると良いか整理しやすくするため」という目的もあったのだと気づかされました。

 

課題2 機能追加

概要

「組織図を読み込み、指定した部署の社員数や関連する組織の関係を可視化するプログラム」に対して、新しい機能を追加しよう!

 

課題として、まず「組織図のExcelファイルを読み込み、指定した部署の社員数やその部署と関連する組織の関係を可視化するプログラム」が与えられます。

 

イメージしやすいようにディレクトリ構造を見てみましょう。

課題2_ディレクトリ構造

まずsettings_dummy.jsonをコピーしてsettings.jsonを作成し、そこで部署を指定します。

今回は試しに「a部」、「b部」を指定してみましょう。

続いてmain.pyを実行すると、dataディレクトリ配下にoutディレクトリとhtmlファイルが生成されます。

そのhtmlを開くと、以下のような図が表示されます。

課題2_組織と所属人数の可視化

組織は会社>本部>統括部>部>グループのような階層構造になっています。

この図では先ほど指定した「a部」、「b部」と関連のある組織名その関係性がノードとエッジで表現されています。

また、各部署に所属している社員の人数が括弧書きで表示され、人数の大小に応じてノードの大きさが変わっていることも分かります。

 

raw_data.xlsxには部署以外の情報も記載されているので、それらの情報を活用してこのプログラムに自分で考えた新しい機能を追加するというのが第2の課題になります。

 

私は「職種ごとの人数を可視化する機能」を追加することにしました。

 

機能追加にあたって変更を加えたのはanalyzerディレクトリ配下です。

 

課題2_機能追加後のanalyzerディレクトリ

組織に関する分析と職種に関する分析では階層構造の有無という違いがあるため処理の内容が異なってきます。

そのため、each_analyticsというディレクトリを作成し、その配下に各分析に関する具体的な処理を切り分けてモジュール化することにしました。

 

逆に、ネットワークグラフのオブジェクトにノードやエッジを付与したり人数に応じてノードサイズを変えたりする処理は共通しているためcommonというディレクトリの配下に格納することにしました。

 

その結果、analyzer.pyがとても簡潔になりました。

 

課題2_機能追加後のanalyzer.py

せっかくですので、機能追加の結果も確認してみましょう。

 

「職種A」、「職種B」、「職種C」、「職種D」と職種を指定して実行すると、以下のような図が生成されます。

 

課題2_職種ごとの人数の可視化

 

指定した職種ごとの人数を数字とノードの大きさにより可視化することができるようになりました。

 

学んだこと

課題2に取り組む中で学んだことをまとめます。

  • 独立性・分離を意識すること
    • モジュール化
    • ディレクトリ分け
      • ディレクトリ間の関係に則した構造や命名にする
    • よく変更する値はpythonスクリプトに直書きせず、設定ファイルで指定する
    • 分離させることのメリット
      • 機能追加・修正時の変更範囲が小さくて済む
      • 可読性UP
      • 再利用性UP
  • VS Codeのデバッグ機能の活用
    • これまでは確認したいものをprint関数でいちいち出力していたが、デバッグ機能を使うことで効率よく確認できるようになった
  • VS Codeのヒント機能の活用
    • ヒント機能を活用するためにも、変数や関数の引数、戻り値の型などをしっかり明示しておくことが大切
  • VSCode Counterの活用
    • ファイルやディレクトリの階層構造把握に役立つ
    • LLMにコードに関する質問をする場合はVSCode Counterで得られた構造情報も一緒に与えてあげるとより的確な返答をしてもらいやすくなる

課題3 Webアプリケーションの設計/実装

概要

Webで動く電卓アプリを作ろう!

 

第3の課題では2つのチームに分かれて電卓アプリを作成していきます。

 

実装にあたって、チームごとに以下の役割分担を決めました。

  • フロントエンド
  • バックエンド(アーキテクチャ)
  • バックエンド(アルゴリズム)

 

私はチームAのバックエンド(アーキテクチャ)を担当です。

 

合宿当日まで、以下のような流れで開発を進めました。

 

  • 要求定義
    • ユーザーの欲しているものを明確にする
      • どんな計算ができる電卓か(四則演算のみ、()の計算、関数電卓など)
      • デザインの方向性はどんなものが良いか
  • 要件定義
    • 要求を具体的な仕様で表現
      • 画面の要件
      • バックエンドの要件
  • 基本設計
    • どんなシステムをどこでどのように開発するか(言語、オンプレ、クラウドなど)は事前に主催者が決定済み
  • 詳細設計
    • 具体的な設計を日本語で書き下していく
  • コーディング
合宿当日

そしてむかえた合宿当日は以下を行いました。

  • 設計レビュー/コードレビュー
  • Webアプリケーションのデプロイ・実行
  • 各チームの発表会

 

実際に各チームが作成した電卓がこちらになります。

 

チームA 

ユーザビリティ重視(かわいいデザイン、キーボードに似せたボタン配置など)

チームAの電卓

チームB

計算の厳密性の重視(値をDecimalでもつことで計算誤差を減らすなど)

チームBの電卓

「Webで動く電卓アプリを作る」というお題が同じでも、チームAとチームBではコンセプトが異なり、それによって実装にも違いがうまれていたのが興味深かったです。

チーム間でコンセプトの違いがある分には面白いのですが、想定している「電卓アプリ」のイメージがチームメンバー同士でも異なっていたら上手くかみ合わなくなるおそれがあります。

実装に入る前に、チーム内での認識のすり合わせが大切であると改めて感じました。

 

バックエンド(アーキテクチャ)の取り組み

先述の通り、私はチームAのバックエンド(アーキテクチャ)を担当しました。

主に行ったのは「バックエンドのディレクトリ構成を考えること」と「Validatorの設計・実装」です。

 

バックエンドのディレクトリ構成

バックエンドのディレクトリ構成は以下のような構成にしました。

課題3_バックエンドのディレクトリ構成

課題1や課題2で学んだ「機能ごとに分離する」というポイントを意識しました。

具体的には計算やバリデーションの処理を切り分けapi/endpoints/配下に配置したり、CORS設定をmain.pyから切り出したりといった工夫をしました。

calculator.pyの中身の実装はバックエンド(アルゴリズム)担当の方にお願いすることになります。

 

こうして切り分けられた各機能はmain.pyで以下の図のような形で利用されます。

課題3_main.py

calculate_postの部分に注目してみてください。

 

①requestからexpressionを取得

②expression整形のための置換処理

③バリデーション validate_expression関数

④バリデーション結果に応じた処理

  • バリデーション結果がOKの場合
    • 計算 calculate_expression関数
    • 計算結果を返す
  • バリデーション結果がNGの場合
    • エラーメッセージとともにHTTP 400エラーを返す

calculate_postというエンドポイントの処理はおおまかに上記の流れで進みます。

 

バリデーション処理のvalidate_expression関数はバックエンド(アーキテクチャ)の山内が担当しますが、計算処理の関数calculate_expressionはバックエンド(アルゴリズム)の担当者がcalculator.pyに実装します。

バリデーション処理を修正するたびに計算処理にも修正を加える必要があるようだと面倒ですよね。

バリデーション処理の修正が計算処理にも影響を与えないようにするために、Pydanticを活用してリクエストやレスポンスの型を次のように定義しました。

課題3_リクエスト・レスポンスの型

チーム開発においては、このように各担当者が独立して作業するための工夫が必要だという学びになりました。

 

Validatorの設計・実装

Validatorの設計・実装も担当しました。

バリデーション処理の関数であるvalidate_expressionはCalculationRequestを引数として受け取り、ValidationResponseを返す関数です。

 

先ほどのリクエスト・レスポンスの型の定義を確認し、validate_expressionが何を受け取り何を返すのか確認しましょう。

  • 引数 CalculationRequest
    • expression (リクエストの文字列 例:"(1+3)*27")
  • 戻り値 ValidationResponse
    • expression (リクエストの文字列)
    • result (バリデーション結果のTrue/False)
    • error_list (エラーのリスト)

この通りに動作するように具体的なバリデーション処理の設計・実装をしていくことになります。

 

過去の課題でも学んだ通り、まずは想定されるエラー(不正なexpression)のパターンを書き出し、各エラーの判定処理の内容を日本語で記述するところから始めます。

エラー判定のためのアルゴリズムを考えるのには時間がかかりましたが、アルゴリズムが決まってからの実装自体は比較的スムーズに進みました。

事前に設計を行うことで実装段階での迷いや手戻りが減り効率良くコーディングができるのだと改めて実感しました。

 

デプロイ作業

作成した電卓アプリをWeb上で動かせるようにするためにはデプロイ作業が必要です。

ローカルホストで動作確認を行ったうえで、リモートサーバーへのデプロイを試みます。

具体的な方法としては、ローカルPCにあるファイルをEC2へ送り、FastAPIでアプリを起動させてnginxのサーバー上に電卓アプリをデプロイしました。

 

FastAPIやnginxに触れるのが初めてだったこともあり、どこを修正すれば何が変わるのか分からず苦戦しましたが、無事に発表会前にデプロイを完了させることができました。

 

当初はローカルPCにあるファイルがどうやったらWebで動作するアプリになるのか想像がついていませんでしたが、今回のデプロイ作業を通じておおまかな流れを把握することができました。

 

合宿当日のコード修正

main.pyのcalculate_postの「expression整形のための置換処理」ですが、"×"を"*"へ、"÷"を"/"へ置換する処理は合宿当日に追加修正したものになります。

 

合宿前は別々に実装を進めており、合宿当日にはじめてフロントエンドとバックエンドを合わせて動作確認をしました。

その際に、「加算・減算は計算できるのにもかかわらず乗算・除算ではエラーになる」ことが発見されたのが修正のきっかけです。

チームAの電卓の画像を確認いただけると分かる通り、電卓のボタンでは乗算の記号を"×"、除算の記号を"÷"で入力するようになっています。

ところが、バックエンドでは乗算の記号は"*"、除算の記号は"/"で受け取る前提の実装になっていました。

 

このエラーを解消するための修正自体は置換処理のコードを2行追加するという軽微なもので済みましたが、「フロントエンドとバックエンドがお互い何をやっているのか」のすり合わせが不足していたことを痛感しました。

チーム内でのコミュニケーションを大切にしていきたいです。

 

また、コード修正後のレビューの際に「不正な値の制御はフロントエンドとバックエンドの両方で行った方が良い」ということも知りました。

フロントエンドのみによる制御ではSQLインジェクションなどのリスクがあったり、バックエンドのみによる制御ではユーザーが入力送信してエラーが表示されるまでミスに気づけずUXが低下したりするというデメリットがあるようです。

「フロントエンドが制御してくれているはず」「バックエンドが制御してくれているはず」と思い込むのではなく、セキュリティやUXの向上、データの整合性の確保のためには双方で制御をした方が良いという学びになりました。

 

学んだこと

課題3を通じて学んだことを整理します。

  • チーム開発におけるコミュニケーションの大切さ
    • チームAとチームBのコンセプトの違い
    • フロントエンドとバックエンドのコミュニケーション不足による「×と*、÷と/の置換処理」忘れ
  • Web上で動くアプリを作るまでのおおまかな流れの把握
  • 課題1・2で学んだことの重要性を再認識
    • 分離・独立性の意識
      • 型チェックにはPydanticを活用
    • 実装前の設計

■ 主催者からのコメント・振り返り

今回の開発合宿の主催者にも振り返りコメントをいただきました!

 皆様、開発合宿本当にお疲れ様でした。

 最終的にWebアプリのデプロイまで完遂できたこと、そして何より課題に非常に積極的に取り組んでもらえたこと、大変うれしく思います。

 

 さて、表の目標として「関数->モジュール->全体の順番で設計/実装が出来るようになってもらい、 Webアプリのデプロイを行うこと」を掲げましたが、実は、裏の目標は「システム開発におけるコミュニケーション能力を体得すること」でした。

関数にしろモジュールにしろ、「設計を行うこと」というのは、「将来の自分や周囲のエンジニア/アナリストに整理整頓された資産を遺すこと」と言い換えられると思います。

それは結局、「どのようにディレクトリを分割すれば良いか?」や「どのようにコメントを残すか?」など、コミュニケーションに帰着します。

合宿中のインターフェース設計の議論や各メンバーとの摺り合わせを通して、その重要性を肌で感じてもらえたのではないでしょうか。

 

 この合宿で掴んだ「設計の取っ掛かり」、「Webアプリの概要」、「チームで開発する力」は、皆様のキャリアにおける強力な武器になるはずです。

今後もアナリストとしてコードを書く日々が続くと思いますが、その際には少しでも設計を考えてもらえると、私としては望外の幸せです。

参加してくれてありがとうございました。

■ 合宿ならではの良さ  

ここまで開発合宿での取り組みとそこから学んだことを紹介させていただきました。

 

ここまでご覧いただいたうえでも「わざわざ合宿という形式をとらずとも事前課題と同様にオンラインで完結させれば良いのでは?」という疑問を抱く方もいらっしゃるかもしれないので、合宿ならではの良さだと感じた点についても共有しておこうと思います。

 

オンラインで進めていた事前課題の時と違い、合宿当日はチーム内での認識のすり合わせが非常にスムーズに進みました。

また、他チームの会話から伝え漏れてくる情報がエラー解消のヒントになり自分たちの作業の役に立ったこともありました。

 

これらは対面形式で行うことのメリットだといえそうです。

では、単に対面形式なだけではなく合宿形式であるという観点でさらに深掘りしていきましょう。

 

「開発合宿」として1泊2日分の時間をまとめて確保することで、業務から離れられ集中して作業に取り組むことができるというのが大きな魅力の1つだと思います。

また、食事中や移動中など作業時間外の会話などを通じて参加者同士の仲が深まるというのも合宿の魅力の1つです。

美味しい料理や合宿の非日常感によって普段よりも会話がはずみやすくなるので、チームビルディングという点では合宿は効果的だと思います。

 

言葉だけでは合宿の雰囲気が伝わりにくいと思うので、せっかくなので写真で合宿の空気感をお届けしようと思います。

 

こちらはロビーでの集合写真です。

参加者の笑顔から、合宿の楽しさが伝わってきます。

集合写真

 

続いてはチームA、チームBそれぞれの発表の様子を撮影した写真です。

モニターに発表資料を映写しながら各チームの工夫した点などを共有しています。

真剣に相手チームの発表を聞いている様子から、合宿でワクワクしつつも作業・発表時はしっかりと集中モードに切り替わっているのが伝わってきますね。

 

チームA発表

 

チームB発表

こちらは1日目の夕食の様子です。お酒や料理を片手ににこやかに笑っており、見るからに楽しそうですね。

この日はちょうど北海道フェアのビュッフェをやっていたので、蟹やお肉、お刺身など豪華な料理が食べ放題でした。

 

 

1日目夕食

北海道フェア

 

 

このように、作業・発表時間もそれ以外も非常に充実した時を過ごすことができました!

 

■ まとめ

開発合宿の参加レポートを最後までご覧いただきありがとうございます。

開発合宿及び事前課題における取り組みとそこから得られた様々な学びについて紹介してきました。

 

ここで紹介してきた私の学びは以下の4つのポイントに大別されると思います。

  • コードを書き始める前に、まずは設計をすること
  • 機能ごとの分離・独立性を意識すること
  • チーム開発におけるコミュニケーションの大切さ
  • VSCodeの便利な各種機能

 

学びは実践につなげていくことが大切です。

課題2や課題3においても過去の課題で学んだことを実践しようと試みてきました。

それと同様に開発合宿における学びを今後の業務に積極的に活かし、効率よく開発を進められるよう努めていきたいです。

 

また、開発力に不安のある若手データサイエンティストは少なくないと思うので、来年以降もこの取り組みが継続・拡大していくことを心より期待しております。

 

alt

山内 望 Nozomi Yamauchi

データ・AIソリューション本部データソリューション統括部 データサイエンス部プロダクトサイエンスグループ

2024年度新卒入社。大学時代は教育社会学を専攻。 人の進路選択や成長・活躍にもともと関心があり、 そのプロセスをデータの力でサポートしたり分析により理解を深めたりしたいという思いからPCAに入社。 現在は主にデータ・AIを活用して検索体験向上を図るプロジェクトに参加。

※この記事では、2025年9月時点の内容を記載しています。