목록전체 글 (244)
방프리
Item 24 : 설계 선택지를 제한하는 ICloneable은 사용을 피하라 복사를 지원해야하는 타입에서 ICloneable은 좋은 선택지이다. 하지만 해당 타입이 상속 계통상에 있는 타입이라면? 조금 사용하는 것에 있어서 고려를 해보아야 한다. 타입의 멤버가 값타입이라면 ICloneable을 지원할 필요가 없다. ICloneable에 있는 Clone()은 object 형태이기 때문에 박싱 언박싱으로 인해 연산량이 더 오래 걸려 굳이 사용할 필요가 없다. 하지만 string과 같은 참조 타입이 있을 경우 Clone()을 사용하게 되는데 이때에도 깊은 복사를 지원하는지 살펴볼 필요가 있다. 만약 파생 계층에 있는 타입에서 ICloneable을 지원하게 한다면 모든 파생 클래스들에서 Clone()을 구현해야..
Item 23 : 생성자, 변경자, 이벤트 핸들러를 위해 partial 클래스와 메서드를 제공하라 C#에서는 UI와 코드를 분리하기 위해서 partial이라는 키워드를 생성했다. 이로인해 디자이너와 개발자의 영역을 확실히 구분되었다. (각 부분에서 문제가 생기면 자기가 맡은 영역만 확인) C# 3.0 버전에서는 기본 partial에서 새로운 기능을 추가하였는데 바로 partial 메서드이다. 간단히 설명하자면 기본 partial 클래스의 역할에서 조금 더 세분화되어 구현영역과 선언영역을 분리했다고 보면 좋을 것 같다. (처음 예제를 보고 C++의 .h 와 .cpp 의 구조를 보는 듯 했다.) 대신 struct, class, interface와 달리 partial method를 선언할 때에는 약간의 제약이..
1. async 메서드의 단위 테스트 //단위 테스트 프레임워크가 async Task를 지원한다면 [TestMethod] public async Task MyMethodAsync_ReturnsFalse() { var objectUnderTest = ...; bool result = await objectUnderTest.MyMethodAsync(); Assert.IsFalse(result); } //async Task를 지원하지 않는다면, Nito.AsyncEx Nuget 패키지 사용해볼 것 [TestMethod] public void MyMethodAsync_ReturnsFalse() { AsyncContext.Run(async () => { var objectUnderTest = ...; bool r..
Item 22 : 명확하고 간결하며 완결된 메서드 그룹을 생성하라 API를 구성할 때 유의해야할 점이 사용하는 사람이 보았을 때 혼동이 있어서는 안된다. 명확하고 사용자가 API를 사용함으로써 실수를 줄일 수 있는 몇 가지 방법이 있다. 1. 적은 양의 오버로드 함수 - 오버로드된 함수를 만드는 것은 좋으나, 그 개수가 많아진다면 사용자 측면에서 혼동이 일어날 수 있다. 나중에는 각 함수 별 각주를 달거나 사용자가 해당 API를 사용할 때마다 기능을 확인해야 하는 경우가 발생할 수 있으니 무분별한 오버로드 함수는 좋지 않다. 2. 동일 명에 동일 동작이 원칙 - 같은 메서드 명이라면 그 안에서 동작하는 행위는 무조건 같아야 한다. 다를 경우 사용자 측면에서 구분하기 어렵고 사용 시 예측 불가능한 동작이 ..
1. 닷넷 이벤트 변환 - FromEventPattern을 통해 범용적인 이벤트를 사용 - EventPattern을 선언할 때 강력하게 할 것인가? 혹은 강력한 데이터를 포기할 것인가 //강력한 데이터를 가져올 때 var timer = new System.Timers.Timer(interval: 1000) { Enabled = true }; IObservable ticks = Observable.FromEventPattern( handler => (s, a) => handler(s, a), handler => timer.Elapsed += handler, handler => timer.Elapsed -= handler); ticks.Subscribe(data => Console.WriteLine("OnN..
1. 블록 연결 var multiplyBlock = new TransformBlock(item => item * 2); var subtractBlock = new TransformBlock(item => item - 2); //PropagateCompletion 옵션을 통해 연결 대상의 완료 및 오류 알림 여부 확인 var options = new DataflowLinkOptions { PropagateCompletion = true }; multiplyBlock.LinkTo(subtractBlock, options); ... //첫 번째 블록의 완료를 자동으로 두 번째 블록에 전파한다. multiplyBlock.Complete(); await subtractBlock.Completion; 2. 오류 전..
1. 데이터의 병렬처리 - 병렬로 여러 데이터를 반복문을 통해 처리할 때 - 만약 공유하는 변수 혹은 리소스가 있다면 잠금(lock)을 사용해보는 것도 좋다. - 책에서는 ForEach 위주로 설명하였지만 순차처리를 목적으로 한다면 ForEachAsync도 고려해볼만 하다. void RotateMatrices(IEnumerable matrices, float degrees, CancellationToken token) { Parallel.ForEach(matrices, new ParallelOptions { CancellationToken = token }, matrix => matrix.Rotate(degress)); } 2. 병렬 집계 - 병렬 작업이 끝난 후 결과를 집계할 때 int Parallel..
1. 비동기 스트림 생성 - yield return을 사용해서 반환 - 비동기 스트림은 내부적으로 ValueTask를 사용, 취소해야할 경우 CancellationToken을 사용하여 취소 async IAsyncEnumerable GetValuesAsync(HttpClient client) { var offset = 0; const int limit = 10; while (true) { var result = await client.GetStringAsync( $"https://example.com/api/values?offset={offset}&limit={limit}"); string[] valuesOnThisPage = result.Split('\n'); foreach (string value in..