Skill: Code Quality Audit
Last Verified: 2026-01-23 Applicable SDK: Android 14+ (API 34+) Dependencies: best-practice-check, codebase-aware-implementation
Purpose
After completing a development phase, perform a comprehensive code quality audit focusing on production code (excluding test files). This skill provides a systematic approach to identify technical debt, architectural issues, and potential bugs before they become problems.
When to Use
- •After completing a major feature or development milestone
- •Before releasing a new version
- •When preparing for code review or handoff
- •When technical debt needs assessment
- •Periodically (e.g., monthly) for ongoing projects
Audit Dimensions
1. File Structure & Organization (Project Structure)
Objective: Ensure logical, maintainable project organization
Check Points:
- • Files are in correct packages matching their purpose
- • Package naming follows conventions (
feature,ui,data,domain, etc.) - • No orphaned files in wrong locations
- • Resource files properly organized by type and qualifier
- • Clear separation between layers (presentation, domain, data)
- • Consistent naming conventions across packages
Commands to Run:
# List all Kotlin/Java files with their packages
find ./app/src/main -type f \( -name "*.kt" -o -name "*.java" \) -exec head -1 {} \; -print
# Find files that might be misplaced (e.g., Activities not in ui package)
grep_search for class definitions and check package declarations
Review Questions:
- •Does each package have a clear, single responsibility?
- •Are feature modules properly isolated?
- •Should any files be moved to better reflect their purpose?
- •Is the resource organization intuitive?
2. Code Hygiene (Code Cleanliness)
Objective: Remove clutter and ensure code quality standards
Check Points:
- • No commented-out code blocks (use version control instead)
- • No TODO/FIXME comments older than current sprint
- • No hardcoded strings (should be in
strings.xml) - • No hardcoded colors (should be in
colors.xmlor theme) - • No hardcoded dimensions (should be in
dimens.xml) - • No magic numbers (extract to constants)
- • No unused imports
- • No unused resources (layouts, drawables, strings)
- • Consistent code formatting
- • Meaningful variable/function names matching project conventions
- • No debug logs left in production code
- • No temporary files (
.tmp, backup files)
Commands to Run:
# Find hardcoded strings in Kotlin files grep_search for string literals in .kt files (exclude test files) # Find TODO/FIXME comments grep_search for "TODO" and "FIXME" in source files # Find commented code blocks grep_search for "//.*fun " or "//.*val " patterns # Find debug logs grep_search for "Log.d", "Log.v", "println" in source files # Check for unused resources (use Android Lint) ./gradlew lint
Review Questions:
- •Are all string resources properly named and organized?
- •Do constant names follow UPPER_SNAKE_CASE convention?
- •Are dimension values semantic (e.g.,
button_heightnotsize_48dp)? - •Is there dead code that can be removed?
3. Separation of Concerns (Architecture)
Objective: Ensure proper layering and responsibility distribution
Check Points:
- • No business logic in Activities/Fragments
- • No direct database/network calls in UI layer
- • ViewModels don't hold Context references
- • Custom Views handle only rendering, not business logic
- • Repositories abstract data sources properly
- • Use cases/interactors contain reusable business logic
- • No God classes (classes doing too much)
- • Proper dependency injection (not manual instantiation)
- • Clear data flow (UI → ViewModel → Repository → DataSource)
Commands to Run:
# Find Activities/Fragments with potential business logic view_file_outline for each Activity/Fragment and check method complexity # Find ViewModels holding Context grep_search for "Context" in ViewModel files # Find large classes (potential God classes) # Check line counts and method counts per class
Review Questions:
- •Can each class be described in one sentence?
- •Are responsibilities clearly separated between layers?
- •Would a new developer understand the architecture from file organization?
- •Are there any circular dependencies?
- •Is dependency injection used consistently?
Red Flags:
- •Activities/Fragments > 300 lines
- •Methods > 50 lines
- •Classes with > 10 dependencies
- •Direct use of
Contextin non-UI classes - •Database queries in ViewModels
- •Network calls in UI layer
4. Performance & Memory (Critical Issues)
Objective: Identify memory leaks and performance bottlenecks
Check Points:
Memory Leaks
- • No Activity/Fragment references held in static fields
- • No Context leaks in singletons
- • Listeners/callbacks properly unregistered
- • Coroutines properly scoped (viewModelScope, lifecycleScope)
- • Handlers use WeakReference or are cleared
- • No anonymous inner classes holding implicit references
- • Bitmaps properly recycled (if not using modern libraries)
- • Streams/Cursors/Files properly closed (use
use {})
Performance Issues
- • No blocking operations on main thread
- • Database queries use proper indexing
- • RecyclerView ViewHolders properly recycled
- • Images loaded with appropriate libraries (Glide/Coil)
- • No N+1 query problems
- • Proper use of
lazyfor expensive initializations - • No unnecessary object allocations in loops
- • Custom View
onDraw()has zero allocations
Commands to Run:
# Find static Context references
grep_search for "companion object.*Context" or "static.*Context"
# Find Handler usage without WeakReference
grep_search for "Handler(" in source files
# Find potential main thread blocking
grep_search for "Thread.sleep", ".get()" on futures, blocking IO
# Find unclosed resources
grep_search for "FileInputStream", "Cursor", "InputStream" without ".use"
# Find allocations in onDraw
view_code_item for custom Views and check onDraw methods
Review Questions:
- •Are all lifecycle-aware components properly scoped?
- •Are background operations using coroutines or WorkManager?
- •Is image loading optimized with caching?
- •Are there any potential ANR (Application Not Responding) risks?
Critical Patterns to Check:
// ❌ BAD: Context leak
companion object {
lateinit var context: Context
}
// ✅ GOOD: Application context if needed
companion object {
lateinit var appContext: Application
}
// ❌ BAD: Listener not unregistered
class MyFragment : Fragment() {
override fun onViewCreated(...) {
someManager.addListener(this)
}
}
// ✅ GOOD: Proper cleanup
class MyFragment : Fragment() {
override fun onViewCreated(...) {
someManager.addListener(this)
}
override fun onDestroyView() {
someManager.removeListener(this)
super.onDestroyView()
}
}
// ❌ BAD: Allocation in onDraw
override fun onDraw(canvas: Canvas) {
val paint = Paint() // Creates new object every frame!
canvas.drawCircle(x, y, radius, paint)
}
// ✅ GOOD: Reuse objects
private val paint = Paint()
override fun onDraw(canvas: Canvas) {
canvas.drawCircle(x, y, radius, paint)
}
Execution Workflow
Step 1: Preparation
- •Ensure all code is committed to version control
- •Run a clean build:
./gradlew clean build - •Run lint:
./gradlew lintand review the report - •Note current project state (branch, last commit)
Step 2: Automated Checks
Run these commands and collect output:
# Find all production source files
find ./app/src/main -type f -name "*.kt" | grep -v Test
# Check for common issues
grep -r "TODO" app/src/main --include="*.kt"
grep -r "FIXME" app/src/main --include="*.kt"
grep -r "Log\.[dv]" app/src/main --include="*.kt"
grep -r "println" app/src/main --include="*.kt"
# Find large files (potential refactoring candidates)
find ./app/src/main -name "*.kt" -exec wc -l {} \; | sort -rn | head -20
# Check for unused resources (requires Android Studio or gradlew)
./gradlew lint
Step 3: Manual Review
For each dimension (1-4 above):
- •Review check points systematically
- •Use
view_file_outlineto understand class structure - •Use
view_code_itemto examine specific methods - •Use
grep_searchto find patterns - •Document findings with file names and line numbers
Step 4: Generate Report
Create a markdown report with:
# Code Quality Audit Report **Date**: [Current Date] **Commit**: [Git commit hash] **Auditor**: [Your name or "AI Assistant"] ## Executive Summary [Brief overview of findings] ## 1. File Structure & Organization ### Issues Found - [ ] **[Severity]** `path/to/File.kt` - [Description] - **Line**: [Line number if applicable] - **Suggestion**: [How to fix] ## 2. Code Hygiene ### Issues Found - [ ] **[Severity]** `path/to/File.kt:123` - [Description] - **Suggestion**: [How to fix] ## 3. Separation of Concerns ### Issues Found - [ ] **[Severity]** `path/to/File.kt:45-67` - [Description] - **Suggestion**: [How to fix] ## 4. Performance & Memory ### Critical Issues - [ ] **HIGH** `path/to/File.kt:89` - [Memory leak description] - **Risk**: [Explain the risk] - **Fix**: [How to fix] ### Performance Issues - [ ] **MEDIUM** `path/to/File.kt:123` - [Performance issue] - **Impact**: [Explain impact] - **Fix**: [How to fix] ## Recommendations 1. [Priority 1 recommendation] 2. [Priority 2 recommendation] ... ## Metrics - Total files reviewed: X - Issues found: Y - Critical issues: Z - Estimated effort: [hours/days]
Step 5: Prioritization
Categorize findings by severity:
- •CRITICAL: Memory leaks, crashes, security issues
- •HIGH: Performance problems, architectural violations
- •MEDIUM: Code hygiene, minor refactoring
- •LOW: Naming conventions, formatting
Output Format
For each issue found, provide:
- •Severity: CRITICAL | HIGH | MEDIUM | LOW
- •Category: Structure | Hygiene | Architecture | Performance
- •File: Full path to the file
- •Line(s): Specific line numbers
- •Issue: Clear description of the problem
- •Impact: Why this matters
- •Suggestion: Concrete fix with code example if applicable
Example:
❌ **HIGH** - Performance & Memory
📁 `app/src/main/java/com/example/ui/MainActivity.kt:45-52`
🔍 **Issue**: Coroutine launched with GlobalScope instead of lifecycleScope
💥 **Impact**: Potential memory leak - coroutine continues after Activity destroyed
✅ **Fix**: Replace `GlobalScope.launch` with `lifecycleScope.launch`
// Before
GlobalScope.launch {
repository.loadData()
}
// After
lifecycleScope.launch {
repository.loadData()
}
Best Practices
- •Exclude Test Files: Use grep/find patterns to exclude
*Test.kt,androidTest/,test/ - •Focus on Impact: Prioritize issues that affect users or stability
- •Be Specific: Always provide file paths and line numbers
- •Provide Examples: Show before/after code for fixes
- •Consider Context: Some patterns are acceptable in specific contexts
- •Batch Similar Issues: Group similar issues together for efficiency
- •Verify Suggestions: Ensure suggested fixes are compatible with project architecture
Tools Integration
Android Lint
./gradlew lint # Review: app/build/reports/lint-results.html
Detekt (if configured)
./gradlew detekt
Manual Inspection Tools
- •
view_file_outline: Get class structure overview - •
view_code_item: Examine specific methods - •
grep_search: Find patterns across codebase - •
find_by_name: Locate files by name/pattern
Common Anti-Patterns to Check
Android-Specific
- •Context Leaks: Static references, singletons holding Activity context
- •Lifecycle Violations: Operations after lifecycle destroyed
- •Main Thread Blocking: Network/DB on UI thread
- •Resource Leaks: Unclosed Cursors, Streams, Bitmaps
- •Memory Churn: Allocations in
onDraw(),onMeasure()
General Code Quality
- •God Classes: Classes > 500 lines or > 20 methods
- •Long Methods: Methods > 50 lines
- •Deep Nesting: > 3 levels of indentation
- •Magic Numbers: Unexplained numeric literals
- •Hardcoded Values: Strings, colors, dimensions in code
- •Dead Code: Unused methods, classes, resources
- •Inconsistent Naming: Mixed conventions in same project
Exclusions
Do NOT audit:
- •Test files (
*Test.kt,androidTest/,test/) - •Generated code (
build/,.gradle/) - •Third-party libraries (
libs/) - •Gradle configuration (unless specifically requested)
- •Documentation files (unless checking for outdated info)
Success Criteria
A successful audit should:
- •✅ Cover all production source files
- •✅ Identify critical issues (memory leaks, crashes)
- •✅ Provide actionable, specific suggestions
- •✅ Include file paths and line numbers
- •✅ Prioritize findings by severity
- •✅ Estimate effort required for fixes
- •✅ Be delivered in clear, structured format
Follow-Up Actions
After audit completion:
- •Create GitHub issues or task tickets for each finding
- •Prioritize fixes in upcoming sprints
- •Address CRITICAL issues immediately
- •Schedule refactoring for HIGH/MEDIUM issues
- •Consider adding lint rules to prevent recurrence
- •Update coding guidelines based on findings
- •Schedule next audit (recommend: after each major feature)