3์ฅ ํจ์
ํจ์๋ ํ๋ก๊ทธ๋จ์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋จ์์ด๋ค.
์ด ์ฅ์์๋,
- ์๋๋ฅผ ๋ถ๋ช ํ๊ฒ ํํํ๋ ํจ์๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ
- ํ๋ก๊ทธ๋จ ๋ด๋ถ๋ฅผ ์ง๊ด์ ์ผ๋ก ํ์ ํ ์ ์๋๋ก ํจ์๋ฅผ ์ฝ๊ฒ ์ฝ๊ณ ์ดํดํ ์ ์๋๋ก ๋ง๋๋ ๋ฐฉ๋ฒ
์ ๋ํด์ ์์๋ณธ๋ค.
์๊ฒ ๋ง๋ค์ด๋ผ!
ํจ์๋ ์์์๋ก ๋ ์ข๋ค. ๊ทธ๋์ผ ์ฝ๊ณ ์ดํดํ๊ธฐ ์ฌ์์ง๋ค.
์กฐ๊ฑด๋ฌธ, ๋ฐ๋ณต๋ฌธ ๋ฑ์ ๋ค์ด๊ฐ๋ ๋ธ๋ก์ ํ ์ค์ด์ด์ผ ํ๋ค. ์ฆ,
- ์ค์ฒฉ ๊ตฌ์กฐ๊ฐ ์๊ธธ ๋งํผ ํจ์๊ฐ ์ปค์ ธ์๋ ์ ๋๋ค.
- ํจ์์์ ๋ค์ฌ ์ฐ๊ธฐ ์์ค์ 2๋จ์ ๋์ด์๋ฉด ์ ๋๋ค.
ํ ๊ฐ์ง๋ง ํด๋ผ!
ํจ์๋ ํ ๊ฐ์ง๋ฅผ ํด์ผ ํ๋ค. ๊ทธ ํ ๊ฐ์ง๋ฅผ ์ํด์ผ ํ๋ค. ๊ทธ ํ ๊ฐ์ง๋ง์ ํด์ผ ํ๋ค.
์ฌ๊ธฐ์์ ‘ํ ๊ฐ์ง๋ฅผ ํ๋ค’๊ฐ ์๋ฏธํ๋ ๊ฒ์ ์ถ์ํ ์์ค์ด ํ๋์ธ ๋จ๊ณ๋ง ์ํํ๋ค๋ ๊ฒ์ด๋ค.
๋จ์ํ ๋ค๋ฅธ ํํ์ด ์๋๋ผ ์๋ฏธ ์๋ ์ด๋ฆ์ผ๋ก ๋ค๋ฅธ ํจ์๋ฅผ ์ถ์ถํ ์ ์๋ค๋ฉด ๊ทธ ํจ์๋ ์ฌ๋ฌ ์์ ์ ํ๋ ์ ์ด๋ค.
ํจ์ ๋น ์ถ์ํ ์์ค์ ํ๋๋ก!
ํจ์๊ฐ ํ์คํ ํ ๊ฐ์ง ์์ ๋ง ํ๋ ค๋ฉด ํจ์ ๋ด ๋ชจ๋ ๋ฌธ์ฅ์ ์ถ์ํ ์์ค์ด ๋์ผํด์ผ ํ๋ค.
ํ ํจ์ ๋ด์ ์ถ์ํ ์์ค์ ์์ผ๋ฉด ์ฝ๋๋ฅผ ์ฝ๋ ์ฌ๋์ด ํท๊ฐ๋ฆฐ๋ค. ํน์ ํํ์ด ๊ทผ๋ณธ ๊ฐ๋ ์ธ์ง, ์ธ๋ถ์ฌํญ์ธ์ง ๊ตฌ๋ถํ๊ธฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทผ๋ถ ๊ฐ๋ ๊ณผ ์ธ๋ถ์ฌํญ์ด ๋ค์์ด๋ฉด ํจ์์ ์ธ๋ถ์ฌํญ์ ์ ์ ์ถ๊ฐํ๊ฒ ๋๋ค.
์์์ ์๋๋ก ์ฝ๋ ์ฝ๊ธฐ: ๋ด๋ ค๊ฐ๊ธฐ ๊ท์น
๋ด๋ ค๊ฐ๊ธฐ ๊ท์น์ด๋, ์์์ ์๋๋ก ๊ฐ์๋ก ํจ์ ์ถ์ํ ์์ค์ด ํ ๋จ๊ณ์ฉ ๋ฎ์์ง๋ค๋ ๊ท์น์ด๋ค.
์์์ ์๋๋ก ์ฝ์ด ๋ด๋ ค๊ฐ๋ฏ ์ฝ๋๋ฅผ ๊ตฌํํ๋ฉด ์ถ์ํ ์์ค์ ์ผ๊ด๋๊ฒ ์ ์งํ๊ธฐ ์ฌ์์ง๋ค.
Switch ๋ฌธ
๋ณธ์ง์ ์ผ๋ก switch ๋ฌธ์ N๊ฐ์ง ์ผ์ ํ๋ค. ๋ํ ์๊ฒ ๋ง๋ค๊ธฐ ํ๋ค๋ค.
switch๋ฌธ์ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด ์ฝ๋๋ฅผ ์ ์ฐจ์ ํด๋์ค์ ์จ๊ธฐ๊ณ ์ ๋๋ก ๋ฐ๋ณตํ์ง ์๋๋ก ํ๋ค.
function calculatePay(e: Employee) {
switch (e.type) {
case COMISSIONED:
return calculateComissionedPay(e);
case HOURLY:
return calculateHourlyPay(e);
case SALARIED:
return calculateSalariedPay(e);
default:
throw new InvalidEmployeeType(e.type)
}
}
์ ์ฝ๋์ ๋ฌธ์ ์ ์ ๋ค์๊ณผ ๊ฐ๋ค
- ํจ์๊ฐ ๊ธธ๋ค. Employee type์ด ์ถ๊ฐ๋๋ค๋ฉด ๋ ๊ธธ์ด์ง๋ค.
- ํ ๊ฐ์ง ์์ ๋ง ์ํํ์ง ์๋๋ค.
- Single Responsibility Principle์ ์๋ฐํ๋ค. ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ์ด์ ๊ฐ ์ฌ๋ฟ์ด๊ธฐ ๋๋ฌธ์
- Open Closed Principle์ ์๋ฐํ๋ค. ์ type์ด ์ถ๊ฐํ ๋๋ง๋ค ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ๋๋ฌธ์
- ์ ํจ์์ ๊ตฌ์กฐ๊ฐ ๋์ผํ ์ฝ๋๊ฐ ๋ฌดํ์ ์กด์ฌํ๊ฒ ๋๋ค.
- ex) isPayday(e: Employee, date: Date), deliverPay(e: Employee, pay: Money)
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด
- switch ๋ฌธ์ ํฉํ ๋ฆฌ ํจ์๋ก ๊ฝ๊ฝ ์จ๊ธด๋ค.
- ์ ํ๋ณ Employee๋ ์์์ ํตํ ๋คํ์ฑ์ ์ด์ฉํ์ฌ ๊ตฌํํ๊ณ , ํฉํ ๋ฆฌ ํจ์๋ฅผ ํตํด์๋ง ์์ฑํ๋ค.
๋จผ์ ๋ชจ๋ ์ ํ์ Employee๊ฐ ์์๋ฐ๋ ์ถ์ ํด๋์ค๋ ๋ค์์ฒ๋ผ ๊ตฌํํ ์ ์๋ค.
abstract class Employee {
protected record: EmployeeRecord;
protected abstract isPayday(): boolean;
protected abstract caclulatePay(): Money;
protected abstract deliverPay(pay: Money): void;
constructor(r: EmployeeRecord) {
this.record = r;
}
}
๊ฐ type ๋ณ๋ก ํ์ ํด๋์ค๋ฅผ ๋ค์์ฒ๋ผ ๊ตฌํํ๋ค.
// Employee์ ํ์ ํด๋์ค
class ComissionedEmployee extends Employee {
protected isPayday(): boolean {
...
}
protected caclulatePay(): number {
...
}
protected deliverPay(pay: number): void {
...
}
}
ํฉํ ๋ฆฌ ํจ์๋ ๋ค์์ฒ๋ผ ๊ตฌํํ๋ค.
function makeEmployee(r: EmployeeRecord): Employee {
switch (r.type) {
case 'COMISSIONED':
return new ComissionedEmployee(r); //Employee์ ํ์ ํด๋์ค
case 'HOURLY':
return HourlyEmployee(r); //Employee์ ํ์ ํด๋์ค
case 'SALARIED':
return SalariedEmployee(r); //Employee์ ํ์ ํด๋์ค
default:
throw new InvalidEmployeeType(r.type);
}
}
์ด์ ๋ค๋ฅธ ๋ชจ๋ ์ฝ๋์์ Employee์ type๋ณ๋ก switch๋ฌธ์ ์ฌ์ฉํ ์ผ์ด ์์ด์ง๋ค.
๋ํ, ์๋ก์ด type์ด ์ถ๊ฐ๋๋๋ผ๋ ํฉํ ๋ฆฌ ํจ์๋ฅผ ์ ์ธํ ๋ค๋ฅธ ์ฝ๋๋ ๋ณ๊ฒฝํ์ง ์์๋ ๋๋ค.
const employee = makeEmployee(record);
// switch ๋ฌธ์ด ํ์์๋ค
if(employee.isPayday())
employee.deliverPay();
์์ ์ ์ธ ์ด๋ฆ์ ์ฌ์ฉํ๋ผ!
์ข์ ์ด๋ฆ์ด ์ฃผ๋ ๊ฐ์น๋ ํด๋ฆฐ์ฝ๋ ์ ๋ฐ์ ๊ฑฐ์ณ์ ๊ฐ์กฐํ๊ณ ์๋ ๋ด์ฉ์ด๋ค.
ํจ์๊ฐ ์๊ณ ๋จ์ํ ์๋ก ์์ ์ ์ธ ์ด๋ฆ์ ๊ณ ๋ฅด๊ธฐ๋ ์ฌ์์ง๋ค.
- ๊ธธ๊ณ ์์ ์ ์ธ ์ด๋ฆ์ด ์งง๊ณ ์ด๋ ค์ด ์ด๋ฆ๋ณด๋ค ์ข๋ค.
- ์ด๋ฆ์ ๋ถ์ผ ๋ ์ผ๊ด์ฑ์ด ์์ด์ผ ํ๋ค. ๋ชจ๋ ๋ด์์ ๊ฐ์ ๋ฌธ๊ตฌ, ๋ช ์ฌ, ๋์ฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ฒด๋ฅผ ๋น์ทํ๊ฒ ๋ง๋ค์ด๋ผ
ํจ์ ์ธ์
- ํจ์ ์ธ์๋ 0๊ฐ ์ธ ๊ฒ์ด ๊ฐ์ฅ ์ข๊ณ ๊ฐ๋ฅํ 3๊ฐ ์ด์์ ํผํ๋ ํธ์ด ์ข๋ค.
- ํ ์คํธ ๊ด์ ์์๋ ์ธ์๊ฐ ๋ง์์๋ก ๋ชจ๋ ์กฐํฉ์ ๊ตฌ์ฑํด ํ ์คํธํ๊ธฐ๊ฐ ๋ถ๋ด์ค๋ฌ์์ง๋ค.
- ์ถ๋ ฅ ์ธ์๋ ์ดํดํ๊ธฐ ์ด๋ ค์ฐ๋ฏ๋ก ์ง์ํ๋ค. ํจ์์์ ์ธ์๋ก ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๋ ๊ฒ์ ์ง๊ด์ ์ด์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋ง์ด ์ฐ๋ ๋จํญ ํ์
๋จํญ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ํฌ๊ฒ ์ธ ๊ฐ์ง์ด๋ค.
- ์ธ์์ ์ง๋ฌธ์ ๋์ง๋ ๊ฒฝ์ฐ
- ex) fileExists: (path: string) ⇒ boolean
- ์ธ์๋ฅผ ๋ญ๊ฐ๋ก ๋ณํํด ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ๊ฒฝ์ฐ
- ex) fileOpen: (path: string) ⇒ InputStream
- ๋จํญ ํจ์๋ฅผ ์ด๋ฒคํธ๋ก ์ฌ์ฉํ๋ ๊ฒฝ์ฐ - ํ๋ก๊ทธ๋จ์ ํจ์ ํธ์ถ์ ์ด๋ฒคํธ๋ก ํด์ํด ์ ๋ ฅ ์ธ์๋ก ์์คํ ์ํ๋ฅผ ๋ฐ๊พผ๋ค. ex) passwordAttemptFailedNtimes: (attempts: number) ⇒ void
ํจ์ ์ด๋ฆ์ ์ง์ ๋๋ ์ธ ๊ฒฝ์ฐ๋ฅผ ๋ถ๋ช ํ ๊ตฌ๋ถํ๊ณ , ์ผ๊ด์ ์ธ ๋ฐฉ์์ผ๋ก ๊ฐ ํ์์ ์ฌ์ฉํด์ผ ํ๋ค.
์ด๋ฒคํธ ํจ์๋ ์ด๋ฒคํธ๋ผ๋ ์ฌ์ค์ด ์ฝ๋์ ๋ช ํํ ๋๋ฌ๋์ผ ํ๋ค.
ํ๋๊ทธ ์ธ์
ํ๋๊ทธ ์ธ์๋ ํจ์๊ฐ ์ฌ๋ฌ ๊ฐ์ง ์ผ์ ํ๋ค๋ ๋ป์ด๋ค.
๊ฐ๋ฅํ ๋ ๊ฐ์ ํจ์๋ก ๋ถ๋ฆฌํ๋ค.
์ดํญ ํจ์, ์ผํญ ํจ์
์ดํญํจ์๊ฐ ์ ์ ํ ๊ฒฝ์ฐ๋ ํ ๊ฐ์ ํํํ๋ ๋ ์์์ธ ๊ฒฝ์ฐ, ์์ฐ์ ์ธ ์์๊ฐ ์๋ ๊ฒฝ์ฐ์ด๋ค.
ex) const point = new Point(0, 0)
์ดํญ ํจ์๋ ๋จํญ ํจ์๋ณด๋ค ์ดํดํ๊ธฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ์ง์ํ๋ ํธ์ด ์ข๋ค.
๋ฌด์กฐ๊ฑด ๋์ ๊ฑด ์๋์ง๋ง ์ํ์ด ๋ฐ๋ฅธ๋ค๋ ์ฌ์ค์ ์ดํดํ๊ณ , ๊ฐ๋ฅํ๋ฉด ๋จํญ ํจ์๋ก ๋ฐ๊พธ๋๋ก ์ ์จ์ผ ํ๋ค.
์ผํญ ํจ์ ๋ํ ๋น์ฐํ ์ดํญ ํจ์๋ณด๋ค ํจ์ฌ ๋ ์ด๋ ต๋ค. ์ ์คํ ๊ณ ๋ คํ์ฌ ์ฌ์ฉํด์ผ ํ๋ค.
์ธ์ ๊ฐ์ฒด
์ธ์๊ฐ 2๊ฐ ์ด์ ํ์ํ๋ค๋ฉด ์ผ๋ถ๋ฅผ ๋ ์์ ์ธ ํด๋์ค๋ object ๋ณ์๋ก ์ ์ธํ ์ ์๋์ง ์ง์ด๋ณธ๋ค.
๋ณ์๋ฅผ ๋ฌถ์ด์ ๋๊ธธ ๋ ์ด๋ฆ์ ๋ถ์ฌ์ผ ํ๋ฏ๋ก ๊ฒฐ๊ตญ์ ๊ฐ๋ ์ ํํํ ์ ์๊ฒ ๋๋ค.
function makeCircle(x: number, y: number, radius: number)
type Point = {x: number, y: number}
function makeCircle(point: Point, radius: number)
๋์ฌ์ ํค์๋
ํจ์์ ์๋๋ ์ธ์์ ์์์ ์๋๋ฅผ ์ ๋๋ก ํํํ๊ธฐ ์ํ ์ข์ ํจ์ ์ด๋ฆ์ ๋ค์์ฒ๋ผ ์ง์ ์ ์๋ค.
- ๋จํญ ํจ์๋ ํจ์์ ์ธ์๊ฐ ๋์ฌ/๋ช ์ฌ ์์ ์ด๋ค์ผ ํ๋ค.
- writeField(name)
- ํจ์ ์ด๋ฆ์ ํค์๋๋ฅผ ์ถ๊ฐํ๋ค. ์ฆ, ํจ์ ์ด๋ฆ์ ์ธ์ ์ด๋ฆ์ ๋ฃ๋๋ค.
- assertEquals(expected, actual) → assertExpectedEqualsActual(expected, actual)
๋ถ์ ํจ๊ณผ๋ฅผ ์ผ์ผํค์ง ๋ง๋ผ!
๋ง์ ๊ฒฝ์ฐ ์๊ฐ์ ์ธ ๊ฒฐํฉ์ด๋ ์์ ์ข ์์ฑ์ ์ด๋ํ ์ ์๋ค.
function checkPassword(username: string, password: string) {
const user = findByName(username)
if(user) {
const codedPhrase = getPhraseEncodedByPassword();
const phrase = decrypt(codedPhrase, password);
if ("Valid Password" === phrase) {
Session.initialize(); // ๐ด ํจ์๊ฐ ์ผ์ผํค๋ ๋ถ์ ํจ๊ณผ
return true
}
}
return false
}
checkPassword๋ผ๋ ํจ์ ์ด๋ฆ์์ ์ธ์ ์ ์ด๊ธฐํํ๋ค๋ ์ฌ์ค์ด ๋๋ฌ๋์ง ์๋๋ค.
์ด๋ฐ ๋ถ์ ํจ๊ณผ๊ฐ ์๊ฐ์ ์ธ ๊ฒฐํฉ์ ์ด๋ํ๋ค. ์ฆ, ์ธ์ ์ ์ด๊ธฐํํด๋ ๊ด์ฐฎ์ ๊ฒฝ์ฐ์๋ง ํธ์ถ์ด ๊ฐ๋ฅํ๋ค.
์๊ฐ์ ์ธ ๊ฒฐํฉ์ด ํ์ํ๋ค๋ฉด ํจ์ ์ด๋ฆ์ ๋ถ๋ช ํ ๋ช ์ํ๋๋ก ํ๋ค.
๋ช ๋ น๊ณผ ์กฐํ๋ฅผ ๋ถ๋ฆฌํ๋ผ!
ํจ์๋ ๊ฐ์ฒด ์ํ๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋, ๊ฐ์ฒด ์ ๋ณด๋ฅผ ๋ฐํํ๊ฑฐ๋ ๋ ์ค ํ๋๋ง ํ๋๋ก ํ๋ค.
// ๐ด username ์์ฑ์ unclebob์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ์ ์ฑ๊ณตํ๋ฉด true, ์คํจํ๋ฉด false๋ฅผ ๋ฐํํ๋ ํจ์
// username์ด unclebob์ผ๋ก ์ค์ ๋์ด ์๋ค๋ฉด...์ผ๋ก ์ฝํ๋ค
if(set("username", "unclebob")) ...
// ๐ข ์กฐํ์ ๋ช
๋ น์ ๋ค๋ฅธ ํจ์๋ก ๋ถ๋ฆฌํด์ ํผ๋์ ์ผ์ผํค์ง ์๋๋ค.
if(attributeExists("username")) {
setAttribute("username", "unclebob")
}
์ค๋ฅ ์ฝ๋๋ณด๋ค ์์ธ๋ฅผ ์ฌ์ฉํ๋ผ!
์ค๋ฅ ์ฝ๋๋ฅผ ๋ฐํํ๋ ๋ฐฉ์์ ๋ช ๋ น/์กฐํ ๋ถ๋ฆฌ ๊ท์น์ ์๋ฐํ๋ค.
๋ํ, ์ฌ๋ฌ ๋จ๊ณ๋ก ์ค์ฒฉ๋๋ ์ฝ๋๋ฅผ ์ผ๊ธฐํ๊ฒ ๋๋ค. ํธ์ถ์๋ ์ค๋ฅ ์ฝ๋๋ฅผ ๊ณง๋ฐ๋ก ์ฒ๋ฆฌํด์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
๋ฐ๋ฉด ์์ธ๋ฅผ ์ฌ์ฉํ๋ฉด try/catch ๋ฌธ์ ํตํด ์ค๋ฅ ์ฒ๋ฆฌ ์ฝ๋๊ฐ ์๋ ์ฝ๋์์ ๋ถ๋ฆฌ๋ ์ ์๋ค.
try/catch ๋ธ๋ก ๋ฝ์๋ด๊ธฐ
try/catch๋ฌธ์ ์ ์ ๋์๊ณผ ์ค๋ฅ ์ฒ๋ฆฌ ๋์์ ๋ค์๋๋ค.
๋ฐ๋ผ์ ๋ณ๋ ํจ์๋ก ๋ฝ์๋ด๋ ํธ์ด ์ข๋ค.
์ค๋ฅ ์ฒ๋ฆฌ๋ ํ ๊ฐ์ง ์์ ์ด๋ค.
๋ฐ๋ผ์ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๋ ํจ์๋ ์ค๋ฅ๋ง ์ฒ๋ฆฌํ๋ค.
๊ตฌ์กฐ์ ํ๋ก๊ทธ๋๋ฐ
๋ชจ๋ ํจ์์ ํจ์ ๋ด ๋ชจ๋ ๋ธ๋ก์ ์ ๊ตฌ์ ์ถ๊ตฌ๊ฐ ํ๋๋ง ์กด์ฌํด์ผ ํ๋ค.
- ํจ์๋ return ๋ฌธ์ด ํ๋์ฌ์ผ ํ๋ค
- ๋ฃจํ ์์์ break, continue๋ฅผ ์ฌ์ฉํด์ ์๋๋ค.
๋จ, ํจ์๊ฐ ์์ฃผ ํด ๋๋ง ์๋นํ ์ด์ต์ ์ ๊ณตํ๋ค.
ํจ์๋ฅผ ์๊ฒ ๋ง๋ ๋ค๋ฉด return, break, continue์ ์ฌ์ฉ์ด ์๋๋ฅผ ํํํ๋ ๋ฐ ๋ ์ ๋ฆฌํ ์ ์๋ค.