TDD unit test 공부해보기
Model-View-Controller(MVC) 디자인 패턴은 애플리케이션에서 객체들이 모델(Model), 뷰(View), 혹은 컨트롤러(Controller) 세 가지 역할 중 하나를 부여하는 방식으로 객체들이 서로 통신하는 방법을 정의합니다. 이 패턴은 객체들이 애플리케이션에서 어떤 역할을 수행하는지 뿐만 아니라, 객체들이 서로 통신하는 방식도 정의합니다. 세 가지 유형의 객체 각각은 추상적인 경계로 구분되어 있으며, 다른 유형의 객체와 이 경계를 통해 통신합니다. 애플리케이션에서 MVC 유형의 객체 모음은 때로 모델 레이어(Model Layer)와 같은 용어로 참조됩니다.
MVC는 Cocoa 애플리케이션에 대한 좋은 디자인의 중추입니다. 이 패턴을 채택하는 것의 이점은 많습니다. 이러한 애플리케이션의 많은 객체들은 재사용성이 높아지며, 그들의 인터페이스는 보다 명확해집니다. MVC 디자인을 갖는 애플리케이션은 다른 애플리케이션보다 확장성이 더 높습니다. 게다가, 많은 Cocoa 기술과 아키텍처가 MVC에 기반하며, 사용자 지정 객체가 MVC 역할 중 하나를 수행해야 합니다.
모델 객체는 애플리케이션에 특화된 데이터를 캡슐화하며 해당 데이터를 조작하고 처리하는 로직과 계산을 정의합니다. 예를 들어, 모델 객체는 게임에서 캐릭터나 주소록에서 연락처를 나타낼 수 있습니다. 모델 객체는 다른 모델 객체와 일대일 및 일대다 관계를 가질 수 있으며, 때로는 애플리케이션의 모델 계층이 사실상 하나 이상의 객체 그래프가 됩니다. 애플리케이션의 지속적인 상태의 일부인 데이터(이 지속적인 상태가 파일이나 데이터베이스에 저장되는 경우) 중 상당 부분은 애플리케이션이 로드된 후 모델 객체에 머무르는 것이 좋습니다. 모델 객체는 특정 문제 영역과 관련된 지식과 전문성을 나타내므로, 유사한 문제 영역에서 재사용할 수 있습니다. 이상적으로, 모델 객체는 데이터를 제공하고 사용자가 해당 데이터를 편집하는 뷰 객체와 명시적으로 연결되지 않아야 하며, 사용자 인터페이스와 표현 문제에 대해 관심을 가지지 않아야 합니다.
통신: 뷰 계층에서 사용자 동작으로 데이터를 생성하거나 수정하면, 컨트롤러 객체를 통해 모델 객체가 생성 또는 업데이트되고, 모델 객체가 변경되면(예를 들어 네트워크 연결을 통해 새로운 데이터를 받은 경우) 컨트롤러 객체에게 알립니다. 그런 다음 컨트롤러 객체가 적절한 뷰 객체를 업데이트합니다.
뷰 객체는 사용자가 볼 수 있는 애플리케이션 객체입니다. 뷰 객체는 스스로 그리는 방법을 알고 사용자 동작에 응답할 수 있습니다. 뷰 객체의 주요 목적 중 하나는 애플리케이션의 모델 객체에서 데이터를 표시하고 해당 데이터를 편집할 수 있도록 하는 것입니다. 그러나 일반적으로 MVC 애플리케이션에서 뷰 객체는 모델 객체와 분리됩니다.
보통 재사용하고 다시 구성하기 때문에 뷰 객체는 애플리케이션 간 일관성을 제공합니다. UIKit 및 AppKit 프레임워크는 뷰 클래스의 컬렉션을 제공하며, Interface Builder는 라이브러리에서 수십 개의 뷰 객체를 제공합니다.
통신: 뷰 객체는 응용 프로그램의 컨트롤러 객체를 통해 모델 데이터의 변경 사항을 학습하고, 사용자가 시작한 변경 사항 (예 : 텍스트 필드에 입력된 텍스트)을 컨트롤러 객체를 통해 애플리케이션의 모델 객체로 전달합니다.
컨트롤러 객체는 애플리케이션의 하나 이상의 뷰 객체와 모델 객체 간의 중개자 역할을 합니다. 컨트롤러 객체는 뷰 객체가 모델 객체의 변경 사항을 알게 하고 그 반대로도 중개합니다. 컨트롤러 객체는 또한 애플리케이션의 설정 및 조정 작업, 다른 객체들의 수명주기 관리를 수행할 수 있습니다.
통신: 컨트롤러 객체는 뷰 객체에서 발생하는 사용자 작업을 해석하고 모델 레이어에 새로운 또는 변경된 데이터를 전달합니다. 모델 객체가 변경되면 컨트롤러 객체는 해당 새로운 모델 데이터를 뷰 객체에게 전달하여 화면에 표시할 수 있도록 합니다.
https://developer.apple.com/documentation/swift/choosing-between-structures-and-classes
Heap 영역에 저장된다.
Heap 영역에 저장된 데이터들은 모두 컴파일 타임이 아닌 런타임에 크기가 결정된다.
즉, 런타임에 추가적인 연산이 이루어 진다.
또한 한 프로세스의 스레드들이 함께 공유하는 영역이기 떄문에 Thread-Safe를 보장하지 않는다.
=== 을 통해 두 참조 타입을 비교할 수 있다.
(두 인스턴스의 모든 프로퍼티가 같은지 비교)
참조타입은 하나의 데이터를 공유하기때문에 앱의 여러 곳에서 사용 시 한 영역에서 수정한 값이 다른 곳에서도 적용된다.
Objectice-C 에서 지원하는 API를 사용할 때는 Objectice-C 의 클래스를 상속받아서 사용해야 하기 때문에,
이런 경우에도 클래스를 사용한다.
Stack 영역에 저장된다.
Stack 영역은 각 스레드가 독립적으로 사용하기 때문에 Thread-Safe 하다.
스택 포인터만 이동시키면 되기 떄문에 한 번의 명령으로 할당과 해제가 가능하다.
컴파일 타임에 할당할 크기가 결정되기 떄문에 메모리를 따로 관리해주지 않아도된다.
즉, 새로 데이터를 할당할 영역을 따로 계산하지 않아도된다는 뜻이다.
== 을 통해 두 값 타입을 비교할 수 있다.
(두 인스턴스가 같은 메모리 주소를 참조하고 있는지 비교)
값타입은 항상 유니크하고 복제된 인스턴스를 가지고 있기때문에,
해당 데이터가 앱의 다른 부분에서 변경될 일이 없다.
그렇기 때문에 multi-threaded 환경에서 다른 스레드가 데이터를 바꿀 격정이 없다.
Thread-Safe란 여러 스레드가 동시에 하나의 자원 또는 데이터를 접근해도 안전하게 처리할 수 있는 상태를 말합니다. 즉, 다중 스레드 환경에서 하나의 자원을 여러 스레드가 공유하여 접근할 때, 이를 안전하게 사용할 수 있는 상태를 말합니다.
예를 들어, 한 스레드에서 데이터를 수정하는 중에 다른 스레드에서 동시에 같은 데이터에 접근하면 데이터의 일관성이 깨져버리거나 예상치 못한 결과가 발생할 수 있습니다. 이를 방지하기 위해 Thread-Safe한 코드를 작성해야 합니다.
Thread-Safe한 코드를 작성하는 방법은 여러 가지가 있지만, 일반적으로는 다음과 같은 방법들이 사용됩니다.
Thread-Safe한 코드를 작성함으로써, 다중 스레드 환경에서 안전하게 자원을 공유하고, 예기치 않은 버그와 문제를 방지할 수 있습니다.
static 키워드를 사용하면 타입 멤버를 인스턴스 멤버 대신 타입 자체에 속한 멤버로 만들 수 있습니다
일반적으로 멤버 변수(Member Variable)와 프로퍼티(Property)는 비슷한 의미로 사용됩니다.
static 멤버함수를 통해 static private 접근 가능
class ExampleClass {
static private var privateVariable = 0
static var publicVariable = 0
static func incrementPrivateVariable() {
privateVariable += 1
}
static func incrementPublicVariable() {
publicVariable += 1
}
static func getPrivateVariable() -> Int {
return privateVariable
}
}
ExampleClass.incrementPrivateVariable()
ExampleClass.incrementPublicVariable()
print(ExampleClass.getPrivateVariable()) // 출력 결과: 1
print(ExampleClass.publicVariable) // 출력 결과: 1