---
title: 'SmellCC: LLM-Based Code Smell Cleaner'
url: https://www.emergentmind.com/topics/smellcc
type: topic
---

# SmellCC: LLM-Based Code Smell Cleaner

SmellCC, short for **Smell Code Cleaner**, is an **LLM‑based automatic refactoring tool** whose goal is to **detect and remove code smells in a large training corpus**, and thereby curate a **smell‑cleaned dataset** for training and fine‑tuning code LLMs. In the reported implementation, SmellCC uses **SonarQube** smell reports over **CodeSearchNet‑Python** and **DeepSeek‑Coder‑V2** to refactor code, with the stated aim of preserving behavior as much as possible through static re‑analysis and test‑based validation. It is presented both as a concrete tool and as a methodological scaffold for studying how **training data quality in terms of code smells** affects the smells in generated code and downstream performance on code completion and code search [2508.11958].

## 1. Research setting and motivation

SmellCC is situated in the broader software‑engineering view that **code smells are poor design or implementation practices that are not bugs but are violations of design/construction principles that hurt maintainability, readability, and may lead to technical debt, performance or security issues later**. Earlier work had already linked smells to maintainability, technical debt, and detection subjectivity, while also showing that smells are not equally actionable and are not uniformly surfaced in review practice [2012.12590] [2103.01861] [2103.11446].

The immediate motivation for SmellCC is empirical. In the **CodeSearchNet‑Python** slice of approximately **450K Python functions**, SonarQube detects **203,180** smell instances across **10 smell types**. These smell types are **Commented Code** (10,509), **Naming Convention** (133,323), **Empty Nested Code Blocks** (2,446), **Collapsible if Statements** (8,631), **Long Parameter List** (12,967), **High Cognitive Complexity** (33,926), **Dead Code** (458), **Self‑assigned Variables** (458), **Identical Expressions** (267), and **Return and Yield** (195) [2508.11958].

The same study reports that smell issues are not confined to training data. When **DeepSeek‑Coder**, **CodeLlama**, and **MagiCoder** each generate **1,000 Python functions** from CodeSearchNet descriptions, SonarQube again finds many smells, notably **Naming Convention**, **High Cognitive Complexity**, **Long Parameter List**, and **Collapsible if**. A companion user study with **10 senior developers** found that **83.3% of smell‑free snippets are accepted as‑is**, **76.7% of smelly snippets are marked for refactoring**, and **71% prefer to use LLMs for complex smells** such as high cognitive complexity. This combination of dataset contamination, output contamination, and human preference for smell‑free code provides the immediate rationale for automated smell cleaning before fine‑tuning [2508.11958].

## 2. System architecture and workflow

SmellCC is embedded in a five‑stage workflow. The first stage is **preliminary analysis**, used to quantify smells in **CodeSearchNet‑Python** and in the outputs of several code LLMs. The second stage is SmellCC itself: it takes CodeSearchNet‑Python methods, uses **SonarQube** to detect smells, applies **DeepSeek‑Coder‑V2** with smell‑specific prompts to refactor each smell instance, and produces a **smell‑cleaned version of CodeSearchNet‑Python**. The third stage is **correctness verification** on a curated **50‑repository** subset with executable tests. The fourth stage fine‑tunes code LLMs on the original versus smell‑cleaned corpora and evaluates smell rate, code completion, and code search. The fifth stage is the user study and implications [2508.11958].

Smell detection itself is **rule‑based**. SmellCC **does not detect smells**; it consumes SonarQube’s output. Each SonarQube report provides the file path, line or column location, smell type, and diagnostic message. SmellCC then constructs a **smell‑specific prompt** containing three components: a **role designation**, **chain‑of‑thought reasoning**, and **few‑shot examples**. For **Collapsible if Statements**, for example, the prompt asks the model to refactor code to eliminate the smell while the code function remains unchanged, instructs it to merge nested conditions based on their logic, and supplies a small transformation example of nested `if` statements into a single conjunctive condition [2508.11958].

The refactoring engine is **DeepSeek‑Coder‑V2**, chosen for strong code abilities and lower inference cost than GPT‑4o. The reported settings are **`temperature = 0`**, **`max_tokens = 8192`** for long cases such as **Long Parameter List**, and **`max_tokens = 2048`** otherwise. For each smell report, SmellCC extracts the relevant function or file region, composes the smell‑specific prompt, queries the model, and applies an in‑place modification at the SonarQube‑reported location. Post‑refactoring validation is twofold: **SonarQube** is rerun to measure residual smells, and the **50‑repository test set** is used for dynamic validation via regression tests [2508.11958].

A notable technical characteristic is that SmellCC includes smell‑specific operational strategies when local refactoring alone is insufficient. For **Long Parameter List** on the 50‑repository test set, it uses an **adapter pattern** that retains the original function signature, introduces a **dataclass**, and delegates to a new implementation function so that existing tests continue to pass. For **Return and Yield**, SmellCC may override SonarQube when the flagged pattern is actually valid, such as `yield from` plus `return` in Python ≥ 3.3, and in such cases may intentionally decide not to refactor [2508.11958].

