Skip to content

言語別開発ガイド

本プロジェクトでは、Nix を使用して各プログラミング言語の開発環境を個別に提供しています。各環境は nix develop .#<言語名> コマンドで起動でき、必要なツールや LSP、Vim 設定が自動的に適用されます。

ソフトウェア開発の三種の神器

開発を効率的に進めるために、以下の3つの要素を重視します。

1. バージョン管理 (Git)

全ての変更は Git で管理し、意味のある単位でコミットします。

  • コミットメッセージ規約(Angular形式):

type(scope): subject の形式で記述します。 - feat:

新機能
  • fix:

    バグ修正 - test:

    テストの追加・修正 - refactor:

    リファクタリング - chore:

    雑事(設定変更等)

2. テスティング (TDD)

テスト駆動開発 (Test-Driven Development) を実践します。 1. Red:

失敗するテストを書く 2. Green:

テストを通す最小限の実装を書く 3. Refactor:

コードをきれいに整理する

3. 自動化

コマンド一つでビルド、テスト、静的解析を実行できるようにします。また、ファイル変更を監視して自動的にテストを実行する「継続的テスト」を活用します。


共通の開発フロー

  1. 環境の起動:

nix develop .#<language> 2. プロジェクトの初期化:

各言語のパッケージマネージャで初期化 3. Git初期化:

git init (まだの場合) 4. TDDサイクル:

継続的テストを回しながら実装 5. 静的解析:

リンターやフォーマッタでコード品質をチェック 6. コミット:

git add . -> git commit -m '...'


言語別ガイド

1. Node.js / TypeScript

  • 起動コマンド:

nix develop .#node - 主要ツール:

Node.js (v22), npm, TypeScript, ESLint, Prettier - 初期化:

npm init -y
- TDDチュートリアル: 1. Red: hello.test.js を作成。
import assert from 'node:assert';
import { test } from 'node:test';
import { hello } from './hello.js';

test('hello returns greeting', () => {
  assert.strictEqual(hello(), 'Hello,World!');
});
実行(失敗): node --test hello.test.js 2. Green: hello.js を実装。
export function hello() { 
  return "Hello, World!"; 
}
3. Refactor: 必要に応じてコードを整理。 - 自動化: - node --watch --test hello.test.js で変更を監視。

2. Python

  • 起動コマンド: nix develop .#python
  • 主要ツール: Python 3.12, uv, pytest, ruff (Linter/Formatter)
  • 初期化:
    uv init
    uv add --dev pytest ruff
    
  • TDDチュートリアル:
  • Red: test_hello.py を作成。
    from hello import hello
    def test_hello():
        assert hello() == "Hello, World!"
    
    実行(失敗): uv run pytest
  • Green: hello.py を実装。
    def hello():
        return "Hello, World!"
    
  • Refactor: uv run ruff check .uv run ruff format . で品質を整える。
  • 自動化:
  • uv run pytest を使用。

3. Go

  • 起動コマンド: nix develop .#go
  • 主要ツール: Go, gopls, golangci-lint, delve
  • 初期化:
    go mod init example.com/hello
    
  • TDDチュートリアル:
  • Red: hello_test.go を作成。
    package hello
    import "testing"
    func TestHello(t *testing.T) {
        want := "Hello, World!"
        if got := Hello(); got != want {
            t.Errorf("Hello() = %q, want %q", got, want)
        }
    }
    
    実行(失敗): go test
  • Green: hello.go を作成。
    package hello
    func Hello() string { return "Hello, World!" }
    
  • Refactor: go fmt ./...golangci-lint run を実行。

4. Rust

  • 起動コマンド: nix develop .#rust
  • 主要ツール: cargo, rust-analyzer, clippy, rustfmt
  • 初期化:
    cargo init
    
  • TDDチュートリアル:
  • Red: src/lib.rs にテストを記述。
    pub fn hello() -> String { todo!() }
    #[cfg(test)]
    mod tests {
        use super::*;
        #[test]
        fn it_works() {
            assert_eq!(hello(), "Hello, World!");
        }
    }
    
    実行(失敗): cargo test
  • Green: hello 関数を実装。
    pub fn hello() -> String { "Hello, World!".to_string() }
    
  • Refactor: cargo clippy で警告を確認し、cargo fmt で整形。
  • 自動化:
  • cargo watch -x test で変更監視(要インストール)。

