[Type: Refactoring]
[Scope: src/Tizen.Multimedia.Remoting]
[Priority: 🟡 Improvement]
[Lens: Performance, Clean Code, Coding Guidelines]
Observation
ScreenMirroring.SendGenericMouseEvent 가 입력 IEnumerable<UibcMouseInfo> 를 3 번 열거 (.Any() → .Count() → foreach) 하고, 빈 입력에 대해 ArgumentNullException 을 던지는 의미상 잘못된 예외 타입 을 사용합니다. UIBC (User Input Back Channel) 는 미러링 세션 중 사용자 마우스 입력 마다 발생할 수 있어 high-frequency 경로입니다.
Before
// src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroring.cs:504-557
public void SendGenericMouseEvent(IEnumerable<UibcMouseInfo> uibcMouseInfos, ScreenMirroringMouseEventType type)
{
ValidateState(ScreenMirroringState.Connected, ScreenMirroringState.Playing);
if (!uibcMouseInfos.Any()) // ← 열거 #1
{
throw new ArgumentNullException(nameof(uibcMouseInfos)); // ← 타입 오용 (empty != null)
}
var uibcMouseInfosSize = uibcMouseInfos.Count(); // ← 열거 #2
var uibcMouse = new Native.UibcMouse[uibcMouseInfosSize];
int i = 0;
IntPtr unmanagedUibcMousePtr;
foreach (var uibcMouseInfo in uibcMouseInfos) // ← 열거 #3
{
uibcMouse[i].id = uibcMouseInfo.Id;
uibcMouse[i].x = uibcMouseInfo.X;
uibcMouse[i++].y = uibcMouseInfo.Y;
}
// ... marshalling 후 Native call
}
Problem
- 🚀 Performance
IEnumerable<T> 가 deferred (e.g. Select, yield-return 시퀀스) 인 경우 3 회 재실행
Any() / Count() 는 LINQ 디스패치 + 가능 시 ICollection cast 시도 → 박싱은 없으나 가상 호출 비용
null 인풋이면 .Any() 호출에서 NullReferenceException 으로 죽음 (예외 메시지 부정확)
- 🧹 Clean Code — 동일 시퀀스를 3 번 평가, 변수명
uibcMouseInfosSize 가 한 번만 사용 후 폐기
- 📐 Coding Guidelines — 빈 컬렉션 →
ArgumentException 이 옳고 ArgumentNullException 은 null 입력 전용. .NET API 가이드라인의 명백한 위반
Proposed Improvement
한 번 materialize 후 인덱스 기반 루프로 변환. 정확한 예외 타입 사용.
After
public void SendGenericMouseEvent(IEnumerable<UibcMouseInfo> uibcMouseInfos, ScreenMirroringMouseEventType type)
{
ArgumentNullException.ThrowIfNull(uibcMouseInfos);
ValidateState(ScreenMirroringState.Connected, ScreenMirroringState.Playing);
// 한 번만 materialize
var infos = uibcMouseInfos as IReadOnlyList<UibcMouseInfo>
?? uibcMouseInfos.ToArray();
if (infos.Count == 0)
{
throw new ArgumentException("uibcMouseInfos cannot be empty.", nameof(uibcMouseInfos));
}
var uibcMouse = new Native.UibcMouse[infos.Count];
for (int i = 0; i < infos.Count; i++)
{
var info = infos[i];
uibcMouse[i].id = info.Id;
uibcMouse[i].x = info.X;
uibcMouse[i].y = info.Y;
}
// ... marshalling 후 Native call (변경 없음)
}
Target Files
src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroring.cs (L504-L557, 위 발췌 범위만 수정)
Expected Impact (Quantitative Metrics)
- 시퀀스 열거: 3회 → 1회 (deferred IEnumerable 입력 시 절감 효과 가장 큼)
- LINQ 호출:
Any() + Count() 제거 = 가상 호출 2회 절감
null 입력 시 예외 타입: NullReferenceException → ArgumentNullException (정확성)
- 빈 입력 시 예외 타입:
ArgumentNullException → ArgumentException (정확성)
- 잠재적 추가 할당:
IReadOnlyList<T> cast 실패 시 .ToArray() 1회 (현재 Count() 도 enumerable cast 시 동일하게 발생할 수 있음 → 순증가 없음)
API Compatibility Check
- Public API signature change: 없음
- Behavior change:
- 정상 입력 (non-null, non-empty): 동일
null 입력: 던지는 예외가 NullReferenceException → ArgumentNullException (의도된 픽스, breaking 으로 보지 않음 — null 가드 강화)
- 빈 컬렉션:
ArgumentNullException → ArgumentException (의도된 픽스)
- Tizen API Level floor: 유지 (
ArgumentNullException.ThrowIfNull 은 .NET 6+, 본 어셈블리는 이미 그 이상 타겟)
Impact Scope
- 호출 사이트: 메서드 내부 변경만, 외부 호출자 영향 없음 (public API 시그니처/문서화된 예외 의미 유지)
- 1 메서드, 약 15 라인 수정
- public API 문서 (
<exception> 태그) 도 함께 갱신 권장
[Type: Refactoring]
[Scope: src/Tizen.Multimedia.Remoting]
[Priority: 🟡 Improvement]
[Lens: Performance, Clean Code, Coding Guidelines]
Observation
ScreenMirroring.SendGenericMouseEvent가 입력IEnumerable<UibcMouseInfo>를 3 번 열거 (.Any()→.Count()→foreach) 하고, 빈 입력에 대해ArgumentNullException을 던지는 의미상 잘못된 예외 타입 을 사용합니다. UIBC (User Input Back Channel) 는 미러링 세션 중 사용자 마우스 입력 마다 발생할 수 있어 high-frequency 경로입니다.Before
Problem
IEnumerable<T>가 deferred (e.g.Select, yield-return 시퀀스) 인 경우 3 회 재실행Any()/Count()는 LINQ 디스패치 + 가능 시 ICollection cast 시도 → 박싱은 없으나 가상 호출 비용null인풋이면.Any()호출에서NullReferenceException으로 죽음 (예외 메시지 부정확)uibcMouseInfosSize가 한 번만 사용 후 폐기ArgumentException이 옳고ArgumentNullException은null입력 전용. .NET API 가이드라인의 명백한 위반Proposed Improvement
한 번 materialize 후 인덱스 기반 루프로 변환. 정확한 예외 타입 사용.
After
Target Files
src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroring.cs(L504-L557, 위 발췌 범위만 수정)Expected Impact (Quantitative Metrics)
Any()+Count()제거 = 가상 호출 2회 절감null입력 시 예외 타입:NullReferenceException→ArgumentNullException(정확성)ArgumentNullException→ArgumentException(정확성)IReadOnlyList<T>cast 실패 시.ToArray()1회 (현재Count()도 enumerable cast 시 동일하게 발생할 수 있음 → 순증가 없음)API Compatibility Check
null입력: 던지는 예외가NullReferenceException→ArgumentNullException(의도된 픽스, breaking 으로 보지 않음 — null 가드 강화)ArgumentNullException→ArgumentException(의도된 픽스)ArgumentNullException.ThrowIfNull은 .NET 6+, 본 어셈블리는 이미 그 이상 타겟)Impact Scope
<exception>태그) 도 함께 갱신 권장