B+treeで効率良く後方一致検索をする方法

初めまして、テックドクターのバックエンドエンジニアの魚木です。

私が担当するプロジェクトに、データベースのテーブルのあるカラムを前方一致検索する機能があります。そこに部分・後方一致検索もしたいという要望がありました。

そのデータベースはB+treeインデックスが使用されていますが、B+tree (または同系統のtree) インデックスは部分・後方一致検索は効率良くできないと言われています。
結果的に機能追加は見送られたのですが、前方・部分・後方一致検索の違いについて考えるよい機会になりました。

本記事は、B+treeが部分・後方一致検索を効率よくできない理由と、その代替手段として後方一致検索を高効率でする方法を説明します。

MySQLを前提としますが、インデックスの構造が同系統であれば同じような結論になります。

なぜ前方一致検索のみ高効率なのか

まずはtree構造が前方一致検索を効率よく処理できるしくみを説明します。ここではシンプルに、二分探索木で考えてみましょう。

下記のような二分探索木があるとします。

  • 葉ノードのみ実データを持ち、それ以外のノードはキーのみを持つ
  • 隣接する葉ノードは相互にリンクされている
  • キーは8個存在し、それぞれ "aec", "afd", "agc", "ahd", "bec", "bfd", "bgc", "bhd" のデータを持っており、辞書順でソート済みであるものとする。

図にすると、このようになります。

図1:二分探索木の例

完全一致検索の場合

まず、完全一致検索について考えます。完全一致検索は前方一致検索の一種であるため、高効率に処理することができるはずです。

上記のtreeから、あるキーを持つ葉ノードを検索した場合……

  1. 根ノードの "ahd" と比較し、入力が "ahd" 以下であれば左のブランチを進みます。"ahd" より大きければ右のブランチを進みます。1つ階層を降りた時点で、入力と同じキーをもつ可能性のある葉ノードは8個から4個に絞られます。
  2. 同様の操作を深さ1のノードで行うと、候補がさらに4個から2個に絞られ、
  3. 同様の操作を深さ2のノードで行うと入力と同じキーを持つノードが特定されるか、存在しないことが判明します。
図2:二分探索木の完全一致検索の様子(ここでは "bec" を検索)

このように、treeの階層をひとつ降りるたびに候補が1/2ずつに絞られることが二分探索木の探索の効率の良さを生んでいます。

データベースでよく使われるB+treeは各ノードの保持するキーが複数になりますが、階層を降りる毎に候補が1/n (二分探索木の場合はnが2) に絞られるという点で同じです。

前方一致検索の場合

次に前方一致検索について考えます。

同じtreeで、"b" から始まるデータを全て取得したいとします。

下記の手順で、"b" から始まるキーを持つ葉ノードの中で、辞書順で一番早いものを1回の探索で特定することができます。

  1. 最初は根ノードで "ahd" と "b" を比較し、"b" の方が辞書順で遅いので右のブランチを進みます。
  2. 次は "bfd" と "b" の比較で "b" の方が辞書順で早いので左のブランチを進み、
  3. 同様に "bec" のノードでも左のブランチを進むことで左から5番目の葉ノードである "bec" が特定されます。
図3:前方一致検索の様子("b" から始まるデータを検索)

そこから図3の緑色の矢印のように、隣接ノードへのリンクを右方向に、"b" から始まらないキーを持つ葉ノードが出現するか (※)、終わりまで走査し終わるかのいずれかになるまで進みます。ここでは "bec"、"bfd"、"bgc"、"bhd" の4件が該当しました。

※葉ノードが辞書順でソート済みであるので、一度 "b" 以外から始まる葉ノードに到達したら、それ以降に "b" から始まる葉ノードは絶対に存在しません


今回は1文字の前方一致の例を示しましたが、前方一致検索の条件が2文字以上になっても基本的な考えは変わりません。肝心なことは、前方一致する辞書順で一番早いキーを持つ葉ノードを1回の探索で特定できることと、葉ノードの並びが辞書順でソート済みであるため効率的に処理できるということです。

後方一致検索の場合

最後に後方一致検索について考えてみます。

例えば "c" で終わるキーを持つ葉ノードを取得したいとしましょう。

上で説明したように、根ノードから左に降りることは条件に合致する候補を1~4番目に限定することです。また、右に降りることは5~8番目に限定することを意味します。

