言語別開発ガイド¶
本プロジェクトでは、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. 自動化¶
コマンド一つでビルド、テスト、静的解析を実行できるようにします。また、ファイル変更を監視して自動的にテストを実行する「継続的テスト」を活用します。
共通の開発フロー¶
- 環境の起動:
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
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!";
}
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チュートリアル:
- Red:
src/test/java/LibraryTest.javaにテスト追加.実行(失敗):@Test void testGreeting() { Library classUnderTest = new Library(); assertEquals("Hello, World!", classUnderTest.getGreeting()); }./gradlew test - Green:
src/main/java/Library.javaを修正.public String getGreeting() { return "Hello, World!"; } - Refactor:
./gradlew qualityCheck(Checkstyle/PMD) を実行.
- Red:
- 自動化:
./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 endruby 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 endmix 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 等のターミナルマルチプレクサの利用を推奨します。