LogoSkills

code-review-checklist Reference

Detailed checklists and review criteria by category.

Code Review Reference Guide#

Detailed checklists and review criteria by category.


1. Architecture#

Clean Architecture Review#

ItemReview CriteriaSeverity
Layer separationDomain โ†’ Data โ†’ Presentation dependency direction๐Ÿ”ด
UseCase usageBusiness logic accessed through UseCases๐Ÿ”ด
Repository interfaceI prefix, defined in Domain layer๐ŸŸก
Entity immutability @immutable + Equatable, copyWith, immutable fields ๐ŸŸก

Feature Module Independence#

// โœ… Correct dependency
import 'package:core/core.dart';
import 'package:feature_common_auth/auth.dart';

// โŒ Incorrect dependency (direct reference to another application feature)
import 'package:feature_application_home/home.dart';

Checklist#

  • Domain โ†’ Data โ†’ Presentation dependency direction followed
  • Business logic accessed through UseCases
  • Repository interface separation (I prefix)
  • No direct dependencies between feature modules
  • Shared code separated into common or core
  • No over-abstraction

2. State Management#

BLoC Pattern Review#

ItemReview CriteriaSeverity
Event/State definition sealed class extends Equatable + const factory sub-states ๐ŸŸก
State immutabilitycopyWith used, no direct mutation๐Ÿ”ด
Error handlingEither pattern, Failure class๐ŸŸก
Resource cleanupSubscriptions cancelled in close()๐Ÿ”ด

State Definition Pattern#

// โœ… Correct status definition (sealed class + Equatable, no codegen)
@immutable
sealed class HomeStatus extends Equatable {
  const HomeStatus();

  const factory HomeStatus.initial() = HomeInitial;
  const factory HomeStatus.loading() = HomeLoading;
  const factory HomeStatus.loaded(User user) = HomeLoaded;
  const factory HomeStatus.error(Failure failure) = HomeError;

  @override
  List<Object?> get props => const [];
}

// โœ… State class: immutable fields + copyWith + Equatable props
@immutable
final class HomeState extends Equatable {
  const HomeState({this.status = const HomeStatus.initial()});

  final HomeStatus status;

  HomeState copyWith({HomeStatus? status}) =>
      HomeState(status: status ?? this.status);

  @override
  List<Object?> get props => [status];
}

// โŒ Incorrect: mutable, ad-hoc flags, no Equatable/copyWith
class HomeState {
  bool isLoading = false;
  User? user;
  String? error;
}

kobic does NOT use @freezed. State/Event are plain sealed class ... extends Equatable with const factory sub-states and copyWith โ€” no *.freezed.dart codegen.

Fire-and-Forget Error Handling (unawaited() + Error)#

Dart's Error (TypeError, StateError, NoSuchMethodError, JsonUnsupportedObjectError, ...) does not extend Exception, but most catch blocks conventionally use on Exception catch only. Behind a normal awaited call this is harmless โ€” an uncaught Error propagates and surfaces as a crash/log. Behind unawaited(fn()) (fire-and-forget), a missed Error becomes an exception no code path observes; whether it also surfaces as a crash/log elsewhere depends on the execution zone (plain Dart isolate vs. a Flutter app's guarded zone) โ€” but regardless, the specific consumer waiting on the result (BLoC/Cubit state, a ValueNotifier/useState-gated button or spinner, a StreamController) hangs forever โ€” infinite loading spinner, permanently disabled button, dialog that never closes.

// โŒ Error thrown inside disappears completely โ€” consumer hangs forever
unawaited(_revalidate(query, controller));

Future<void> _revalidate(...) async {
  try {
    await saveToCache(...);   // may throw a JsonUnsupportedObjectError / TypeError (an Error, not Exception)
  } on Exception catch (e, st) {   // โŒ Error passes straight through
    Log.e('failed', error: e, stackTrace: st);
  }
}

// โœ… on Object catches both Exception and Error
} on Object catch (e, st) {
  Log.e('failed', error: e, stackTrace: st);
}

Real case: kobic #7746 (SwrStrategyImpl._revalidate, see [cc-flutter-dev:swr-pattern] ยง16). A codebase-wide audit of unawaited( call sites found 11 confirmed reproductions of this pattern โ€” see [cc-dev-cycle:discovery-audit] for the triageโ†’verify audit workflow.

Checklist#

  • Event/State are sealed class extends Equatable (no @freezed)
  • State branching with const factory sub-states + final class implementations
  • Proper error handling
  • Loading state management
  • Resources released in dispose
  • Global/local state properly distinguished
  • Any new unawaited(fn()) call: fn()'s full call chain catches Error, not just Exception (see above)