しかし、下の図4からわかるとおり、"c" で終わる葉ノードは左から1、3、5、7番目に存在し、どちらに降りたとしても条件に合致するキーが反対側にも存在することになってしまいます。

とりあえず、全てのノードで左に進んだとしましょう。偶然、一番左の葉ノードのキーが "aec" と "c" で終わっているので、前方一致検索と同様にそこから右のリンクを進んでみましょう。そうすると次の葉ノードのキーは "afd" であり "c" で終わりませんが、それで走査を打ち切れるでしょうか?

 先に述べたように左から3、5、7番目にも "c" で終わるキーを持つ葉ノードが存在するので、走査を打ち切ってしまうと正しい結果は得られません。

図4:後方一致検索は効率的にできない

別のデータセットであれば、偶然1番目にしか "c" で終わるキーを持つ葉ノードが存在しないこともあるかもしれませんが、いずれにせよ葉ノードを全て調べて結果的にわかることであって、tree構造自体が保証するものではありません。

これらのことから、後方一致検索は葉ノードを全走査しなければならず、大抵の場合とても非効率になります。部分一致検索も同じ理由で非効率になります。

(実際にはこの例のようにデータ数が少ない場合は全走査した方が効率が良い可能性が高いですが、データ数が増えたときのことを想像してみてください)

B+treeで高効率で (擬似的に) 後方一致検索をする方法

これまで述べたように、B+tree (または同系統のtree) で後方一致検索を効率よく行うことは原理的に不可能です。しかし、B+treeで後方一致検索と同じ結果を高効率で得る方法もあります。以下のような手順で実現することができます。

  1. 後方一致検索をしたいカラムを反転したカラムを追加する
    • Generated Column (本記事はこれを使う)
    • トリガー
    • ...
  2. 反転したカラムのインデックスを作成する
  3. 後方一致検索対象の文字列を反転し、そのカラムを条件に前方一致検索する

後方一致検索をしたいカラムを反転したカラムを作成し、それに対してインデックスを作成することによって、後方一致検索を前方一致検索に変換することができます。上で説明したように前方一致検索は高効率で行えるので、事実上の後方一致検索を高速に行うことができます。

実際にやってみる

今回はGenerated Columnを使った方法で説明します。(後方一致検索をしたいカラムを反転したカラムさえあればいいので、トリガーでも実現可能です。)

Generated Columnの詳細は公式ドキュメントを参照していただきたいですが、ざっくりいうとカラム定義に式を使えるようにする機能です。

例えば、メールアドレスを保存するカラムが元からあるとして、それを参照しつつ反転したカラムを作成することができます。

このカラムは、参照元カラムの更新も反映されますし、インデックスを作ることもできます。

例として以下のような`email`カラムと`reverse_email`カラムを持ったusersテーブルを作成します。

CREATE TABLE users (
    id INT AUTO_INCREMENT,
    email VARCHAR(255) UNIQUE,
    reverse_email VARCHAR(255) GENERATED ALWAYS AS (REVERSE(email)) VIRTUAL,
    PRIMARY KEY (id),
    index email_index(email),
    index reverse_emai_index(reverse_email)
);

INSERT INTO users (email) VALUES
    ('test1@test.com'),
    ('test2@test.jp'),
    ('test3@test.com'),
    ('test4@test.jp'),
    ('test5@test.com'),
    ('test6@test.jp'),
    ('test7@test.com'),
    ('test8@test.jp')
;

SELECT * FROM users;
+----+----------------+----------------+
| id | email          | reverse_email  |
+----+----------------+----------------+1 | test1@test.com | moc.tset@1tset |
|  2 | test2@test.jp  | pj.tset@2tset  |
|  3 | test3@test.com | moc.tset@3tset |
|  4 | test4@test.jp  | pj.tset@4tset  |
|  5 | test5@test.com | moc.tset@5tset |
|  6 | test6@test.jp  | pj.tset@6tset  |
|  7 | test7@test.com | moc.tset@7tset |
|  8 | test8@test.jp  | pj.tset@8tset  |
+----+----------------+----------------+
8 rows in set (0.00 sec)

emailreverse_emailに対するインデックスを作成しており、SELECTの結果から想定通りにreverse_emailemailを反転したものであることがわかります。

まずは、emailの「.com」後方一致検索をしてみます。

