<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Engineer's Blog | koukibuu3</title>
        <link>https://koukibuu3.net</link>
        <description></description>
        <lastBuildDate>Thu, 09 Apr 2026 21:17:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>Feed for Node.js</generator>
        <language>ja</language>
        <copyright>All rights reserved 2026, koukibuu3</copyright>
        <item>
            <title><![CDATA[7年務めた会社を辞めて、初めての転職をします。]]></title>
            <link>https://koukibuu3.net/articles/58u0ek2oawuk</link>
            <guid>https://koukibuu3.net/articles/58u0ek2oawuk</guid>
            <pubDate>Sun, 07 Sep 2025 14:41:02 GMT</pubDate>
            <description><![CDATA[このたび、新卒で入社した会社を辞めて転職をすることになりました。本日最終出社にて手続きを退職手続きを済ませてきたため、退職エントリとして気持ちを綴ります。私が務めていた会社はいわゆるSES企業で、複数]]></description>
            <content:encoded><![CDATA[<p>このたび、新卒で入社した会社を辞めて転職をすることになりました。<br>本日最終出社にて手続きを退職手続きを済ませてきたため、退職エントリとして気持ちを綴ります。</p><p>私が務めていた会社はいわゆるSES企業で、複数の業務委託を経験しました。</p><p>未経験や文系でも見込みがあれば雇い、充実な研修制度で育て上げてくれる会社で、<br>私は大学は情報系ではあるものの特にインターン経験も実務経験もなかったのですが、ここまで育て上げてくれました。</p><p>この会社ではたくさんの素敵な人と出会えましたが、今回転職を決意したわけで、そのきっかけを書いてみます。</p><h2 id="h735cbd087c">転職を考えたきっかけ</h2><h3 id="he630980255">これからの自分のキャリアを考え始めた。</h3><p>私は光栄なことに昨年に技師という役職をいただきました。<br>技師は技術で他社員を牽引することが求められます。</p><p>私は自己研鑽欲が強いものの、一人だとなかなか継続する意思を強く持てないところがあります。<br>そのため、みんなを巻き込む形で、これまで勉強会や読書会などの積極的に活動を行ってきました。<br>そういった活動を評価していただき役職をいただきました。本当に嬉しいことです。</p><p>そして、役職をいただいたことで私は考えたのです。</p><p>ーーいまの私は「技術」で「牽引」することができているのか。</p><p>確かに技術は好きで、新しい技術記事を読み漁ったり、試したり、質の高いコードや設計を考えるために本を読んだり…といったことはします。ですが、ふと自身を見返して考えたとき、体系的に人に教えられるような知識を持っている自信がなく、「技術」で秀でている自覚が持てなかったのです。</p><p>私の以前までの自身の評価は、今まで会ってきた先輩や先方のエンジニアとの相対評価で構成されていました。他人と比較しすぎるのは良いことではありませんが、それでもエンジニアとしての市場価値、一般的な価値がどのくらいなのかは気になります。</p><p>技師を名乗るのであれば、今見ている範囲に閉じてはダメだ。そう思ったのが活動を始めたきっかけでした。</p><p>活動をする上で、複数のカジュアル面談に挑戦しました。</p><p>他の会社にはどういうエンジニアがいるのか、どんな技術力を持っているのかを知りたかったのです。<br>そしてできれば外の世界での自分の相対位置を知りたかった。</p><p>カジュアル面談をする上で、自身のスキルを棚卸しできたのもとても良かったです。<br>今までどういう案件をやってきたか、そこで経験したこと、自分ができることを見つめ直すことができました。</p><p>カジュアル面談をする上で副業で雇ってもよいという会社とも御縁をいただき、1エンジニアとして挑戦することもできました。</p><h3 id="h240611147e">一緒に働いて行きたかった後輩が辞めた</h3><p>私が4年目のときにとても有望な後輩が入ってきました。<br>しばらくあとで同じ案件に配属され、いくつか一緒にプロジェクトを進めました。</p><p>私と同じで技術に対するこだわりと向上心があり、彼と設計の話をするのは楽しかったものです。<br>3年も歳が離れていますが、とても優秀で、彼から学びを得たことも数え切れないほどです。</p><p>数年後、彼と一緒に技師としてこの会社の技術力を背負って行き、もっと仲間を増やすことをモチベーションに感じていたある日、彼が転職を決意したと話を聞きました。</p><p>ーーあぁ、人は辞めるんだな。</p><p>思いました。今後また有望な若手が入ってきたとしても、その人がずっと居てくれるか分からない。<br>いま在籍している尊敬できる先輩も、いつまで居るか分からない。</p><p>人に、会社に、依存するのは良いことではないと考えることができました。</p><p>もちろん、その後輩やお世話になった先輩とは辞めたあとも仲良くしたいと思っていますし、今後また一緒に働く機会にでも恵まれたら嬉しいなとは思います。</p><p>しかし、私は私として誇れる自分になり、人から会社から自立しなくてはと思ったのです。</p><h3 id="ha2e4f5d547">同じ景色を見てくれる人が見つからなかった</h3><p>前述した2つのきっかけでも触れたように、私は「技術」を強みにしたキャリアを築きたい欲求と、それを「仲間と一緒」に研鑽し、成し遂げたい欲求があります。一人で頑張り抜けるほど強い人間では全くなく、隙あらばだらけてしまう人間だから。</p><p>思い返してみれば、私のこういった思考は会社の中では最初から少し浮いていたように思います。新人のときに計画した部門横断の学んだこと共有会は数回で頓挫した苦い経験もあります。もちろん、これが良い悪いを語りたいわけではないです。人それぞれ大事にしたいことは違うし、スタンスも違います。ただ違うというだけ。</p><p>そういった環境で一緒に同じ景色を見て走ってくれる人が見つけるのが、大変でした。</p><p>全く見つからなかったわけではないです。私の考えに同意を示してくれる人、活動に協力してくれる人は居ました。<br>そういった人たちとともに切磋琢磨し、活動し、ときには失敗したのはとても良い経験です。賛同してくれた方々には本当に感謝しています。</p><p>しかし、人は辞めます。そして人を変えることは出来ません。<br>自分が、特定の人や会社などの環境に依存することなく、自分でやりたいことを満たせる人間になろうと考えました。</p><h2 id="h3bcda3e6b0">最後に</h2><p>今回、初めての転職ということで文章を書いてみました。</p><p>文章を書くことは得意ではなく、今回は特に想いのまま綴ったため読みづらい文章だったかと思います。<br>ここまで読んだくださった方、大変ありがとうございます。</p><p>明日から転職先として御縁をいただいた会社で再スタートとなるため、少ししたら入社エントリも書いてみたいと思います。<br>日々自分の限界を超えるような挑戦の毎日だと思いますが、自分のペースで頑張っていきます。<br></p>]]></content:encoded>
            <category>転職</category>
            <category>POEM</category>
            <enclosure url="https://images.microcms-assets.io/assets/2d0686572ab2476796d594f0ef466b41/c56e467717ed415ca0cc196cd60f238d/6%E5%B9%B4%E5%8B%99%E3%82%81%E3%81%9F%E4%BC%9A%E7%A4%BE%E3%82%92%E8%BE%9E%E3%82%81%E3%81%A6%E3%80%81%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AE%E8%BB%A2%E8%81%B7%E3%82%92%E3%81%97%E3%81%BE%E3%81%99.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[ブログにスライド閲覧機能を追加する：Slidev の活用法]]></title>
            <link>https://koukibuu3.net/articles/1ipcx2fh69e8</link>
            <guid>https://koukibuu3.net/articles/1ipcx2fh69e8</guid>
            <pubDate>Thu, 01 May 2025 15:15:12 GMT</pubDate>
            <description><![CDATA[Markdown でスライドが作れる Slidev を使って、ブログにスライド閲覧機能を実装します。背景スライドを Web 公開するサービスには以下がありますが、どうにも私は UI が好きではなくて…]]></description>
            <content:encoded><![CDATA[<p>Markdown でスライドが作れる Slidev を使って、ブログにスライド閲覧機能を実装します。</p><h2 id="hc69c85bcf9">背景</h2><p>スライドを Web 公開するサービスには以下がありますが、どうにも私は UI が好きではなくて…</p><ul><li><a href="https://www.slideshare.net/">Slideshare</a></li><li><a href="https://speakerdeck.com/">Speakerdeck</a></li><li><a href="https://www.docswell.com/">Docswell</a></li></ul><p>特にスマホで閲覧する際、ナビゲーションボタンが大きすぎてスライドの内容が見づらいと感じていました。</p><p>Docswell は他の 2 つよりシンプルな UI で、日本人の開発者によるサービスということもあり、個人的には応援したいサービスです。</p><h2 id="h3f9c11d064">Slidev の紹介</h2><p>Slidev は、Markdown で記述した内容をスライドとして表示できるツールです。Qiita や VSCode の拡張機能、Obsidian でも同様の機能がありますが、 Slidev の最大の強みは <strong>拡張性と汎用性の高さ</strong> です。</p><ul><li><strong>カスタマイズ性が高い</strong>：テンプレートを用意すれば、統一感のあるデザインのスライドを作成可能</li><li><strong>Vue.js コンポーネントを埋め込める</strong>：独自のインタラクティブ要素を追加できる</li><li><strong>発表者モードや Picture-in-Picture などの機能</strong>：発表時に便利な機能が充実</li></ul><p>ローカル環境で <code>npm run dev</code> を実行すればスライドを確認でき、ビルドすれば SPA としてホスティングも可能です。</p><p>今回は <a href="https://docs-legacy.sli.dev/guide/hosting" target="_blank" rel="noopener noreferrer nofollow">公式ドキュメント</a> を参考に、Slidev をブログに組み込んでみます。</p><h2 id="h61edbb96f7">使用要素</h2><p>今回使用する主な技術スタックは以下のとおりです。</p><ul><li>Slidev</li><li>Vue.js</li><li>pnpm workspace</li><li>Markdown / YAML Front Matter</li><li>GitHub Pages</li><li>GitHub Actions</li></ul><h2 id="h9ff89bd48f">ディレクトリ構成</h2><div data-filename="ディレクトリ構成"><pre><code>├── list.mjs
├── package.json
├── packages
│   ├── 221124-name-development
│   │   ├── index.html
│   │   ├── node_modules
│   │   │   └── slidev-theme-one -&gt; ../../theme
│   │   ├── package.json
│   │   ├── pages
│   │   │   └── title.md // タイトルスライド
│   │   ├── public
│   │   │   └── {画像ファイル}
│   │   └── slides.md // スライド本体
│   ├── 221208-extends-disadvantage
│   ├── {YYMMDD}-{title}
│   └── theme
│       ├── README.md
│       ├── layouts
│       │   ├── cover.vue
│       │   ├── default.vue
│       │   ├── fact.vue
│       │   ├── intro.vue
│       │   └── splash.vue
│       ├── package.json
│       └── styles
│           ├── index.ts
│           └── layout.css
├── pnpm-lock.yaml
└── pnpm-workspace.yaml</code></pre></div><h2 id="h5ff3904df4">発生した課題とその解決策</h2><p>Slidev はデフォルトで <strong>1 スライド＝1 npm package</strong> という構成になっているため、通常はスライドごとに別々のリポジトリを作成する必要があります。複数スライドを作ろうと思ったらその都度リポジトリが増えるわけですね。それは嫌だ…</p><p>この問題に対して、以下の 2 つの方法を検討しました。</p><h4 id="ha32f1ba2d1">1. 1 つのスライドで頑張る（不採用）</h4><p>複数スライドを 1 つにまとめて、リンクでジャンプできるようにする方法です。しかし、スライドが増えるほど管理が大変になるため、不採用としました。</p><h4 id="h5d8e639174">2. モノレポ構成にする（採用）</h4><p>pnpm workspace を使用し、複数のスライドを 1 つのリポジトリで管理する方法を採用しました。以下の記事を参考にしています。先駆者が既に開拓してくれていました。ありがたい。</p><ul><li><a href="https://zenn.dev/s10akir/articles/f6a31bc140d6bc" target="_blank" rel="noopener noreferrer nofollow">Slidev をモノレポで管理する</a></li><li><a href="https://zenn.dev/jy8752/articles/ad565a43ba0e0a" target="_blank" rel="noopener noreferrer nofollow">GitHub Actions で Slidev をデプロイする</a></li><li><a href="https://blog.enpay.co.jp/untitled/presentation-with-slidev" target="_blank" rel="noopener noreferrer nofollow">本気の登壇をSlidevでやってみて感じた「のびしろ」</a></li></ul><p>資料に加えて、今回調整したポイントを少しだけ紹介します。</p><div data-filename="/pnpm-workspace.yaml"><pre><code class="language-yaml">packages:
- &quot;packages/*&quot;</code></pre></div><p>packages/ ディレクトリ配下の任意のディレクトリをワークスペースで管理します。</p><div data-filename="/package.json"><pre><code class="language-json">{
  &quot;scripts&quot;: {
    &quot;build&quot;: &quot;pnpm run -r build&quot;,
  }
}</code></pre></div><p>ルートの package.json のビルドコマンドでは、ワークスペースで管理している個別パッケージの <code>build</code> コマンドを並列実行します。</p><div data-filename="/packages/221124-name-development/package.json"><pre><code class="language-json">{
  &quot;scripts&quot;: {
    &quot;dev&quot;: &quot;slidev --open&quot;,
    &quot;build&quot;: &quot;slidev build --out ../../dist/221124-name-development --base /slides/221124-name-development&quot;
  }
}</code></pre></div><p>個別パッケージでは <code>build</code> コマンドにおいて出力先ディレクトリを、個別パッケージの外の <code>/dist</code> に設定しています。また、base を <code>/slides/221124-name-development</code> に設定することで、パス解決が失敗しないようにします。</p><p><span class="note-info">ディレクトリ名を直接指定するのはイケてないですね。ここを自分で書くのは大変なので、template 作成用のスクリプトを用意するか、勝手に取得するように改善したいです。</span></p><p><code>dev</code> は開発用のコマンドです。個別パッケージのディレクトリ配下で実行して表示確認をします。</p><p>調整したのはこのくらいですが、モノレポ構成にしたことで後述するいくつかの問題が発生しました。ここからはその解消をしていきます。</p><h2 id="h8c77008042">課題②：画像のパスがずれる</h2><p>Slidev は base 設定を使ってルートパスを変更できますが、<strong>YAML Front Matter の image パスには適用されません</strong>。そのため、不格好ですが <code>sed</code> コマンドを使ってビルド前に md ファイルを直接書き換えました。</p><div data-filename="/package.json"><pre><code class="language-json">{
  &quot;scripts&quot;: {
    &quot;fix:image&quot;: &quot;find ./packages -name &apos;*.md&apos; | xargs sed -i &apos;s/image: \&quot;\\/public/image: \&quot;\\./g&apos;&quot;
  }
}</code></pre></div><p>※ MacOS では sed -i &apos;&apos; のようにオプションを調整する必要があります。</p><h3 id="hc8c014dfcf">課題③：サムネイル用の画像が上手く生成できない</h3><p>サムネイル用に <code>title.md</code> だけ PNG エクスポートさせて、その画像を利用したかったのですが、なぜかタイトルページ単体のエクスポートでは画像が適用されませんでした。</p><p>そのため、1 ページ目以外は無駄なのですが全ページを PNG 出力することにしています。</p><p><span class="note-warn">export を実行するには Playwright が必要なので、ローカルで実行する際は必要に応じて pnpm exec playwright install などでインストールします。</span></p><p><span class="note-info">ちなみに、png や pdf のエクスポートのコマンドは提供されていますが、dev コマンドで立ち上げた後に画面上の機能から生成する方法が推奨されているようです。今回は CI で自動生成させたいのでコマンドを利用します。</span></p><h3 id="hcec11f6e93">課題④：ブログサイトから動的に参照させたい</h3><p>ブログサイトからスライドを動的に取得するため、以下の 3 つを用意しました。</p><ol><li>GitHub Pages をホスティングとして利用</li><li>GitHub Actions でスライドを自動デプロイ</li><li>スライドの一覧を JSON で提供する疑似 API</li></ol><p>以下ワークフローの設定内容です。</p><div data-filename="/.github/workflows/deploy.yml"><pre><code class="language-yaml">name: Deploy pages
on: push
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: &apos;18&apos;
      - name: Install pnpm
        run: npm install -g pnpm
      - name: Cache pnpm modules
        uses: actions/cache@v4
        with:
          path: ~/.pnpm-store
          key: ${{ runner.os }}-pnpm-${{ hashFiles(&apos;**/pnpm-lock.yaml&apos;) }}
          restore-keys: |
            ${{ runner.os }}-pnpm-
      - name: Install fonts
        run: |
          sudo apt-get install fonts-noto-cjk
      - name: Setting locale
        run: |
          sudo locale-gen ja_JP.UTF-8
          sudo update-locale LANG=ja_JP.UTF-8
      - name: Install dependencies
        run: pnpm install
      - name: Modify path to public
        run: pnpm run fix:image
      - name: Build all packages
        run: pnpm run -r build
      - name: Install Playwright browsers
        run: pnpm exec playwright install chromium
      - name: Export PNG for all packages
        run: pnpm --workspace-concurrency=1 run -r export:png
      - name: Generate index page
        run: pnpm run generate:index
      - name: Deploy pages to GitHub Pages
        uses: crazy-max/ghaction-github-pages@v2
        with:
          build_dir: dist
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}</code></pre></div><p><span class="note-warn">Export PNG for all packages のステップでは、並列実行させるとエラーが発生しました。確かな原因は分からなかったので、ひとまず --workspace-concurrency=1 で同時実行数を 1 に指定することで回避しています。</span></p><p>API サーバーですが、このためにサーバーを建てたくはなかったので、GitHub Pages を擬似 API サーバーとして利用する方法を採用しました。</p><p>ビルドのタイミングでしかデータは動かないので、簡単な JS を書きスライドの一覧を JSON 形式で <code>index.html</code> として出力します。あとは取得側で <code>&apos;Content-Type&apos;: &apos;application/json&apos;</code> として解釈してデータを取得すれば、ものぐさ API サーバーの完成です。</p><div data-filename="/list.mjs"><pre><code class="language-javascript">import fs from &apos;fs&apos;;
import path from &apos;path&apos;;