3. Security#

Sensitive Information Review#

ItemReview CriteriaSeverity
Hardcoded secretsAPI keys, tokens exposed๐Ÿ”ด
Log outputSensitive information logged๐Ÿ”ด
Environment variablesEnvied used๐ŸŸก

Input Validation#

// โœ… Correct validation
if (!EmailValidator.validate(email)) {
  return left(ValidationFailure('Invalid email'));
}

// โŒ Direct use without validation
final user = await api.login(email, password);

Checklist#

  • No hardcoded API keys or secrets
  • No sensitive information in logs
  • User input sanitization
  • SQL Injection, XSS prevention
  • Protected endpoint access control
  • Proper token management

4. Performance#

Rebuild Optimization#

ItemReview CriteriaSeverity
const widgetsconst used where possible๐ŸŸก
buildWhenBlocBuilder condition specified๐ŸŸก
BlocSelectorRefined state subscription๐ŸŸข

Image Optimization#

// โœ… Correct image handling
CachedNetworkImage(
  imageUrl: url,
  cacheWidth: 200,
  cacheHeight: 200,
)

// โŒ Cache size not specified
Image.network(url)

Checklist#

  • const widgets utilized
  • BlocBuilder buildWhen used
  • Refined with BlocSelector
  • Image cacheWidth/cacheHeight applied
  • Parallelizable tasks parallelized
  • debounce/throttle applied
  • Resources released in dispose
  • Stream subscriptions cancelled

5. Testing#

Test Coverage#

ItemReview CriteriaSeverity
UseCase testsUnit tests required๐Ÿ”ด
Repository testsMocked data source๐ŸŸก
BLoC testsState transition verification๐ŸŸก
Widget testsKey UI components๐ŸŸข

Test Pattern#

// โœ… Correct test pattern (AAA)
test('should return user when repository succeeds', () async {
  // Arrange
  when(() => mockRepository.getUser(any()))
    .thenAnswer((_) async => Right(testUser));

  // Act
  final result = await useCase(GetUserParams(id: 1));

  // Assert
  expect(result, Right(testUser));
  verify(() => mockRepository.getUser(1)).called(1);
});

Checklist#

  • UseCase unit tests
  • Repository tests (mocked)
  • BLoC tests
  • Meaningful test cases
  • Edge cases covered
  • Arrange-Act-Assert pattern
  • External dependencies isolated

6. Readability#

Naming Convention#

ItemRuleExample
ClassesPascalCaseUserRepository
Variables/FunctionscamelCasegetUserData()
ConstantsSCREAMING_SNAKEMAX_RETRY_COUNT
Filessnake_caseuser_repository.dart

Code Structure#

// โœ… Single Responsibility Principle
class UserRepository implements IUserRepository {
  // User-related logic only
}

// โŒ Multiple responsibilities mixed
class UserRepository {
  void getUser() {}
  void sendEmail() {}  // Email should be a separate service
  void generateReport() {}  // Report should be separate too
}

Checklist#

  • Clear and meaningful names
  • Project convention followed
  • Abbreviation usage minimized
  • Appropriate file/class size
  • Single Responsibility Principle
  • Duplicate code removed
  • No unnecessary comments
  • Explanatory comments on complex logic

7. Internationalization (i18n)#

Translation Key Usage#

// โœ… Correct usage
Text(context.t.common.save)
Text(context.t.user.greeting(name: user.name))

// โŒ Hardcoded
Text('Save')
Text('Hello, ${user.name}!')

Checklist#

  • All UI text uses translation keys
  • context.t.* pattern used
  • Proper pluralization
  • Dynamic values parameterized
  • RTL support (if needed)

8. Accessibility#

Semantics Applied#

// โœ… Correct application
Semantics(
  label: 'Add to cart',
  button: true,
  child: IconButton(
    icon: Icon(Icons.add_shopping_cart),
    onPressed: addToCart,
  ),
)

// โŒ No Semantics
IconButton(
  icon: Icon(Icons.add_shopping_cart),
  onPressed: addToCart,
)

Checklist#

  • Appropriate semantic labels
  • Screen reader support
  • Minimum 48x48 touch target
  • WCAG color contrast criteria met
  • Information not conveyed by color alone

Automation Tools#

Static Analysis#

# Full analysis
melos run analyze

# Combined lint check (format-check โ†’ dart analyze โ†’ dcm analyze)
melos run lint:check

# Formatting (kobic uses dcm format, not dart format)
melos run format
# Underlying command: dcm format .

Testing#

# Full test suite
melos run test

# Coverage report
melos run test:with-html-coverage