SELECT * FROM users WHERE email LIKE '%.com';
+----+----------------+----------------+
| id | email          | reverse_email  |
+----+----------------+----------------+1 | test1@test.com | moc.tset@1tset |
|  3 | test3@test.com | moc.tset@3tset |
|  5 | test5@test.com | moc.tset@5tset |
|  7 | test7@test.com | moc.tset@7tset |
+----+----------------+----------------+
4 rows in set (0.09 sec)

EXPLAIN SELECT * FROM users WHERE email LIKE '%.com'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: users
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 8
     filtered: 12.50
        Extra: Using where
1 row in set, 1 warning (0.01 sec)

取得結果は正しいですが、EXPLAINのtypeをみるとALLとなっており、全表走査していることが分かります。

次に、後方一致検索用の文字列を反転し前方一致検索用の文字列にして、reverse_emailに対して検索します。

SELECT * FROM users WHERE reverse_email LIKE REVERSE('%.com');
+----+----------------+----------------+
| id | email          | reverse_email  |
+----+----------------+----------------+1 | test1@test.com | moc.tset@1tset |
|  3 | test3@test.com | moc.tset@3tset |
|  5 | test5@test.com | moc.tset@5tset |
|  7 | test7@test.com | moc.tset@7tset |
+----+----------------+----------------+
4 rows in set (0.13 sec)

EXPLAIN SELECT * FROM users WHERE reverse_email LIKE REVERSE('%.com')\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: users
   partitions: NULL
         type: range
possible_keys: reverse_emai_index
          key: reverse_emai_index
      key_len: 1023
          ref: NULL
         rows: 4
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.07 sec)

emailに対する後方一致検索と同じ結果が得られました。また、EXPLAINのtypeがrange、keyがreverse_email_indexとなっていて、インデックスを使っていることがわかります。

このように、Generated Columnを使えば後方一致検索を高効率で行うことができます。

(例ではデータ数が小さいので、emailに対する後方一致検索の方が早いですが、データ数が大きくなるとreverse_emailに対する前方一致検索の方が早くなります)

注意点

この方法で事実上の後方一致検索を高効率でできますが、別のコストが増加する場合もあるので注意が必要です。

  • インデックスの追加による更新系クエリの性能の悪化
  • アプリケーションで後方一致検索の要求をうまく処理する必要がある

実装にあたってはこれらのコストを考慮して、本当に後方一致検索が必要かどうかを判断する必要があります。

ちなみに部分一致検索はこの方法ではできませんし、私の知る限りB+tree (または同系統のtree) で高効率で部分一致検索をする方法はありません。



この記事を読んで、少しでもテックドクターに興味を持っていただけたら嬉しく思います。
今後も技術系の記事を書いていく予定なので、よろしくお願いします。


書いた人:魚木

データサイエンス部のお仕事~データのもつ可能性を最大限に引き出す

初めまして、テックドクターでデータサイエンス部を統括している深見です。

本エントリでは、私たちデータサイエンス部のメンバーが日々どんなデータをどのように分析しているのかをご紹介します。

24時間365日の活動を測るウェアラブルデータ

テックドクターは、ウェアラブルバイスのデータを分析することで、医療現場で活用されるデジタルバイオマーカーの開発をめざしています。

