ピクシブのエンジニア向け春インターンシップ「PIXIV SPRING BOOT CAMP 2025 」ピクシブ百科事典コースに参加した、ゆはといいます。 普段はGoやRubyでバックエンドを書いています。趣味はDTMや音ゲーです。
インターン開始前
メンターのJavakkyさんと元々知り合いだったため、事前課題として「関数電卓のパーサーを実装する」という課題が与えられていました。字句解析や構文解析についてほとんど知識がありませんでしたが、興味がある分野だったので積極的に取り組み、1週間ほどで完了することができました。
初日
ピクシブ本社の東京オフィスで一番最初に見たのはエントランス付近に飾られたイラストレーターさんの描いた絵馬で、想像以上にたくさんありました。自分が知ってるイラストレーターさんの絵馬もあり、面白かったです。 その後、他のインターン生や人事の方と顔合わせをし、毎週水曜日に開催されている全社会議を視聴しました。最初にラジオ体操があり驚きましたが、各事業部からの報告を聞くことで、ピクシブがどのような方向に向かっているのか知ることができて楽しかったです。 残りの時間はメンターとの顔合わせや環境構築だけでほぼ1日が終わりました。開発環境がローカルではなく、専用の社内サーバーがあったところが面白いなと思いました。
2日目~3日目 午前
ピクシブ百科事典のコースでは独自記法のテキストをリッチにするための新しい仕組みを検討するというタスクが割り当てられました。記事本文のためのパーサーが既に実装されていたので、まずはそのコードリーディングから始めました。事前課題の経験から、「1日で終わるかな」と考えていましたが、行数の多さや内容の複雑さから実際には2日もかかってしまいました。
3日目 午後
3日目の午後からは、パーサー実装の方針を立てました。 既存のパーサーとは別で実装するのか、それとも共通化して実装するのか、という選択肢について「今」と「将来」それぞれの観点で検討しました。
- 既存のパーサーにすべての記法を追加し、オプションで制御する
- メリット
- 追加するコード行が少ない
- 共通の記法についても1つのコードで処理できる
- デメリット
- 1,200行くらいあるパーサーのコードにさらに分岐を追加することになるので、可読性や実装時の漏れに不安がある
- メリット
- 汎用的なパーサーの仕組みを実装する
- メリット
- すべての箇所に適用する新記法の実装コストを下げられる
- 記法単位で疎結合化されるので、テストが記述しやすい
- デメリット
- 設計が技術的に難しい
- インターン期間中に間に合うか?リリース期限に間に合うか?に不安が残る
- メリット
- 既存のパーサーとは別に新しいパーサーを実装する
- メリット
- 記事パーサーを参考にコードを書くだけなので簡単
- デメリット
- 共通の記法が増える場合、2重で実装を行う必要がある
- メリット
上記のメリット、デメリットを検討した結果、一旦は別の新しいパーサーを実装するが、将来的には共通化した仕組みを作りたい。という方針を立てました。
理由として、新規記法の追加が直近では予定されておらず、共通化の恩恵が少ないためリリース期間の方を優先した方がよさそうだと考えたからです。
今回のインターンでは、汎用パーサーの設計について深堀りはしませんでしたが、メンターから以下のような疑似コードを提案されたため検討に用いました。
<?php class Parser { private int $pointer = 0; /** @param list<Notation> $notations */ public function __construct(private readonly array $notations) {} /** @param list<class-string> $arrow_notation_types */ public function parse(string $text, array $arrow_notation_types): Node { $node = new EmptyNode(); foreach ($this->notations as $notate) { if (in_array($notate::class, $arrow_notation_types)) { [$node, $pointer] = $notate->parse($text, $this->pointer, $node); $this->pointer = $pointer; } } return $node; } } interface Notation { public function parse(string $text, int $pointer, Node $parent_node): array; } class BoldNotation implements Notation { // 太字の記法パースを実装する } class ItalicNotation implements Notation { // 斜体の記法パースを実装する } $parser = new Parser([new ItalicNotation(), new BoldNotation()]); $parser->parse("**太字**と***斜体***", [ItalicNotation::class, BoldNotation::class]);
意思決定にあたり、コストやリスクの観点からそれぞれの選択肢のメリット、デメリットを洗い出し、プロダクトの方針や組織の状況と照らし合わせて考えました。
学生開発だと「技術的にどういった実装を行いたいか」等の自身が挑戦したいことを軸に方針を決定することが多かったのですが、実務ではプロダクトが今目指していることを主軸として、方針を考えることができたので面白かったです。
4日目
ピクシブ百科事典チームの定例で昨日検討した方針について相談しました。
議論を進めていく中で、プロダクトマネージャーから「現状、記法を頻繁に追加することを予定してないのでパーサーの作成にコストをあまりかけたくない」という話がありました。これを受け、一旦パーサーは分けて実装するが、記法の追加が多くなるタイミングがあればその時にパーサーの共通化を検討するという結論を出しました。
5日目~7日目
実際にパーサーの実装を始めました。元々あるものとは別に実装したので、トークンを読み進める処理などの基盤部分に苦戦し1日目は時間がかかりましたが、メンターの助けもあり2日半で実装を完了することができました。
パーサーの実装が終わり時間が余ったので、最終日にはphp-mysql-engineというOSSにPRを投げました。1日目に簡単なクエリ追加タスクを行ったのですが、その際に不足した機能に気づいたため追加しよう!という流れになりました。業務に必要なOSS貢献であれば業務時間内に行っていいという文化はとても魅力に感じました。
まだマージはされていませんが、実際のPRは以下で確認することができます。
MySQLにあるSTR_TO_DATE関数をphp-mysql-engineの方にも実装するという機能追加をしました。
<?php $date_format_list = [ "%b" => "M", "%c" => "n", "%d" => "d", "%D" => "jS", "%e" => "j", "%m" => "m", "%M" => "F", "%y" => "y", "%Y" => "Y" ]; $time_format_list = [ "%h" => "h", "%H" => "H", "%i" => "i", "%I" => "h", "%k" => "G", "%l" => "g", "%r" => "h:i:s A", "%s" => "s", "%S" => "s", "%T" => "H:i:s" ]; $has_date_format = false; $has_time_format = false; preg_match_all("/(?:%[a-zA-Z])/u", $format, $matches); foreach ($matches[0] as $match) { $has_date_format = $has_date_format || in_array($match, array_keys($date_format_list)); $has_time_format = $has_time_format || in_array($match, array_keys($time_format_list)); } $format = \str_replace( array_keys($date_format_list + $time_format_list), array_values($date_format_list + $time_format_list), $format ); if ($has_date_format && $has_time_format) { $time = \DateTimeImmutable::createFromFormat($format, $subject); if($time !== false) { return $time->format('Y-m-d G:i:s'); } } if ($has_date_format) { $time = \DateTimeImmutable::createFromFormat($format, $subject); if($time !== false) { return $time->format('Y-m-d'); } } if ($has_time_format) { $time = \DateTimeImmutable::createFromFormat($format, $subject); if($time !== false) { return $time->format('G:i:s'); } }
P-HUB NIGHT
3日目の終業後に、P-HUB NIGHTという、社員同士の交流イベントに参加させていただきました!VPoEのkonyaさんや様々なプロダクトの社員さんとお話をしたり、麻雀やポーカーで遊んだりしました。社員の皆さんがそれぞれ打ち込んでいる趣味があったり、会社規模が大きいことで社内に同じ趣味の5〜6人見つけられるということに驚きました。また、創作活動をしている社員も多く、ピクシブの文化が社員全体に浸透していると感じられました。
感想
ピクシブの社員のみなさんは幅広く創作活動を楽しんでおり、イラストや小説はもちろん、音楽制作やDJ、ゲーム制作など、幅広い分野に及んでいるところが良い文化だなと感じました。P-HUB NIGHTや部活動などの社員全員で交流を促進する文化もたくさんみられました。全社会議や夕方のチーム定例では自己紹介の時間があったり、朝のチーム定例では一人一言よかったことや美味しいものの話をするるなど、職種や部署を問わずお互いを知ることができる場面が多いところも魅力に感じました。 この8日間は技術面、非技術面どちらの面でも学びが多く、有意義な時間を過ごせました!インターン期間にお世話になったメンターの javakky さん、 ahu さん、ありがとうございました!
反省
定例会や発表など、人にプレゼンテーションをする時に正しく伝わる構成や言葉選びが出来ていない部分があり、メンターにサポートしてもらうことが多かったので、今後は改善していきたいです。