文系出身の私がモノグサでエンジニアを始めた理由

f:id:corp_monoxer:20210905154159j:plain

モノグサ株式会社のTobisatis(@tobisatis)です。2021年2月にソフトウェアエンジニアとして入社しました。

当社には大学や大学院で計算機科学を専攻していたような、技術的に非常に優秀なエンジニアが多く集まっています。そんななか、計算機科学どころか理系ですらない、経営学部出身の私がモノグサで働きはじめる話をしたいと思います。

大学卒業まで

高校卒業まで、私は理系の生徒でした。といっても、理科や数学が得意だったわけではありません。在学中、理系から文系は変えられるけれどその逆は難しいと聞いたからでした。理科の中でも物理ではなく生物を選んでいたので、典型的な理系の生徒像とは少し違うかもしれません。

高校時代に勉強していた生物は割と楽しかったので、特に根拠もなく「iPS細胞を応用して、食糧問題や環境問題、エネルギー問題などのあらゆる問題を解決する!」と意気込むようになりました。大学受験は第一志望に落ちたため、合格した大学の経営学部に進学することにしました。

大学生活は特に変わったことをせず、しばらく過ごしていたのですが、大学4年でいわゆるレールから外れることになりました。

大学での社会科学の勉強を通してさまざまな思考を巡らせた結果、大雑把に表現すると「裕福でない子どもたちにも、よりよい教育を提供する必要がある」という結論に達し、これに使命感を抱くようになりました。しかし、この目標はビジネス的にはあまり歓迎されるものではないと気づき、就職によってこれを達成しようとすることはやめました。新卒での就職をしないことに決めたのです。

就活をせずに時間があったため、なんとなく始めたことがありました。それが競技プログラミングです。競技プログラミングとは、与えられた問題を解くためのプログラムを提出して得点や速度を競う競技です。これまで、確率の問題を解くためにJavaScriptを使って簡単なシミュレーションをしたり、無料レンタルサーバーを使ってPHPで遊んでみたりとプログラミングに触れる機会があったので、競技プログラミングを始めたのは自分にとって自然な成り行きだったな、と思います。

大学卒業後

先のような使命感から、「自分で塾を経営する」という計画を立てていました。しばらくの生活費を稼ぐためにフリーランスのPHPエンジニアとして8ヶ月ほど働いたのち、2020年5月、私の両親が神奈川県茅ヶ崎市で経営する「カフェのあるめがね屋さん一丁目四番地」内で「総合教室Salite(サリーテ)」をオープンしました。

しかし、新型コロナウイルスの影響もあり、宣伝が思うようにできませんでした。約1時間のマンツーマン授業を990円で受講できる破格のプランを掲げていても、問い合わせはなかなか増えませんでした。この塾の人気が上がる見込みを期待できない状況だったため、悶々とした日々を送っていました。

モノグサとの出会い

そんななか、Wantedly(ビジネス向けSNS)を経由して、モノグサ株式会社から直接、ソフトウエアエンジニア採用のお誘いをもらい、「教育の業界を少しでも勉強できたらラッキー」くらいの軽い気持ちで面接を受けることにしました。

そのときは、あっけなく落ちるだろうと思っていました。チームでの実務経験が高々8ヶ月。塾の営業に必要なホームページやカレンダー関連のシステムは自作していたものの、職業エンジニアとしてはブランクがある状態。転職市場ではほとんど評価されない経歴だろうと根拠はないものの感じており、胸を張って面接に臨むことはできませんでした。

結果的に内定を得ることができ、そのときは信じられませんでした。技術面接ではひたすらに自分のエンジニア領域の知識のなさを気付かされ、恥ずかしさのようなものだけを感じながら帰路についた覚えがあります。ただ、そんななか振り返ると、競技プログラミングで培った問題解決能力が高く評価されたのだろうと感じています。

競技プログラミングで得た力

私はAtCoderというサイトで競技プログラミングに参加していました。AtCoderにはレーティングのシステムがあり、定期的に開催されるコンテストで良い結果を出すほど高いレートが付きます。コンテストは出題される問題の難易度によって、ABC、ARC、AGCという種類に分かれています。

コードを書くのはとても遅いものの難しい問題の考察に取り組むことが好きだった私は、最も難易度の高いAGCに出場して2問だけ選んでじっくり解く、という戦略をよくとっていました。

業務における開発では、ひとつの問題にじっくりと取り組む力が重要です。このため、大学院で熱心に研究に打ち込んでいるような学生は、モノグサでも高く評価される傾向にあります。私は大学院に行っておらず、学部での研究も卒業論文の提出の他にはなかったのですが、競技プログラミングを通してこの力を身につけることができました。

f:id:corp_monoxer:20210905153625j:plain

入社を決めた理由

モノグサのエンジニア採用は、技術面接をすべて通過すると最終面接に移る、というプロセスです。最終面接ではエンジニアだけでなく、さまざまな部署のメンバーと面接をします。

就職をすることは、そもそも私にとって目的ではありませんでした。したがって、技術面接を通過したあとも、面接の準備や練習を一切することなく最終面接に行きました。

最終面接では、自分がどのような思いで塾の先生をやっているか、すなわち、先に述べたビジネス性がないと結論付けた目標をひたすら正直に語りました。おそらくこのときは生徒が多く集まらない孤独感から話を聞いて欲しい思いが強くなってしまっていたのだろうと振り返ると、顔が赤くなります。