※デジタルバイオマーカー……デジタルデバイスで測定した『日常データ』をもとにした、病気の早期発見や治療につながる客観的指標(前回記事参照

これまで医療現場で扱われるデータは、検査や健康診断など、病院に来院したときにだけ計測される一時点のデータでした。これに対しウェアラブルデータは、その人の24時間365日の活動を継続的に測定したデータです。この性質のちがいにより、ウェアラブルデータは「これまでわかっていなかった、病気と人の行動の関係」を明らかにする可能性を秘めているのです。

データサイエンス部ではそうしたウェアラブルデータのもつ可能性を最大限に引き出すため、その加工方法や分析手法を日々模索しています。

私が使用しているウェアラブルバイス。普段からデータ取得ができるように、左右の腕に別のデバイスを2個付けしています(ブログ用の演出ではありません!)

扱っているデータ・分析事例

私たちが計測に使っているウェアラブル端末には、みなさんが使用している一般的なスマートウォッチも含まれます。それらは睡眠・脈拍・活動量に関するデータを収集することができます。

たとえば、睡眠の質は自分ではわかりにくいものですが、収集した睡眠データを使えば計測できます。同じように、日頃の睡眠量や生活の規則正しさを定量的に知ることもできます。

いっぽう活動量のデータでは歩数を分単位で計測できるため、運動不足や運動習慣の有無などが可視化されます。

こういった行動のデータにくわえて、脈拍データからは心臓の拍動を通して、自律神経の動きを評価できると言われています。

さらにそれらを組み合わせることによって、睡眠中/運動中の脈拍数など、生活シーンを念頭においた分析ができるようになります。
下の図は、睡眠・脈拍・活動量(歩数)のデータを可視化した例です。

 

脈拍数のグラフに睡眠や活動量の状況を重ねたもの

こうして単純にグラフにしただけでも、なかなか興味深いものです。
しかし私たちは、データサイエンスの力を使って、このデータからさらに多くのことを知ろうとしています。わかりやすい例を2点ほどご紹介しましょう。

分析事例1.長期変動が見えてくる

テックドクターには創業間もないころからウェアラブル端末を着けつづけているメンバー、Mさん(男性)がおり、数年単位のデータが揃っているため絶好の解析対象となっています。

彼の数年にわたる脈拍データを解析した結果が下の図です。

測定した脈拍データをもとに、心拍変動という数値を算出し、STL分解したもの

STL分解……時系列データを季節成分、トレンド成分、残差成分に分ける分析手法

トレンドのグラフに注目してほしいのですが、時間の経過とともに数値が減少しています。これはMさんの身体が年齢を重ねていることを表しています。

この心拍変動は年齢とともに減少することが論文で報告されていますが、それは多数の被験者から統計的に導かれたものです。一人の人間の数値をこれだけ細かく、長期に可視化した例は珍しいのではないでしょうか。 

分析事例2.飲酒と脈拍

お酒を飲むと脈拍が上昇すると感じる方は多いと思います。ウェアラブルからの脈拍データを見ても、そのようすは明らかです。

この現象は飲酒習慣を定量化するには非常に役立つのですが、ときに困ることもあります。たとえば病気と脈拍との関連を解析したいとき、脈拍上昇の要因が病気のせいなのか飲酒のせいなのか判別がつかず、ノイズになるのです。

テックドクター社では、収集した飲酒日のデータと脈拍データを分析することで、飲酒判定モデルを構築しました。このモデルを使用すると、脈拍データのみをもとに飲酒日を推定することができます。

ピンクのハイライトが脈拍データから推定した飲酒日の予測。丸が実際の飲酒量

飲酒日が見事に推定されている様子がわかるでしょうか。このモデルは、先述した分析ノイズを除去するために役立てることができます。

どんな人がいるの? メンバーのバックグラウンドはさまざま

データサイエンス部には現在5人のメンバーがいます。

一貫して分析を経験してきたメンバーはむしろ少数派で、さまざまなバックグラウンドを持ちながら、その経験値をそれぞれの分析に活かしています。実はウェアラブルデータ自体がまだまだ新しいデータのため、分析経験がある人は世の中にほとんどいません。そのため全員テックドクターに入社後に初めて実分析を経験しています。

ふだんの業務では、毎日の朝会で業務の進捗確認や困りごとの相談を行っています。日々メンバー間でフレッシュな情報を共有しつつ、他のメンバーの分析方法を参考にしたりアドバイスをもらったりして、相互に助け合って業務をこなしています。

また定例MTGや個別案件の相談などは、一元化したりなるべくマネージャが受けることにして、メンバーにはなるべく多くの時間を分析にあててもらっています。

例として、私ともう一人のメンバーについて、そのバックグラウンドと一日の過ごし方をご紹介します。

👤マネージャ(私、入社3年以上、データ分析歴10年以上)

バックグラウンド

  • 計算理工学専攻卒
  • アンケートデータ分析
  • 事業開発(M&A)
  • Q&Aデータのテキスト分析
  • 位置情報分析
  • ウェブ広告データ分析
  • imp/click予測モデル

ある一日のスケジュール

時刻 内容
6:30 出社
  タスク整理・雑務
9:00 朝会
  分析定例
12:00 昼食
13:00 データ整理
  案件相談
  1on1
  定例会議
  全社会議
18:30 退社

私の仕事デスクです。分割キーボードに興味のある方大歓迎!笑

👤フレッシュメンバー(入社8ヶ月目)

バックグラウンド

ある一日のスケジュール

時刻 内容
8:00 出社
  雑務
9:00 朝会
  分析
12:00 昼食
13:00 分析
17:00 家事(業務外)
20:00 分析
21:00 終業

 

データの可能性を信じ、価値を引き出せる人と仕事がしたい

テックドクター社のデータサイエンス部では、技術面のスキルだけでなく、ウェアラブルデータに興味を持ち、人のために何かをしたいという思いを持った方々とともに働きたいと考えています。
具体的には、こんな人です。

データを見る/集める/分析することが好き

データには無限の可能性があり、どういった人がどういった関心を持って分析するかで結果が大きく変わってくるものです。分析要件や指示をこなすだけではなく、データの可能性を信じて、その価値を引き出せるようなマインドを重視しています。

ウェアラブルデータはまだまだ顧客でも理解が追いついていない面があります。データを見ている最中にふと思いついた分析内容が大いに評価される、といったことも多々あるのです。

ヘルステックへの興味・関心がある

ヘルステックの領域では、病気一つ一つに膨大なドメイン知識が存在しています。それらの中には解明が進んでいる病気もあれば、精神疾患のようにまだまだ未知の部分が残っている病気もあります。そういったドメイン知識を貪欲に吸収することができると、データ分析の精度・信頼度が向上していきます。

地道な努力ができる/一つ一つのデータを丁寧に根気強く確認することができる

データ分析をしていると、機械学習モデルの構築のような花形な業務よりも、手前のデータクレンジングに時間をとられることが多いです。弊社も例外ではなく、とりわけウェアラブルデータという24時間365日、いついかなる状況かに関わらず採取されたデータから結果を導くには、ことさら地味な作業が重要です。

これまでの分析をふりかえっても、きちんと医師や専門家の意見を聞き、細かなノイズを除去する作業を1年近くに渡って繰り返した結果、高精度な分類モデルの構築に成功する、といった例も多いです。

データを代表値として扱わず、個々の数値の意味を追求できる

分析作業を言われたことをこなす業務としてとらえてしまうと、検定で統計的な差異が出た/出なかった、機械学習モデルの精度が良かった/悪かった、で終わってしまいがちです。

しかしながら、うまくいかなかった時はもちろん、うまくいった時でも、なぜうまくいったのか、偶然ではなく汎用的な結果となっているのかを追求する姿勢はとても大事です。部内では、数百人規模のデータが対象であっても、分析を重ねていくうちに気がついたら一人一人のデータを細かく確認していたという例がよくありますし、そういった姿勢が重要だと考えています。

 

以上です。
このエントリを読んで、少しでもテックドクターに興味を持っていただけたら、そして困っている人のためにデータ分析をしたいと思っていただけたら、嬉しいです。

次回のデータサイエンス部の記事では、具体的な分析手法や、事例の紹介をしていきたいと思っています!

 

書いた人:深見

TechDoctor開発者Blogをはじめます

初めまして、テックドクターでCTOをしている、佐藤大樹と申します。このたび、弊社の技術ブログ「TechDoctor開発者Blog」を立ち上げることにしました。

みなさんはテックドクターが何をしている会社かご存じでしょうか。私たちテックドクターは、デジタルバイオマーカーの開発をしています。

デジタルバイオマーカーってなに?

たとえば健康診断の血液検査で測定するHbA1cヘモグロビンA1c)という数値。この値が高いと糖尿病の疑いがあるとされます。このような指標は(「デジタル」のつかない)バイオマーカーと呼ばれています。

