1. ð ã¯ããã«
ååã¯ãšã©ãŒãã³ããªã³ã°ïŒäŸå€åŠçã»é²åŸ¡çããã°ã©ãã³ã°ïŒãåŠã³ãŸããã
æçµå㯠ãã¹ãã»ãã¡ã€ã«æ§é ã»ããŒãžã§ã³ç®¡ç ã®3ã€ã解説ããŸãïŒ
ãåãã³ãŒããæžããã ãããšã³ãžãã¢ã®ä»äºã§ã¯ãããŸããã
ãé·ãã»ããŒã ã§ã»å®å¿ããŠäœ¿ããã³ãŒãããäœãããã«ã
ãã¹ãã»æŽçã»èšé²ã®3ã€ãæ¬ ãããŸããã
2. 𧪠ãŠããããã¹ãã®åºæ¬
ãã¹ããšã¯ïŒ
ãã¹ããšã¯ãã³ãŒããæåŸ éãã«åãããšãèªåã§ç¢ºèªããä»çµã¿ãã§ãã
æåã§åäœç¢ºèªããã®ã§ã¯ãªããã³ãŒãã§ã³ãŒãããã¹ãããŸãã
ãªããã¹ããå¿ èŠãªã®ã
| æå確èªïŒãã¹ããªãïŒ | èªåãã¹ãïŒãã¹ãããïŒ |
|---|---|
| æ¯åæåã§ç¢ºèªãå¿ èŠ | ã³ãã³ãäžçºã§å šéšç¢ºèªã§ãã |
| ä¿®æ£ãããå šéšå確èªãå¿ èŠ | 圱é¿ç¯å²ãèªåã§æ€åºã§ãã |
| ç¢ºèªæŒããèµ·ãããã | æŒããªã確èªã§ãã |
| ããŒã ã«å ¥ã£ã人ãæããŠè§Šããªã | å®å¿ããŠã³ãŒãã倿Žã§ãã |
ð¡ ããã¹ãã¯ä¿éºã
ãã¹ãããããšãä¿®æ£ããŠãã¡ãããšåããããå³åº§ã«ç¢ºèªã§ããŸãã
ãã¹ãããªãã³ãŒãã¯ãäœããå€ãããšäœããå£ãããããããªãããšããææãšã®æŠãã«ãªããŸãã
ãŠããããã¹ãã®æžãæ¹ïŒPythonã»pytestïŒ
# calc.pyïŒãã¹ã察象ã®ã³ãŒãïŒ
def add(a: int, b: int) -> int:
"""2ã€ã®æ°å€ãè¶³ãç®ããã
Args:
a: 1ã€ç®ã®æ°å€
b: 2ã€ç®ã®æ°å€
Returns:
åèšå€
"""
return a + b
def divide(a: int, b: int) -> float:
"""2ã€ã®æ°å€ãå²ãç®ããã
Args:
a: å²ãããæ°
b: å²ãæ°
Returns:
å
Raises:
ValueError: bã0ã®å Žå
"""
if b == 0:
raise ValueError("ãŒãã§å²ãããšã¯ã§ããŸãã")
return a / b
# test_calc.pyïŒãã¹ãã³ãŒãïŒ
import pytest
from calc import add, divide
class TestAdd:
"""add颿°ã®ãã¹ãã"""
def test_æ£ã®æ°å士ãè¶³ã(self) -> None:
"""æ£ã®æ°å士ã®è¶³ãç®ãæ£ããããšã確èªããã"""
assert add(3, 5) == 8
def test_è² ã®æ°ãè¶³ã(self) -> None:
"""è² ã®æ°ãå«ãè¶³ãç®ãæ£ããããšã確èªããã"""
assert add(-3, 5) == 2
def test_ãŒããè¶³ã(self) -> None:
"""ãŒããè¶³ããå Žåã«å€ãå€ãããªãããšã確èªããã"""
assert add(5, 0) == 5
class TestDivide:
"""divide颿°ã®ãã¹ãã"""
def test_æ£åžžãªå²ãç®(self) -> None:
"""éåžžã®å²ãç®ãæ£ããããšã確èªããã"""
assert divide(10, 2) == 5.0
def test_ãŒãã§å²ããšãã«äŸå€ãçºçãã(self) -> None:
"""ãŒãã§å²ã£ãå Žåã«ValueErrorãçºçããããšã確èªããã"""
with pytest.raises(ValueError) as exc_info:
divide(10, 0)
assert "ãŒãã§å²ãããšã¯ã§ããŸãã" in str(exc_info.value)
# ãã¹ãã®å®è¡
pytest test_calc.py -v
# åºåäŸ
# test_calc.py::TestAdd::test_æ£ã®æ°å士ãè¶³ã PASSED
# test_calc.py::TestAdd::test_è² ã®æ°ãè¶³ã PASSED
# test_calc.py::TestAdd::test_ãŒããè¶³ã PASSED
# test_calc.py::TestDivide::test_æ£åžžãªå²ãç® PASSED
# test_calc.py::TestDivide::test_ãŒãã§å²ããšãã«äŸå€ãçºçãã PASSED
# 5 passed in 0.12s â
ãŠããããã¹ãã®æžãæ¹ïŒTypeScriptã»VitestïŒ
// calc.tsïŒãã¹ã察象ã®ã³ãŒãïŒ
export function add(a: number, b: number): number {
return a + b;
}
export function divide(a: number, b: number): number {
if (b === 0) {
throw new Error("ãŒãã§å²ãããšã¯ã§ããŸãã");
}
return a / b;
}
// calc.test.tsïŒãã¹ãã³ãŒãïŒ
import { describe, it, expect } from "vitest";
import { add, divide } from "./calc";
describe("add", () => {
it("æ£ã®æ°å士ãè¶³ã", () => {
expect(add(3, 5)).toBe(8);
});
it("è² ã®æ°ãå«ãè¶³ãç®", () => {
expect(add(-3, 5)).toBe(2);
});
});
describe("divide", () => {
it("éåžžã®å²ãç®", () => {
expect(divide(10, 2)).toBe(5);
});
it("ãŒãã§å²ã£ããäŸå€ãçºçãã", () => {
expect(() => divide(10, 0)).toThrow("ãŒãã§å²ãããšã¯ã§ããŸãã");
});
});
è¯ããã¹ãã®3åå
| åå | å 容 |
|---|---|
| ð¯ 1ãã¹ã1ç¢ºèª | 1ã€ã®ãã¹ãã¯1ã€ã®ããšã ã確èªãã |
| ð ãã¹ãåã§æå³ãããã | ãäœããã¹ãããããããã¹ãåã§ããã |
| ð äœåºŠå®è¡ããŠãåãçµæ | å€éšã«äŸåããã»å®è¡é åºã«é¢ä¿ãªãåãçµæã«ãªã |
ãã¹ãããããã³ãŒããæžã
# â ãã¹ããã«ããã³ãŒãïŒå€éšã«äŸåããŠããïŒ
def get_discount_price(product_id: int) -> int:
"""å²åŒäŸ¡æ Œãè¿ãã"""
product = db.find(product_id) # DBã«çŽæ¥ã¢ã¯ã»ã¹
now = datetime.now() # çŸåšæå»ã«äŸå
if now.hour < 12:
return int(product.price * 0.9)
return product.price
# â
ãã¹ãããããã³ãŒãïŒäŸåãå€ããæž¡ãïŒ
def get_discount_price(price: int, current_hour: int) -> int:
"""å²åŒäŸ¡æ Œãè¿ãã
Args:
price: å
ã®äŸ¡æ Œ
current_hour: çŸåšã®æéïŒ0ã23ïŒ
Returns:
å²åŒåŸã®äŸ¡æ ŒïŒååäžã¯10%åŒãïŒ
"""
if current_hour < 12:
return int(price * 0.9)
return price
# ãã¹ããç°¡åã«æžããïŒ
assert get_discount_price(1000, 10) == 900 # ååäžã¯10%åŒã
assert get_discount_price(1000, 15) == 1000 # ååŸã¯å²åŒãªã
ð¡ ãå€ããæž¡ããã ãã§ãªããã¹ããããããªãã®ãïŒ
ä¿®æ£åã¯é¢æ°ã®äžã§
datetime.now()ãåŒãã§ããããããååäžã®å²åŒããã¹ãããããã°ãæ¬åœã«ååäžã«ã³ãã³ããå®è¡ããªããã°ãªããªãããšããç¶æ³ã§ãããä¿®æ£åŸã¯
current_hourãåŒæ°ãšããŠåãåãããã«ããããã
10ïŒåå10æïŒã15ïŒååŸ3æïŒãèªç±ã«æž¡ããŸãã
ãæéãå€ããã³ã³ãããŒã«ãããŠæž¡ããããã«ãªã£ãã®ã§ããã€ã§ã奜ããªæéã®ãã¹ããèªååã§ããŸãããã®ããã«ãå€éšã«äŸåãããã®ïŒæå»ã»DBã»APIãªã©ïŒãåŒæ°ãšããŠåãåããèšèšã
äŸåæ§ã®æ³šå ¥ïŒDependency InjectionïŒ ãšåŒã³ãŸãã
ãã¹ãããããã³ãŒãã¯ãèšèšãšããŠãæè»ã§è¯ãã³ãŒãã«ãªã£ãŠããŸãã
3. ð ãã¡ã€ã«ã»ãã£ã¬ã¯ããªæ§é
ãªãæ§é ãæŽããã®ã
ãã³ãŒãã¯æžãå Žæãèšèšã®ãã¡ã
ãã¡ã€ã«ã®çœ®ãå ŽæãæŽã£ãŠãããšãæ°ããã¡ã³ããŒããããžã§ã¯ãã«å ¥ã£ãŠãããšããã©ãã«äœããããããããããããŸãã
Python ãããžã§ã¯ãã®åºæ¬æ§é
my_project/
âââ src/ # ã¢ããªã±ãŒã·ã§ã³ã®ãœãŒã¹ã³ãŒã
â âââ __init__.py
â âââ main.py # ãšã³ããªãŒãã€ã³ã
â âââ models/ # ããŒã¿ã¢ãã«
â â âââ __init__.py
â â âââ user.py
â â âââ order.py
â âââ services/ # ããžãã¹ããžãã¯
â â âââ __init__.py
â â âââ user_service.py
â â âââ order_service.py
â âââ utils/ # æ±çšãŠãŒãã£ãªãã£
â âââ __init__.py
â âââ email_helper.py
âââ tests/ # ãã¹ãã³ãŒã
â âââ test_user_service.py
â âââ test_order_service.py
âââ .env # ç°å¢å€æ°ïŒGitã«å«ããªãïŒïŒ
âââ .gitignore # Gitã§ç®¡çããªããã¡ã€ã«ã®èšå®
âââ requirements.txt # äŸåããã±ãŒãžã®ãªã¹ã
âââ README.md # ãããžã§ã¯ãã®èª¬æ
TypeScriptïŒNext.jsïŒãããžã§ã¯ãã®åºæ¬æ§é
my-app/
âââ src/
â âââ app/ # ããŒãžã»ã«ãŒãã£ã³ã°ïŒApp RouterïŒ
â â âââ page.tsx # ãããããŒãž
â â âââ users/
â â âââ page.tsx # ãŠãŒã¶ãŒäžèЧããŒãž
â âââ components/ # åå©çšå¯èœãªUIã³ã³ããŒãã³ã
â â âââ Button.tsx
â â âââ UserCard.tsx
â âââ lib/ # ãŠãŒãã£ãªãã£ã»ãã«ããŒé¢æ°
â â âââ api.ts
â âââ types/ # åå®çŸ©
â âââ user.ts
âââ tests/ # ãã¹ãã³ãŒã
â âââ components/
â âââ Button.test.tsx
âââ .env.local # ç°å¢å€æ°ïŒGitã«å«ããªãïŒïŒ
âââ .gitignore
âââ package.json # äŸåããã±ãŒãžã®ãªã¹ã
âââ README.md
ãã¡ã€ã«åå²ã®ç®å®
| ç¶æ³ | 倿 |
|---|---|
| 1ãã¡ã€ã«ã200è¡ãè¶ ããŠãã | åå²ãæ€èšããã¿ã€ãã³ã° |
| ããã®ãã¡ã€ã«ã¯äœããããã¡ã€ã«ããã説æãã«ãã | è²¬ä»»ãæ··åšããŠããå¯èœæ§ãã |
| åãã³ãŒããå¥ã®ãã¡ã€ã«ããã䜿ããã | å ±éã¢ãžã¥ãŒã«ã«åãåºã |
| ãã¹ããæžãã«ãã | äŸåé¢ä¿ãè€éã«ãªã£ãŠããå¯èœæ§ãã |
4. ð ããŒãžã§ã³ç®¡çïŒGitïŒ
ã³ãããã¡ãã»ãŒãžã®æžãæ¹
ã³ãããã¡ãã»ãŒãžã¯ãæªæ¥ã®èªåã仲éãžã®æçŽãã§ãã
git logãèŠããšãããªããã®å€æŽãããããããããããã«æžããŸãããã
æªãã³ãããã¡ãã»ãŒãž vs è¯ãã³ãããã¡ãã»ãŒãž
| â æªãäŸ | åé¡ç¹ |
|---|---|
fix |
äœãçŽãããããããªã |
ä¿®æ£ |
äœãä¿®æ£ãããããããªã |
wip |
äœæ¥äžãšããæå³ã ãäœã®äœæ¥ãããããªã |
aaa |
è«å€ |
ããããçŽãã |
ãããããããäœãããããªã |
ð¡
wipã®æ£ããäœ¿ãæ¹
wipåäœã®ã³ããããã¡ã€ã³ãã©ã³ãã«æ®ãã®ã¯NGã§ããããPCãå£ããåã«ãªã¢ãŒãã«éé¿ãããããšããå Žé¢ã§ã¯ãèªåã®äœæ¥ãã©ã³ãã§äžæçã«äœ¿ãããšã¯ãããŸãããã®å Žåã§ã å ·äœçãªå å®¹ãæžã ã®ããããŒã§ãã
â wip: ãŠãŒã¶ãŒç»é²ãã©ãŒã ã®ããªããŒã·ã§ã³å®è£ äž â wipæçµçã«ã¯ãã®ã³ãããã1ã€ã«ç¶ºéºã«ãŸãšããŠããïŒ
git squashïŒ
ããŒã ã®ãã©ã³ãã«åæµãããŸãããã
| â è¯ãäŸ | è¯ãçç± |
|---|---|
fix: ãã°ã€ã³æã®ãã¹ã¯ãŒãæ€èšŒãã°ãä¿®æ£ |
äœãã»ã©ãçŽãããããã |
feat: ãŠãŒã¶ãŒãããã£ãŒã«ç·šéæ©èœã远å |
æ°æ©èœã®è¿œå ãšããã |
refactor: calculate_tax颿°ã宿°ã䜿ãããã«å€æŽ |
ãªãã¡ã¯ã¿ãªã³ã°ãšããã |
docs: READMEã«ã»ããã¢ããæé ã远å |
ããã¥ã¡ã³ãã®å€æŽãšããã |
Conventional CommitsïŒã³ãããã¡ãã»ãŒãžã®èŠçŽïŒ
å€ãã®ãããžã§ã¯ãã§æ¡çšãããŠãã Conventional Commits ãšããèŠçŽããããŸãã
<type>: <æŠèŠ>
[æ¬æïŒä»»æïŒ]
[ããã¿ãŒïŒä»»æïŒ]
| ã¿ã€ã | æå³ | äŸ |
|---|---|---|
feat |
æ°æ©èœã®è¿œå | feat: ãŠãŒã¶ãŒç»é²æ©èœã远å |
fix |
ãã°ä¿®æ£ | fix: ã¡ãŒã«éä¿¡ã倱æããåé¡ãä¿®æ£ |
refactor |
æ©èœå€æŽãªãã®ã³ãŒãæ¹å | refactor: éè€ããåŠçã颿°ã«åãåºã |
docs |
ããã¥ã¡ã³ãã®å€æŽ | docs: APIããã¥ã¡ã³ããæŽæ° |
test |
ãã¹ãã®è¿œå ã»ä¿®æ£ | test: ãŠãŒã¶ãŒãµãŒãã¹ã®ãã¹ãã远å |
chore |
ãã«ãã»èšå®ã®å€æŽ | chore: äŸåããã±ãŒãžãã¢ããããŒã |
style |
ã³ãŒãã¹ã¿ã€ã«ã®å€æŽ | style: ã€ã³ãã³ããã¹ããŒã¹4ã€ã«çµ±äž |
å°ããªåäœã§ã³ããããã
# â 1ã€ã®ã³ãããã«å€§éã®å€æŽãè©°ã蟌ã
git commit -m "ãŠãŒã¶ãŒæ©èœã®å®è£
ããã°ä¿®æ£ããã¹ã远å ãããã¥ã¡ã³ãæŽæ°"
# â
1ã€ã®ã³ãããã¯1ã€ã®å€æŽ
git commit -m "feat: ãŠãŒã¶ãŒç»é²APIã®ãšã³ããã€ã³ãã远å "
git commit -m "test: ãŠãŒã¶ãŒç»é²APIã®ãã¹ãã远å "
git commit -m "docs: ãŠãŒã¶ãŒç»é²APIã®ããã¥ã¡ã³ãã远å "
å°ããã³ãããããã¡ãªããïŒ
ã¡ãªãã 説æ ð ã¬ãã¥ãŒãããã 倿Žç¹ãå°ãããšäœãããããããããã â©ïž æ»ãããã åé¡ã®ããã³ãããã ãåãæ¶ãã ð ãã°ã®åå ãç¹å®ãããã git bisectã§åé¡ã®ã³ããããçµã蟌ãã
.gitignoreã§ç®¡çããªããã¡ã€ã«ãæå®ãã
# .gitignore ã®äŸ
# ç°å¢å€æ°ïŒAPIããŒã»ãã¹ã¯ãŒããå«ãŸããïŒ
.env
.env.local
.env.production
# äŸåããã±ãŒãžïŒnpm installã§åçæã§ããïŒ
node_modules/
# Pythonã®ãã£ãã·ã¥
__pycache__/
*.pyc
# IDEã®èšå®ãã¡ã€ã«ïŒå人ã®èšå®ã¯å
±æããªãïŒ
.vscode/settings.json
.idea/
# ãã«ãææç©
dist/
build/
â ïž
.envãã¡ã€ã«ã¯çµ¶å¯Ÿã«Gitã«ã³ãããããªãïŒ
APIããŒããã¹ã¯ãŒããå«ãŸããããã
äžåºŠã§ãã³ããããããšå±¥æŽã«æ®ãç¶ããŸãã
.gitignoreãžã®è¿œå ãæåã«å¿ ãè¡ããŸãããã
ð¡ 代ããã«
.env.exampleãGitã§ç®¡çããïŒã
.envãã³ãããããªããªããä»ã®ããŒã ã¡ã³ããŒã¯ã©ã®ç°å¢å€æ°ãå¿ èŠãã©ããã£ãŠç¥ãã°ããã®ïŒããšããåé¡ããããŸãã解決ç㯠å€ã ãã空ã«ãã
.env.exampleãGitã«å«ãã ããšã§ãã# .env.exampleïŒGitã«å«ããã»å€ã¯ç©ºã«ããïŒ DATABASE_URL= API_KEY= JWT_SECRET=# .envïŒGitã«å«ããªãã»å®éã®å€ãæžãïŒ DATABASE_URL=postgresql://localhost:5432/mydb API_KEY=sk-1234567890abcdef JWT_SECRET=my-super-secret-keyéçšã®æµãïŒ
â.env.exampleãGitã§å ±æ
â¡ æ°ããã¡ã³ããŒãåå ããã.env.exampleãã³ããŒããŠ.envãäœã
ïŒâ».env.txtã®ããã«æ¡åŒµåãã€ããªãããæ³šæïŒç°å¢å€æ°ãèªã¿èŸŒãŸããªããªããŸãïŒ
⢠åèªãèªåã®ç°å¢ã®å€ãå ¥åããŠäœ¿ãããã§ãã©ããªç°å¢å€æ°ãå¿ èŠãããããŒã ã§å ±æãã€ã€ã
å®éã®å€ã¯å®å šã«ç®¡çã§ããŸãð
5. ð¯ ã·ãªãŒãºç·ãŸãšã
6åã«ããã£ãŠåŠãã å å®¹ãæ¯ãè¿ããŸãããã
| å | ããŒã | éèŠãã€ã³ã |
|---|---|---|
| 第äžå | ã³ãŒãã®åºæ¬æ§é | é æ¬¡ã»åå²ã»å埩ã»é¢æ°ã»ã¹ã³ãŒãã»å |
| 第äºå | åœåèŠå | ãã£ã¡ã«ã»ã¹ããŒã¯ã»ãã¹ã«ã«ã»è¯ãååã®åºæº |
| 第äžå | ã³ãŒãã®èšèšåå | DRYã»KISSã»åäžè²¬ä»»ã»SOLIDåå |
| 第åå | ã³ã¡ã³ãã»ããã¥ã¡ã³ã | ããªãããæžãã»docstringã»ããžãã¯ãã³ããŒæé€ |
| 第äºå | ãšã©ãŒãã³ããªã³ã° | äŸå€åŠçã»ã¬ãŒãç¯ïŒæ©æãªã¿ãŒã³ïŒã»é²åŸ¡çããã°ã©ãã³ã° |
| 第å å | ãã¹ãã»æ§é ã»ããŒãžã§ã³ç®¡ç | ãŠããããã¹ãã»ãã¡ã€ã«æŽçã»ã³ãããèŠçŽ |
ãè¯ãã³ãŒããã®å ±éç¹ïŒ
â èªãã§æå³ããããïŒåœåã»ã³ã¡ã³ãïŒ
â 倿ŽããããïŒèšèšååã»åäžè²¬ä»»ïŒ
â å£ãã«ããïŒãšã©ãŒãã³ããªã³ã°ã»ãã¹ãïŒ
â è¿·ãã䜿ããïŒãã¡ã€ã«æ§é ã»ããŒãžã§ã³ç®¡çïŒãããã¯ãã¹ãŠãæªæ¥ã®èªåãããŒã ãžã®æããããããæ¥ãŠããŸãã
ã³ãŒãã£ã³ã°ã®åºç€ã¯ãæè¡ãã§ããåã«ãæåãã§ãðªð 次ã®äžæ©ïŒä»æ¥ããã§ããããš
å š6åãèªã¿çµããããªããžã
é£ããèããªããŠå€§äžå€«ã§ãã
- 仿žããŠããã³ãŒãã®å€æ°ã«ã1ã€ã ãå ·äœçãªååãã€ããŠã¿ã
- é·ããªã£ãŠãã颿°ãã1ã€ã ã20è¡ä»¥å ã«åããŠã¿ã
- ã³ãããã¡ãã»ãŒãžãã1ã€ã ã
feat:ãfix:ã§å§ããŠã¿ããã®å°ããªäžæ©ã®ç©ã¿éããã
ããªããçŽ æŽããããšã³ãžãã¢ã«è²ãŠãŠãããŸãðãã®ã·ãªãŒãºããããè¯ãã³ãŒããæžãããã®ç¬¬äžæ©ã«ãªãã°å¹žãã§ãã
ð¬ 質åãææ³ãããã°ãã³ã¡ã³ãæ¬ã§ãæ°è»œã«ã©ãã!
ð 圹ã«ç«ã£ãããããã&ã¹ããã¯ããé¡ãããŸã!
ð ãããŸã§èªãã§ãã ãã£ãŠãæ¬åœã«ããããšãããããŸãã!
ð ã·ãªãŒãºèšäº
- ã第äžåãã³ãŒãã®åºæ¬æ§é
- ã第äºåãåœåèŠå
- ã第äžåãã³ãŒãã®èšèšåå
- ã第ååãã³ã¡ã³ãã»ããã¥ã¡ã³ã
- ã第äºåããšã©ãŒãã³ããªã³ã°
- ã第å åããã¹ãã»ãã¡ã€ã«æ§é ã»ããŒãžã§ã³ç®¡çïŒãã®èšäºïŒ