## 3. Refactoring scope, prompt engineering, and smell-specific behavior

SmellCC targets ten Python smell types frequently reported by SonarQube: **Commented Code**, **Naming Convention**, **Empty Nested Code Blocks**, **Collapsible if Statements**, **Long Parameter List**, **High Cognitive Complexity**, **Dead Code**, **Self‑assigned Variables**, **Identical Expressions**, and **Return and Yield**. Its refactoring strategies are encoded in prompts rather than hard‑coded rewrite rules. For **Naming Convention**, the prompt encourages renaming identifiers to satisfy regex‑style conventions while preserving semantics. For **Dead Code**, it removes unreachable statements. For **High Cognitive Complexity**, it favors method extraction, simplification of nested conditionals, and removal of redundant branches. For **Long Parameter List**, it suggests introducing a dataclass or decomposing large functions [2508.11958].

The prompt design is itself an experimental object. On the **15,994** smells in the **50‑repository** test set, the authors evaluate four prompt variants: **Role‑only**, **Role + Few‑shot**, **Role + CoT**, and **Role + CoT + Few‑shot**. The number of residual smells after refactoring is **1,081**, **1,050**, **641**, and **508**, corresponding to cleaning rates of **93.2%**, **93.4%**, **96.0%**, and **96.8%**, respectively. The reported interpretation is that **CoT provides the main gain**, while **few‑shot** gives an additional but smaller improvement over **Role + CoT** [2508.11958].

The smell‑specific case analyses also reveal where SmellCC is strong and where it is structurally limited. It performs especially well on local, syntax‑proximal smells such as **Commented Code**, **Dead Code**, **Self‑assigned Variables**, and **Collapsible if Statements**. It is substantially less effective on smells that require cross‑file reasoning or broader interface changes. In one **Long Parameter List** example, SmellCC introduces a dataclass `AccountParams` and a helper `from_legacy_params`, but the main constructor still exposes **11 parameters**, so the smell remains. In one **High Cognitive Complexity** example, SmellCC reduces complexity but also introduces a subtle bug by using `atr[idx]` instead of `atr[idx[0]]`. These cases suggest that SmellCC is strongest when the repair is local and weakest when repair requires global reasoning across call sites or modules [2508.11958].

## 4. Cleaning effectiveness and behavioral preservation

On the full **CodeSearchNet‑Python** corpus, SmellCC reduces SonarQube‑reported smells from **203,180** to **17,075**, for an overall cleaning ratio of **91.6%** [2508.11958].

| Smell type | Before → After | Cleaning ratio (%) |
|---|---:|---:|
| Commented Code | 10,509 → 735 | 93.0 |
| Naming Convention | 133,323 → 7,975 | 94.0 |
| Empty Nested Blocks | 2,446 → 226 | 90.8 |
| Collapsible if | 8,631 → 185 | 97.9 |
| Long Parameter List | 12,967 → 5,502 | 57.6 |
| High Cognitive Complexity | 33,926 → 2,348 | 93.1 |
| Dead Code | 458 → 9 | 98.0 |
| Self-assigned Variables | 458 → 14 | 96.9 |
| Identical Expressions | 267 → 34 | 87.3 |
| Return and Yield | 195 → 47 | 75.9 |

A manual validation on **387 files** and **1,272 functions** reports **1,272** smells before and **104** after, corresponding to **91.8%** cleaning. The manually checked cleaning ratios broadly align with the automatic analysis, but two smell types are markedly harder: **Long Parameter List** is reduced from **13** to **7** (**46.2%**), and **High Cognitive Complexity** from **31** to **12** (**61.3%**). The paper attributes part of the discrepancy on **High Cognitive Complexity** to the way SonarQube recomputes cognitive complexity: some refactorings reduce complexity but not enough to fall below the threshold, so they remain flagged [2508.11958].

The strongest behavioral validation comes from the **50‑repository** test set. There, the dataset contains **15,994** smells, of which SmellCC removes **15,486**, yielding **96.8%** smell removal. Re‑running tests shows that **14,597** instances preserve behavior, giving **91.3% correctness**. Six smells—**Commented Code**, **Collapsible if**, **Dead Code**, **Self‑Assigned Variables**, **Identical Expressions**, and **Return and Yield**—achieve **100% cleaning and 100% test correctness**. By contrast, **Naming Convention** is **99.5%** cleaned with **91.4%** correctness, **High Cognitive Complexity** is **90.5%** cleaned with **88.4%** correctness, **Empty Nested Blocks** is **85.3%** cleaned with **98.2%** correctness, and **Long Parameter List** is **60.9%** cleaned with **72.4%** correctness [2508.11958].

## 5. Effect on fine-tuning, generated smells, and downstream tasks