const baseUrl = &apos;https://koukibuu3.github.io/slides&apos;;

function getDirectoryContents(dirPath) {
  const contents = fs.readdirSync(dirPath, { withFileTypes: true });
  return contents.map(dirent =&gt; {
    if (!dirent.isDirectory()) return null;

    const indexHtml = fs.readFileSync(path.join(dirPath, dirent.name, &apos;index.html&apos;), &apos;utf8&apos;);
    const title = indexHtml.match(/&lt;title&gt;(.*) - Slidev&lt;\/title&gt;/)?.[1] || dirent.name;

    return {
      title,
      url: `${baseUrl}/${dirent.name}`,
      mainImagePath: `${baseUrl}/${dirent.name}/images/1.png`
    };
  });
}

function main() {
  const directoryContents = getDirectoryContents(&apos;./dist&apos;);
  const jsonOutput = JSON.stringify(directoryContents, null, 2);
  console.log(jsonOutput);
  fs.writeFileSync(&apos;./dist/index.html&apos;, jsonOutput);
}

main();</code></pre></div><h2 id="ha214098e44">まとめ</h2><p>Slidev を使い、ブログにスライド閲覧機能を組み込む方法を紹介しました。</p><ul><li>Markdown でスライドを作成</li><li>モノレポ構成で管理しやすくする</li><li>GitHub Pages でホスティングし、GitHub Actions で自動デプロイ</li><li>JSON を使った擬似 API でスライド一覧を提供</li></ul><p>この方法なら、シンプルかつ管理しやすい形でスライドを公開できます。実際に動作している例は <a href="https://koukibuu3.github.io/slides/221124-name-development/" target="_blank" rel="noopener noreferrer nofollow">こちら</a> 、リポジトリは <a href="https://github.com/koukibuu3/slides" target="_blank" rel="noopener noreferrer nofollow">GitHub</a> に公開しています。</p>]]></content:encoded>
            <category>JavaScript</category>
            <category>pnpm</category>
            <category>Slidev</category>
            <category>TECH</category>
            <enclosure url="https://images.microcms-assets.io/assets/2d0686572ab2476796d594f0ef466b41/b9609afacb4d430d8d5f74c210c620d7/%E3%83%95%E3%82%99%E3%83%AD%E3%82%AF%E3%82%99%E3%81%AB%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%88%E3%82%99%E9%96%B2%E8%A6%A7%E6%A9%9F%E8%83%BD%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B%EF%BC%9ASlidev%20%E3%81%AE%E6%B4%BB%E7%94%A8%E6%B3%95.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[なぜリポジトリはエンティティ単位で設計すべきなのか？]]></title>
            <link>https://koukibuu3.net/articles/z7g19vk5jecr</link>
            <guid>https://koukibuu3.net/articles/z7g19vk5jecr</guid>
            <pubDate>Thu, 01 May 2025 15:15:20 GMT</pubDate>
            <description><![CDATA[ソフトウェア開発において、データの永続化は避けて通れない課題です。この課題を効率的に解決する設計パターンのひとつが リポジトリ（Repository） です。リポジトリは、データベースやストレージ、イ]]></description>
            <content:encoded><![CDATA[<p>ソフトウェア開発において、データの永続化は避けて通れない課題です。この課題を効率的に解決する設計パターンのひとつが <strong>リポジトリ（Repository）</strong> です。リポジトリは、データベースやストレージ、インメモリキャッシュなどのデータ永続化層と直接やり取りを行う役割を担います。</p><p><span class="note-info">リポジトリを導入することで、アプリケーションのドメインロジックをデータ永続化層から切り離し、疎結合を実現します。</span></p><p>そして、しばしば議論になるのが、<strong>リポジトリはデータベースのレコード単位で作成するべきか、それともエンティティ単位で作成すべきか</strong> という点です。</p><p>本記事では、結論として <strong>エンティティ単位の設計を推奨</strong> します。その理由を、レコード単位のリポジトリが抱える問題点とともに解説します。</p><h2 id="h6ec7ce1a99">なぜレコード単位のリポジトリでは問題が起きるのか？</h2><p>結論として、<strong>データベースのレコードは単なるデータの塊であり、実際の利用方法を反映していない</strong> ためです。実際にデータを利用する際は、適宜結合や選択を行った上で使用する必要があります。</p><h3 id="h47230aa3a3">データベースのレコードは単なるデータの塊である</h3><p>リレーショナルデータベースでは、正規化の程度によってテーブルの数や粒度が異なります。例えば、従業員（Employee）テーブルを考えてみましょう。</p><p></p><p>▼<strong>Before: 正規化されていないテーブル（Employee）</strong></p><table><tbody><tr><th colspan="1" rowspan="1"><p>社員ID</p></th><th colspan="1" rowspan="1"><p>名前</p></th><th colspan="1" rowspan="1"><p>部署ID</p></th><th colspan="1" rowspan="1"><p>部署名</p></th><th colspan="1" rowspan="1"><p>役職</p></th><th colspan="1" rowspan="1"><p>住所</p></th><th colspan="1" rowspan="1"><p>緊急連絡先</p></th></tr><tr><td colspan="1" rowspan="1"><p>0001</p></td><td colspan="1" rowspan="1"><p>サンプル 太郎</p></td><td colspan="1" rowspan="1"><p>01</p></td><td colspan="1" rowspan="1"><p>総務部 </p></td><td colspan="1" rowspan="1"><p>部長</p></td><td colspan="1" rowspan="1"><p>XXX</p></td><td colspan="1" rowspan="1"><p>XXX-XXXX-XXXX</p></td></tr><tr><td colspan="1" rowspan="1"><p>0002</p></td><td colspan="1" rowspan="1"><p>サンプル 次郎</p></td><td colspan="1" rowspan="1"><p>02</p></td><td colspan="1" rowspan="1"><p>営業部</p></td><td colspan="1" rowspan="1"><p></p></td><td colspan="1" rowspan="1"><p>XXX</p></td><td colspan="1" rowspan="1"><p>XXX-XXXX-XXXX</p></td></tr><tr><td colspan="1" rowspan="1"><p>0003</p></td><td colspan="1" rowspan="1"><p>サンプル 花子</p></td><td colspan="1" rowspan="1"><p>01</p></td><td colspan="1" rowspan="1"><p>総務部</p></td><td colspan="1" rowspan="1"><p></p></td><td colspan="1" rowspan="1"><p>XXX</p></td><td colspan="1" rowspan="1"><p>XXX-XXXX-XXXX</p></td></tr></tbody></table><p>このテーブルには <strong>「部署 ID」</strong> と <strong>「部署名」</strong> の冗長なデータが含まれています。仮に「総務部」の名称を「人事・総務部」に変更する場合、総務部に属するすべての従業員レコードを更新しなければならず、非効率的です。</p><p></p><p>そこで、<strong>正規化</strong> を行い、部署の情報を別テーブルに切り出すのが一般的な対応です。</p><p></p><p>▼<strong>After: 正規化されたテーブル（Employee）</strong></p><table><tbody><tr><th colspan="1" rowspan="1"><p>社員ID</p></th><th colspan="1" rowspan="1"><p>名前</p></th><th colspan="1" rowspan="1"><p>部署ID</p></th><th colspan="1" rowspan="1"><p>役職</p></th><th colspan="1" rowspan="1"><p>住所</p></th><th colspan="1" rowspan="1"><p>緊急連絡先</p></th></tr><tr><td colspan="1" rowspan="1"><p>0001</p></td><td colspan="1" rowspan="1"><p>サンプル 太郎</p></td><td colspan="1" rowspan="1"><p>01</p></td><td colspan="1" rowspan="1"><p>部長</p></td><td colspan="1" rowspan="1"><p>XXX</p></td><td colspan="1" rowspan="1"><p>XXX-XXXX-XXXX</p></td></tr><tr><td colspan="1" rowspan="1"><p>0002</p></td><td colspan="1" rowspan="1"><p>サンプル 次郎</p></td><td colspan="1" rowspan="1"><p>02</p></td><td colspan="1" rowspan="1"><p></p></td><td colspan="1" rowspan="1"><p>XXX</p></td><td colspan="1" rowspan="1"><p>XXX-XXXX-XXXX</p></td></tr><tr><td colspan="1" rowspan="1"><p>0003</p></td><td colspan="1" rowspan="1"><p>サンプル 花子</p></td><td colspan="1" rowspan="1"><p>01</p></td><td colspan="1" rowspan="1"><p></p></td><td colspan="1" rowspan="1"><p>XXX</p></td><td colspan="1" rowspan="1"><p>XXX-XXXX-XXXX</p></td></tr></tbody></table><p>▼<strong>After: 正規化されたテーブル（Department）</strong></p><table><tbody><tr><th colspan="1" rowspan="1"><p>部署ID</p></th><th colspan="1" rowspan="1"><p>部署名</p></th></tr><tr><td colspan="1" rowspan="1"><p>01</p></td><td colspan="1" rowspan="1"><p>総務部</p></td></tr><tr><td colspan="1" rowspan="1"><p>02</p></td><td colspan="1" rowspan="1"><p>営業部</p></td></tr></tbody></table><p><span class="note-warn">正規化を行わないと、データの整合性が担保されず、「人事・総務部」と「総務部」のようにデータの不整合が発生する可能性があります。</span></p><p>この正規化されたテーブルに対して、それぞれのレコード単位で <code>EmployeeRepository</code> と <code>DepartmentRepository</code> を作成するのが <strong>レコード単位のリポジトリ</strong> です。</p><h3 id="ha3615b882e">レコード単位のリポジトリの問題点</h3><p>例えば、従業員の組織図を作成する場合、 <code>EmployeeRepository</code> と <code>DepartmentRepository</code> それぞれからデータを取得し、手動で結合する必要があります。</p><p></p><p>問題点:</p><ol><li><strong>アプリケーション側でデータの結合処理が必要になる</strong></li><li><strong>リポジトリがデータベースのテーブル構造に依存してしまう</strong></li></ol><p>リポジトリを導入する本来の目的は、<strong>データ永続化層とドメインロジックを切り離すこと</strong> です。しかし、レコード単位のリポジトリでは、<strong>アプリケーション側がデータベースのテーブル構造を意識しなければならない</strong> という問題が生じます。</p><p><span class="note-info">データ永続化層から関心を切り離すためのリポジトリであるはずなのに、テーブル構造を知っていないとデータを適切に扱えない。この点が、レコード単位のリポジトリの大きな問題です。</span></p><h2 id="h08c5fa55c4">エンティティ単位のリポジトリが導く理想の設計</h2><p>前述した課題を解決するために、<strong>エンティティ単位のリポジトリ</strong>を推奨します。</p><h3 id="hcaad64da02">リポジトリは用途ごとに設計するべき</h3><p>リポジトリを設計する際は、<strong>そのデータを取得したい目的・用途を考慮</strong> するべきです。</p><p>例えば、従業員データを扱う場合でも、用途によって異なるリポジトリが考えられます。</p><table><tbody><tr><th colspan="1" rowspan="1"><p>用途</p></th><th colspan="1" rowspan="1"><p>リポジトリ名</p></th><th colspan="1" rowspan="1"><p>必要なデータ</p></th></tr><tr><td colspan="1" rowspan="1"><p>組織図作成</p></td><td colspan="1" rowspan="1"><p>OrganizationEmployeeRepository</p></td><td colspan="1" rowspan="1"><p>社員 ID、名前、部署情報、役職</p></td></tr><tr><td colspan="1" rowspan="1"><p>給与支払い</p></td><td colspan="1" rowspan="1"><p>SalaryEmployeeRepository</p></td><td colspan="1" rowspan="1"><p>社員 ID、名前、口座情報、支払い履歴</p></td></tr></tbody></table><p>このように、<strong>異なる目的ごとに適切なエンティティを設計することで、データベースのテーブル構造を意識せずに済む</strong> のです。</p><p><span class="note-info">OrganizationEmployee と SalaryEmployee を別のエンティティとして用意することで、データベースのレコード構造に依存しない柔軟な設計が可能になります。</span></p><h2 id="hb6d87dbabd">まとめ：エンティティ単位の設計を選ぶ理由</h2><ul><li><strong>レコード単位のリポジトリでは、アプリケーションがデータベース構造を意識する必要がある</strong></li><li><strong>エンティティ単位のリポジトリを導入することで、ドメインロジックとデータ永続化層を明確に分離できる</strong></li><li><strong>リポジトリはデータの用途に応じて設計するのが望ましい</strong></li></ul><p>エンティティ単位の設計を採用することで、より柔軟で保守性の高いアーキテクチャを実現できます。</p>]]></content:encoded>
            <category>ドメイン駆動設計</category>
            <category>リポジトリ </category>
            <category>TECH</category>
            <enclosure url="https://images.microcms-assets.io/assets/2d0686572ab2476796d594f0ef466b41/5f289dd45fa246b1bbbcb0de09d524bf/%E3%81%AA%E3%81%9B%E3%82%99%E3%83%AA%E3%83%9B%E3%82%9A%E3%82%B7%E3%82%99%E3%83%88%E3%83%AA%E3%81%AF%E3%82%A8%E3%83%B3%E3%83%86%E3%82%A3%E3%83%86%E3%82%A3%E5%8D%98%E4%BD%8D%E3%81%A6%E3%82%99%E8%A8%AD%E8%A8%88%E3%81%99%E3%81%B8%E3%82%99%E3%81%8D%E3%81%AA%E3%81%AE%E3%81%8B%EF%BC%9F.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[コード品質を高める！明日から使えるGitのコミット3つのコツ]]></title>
            <link>https://koukibuu3.net/articles/7hltyl68nznj</link>
            <guid>https://koukibuu3.net/articles/7hltyl68nznj</guid>
            <pubDate>Thu, 01 May 2025 15:15:29 GMT</pubDate>
            <description><![CDATA[近年ではエンジニアの必須スキルとなった Git の活用法について、コード品質を向上させるポイントを 3 つ紹介します。エンジニアになりたての方や「Git は使っているけど自信がない」という方にも、ぜひ]]></description>
            <content:encoded><![CDATA[<p>近年ではエンジニアの必須スキルとなった Git の活用法について、コード品質を向上させるポイントを 3 つ紹介します。エンジニアになりたての方や「Git は使っているけど自信がない」という方にも、ぜひ役立てていただければ幸いです。</p><p>今回、登場人物を大きく以下の 3 つに分けます。</p><ul><li>実装者</li><li>レビュアー</li><li>他のエンジニア</li></ul><h2 id="hddb9421d9f">コミットメッセージに Prefix を付ける</h2><p>コミットメッセージに <code>feat:</code> や <code>fix:</code> などの Prefix（接頭辞）を付けることで、修正内容を一目で明確に伝えられます。</p><p>一般的に共通して使われ、使用頻度も多い Prefix は以下の 4 つです。</p><ul><li><code>feat:</code> 新しい機能の追加</li><li><code>fix:</code> バグ修正</li><li><code>refactor:</code> 仕様に影響しないリファクタ</li><li><code>chore:</code> CI/CD やライブラリなどの基盤修正</li></ul><p>チームで共通の仕様が決まっていない場合は、<a href="https://www.conventionalcommits.org/ja/v1.0.0/">Conventional Commits</a> のガイドラインを活用すると、業界標準に基づく統一的なメッセージが書けます。</p><p>Prefix を付けることで得られるメリットの 1 つは、後からコミット履歴を確認する際に、修正内容が一目で把握できる点です。</p><p>さらに、どの Prefix を付けるかを意識することで、余計な修正がコミットに混入するのを防ぎ、1 コミットあたりの修正差分を少なく抑える効果もあります。</p><p>コミット履歴を確認するのは、レビュアーや、数日後・数カ月後の自分自身かもしれません。そのとき、コミット単位の修正量が適切に抑えられていれば、修正内容を素早く正確に把握することが可能です。</p><p><span class="note-info">修正内容を素早く正確に把握できれば、レビューで仕様の確認に留まらず、パフォーマンスや処理改善の議論が可能になり、コード品質の向上に繋がります。</span></p><h2 id="hfa3bb6e332">コミット単位は機能のまとまりを意識する</h2><p>私がレビュアーとして実際に見た、改善の余地があるコミット履歴の例を 2 つ紹介します。</p><h3 id="hc3ffec4686">例 1：コミット履歴が作業ログになっている例</h3><pre><code>5 refactor: ビューの処理をリファクタ
4 refactor: コントローラーの処理をリファクタ
3 feat: 12/22 までの作業分コミット/一旦完成
2 feat: 12/21 までの作業分コミット
1 feat: 12/20 までの作業分コミット</code></pre><p>これは、実装者の作業の単位でコミットが作られています。1~3 のコミットはその日の作業単位でコミットされています。</p><p>レビュアーや他のエンジニアが関心があるのは、どのようにして機能が追加されたかどうかです。</p><p>そのため、このようなコミット履歴だと、コミットごとに修正差分を見るときに不完全な差分を見ることになり、実装の全貌を見るためには全ての差分（GitHub の File Changes）を見ることを強いられてしまいます。</p><p>そのため、このような自身の作業ログを保存しておくようなコミット単位は避けましょう。他のエンジニアは、あなたがその日どこまで進めたかには関心がありません。</p><p><span class="note-warn">TODO コメントを残した仮実装のコミットを追加し、後で本実装するケースをよく見かけますが基本的には避けるべきです。仮実装のコードは動作が保証されず、レビュアーが本実装のコミットと併せて確認する手間が増えてしまいます。</span></p><p>4~5 のコミットは、1~3 までのコミットのリファクタリングになっています。</p><p>レビューに出す前にリファクタリングを行う意識はとても素晴らしいですが、リファクタリング対象のコミットが同一の PullRequest にある場合、分けておく必要はありません。1 つのコミットにまとめてしまいましょう。</p><h3 id="h3a7cd3b2f5">例 2：指摘に対する修正がコミット履歴にある例</h3><pre><code>5 fix: 一覧コントローラーのバグ修正
4 fix: 一覧ビューの指摘修正
3 fix: 一覧コントローラーの指摘修正
2 feat: 一覧ビューの新規作成
1 feat: 一覧コントローラーの新規作成</code></pre><p>この例では、1〜2 のコミットは機能ごとにまとまっており非常に見やすいです。しかし、3〜5 のコミットはレビュー指摘やバグ修正が個別に積まれており、履歴が冗長になっています。</p><p>1〜2 の後、レビュー指摘を受けて 3〜4 の修正を行い、最終的に 5 でバグ修正を行ったというストーリーが想像できます。しかし、こうした履歴は実装者やレビュアーには有用でも、他のエンジニアにとっては不要な情報となりがちです。</p><p>そのため、3〜5 のようなコミットは残さず、レビューでの修正内容やバグ修正は元のコミットにまとめる方が望ましいでしょう。これにより、履歴が簡潔になり、全体の把握が容易になります。</p><p><span class="note-warn">修正内容を別コミットに分けておかないと、再レビュー時に指摘に対する修正差分が確認できないという問題があります。この問題の解決策は次のポイントで紹介します。</span></p><h2 id="h500751d841">fixup と rebase でコミットログを綺麗にする</h2><p>コミット単位を意識しても、途中で修正が必要になる場合があります。その際に履歴を整理するための便利な機能が、<code>fixup</code> と <code>rebase</code> です。</p><p>先に述べた以下の 2 つのポイント：</p><ul><li>コミットメッセージに Prefix を付ける</li><li>コミット単位を機能のまとまりで意識する</li></ul><p>これらを常に守るのは難しい場合もあります。たとえば、実装途中で漏れに気づいたり、レビュー指摘に対する修正をコミットとして積むケースです。</p><p>特に後者のケースは、レビューを効率的に進めるべきにもむしろ積極的に行うべきです。</p><p><code>rebase</code> は非常に色々なことができる機能なので詳細は割愛し、今回は限定的な使い方の紹介に留めます。</p><p>指摘に対する修正を行う場合、</p><pre><code>dfc67acb feat: 一覧コントローラーの新規作成
1f315272 feat: 一覧ビューの新規作成</code></pre><p>一覧コントローラーに修正が必要な場合、該当のコミットに <code>fixup</code> を利用して修正を加えます。</p><pre><code class="language-shell">git commit --fixup dfc67acb</code></pre><p>これにより、以下のような <code>fixup!</code> 付きのコミットが生成されます</p><pre><code>4320bf0d fixup! feat: 一覧コントローラーの新規作成</code></pre><p>レビュアーにはこの修正コミットを見てもらい、再レビューをお願いします。</p><p>レビューが完了したら <code>fixup</code> で積んだ修正コミットを main ブランチにマージする前に、<code>git rebase</code> を使用して整理します。</p><pre><code class="language-shell">git rebase --autosquash -i 1f315272</code></pre><p>このコマンドで、<code>fixup!</code> 付きのコミットが元のコミットに自動的にまとめられます。これにより、main ブランチの履歴がすっきりし、他のエンジニアにとって見やすい履歴を保つことができます。</p><p><code>rebase</code> を行ったことによりリモートとコミット履歴に差異が発生するため、<code>push</code> する際は <code>--force-with-lease</code> を付けて強制 push を行います。</p><pre><code class="language-shell">git push --force-with-lease</code></pre><p><span class="note-warn">git push --force-with-lease は慎重に扱うべきコマンドです。特にチームでの利用時は、運用ルールを明確にし、誤操作を防ぐ仕組みを整えることが重要です。</span></p><p>レビュー中は修正コミットを <code>fixup</code> として積み、マージ時に <code>rebase</code> でまとめる。この手順を踏むことで、レビュー効率を高めつつ、main ブランチの履歴を綺麗に保つことができます。これにより、他のエンジニアにとっても理解しやすいコミット履歴を実現できます。</p><h2 id="ha214098e44">まとめ</h2><p>Git のコミットを通して、コード品質の向上に繋がる使い方のポイントを紹介しました。</p><p>エンジニアの業務に占める割合は、コードを書くより読む時間の方が圧倒的に多いです（コードレビュー、仕様調査、バグ調査、etc...）。そのため、読みやすいコードや把握しやすいコミット粒度・メッセージを意識することは、コード全体の品質に大きな影響を与えます。</p><p>今回紹介したポイントを日頃の業務に活かし、より良いチーム開発を目指しましょう。些細な工夫が、コード品質とチーム全体の生産性向上に大きく繋がります。</p><h2 id="h3de35099b3">参考</h2><p></p><div class="iframely-embed"><div class="iframely-responsive" style="height: 140px; padding-bottom: 0;"><a href="https://www.conventionalcommits.org/ja/v1.0.0/" data-iframely-url="//cdn.iframe.ly/api/iframe?url=https%3A%2F%2Fwww.conventionalcommits.org%2Fja%2Fv1.0.0%2F&amp;key=c271a3ec77ff4aa44d5948170dd74161"></a></div></div><script async src="//cdn.iframe.ly/embed.js" charset="utf-8"></script><p></p><p></p>]]></content:encoded>
            <category>Git</category>
            <category>駆け出しエンジニア応援</category>
            <category>TECH</category>
            <enclosure url="https://images.microcms-assets.io/assets/2d0686572ab2476796d594f0ef466b41/2c5b167b05c6492a8a70930913321ecb/%E3%82%B3%E3%83%BC%E3%83%88%E3%82%99%E5%93%81%E8%B3%AA%E3%82%92%E9%AB%98%E3%82%81%E3%82%8B%EF%BC%81%20%E6%98%8E%E6%97%A5%E3%81%8B%E3%82%89%E4%BD%BF%E3%81%88%E3%82%8BGit%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%883%E3%81%A4%E3%81%AE%E3%82%B3%E3%83%84.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>