モノグサに入社を決めたのは、内定をもらったからに他なりません。メールボックスにモノグサからの内定通知が届いたとき、道を間違ってはいなかった、と感じたのを覚えています。

現代に生まれたものとして、掲げる理想だけでも高潔でいたい。経済的な成長のためだけにそれを犠牲にしたくない。こんな思い全てを明かしても私を迎え入れてくれるこの会社でなら、自身の尊厳を毀損せずに生きられるだろう。

そう確信し、私は入社を決めました。

入社してからは、周りのエンジニアの優秀さに圧倒される日々が続いています。

それでもできることを自分なりに探しながら、「記憶を日常に。」のスローガンの元で自分の信念に基づいて仕事をできている今は、過去になく充実しています。

モノグサ株式会社では一緒に働く仲間を募集しています。

少しでも興味を持っていただけた方はぜひお話しましょう!

careers.monoxer.com

『記憶を日常に。』を実現するための大切な仕組み。Monoxerのオフライン学習とは

モノグサエンジニアの井岡です。 モノグサでも技術的な情報を技術ブログとして発信していきます。プロダクトのMonoxerに関連することだけでなく、モノグサ社員が趣味で行っている内容等についても紹介していく予定です。

記念すべき第1回は、Monoxerの特徴的な機能であるオフライン学習についてご紹介します。

Monoxerとは

Monoxerは解いて憶える記憶アプリです。憶えたい内容を登録すると、記憶している状況(=記憶度)に応じてアプリが問題を生成します。まったく憶えていないときは写経形式(薄く答えが出ている状態で回答)で、少し憶えているときは択一形式で、すでに記憶していそうであれば自由入力形式で、といったように記憶度に応じて出題形式が変化します。そのため無理なく自然に憶えることができます。

出題形式をコントロールするための重要な機能として記憶の一元管理*1があります。簡単に説明すると、問題を要素に分解し、それぞれの記憶度を管理するための機能です。例えば、数式の「2+3」であれば整数「2」、「3」と、「足し算」の要素に分解できます。これらを記憶している状況で、「3+4」を出題する際には、整数「3」と「足し算」は記憶しているとみなして、出題形式を決定しています。

管理機能も充実しており、塾や学校の先生が生徒に課題(=タスク)を配信できます。配信したタスクを生徒が学習すると、その学習結果や記憶度を逐次サーバーに送信していきます。そのため、生徒ごとの進捗や記憶度をリアルタイムに確認することができます。

f:id:corp_monoxer:20210819163503p:plain

オフライン学習の仕組み

Monoxerを用いた記憶は日常的に行われるものであり、飛行機や地下鉄の中、山でのキャンプ中等のように通信が不安定な環境下でも学習できる必要があります。もちろん、タスク配信時にはサーバーからデータを取得する必要がありますが、学習については可能な限りオフラインでも実行できるような仕組みにしています。

Monoxerでの学習は以下のような流れで行います。

  1. サーバーからタスクをダウンロード (初回のみ)
  2. タスクを学習
  3. 学習結果・記憶度をローカルに保存
  4. 学習結果・記憶度をサーバーに送信 f:id:corp_monoxer:20210819163527p:plain

サーバーに確実にデータが保存された状態にするために、データがサーバーに保存されたかどうかをdirtyフラグを用いて管理しています。ローカルに保存するタイミングではdirtyフラグをtrueにし、サーバーへの保存が成功した場合にfalseに変更します。オフライン時には上記4.のサーバーへの送信が失敗するため、dirtyフラグがtrueのままローカルに保存された状態になります。 f:id:corp_monoxer:20210819163530p:plain

その後、端末がオンラインに変わったタイミング*2で、ローカルに保存されている学習結果や記憶度のうちdirtyフラグがtrueのものをすべて取得し、あらためてサーバーに送信します。

f:id:corp_monoxer:20210819163523p:plain

また、記憶度は最新のものがサーバーに保存された状態になっています。Monoxerでは複数端末での学習も可能なため、保存されているものと受け取ったもののうち新しいものが保存されるようにタイムスタンプのチェックも行っています。

他にもサーバーでの保存は成功しているが、レスポンスを受け取れないということも起こり得ます。この場合、ローカルに保存されている学習結果のdirtyフラグはtrueのままであるため再度サーバーにデータが送信されますが、サーバーではすでに同じデータが保存されているため、重複して保存されないようにする必要があります。そのため、サーバーで管理しているIDとは別に、ローカルでユニークIDを生成し、これを比較して保存済みかを判断しています。

まとめ

Monoxerでは日常的に記憶するために様々な機能を提供しています。今回はその中のオフライン学習についてご紹介しました。様々な状況での学習に対応するために、整合性を取れるようにデータを管理しています。 他の機能については、別の機会にご紹介できればと思います。

*1:記憶の一元管理の詳細はCTOのインタビュー記事をご確認ください。

*2:iOSではReachabilityのwhenReachableおよびwhenUnreachableを用いて通信可否の変更を検知しています。Androidではandroid.net.ConnectivityManagerのNetworkCallbackを用いて通信可否の変更を検知しています。