/** 캡슐화 javascript X typescript O
class User {
private name: string; // name 변수를 외부에서 접근을 할 수 없게 만듭니다.
private age: number; // age 변수를 외부에서 접근을 할 수 없게 만듭니다.
setName(name: string) { // Private 속성을 가진 name 변수의 값을 변경합니다.
this.name = name;
}
getName() { // Private 속성을 가진 name 변수의 값을 조회합니다.
return this.name;
}
setAge(age: number) { // Private 속성을 가진 age 변수의 값을 변경합니다.
this.age = age;
}
getAge() { // Private 속성을 가진 age 변수의 값을 조회합니다.
return this.age;
}
}
const user = new User(); // user 인스턴스 생성
user.setName('이용우');
user.setAge(30);
console.log(user.getName()); // 이용우
console.log(user.getAge()); // 30
console.log(user.name); // Error: User 클래스의 name 변수는 private로 설정되어 있어 바로 접근할 수 없습니다.
**/
/** 상속 : 하나의 클래스를 다른 클래스가 물려받음 javascript X typescript O
class Mother { // Mother 부모 클래스
constructor(name, age, tech) { // 부모 클래스 생성자
this.name = name;
this.age = age;
this.tech = tech;
}
getTech(){ return this.tech; } // 부모 클래스 getTech 메서드
}
class Child extends Mother{ // Mother 클래스를 상속받은 Child 자식 클래스
constructor(name, age, tech) { // 자식 클래스 생성자
super(name, age, tech); // 부모 클래스의 생성자를 호출
}
}
const child = new Child("이용우", "28", "Node.js");
console.log(child.name); // 이용우
console.log(child.age); // 28
console.log(child.getTech()); // 부모 클래스의 getTech 메서드 호출: Node.js
**/
/** 추상화 javascript X typescript O
interface Human { 여기가 틀을 잡아놓음
name: string;
setName(name);
getName();
}
// 인터페이스에서 상속받은 프로퍼티와 메소드는 구현하지 않을 경우 에러가 발생합니다.
class Employee implements Human { 휴먼에서
constructor(public name: string) { } name은 스트링값임.
// Human 인터페이스에서 상속받은 메소드
setName(name) { this.name = name; } name 가져옴.
// Human 인터페이스에서 상속받은 메소드
getName() { return this.name; } 리턴.
}
const employee = new Employee("");
employee.setName("이용우"); // Employee 클래스의 name을 변경하는 setter
console.log(employee.getName()); // Employee 클래스의 name을 조회하는 getter
**/
/** 다형성
class Person {
constructor(name) { this.name = name; }
buy() {}
}
class Employee extends Person {
buy() { console.log(`${this.constructor.name} 클래스의 ${this.name}님이 물건을 구매하였습니다.`); }
}
class User extends Person {
buy() { console.log(`${this.constructor.name} 클래스의 ${this.name}님이 물건을 구매하였습니다.`); }
}
const employee1 = new Employee("이용우");
const employee2 = new Employee("김창환");
const user1 = new User("이태강");
const user2 = new User("김민수");
const personsArray = [employee1, employee2, user1, user2];
// personsArray에 저장되어 있는 Employee, User 인스턴스들의 buy 메소드를 호출합니다.
personsArray.forEach((person) => person.buy());
// Employee 클래스의 이용우님이 물건을 구매하였습니다.
// Employee 클래스의 김창환님이 물건을 구매하였습니다.
// User 클래스의 이태강님이 물건을 구매하였습니다.
// User 클래스의 김민수님이 물건을 구매하였습니다.
**/
/** 객체 지향 설계 5원칙
S단일 책임 원칙 : 클래스나 모듈을 변경할 이유가 단 하나뿐이여야한다. "하나의 코드에 하나의 기능만 들어가서, 보기 쉽게 만들어야한다."
O개방폐쇄원칙 : 확장에는 열려있으나 변경에는 닫혀있어야한다. "수정할때 가볍게만 건들 수 있게,추가할 거 있으면 콜백함수."
L리스코프 치환 원칙 : 부모 클래스와 자식 클래스가 변경되었을때도 정상적인 값을 출력해야한다.
I인터페이스 분리 원칙 : 사용자가 필요하지않은것들에 의존하지않도록, 작고 구체적으로 유지 "외부에 함수를 조그맣게 만들어버리고 콜백함수로."
D의존성 역전 원칙 : 높은 계층의 모듈이 저수준의 모듈에 직접 의존해서는 안된다.
**/
/** 아키텍쳐 패턴
아키텍처 패턴 = 소프트웨어의 구조를 위한 기본적인 토대.
시스템들과 역할을 정의, 여러 시스템사이의 관계와 규칙 포함
그중 계층형 아키텍처 패턴을 많이 채택하게된다.
계층을 확실하게 나누고, 자신의 바로 아래 계층에만 의존하게 만드는게 목표.
컨트롤러 = 클라이언트의 요청을 받고 응답을 해주는 역할 요청에 들어온 데이터 내용 검증또한 기능
서비스 = API 핵심적인 동작, 비즈니스 로직이 수행되는 부분
저장소 = 데이터베이스 혹은 데이터베이스와 통신하는 부분
**/
/** MOCK
.mockReturnValue() Mock 함수의 반환값 지정
.tobe(value) = .toEqual(value) 근데 투비는 더 엄격함
.toMatch(regexp|string) 입력받은 문자열이 결과값과 같은지
.toBeTruthy() 결과값이 true인지
.toBeInstanceOf(Class) 입력받은 예상값과 Class가 동일한 Instance인지 검증 (error) 검증시에 주로 사용
.toHaveProperty(keyPath, value?) 입력받은 객체의 key와 value가 일치하는지
.toMatchObject(object) 입력받은 객체와 결과 객체가 일치하는지
**/
/** Global Jest
afterAll(fn, timeout) 모든 test()가 완료된 이후에 수행 테스트 완료 이후 변경된 데이터나 mock초기화
afterEach(fn, timeout) 각 test()가 완료된 이후에 수행 MOCK또는 전역변수 초기화
beforeAll(fn, timeout) 테스트코드가 실행되기 전 최초로 수행, db초기화 or 전역MOCK 초기화
beforeEach(fn, timeout) 각 test()가 실행되기 전 수행, 테스트가 실행되기 전 동일한 설정 반복
**/
/** Mock Function
.mock 객체는 특정코드를 실행하지않고, 원하는 부분만 테스트하고싶을때, 실제로 존재하는 값 처럼 사용할 수 있도록 만든 가짜 객체
.toHaveBeenCalledTimes(number) 몇번 호출되었는지 검증
.toHaveBennCalledWith(arg1, arg2, ...) 어떤 인자를 이용해 Mock이 호출되었는지 검사
**/
/**
의존성 주입: 객체사이의 의존 관계를 외부에서 제공
그러니까 간단히 말하자면 Mock test는 나오는 밸류보다, 참조하는 객체가 같으냐, 경로가 같으냐 를 테스트한다고 생각한다.
나오는 value자체를 확인하는 것 은 .toHaveBeenCalledWith method고 그냥 경로가 연결 되어있는가를 확인하는게 .toEqual 혹은 .toBe 이다.
**/