5. Java

  • 起動コマンド: nix develop .#java
  • 主要ツール: JDK, Gradle, Maven, Checkstyle, PMD
  • 初期化:
    gradle init --type java-library --test-framework junit-jupiter
    
  • TDDチュートリアル:
    1. Red: src/test/java/LibraryTest.java にテスト追加.
      @Test
      void testGreeting() {
          Library classUnderTest = new Library();
          assertEquals("Hello, World!", classUnderTest.getGreeting());
      }
      
      実行(失敗): ./gradlew test
    2. Green: src/main/java/Library.java を修正.
      public String getGreeting() { return "Hello, World!"; }
      
    3. Refactor: ./gradlew qualityCheck (Checkstyle/PMD) を実行.
  • 自動化:
    • ./gradlew test --continuous で継続的テスト.
  • 詳細: Javaアプリケーション環境構築ガイド を参照.

6. .NET (C#)

  • 起動コマンド: nix develop .#dotnet
  • 主要ツール: .NET SDK, OmniSharp
  • 初期化:
    # ソリューションの作成
    dotnet new sln --name Hello
    # ライブラリプロジェクトの作成
    dotnet new classlib -o Hello
    # テストプロジェクトの作成
    dotnet new xunit -o Hello.Tests
    # プロジェクトをソリューションに追加
    dotnet sln Hello.sln add Hello/Hello.csproj Hello.Tests/Hello.Tests.csproj
    # テストプロジェクトからライブラリプロジェクトへの参照を追加
    dotnet add Hello.Tests/Hello.Tests.csproj reference Hello/Hello.csproj
    
  • TDDチュートリアル:
  • Red: Hello.Tests/UnitTest1.cs を修正。
    namespace Hello.Tests;
    using Xunit;
    
    public class UnitTest1
    {
        [Fact]
        public void Test1()
        {
            Assert.Equal("Hello, World!", Hello.Lib.Greet());
        }
    }
    
    実行(失敗): dotnet test
  • Green: Hello/Lib.cs を実装。
    namespace Hello;
    
    public static class Lib
    {
        public static string Greet() => "Hello, World!";
    }
    
  • Refactor: dotnet format でコードを整形。
  • 自動化:
  • dotnet watch test で変更を監視し自動テスト実行。

7. Ruby

  • 起動コマンド: nix develop .#ruby
  • 主要ツール: Ruby, Bundler, Minitest, RuboCop
  • 初期化:
    bundle init
    echo 'gem "minitest"' >> Gemfile
    bundle install
    
  • TDDチュートリアル:
  • Red: test_hello.rb を作成.
    require 'minitest/autorun'
    require_relative 'hello'
    class TestHello < Minitest::Test
      def test_hello
        assert_equal "Hello, World!", hello()
      end
    end
    
    実行(失敗): ruby test_hello.rb
  • Green: hello.rb を実装.
    def hello; "Hello, World!"; end
    
  • Refactor: rubocop -a でコードスタイルを自動修正.

8. PHP

  • 起動コマンド: nix develop .#php
  • 主要ツール: PHP, Composer, PHPUnit, PHP_CodeSniffer
  • 初期化:
    composer init -n
    composer require --dev phpunit/phpunit
    
  • TDDチュートリアル:
  • Red: tests/HelloTest.php を作成.
    use PHPUnit\Framework\TestCase;
    class HelloTest extends TestCase {
        public function testHello() {
            $this->assertEquals("Hello, World!", hello());
        }
    }
    
    実行(失敗): ./vendor/bin/phpunit tests
  • Green: src/hello.php を実装.
    function hello() { return "Hello, World!"; }
    
  • Refactor: ./vendor/bin/phpcs src で規約チェック.

9. Haskell

  • 起動コマンド: nix develop .#haskell
  • 主要ツール: GHC, Stack, Cabal, HLS, hlint, fourmolu
  • 初期化:
    stack new hello
    cd hello
    # package.yaml の tests.hello-test.dependencies に hspec を追加
    stack test
    
  • TDDチュートリアル:
  • Red: test/Spec.hs を編集.
    module Main (main) where
    import Test.Hspec
    import Lib (hello)
    
    main :: IO ()
    main = hspec $ do
      describe "hello" $ do
        it "returns greeting" $ do
          hello `shouldBe` "Hello, World!"
    
    実行(失敗): stack test
  • Green: src/Lib.hs を実装.
    module Lib (hello) where
    hello :: String
    hello = "Hello, World!"
    
  • Refactor:
    • hlint . でコードの改善案をチェック.
    • fourmolu -i src/**/*.hs でコードを整形.
  • 自動化:
  • stack test --file-watch で変更を監視し自動テスト実行.

10. Clojure

  • 起動コマンド: nix develop .#clojure
  • 主要ツール: Clojure CLI, Leiningen, Babashka, Clojure LSP, clj-kondo (Linter), zprint (Formatter)
  • 初期化:
    # Clojure CLI を使用する場合
    clj -T:build new :name my-app
    # または Leiningen を使用する場合
    lein new app my-app
    
  • TDDチュートリアル:
  • Red: test/my_app/core_test.clj を作成。
    (ns my-app.core-test
      (:require [clojure.test :refer :all]
                [my-app.core :refer :all]))
    
    (deftest hello-test
      (testing "Greeting test"
        (is (= "Hello, World!" (hello)))))
    
    実行(失敗): clj -X:test または lein test
  • Green: src/my_app/core.clj を実装。
    (ns my-app.core)
    
    (defn hello []
      "Hello, World!")
    
  • Refactor:
    • clj-kondo --lint src で静的解析を実行。
    • bb -cp $(clojure -Spath) -m zprint.main src (zprintが利用可能な場合) でコード整形。
  • 自動化:
  • lein test-refresh で変更を監視し自動テスト実行(要プラグイン設定)。
  • Babashka (bb) を使用して軽量なタスクランナーを構築可能。

11. Elixir

  • 起動コマンド: nix develop .#elixir
  • 主要ツール: Elixir, Erlang, Mix, Elixir LS
  • 初期化:
    mix new my_app
    cd my_app
    
  • TDDチュートリアル:
  • Red: test/my_app_test.exs にテストを記述。
    defmodule MyAppTest do
      use ExUnit.Case
      test "greets the world" do
        assert MyApp.hello() == "Hello, World!"
      end
    end
    
    実行(失敗): mix test
  • Green: lib/my_app.ex を実装。
    defmodule MyApp do
      def hello do
        "Hello, World!"
      end
    end
    
  • Refactor: mix format でコードを整形。
  • 自動化:
  • mix test --watch (要 mix_test_watch パッケージ) で変更を監視。

12. Scala

  • 起動コマンド: nix develop .#scala
  • 主要ツール: Scala 3, sbt, Metals, Scala CLI
  • 初期化:
    # Scala CLI を使用してプロジェクト構造を作成する場合
    mkdir my-app && cd my-app
    # または sbt を使用する場合
    sbt new scala/scala-seed.g8
    
  • TDDチュートリアル:
  • Red: Hello.test.scala を作成(Scala CLI + MUnit の例).
    //> using lib "org.scalameta::munit::0.7.29"
    class HelloTest extends munit.FunSuite {
      test("hello returns greeting") {
        assert(Hello.greeting == "Hello, World!")
      }
    }
    
    実行(失敗): scala-cli test .
  • Green: Hello.scala を実装.
    object Hello {
      def greeting: String = "Hello, World!"
    }
    
  • Refactor: scala-cli fmt . でコードを整形.
  • 自動化:
  • scala-cli test . --watch で変更を監視し自動テスト実行.

13. F

  • 起動コマンド: nix develop .#dotnet
  • 主要ツール: .NET SDK, Ionide (LSP), Fantomas (Formatter)
  • 初期化:
    # ソリューションの作成
    dotnet new sln --name Hello
    # ライブラリプロジェクトの作成
    dotnet new classlib -lang "F#" -o Hello
    # テストプロジェクトの作成
    dotnet new xunit -lang "F#" -o Hello.Tests
    # プロジェクトをソリューションに追加
    dotnet sln Hello.sln add Hello/Hello.fsproj Hello.Tests/Hello.Tests.fsproj
    # テストプロジェクトからライブラリプロジェクトへの参照を追加
    dotnet add Hello.Tests/Hello.Tests.fsproj reference Hello/Hello.fsproj
    
  • TDDチュートリアル:
  • Red: Hello.Tests/Tests.fs を修正。
    namespace Hello.Tests
    open Xunit
    module Tests =
        [<Fact>]
        let ``Hello returns greeting`` () =
            Assert.Equal("Hello, World!", Hello.Lib.greet())
    
    実行(失敗): dotnet test
  • Green: Hello/Library.fs を実装。
    namespace Hello
    module Lib =
        let greet () = "Hello, World!"
    
  • Refactor: dotnet fantomas . (インストール済みの場合) でコードを整形。
  • 自動化:
  • dotnet watch test で変更を監視し自動テスト実行。

環境の切り替え

別の環境に切り替える場合は、現在のシェルを終了 (exit) してから、新しい環境の起動コマンドを実行してください。 複数の環境を同時に使用したい場合は、新しいターミナルタブを開くか、tmux 等のターミナルマルチプレクサの利用を推奨します。