私たちが開発しているデジタルバイオマーカーは、デジタルデータを活用して作成したバイオマーカーです。健康診断のような特別な機会にしか測定できないデータではなく、日常的に使用しているウェアラブルバイスやIoTデバイスなどに蓄積された『日常データ』を活用します。それらを統計処理して状態定量化することで、病気の早期発見や治療につながる客観的指標を得ることができます。そうして得られた指標のことをデジタルバイオマーカーと呼びますが、これをデータドリブンで開発していくのが私たちテックドクターです。

デジタルバイオマーカーのイメージ

デジタルバイオマーカーを活用すると、たとえばこんなことができます。

  • 患者さんに測定デバイスを付けてもらうことで、病勢を把握し、医師とのコミュニケーションを円滑にする
  • 希少疾患の発作の発病をデジタルバイオマーカーを使って予測することで、患者さんの薬のタイミングを調整する
  • まだ病気に至っていない段階でも、このままの生活を続けると病気になりそうだという予兆をつかむ

上記はほんの一例で、他にもさまざまな方法でみなさんの健康に貢献できます。

エンジニアが何をしているのか発信したい

こうしてデジタルバイオマーカーの開発を続けてきて、ありがたいことに狭い業界ではだんだん知名度も上がり、口コミ等を通して指名でお仕事をいただける機会も増えてきました。