SmellCC is evaluated not only as a refactoring tool but as a **dataset curation mechanism** for code LLM training. The study fine‑tunes **DeepSeek‑Coder‑V2‑Lite‑Instruct** (**DeepSeek‑V2**, 16B), **DeepSeek‑Coder‑6.7B‑Instruct** (**DeepSeek‑V1**, 6.7B), and **Qwen2.5‑Coder‑7B‑Instruct** (**Qwen‑Coder**, 7B) on two versions of **CodeSearchNet‑Python**: the original dataset and the SmellCC‑cleaned dataset. Fine‑tuning uses **full fine‑tuning (no LoRA)**, **2 epochs**, and **4× NVIDIA A800 80GB GPUs** [2508.11958].

On **1,000** generation prompts, SonarQube smell counts show a consistent pattern. For **DeepSeek‑V1**, the counts are **152** for the base model, **159** after fine‑tuning on the original dataset, and **62** after fine‑tuning on the smell‑cleaned dataset. For **DeepSeek‑V2**, the counts are **137**, **167**, and **34**. For **Qwen‑Coder**, they are **126**, **154**, and **26**. The paper reports that fine‑tuning on the original dataset increases smell counts, whereas fine‑tuning on the smell‑cleaned dataset reduces them by **59.2%**, **75.2%**, and **79.4%** relative to the corresponding base models, and by **61.0%**, **79.6%**, and **83.1%** relative to the versions fine‑tuned on the original data [2508.11958].

For **code completion**, the task is masked line completion on **1,000 functions** from the **50‑repository** test suite, evaluated with **Pass@1** based on the original tests. **DeepSeek‑V1** scores **0.750** as base, **0.731** after fine‑tuning on the original dataset, and **0.789** after fine‑tuning on the smell‑cleaned dataset. **DeepSeek‑V2** scores **0.730**, **0.664**, and **0.742**. **Qwen‑Coder** scores **0.816**, **0.787**, and **0.883**. The reported relative gains of fine‑tuning on the smell‑cleaned dataset over the corresponding original‑tuned models are **7.9%**, **11.7%**, and **12.2%**, respectively [2508.11958].

For **code search**, the study uses **MRR** and **NDCG** over candidate pools of **100** code snippets. On the original dataset versus smell‑cleaned dataset, **DeepSeek‑V1** improves from **0.564 / 0.604** to **0.587 / 0.620**, **DeepSeek‑V2** from **0.752 / 0.799** to **0.757 / 0.802**, and **Qwen‑Coder** from **0.631 / 0.672** to **0.656 / 0.701**. The paper reports gains of **+4.1% MRR** and **+2.6% NDCG** for DeepSeek‑V1, **+0.7% MRR** and **+0.4% NDCG** for DeepSeek‑V2, and **+4.0% MRR** and **+4.3% NDCG** for Qwen‑Coder. This suggests that smell cleaning reduces semantic noise in code representations, making docstring–code alignment easier for retrieval [2508.11958].

## 6. Position in code-smell research, limitations, and future directions

SmellCC occupies a distinctive place within code‑smell research because it shifts the focus from **detecting smells in code under inspection** to **cleaning smells in the training corpus of code LLMs**. Earlier research emphasized other dimensions of the problem: the interplay of **Large Class**, **Complex Class**, and **Duplicate Code**, where high‑intensity **Complex Class** was found to be more predictive of clone prevalence than **Large Class** [2107.09512]; **crowdsmelling**, where collective developer labels were used to calibrate supervised smell detectors [2012.12590]; causal prioritization, where fewer than **20%** of **151** CheckStyle smells were found to be potentially causal for quality or productivity [2103.01861]; and code‑review‑based smell identification, where smells were not commonly identified in reviews and were often tied to coding conventions [2103.11446]. SmellCC adds a different intervention point: it treats smell density in the **training dataset** itself as a controllable variable [2508.11958].

The tool’s limitations are explicit. It handles only **10 smell types**, all in **Python**, and all within **CodeSearchNet‑Python**. It relies on **SonarQube**, so false positives and false negatives in SonarQube propagate into SmellCC. Its transformations are fundamentally **local**; this is why **Long Parameter List** and some instances of **High Cognitive Complexity** remain difficult. There is no formal behavioral guarantee beyond test suites, and the paper reports occasional LLM‑introduced bugs in complex refactorings. The evaluation also reports point estimates without detailed significance testing [2508.11958].

The proposed future directions follow directly from these constraints. They include extending SmellCC to **more smell types and languages**, combining LLMs with **hybrid static + LLM frameworks**, using **multi‑agent or global context LLM systems** for cross‑file refactoring, adding **formal correctness assurance** such as automated test generation or symbolic execution, and benchmarking against traditional refactoring tools such as **Rope** and **JDeodorant**. A plausible implication is that SmellCC is best understood not as a complete replacement for static analysis or human review, but as a dataset‑level refactoring layer that can be integrated with smell detection, code review, and model fine‑tuning pipelines [2508.11958].

Source: https://www.emergentmind.com/topics/smellcc