非常にやりがいや社会的意義がある仕事だと日々感じていますが、いっぽうでCTOの立場からは現状にひとつ問題意識も感じています。

私たちの会社にいるエンジニアがどんなことをやっているのか、外から見えないのです。

仕事の合間に談笑する弊社エンジニアたち(左から2番目が筆者)

私は昔、Unohという会社で「ウノウラボ」というブログの立ち上げを経験しました。当時まだ珍しかった企業のエンジニアブログの走り的なブログです。

ブログの運営には大きなメリットがありました。ウノウラボが技術情報の発信源として評価された結果、Unohの採用には優秀なエンジニアがたくさん応募してきてくれたのです。

テックドクターでもウノウラボの成功経験を生かし積極的な情報発信を行うことを目的として、このブログを開設しました。

ただ反面で、エンジニアとしての本業があるかたわらでのブログ執筆は、予想以上に負担がかかる業務でした。今回は運営メンバーに編集者を迎えることで、エンジニアの負担を軽減しながらブログを書くことができないかという試みも行っていきます。

在籍当時のUnohの社内サーバー

テックドクターのエンジニア組織

せっかくなので、私たちテックドクターのエンジニア組織についても紹介させてください。

テックドクターでは現在、プロダクトチームとデータサイエンティストチームの2つのチームに分かれ、互いに連携しながら革新的なソリューションを開発しています。

プロダクトチームでは、ユーザーのニーズを把握し、それにもとづいた製品やサービスの設計・開発をおこないます。ミッションは使いやすく高機能なアプリケーションを提供すること。プロダクトマネージャー、フロントエンドエンジニア、バックエンドエンジニアが一体となって、定期的なユーザーテストやフィードバックセッションを通じて、プロダクトの改善を続けています。

一方、データサイエンティストチームは、膨大なビッグデータを分析し、その結果をもとに統計分析や機械学習を駆使して、デジタルバイオマーカーの開発と最適化を行っています。こうして開発したデジタルバイオマーカーは、先ほどご紹介したとおり患者さんの病勢判断や治療効果の評価に活用されています。それ以外にもデータサイエンティストの業務は論文を読んだり、追実験を行ったりと、大学の研究室にかなり近いと感じています。

オフィスの様子

「もうやっちゃいました」精神で獣道を作りたい

テックドクターでは医療や健康、データサイエンス、機械学習といった事業ドメインに興味がある方と一緒に働きたいと思っています。

また社風の点では下記のようなエンジニアの行動指針を定めています。 

なかでも、特に気に入っているものをいくつか紹介します。

 

獣道を作ろう

まだだれもやったことない方法を使って、だれもやったことのない事をやって、医療という課題に向き合っていこう。

 

喧々諤々しよう

誰でも対等に忌憚なく意見が言えるようにしよう、そういう環境を作ろう。

 

もうやっちゃいました

すぐにできることなら、断りなくどんどん改善していこう。たとえばCI/CDの改善などはそれぞれの積極的に担当者が自身の判断で行っており、最近は入社2年目の担当者の発案でCodeRabbitをテスト導入したりしています。

 

フルマラソンチャンピオン

事業自体、比較的にロングスパンで動かしていくことになるので、長い距離でも走りきってチャンピオンになれるように、積極的にリファクタリングを行ったりテストを書いていこう。例えばデジタルバイオマーカー開発プラットフォーム「SelfBase」のプロジェクトでは、新機能の実装をしながら、平行してDDDへのリアーキテクチャなども進めています。

 

このエントリを読んで、少しでもテックドクターに興味をもっていただけたら嬉しく思います。 

次回からは実際の事業内容に沿った技術的な記事や、コードやアーキテクチャの話、データサイエンスや分析手法の話などを記事にできたらと思っております。お楽しみに!

 

テックドクターをよろしくおねがいします



 

書いた人:佐藤