code-quality
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCode Quality Review
代码质量审查
Review $ARGUMENTS (or the whole app if no argument is given) for code quality issues. Work through every step below in order and report all findings with file paths and line numbers.
审查**$ARGUMENTS**(若未提供参数则审查整个应用)的代码质量问题。按顺序完成以下每一步,并附上文件路径和行号报告所有发现。
Step 1 — Run the linter first
步骤1 — 先运行代码检查工具
Before reading any code manually, get a baseline from the automated tools:
bash
pnpm run lintList every error and warning. Fix all errors before proceeding — lint errors are not negotiable. Warnings should be reviewed and resolved unless there is a documented exception.
Also run the TypeScript compiler in strict mode to surface any hidden type issues:
bash
pnpm exec tsc --noEmitList every type error. These must be fixed.
在手动阅读代码前,先用自动化工具获取基准结果:
bash
pnpm run lint列出所有错误和警告。继续下一步前需修复所有错误——代码检查错误不可协商。警告应进行审查并解决,除非有文档记录的例外情况。
同时以严格模式运行TypeScript编译器,排查潜在的类型问题:
bash
pnpm exec tsc --noEmit列出所有类型错误,这些必须修复。
Step 2 — Eliminate any
types
any步骤2 — 消除any
类型
anySearch for usage across the codebase:
anybash
grep -rn --include="*.ts" --include="*.tsx" -E ": any|as any|<any>" src/For each hit, replace with the correct type. Common substitutions:
| Instead of | Use |
|---|---|
| |
| |
| The SDK's own response types (import from |
| |
| Proper type narrowing or explicit overloaded function signature |
The goal is zero in . If a third-party library forces it, wrap the call in a typed adapter function so does not leak into the app.
anysrc/any在整个代码库中搜索的用法:
anybash
grep -rn --include="*.ts" --include="*.tsx" -E ": any|as any|<any>" src/针对每个匹配项,替换为正确的类型。常见替换方案:
| 避免使用 | 推荐使用 |
|---|---|
用于未知外部数据的 | |
用于事件处理器的 | |
用于CDF响应的 | SDK自身的响应类型(从 |
用于数组的 | 带有正确泛型的 |
| 正确的类型收窄或显式重载函数签名 |
目标是目录中零类型。如果第三方库强制使用,请将调用包装在类型适配器函数中,避免泄漏到应用内部。
src/anyanyanyStep 3 — Check component size and single responsibility
步骤3 — 检查组件大小与单一职责
List all files with their line counts:
.tsxbash
node -e "const fs=require('fs'),path=require('path');function walk(d){return fs.readdirSync(d,{withFileTypes:true}).flatMap(e=>{const p=path.join(d,e.name);return e.isDirectory()?walk(p):p.endsWith('.tsx')?[p]:[]})}walk('src').map(p=>({p,l:fs.readFileSync(p,'utf8').split('\n').length})).sort((a,b)=>b.l-a.l).forEach(({l,p})=>console.log(l,p))"Flag every component file over 150 lines. For each, read it and check:
- Does it do more than one thing? (fetch data AND render UI AND handle form state)
- Can the fetch logic move to a custom hook ()?
useAssetData - Can sub-sections be extracted as named sub-components?
Apply the split only when it creates a genuinely cleaner separation — do not split for the sake of line count alone. A well-named 200-line component is better than three poorly-named 60-line ones.
列出所有文件及其行数:
.tsxbash
node -e "const fs=require('fs'),path=require('path');function walk(d){return fs.readdirSync(d,{withFileTypes:true}).flatMap(e=>{const p=path.join(d,e.name);return e.isDirectory()?walk(p):p.endsWith('.tsx')?[p]:[]})}walk('src').map(p=>({p,l:fs.readFileSync(p,'utf8').split('\n').length})).sort((a,b)=>b.l-a.l).forEach(({l,p})=>console.log(l,p))"标记所有超过150行的组件文件。针对每个标记的文件,检查以下内容:
- 它是否承担了多项职责?(同时获取数据、渲染UI、处理表单状态)
- 是否可以将获取逻辑移至自定义Hook(如)?
useAssetData - 是否可以将子部分提取为命名子组件?
仅当拆分能真正实现更清晰的职责分离时才进行拆分——不要单纯为了行数而拆分。一个命名规范的200行组件比三个命名混乱的60行组件更好。
Step 4 — Find and remove duplicate logic (DRY)
步骤4 — 查找并移除重复逻辑(遵循DRY原则)
Search for copy-pasted patterns across hooks, utilities, and components:
bash
undefined在Hook、工具函数和组件中搜索复制粘贴的模式:
bash
undefinedFind repeated fetch patterns
查找重复的获取数据模式
grep -rn --include=".ts" --include=".tsx" -E "sdk.(assets|timeseries|events|files).(list|retrieve)" src/
grep -rn --include=".ts" --include=".tsx" -E "sdk.(assets|timeseries|events|files).(list|retrieve)" src/
Find repeated formatting functions
查找重复的格式化函数
grep -rn --include=".ts" --include=".tsx" -E "toLocaleDateString|toLocaleString|new Date(" src/
grep -rn --include=".ts" --include=".tsx" -E "toLocaleDateString|toLocaleString|new Date(" src/
Find repeated className strings longer than 40 chars
查找超过40字符的重复className字符串
grep -rn --include="*.tsx" -E 'className="[^"]{40,}"' src/
For each set of duplicates:
- Extract to `src/utils/` if it is a pure function
- Extract to `src/hooks/` if it contains React state or effects
- Extract to a shared component if it is JSX
---grep -rn --include="*.tsx" -E 'className="[^"]{40,}"' src/
针对每组重复逻辑:
- 如果是纯函数,提取至`src/utils/`目录
- 如果包含React状态或副作用,提取至`src/hooks/`目录
- 如果是JSX代码,提取为共享组件
---Step 5 — Enforce dependency injection for external calls
步骤5 — 强制外部调用使用依赖注入
Components and hooks must not import the CDF client directly. The SDK client must be obtained from context (via or a prop) so the component is testable in isolation.
useCogniteClient()bash
grep -rn --include="*.ts" --include="*.tsx" -E "new CogniteClient|createCogniteClient" src/Flag any direct client construction outside of the app's bootstrap / auth setup file. The pattern should always be:
ts
// GOOD — client comes from context
export function useMyData() {
const sdk = useCogniteClient(); // from Dune auth context
// ...
}
// BAD — direct construction inside a hook or component
const sdk = new CogniteClient({ project: "my-project", ... });Similarly, Atlas tools should receive their dependencies via 's closure over a hook-provided ref, not by importing a global singleton.
execute组件和Hook不得直接导入CDF客户端。SDK客户端必须从上下文获取(通过或props),以便组件可独立测试。
useCogniteClient()bash
grep -rn --include="*.ts" --include="*.tsx" -E "new CogniteClient|createCogniteClient" src/标记所有在应用启动/认证设置文件之外直接构造客户端的情况。正确的模式应始终为:
ts
// 良好实践 — 客户端来自上下文
export function useMyData() {
const sdk = useCogniteClient(); // 来自Dune认证上下文
// ...
}
// 不良实践 — 在Hook或组件内部直接构造客户端
const sdk = new CogniteClient({ project: "my-project", ... });类似地,Atlas工具应通过的闭包从Hook提供的ref获取依赖,而非导入全局单例。
executeStep 6 — Check naming conventions
步骤6 — 检查命名规范
Read a representative sample of files and verify:
| Artifact | Convention | Examples |
|---|---|---|
| Files & directories | | |
| React components | | |
| Variables, functions, hooks | | |
| Constants (module-level) | | |
| TypeScript types & interfaces | | |
| Boolean variables | Auxiliary verb prefix | |
Search for common violations:
bash
undefined读取代表性的文件样本,验证以下规范:
| 类型 | 规范 | 示例 |
|---|---|---|
| 文件与目录 | | |
| React组件 | | |
| 变量、函数、Hook | | |
| 常量(模块级) | | |
| TypeScript类型与接口 | | |
| 布尔变量 | 辅助动词前缀 | |
搜索常见违规情况:
bash
undefinedTSX components not in PascalCase (filename starts with lowercase)
未使用大驼峰命名的TSX组件(文件名以小写开头)
node -e "const fs=require('fs'),path=require('path');function walk(d){return fs.readdirSync(d,{withFileTypes:true}).flatMap(e=>{const p=path.join(d,e.name);return e.isDirectory()?walk(p):p.endsWith('.tsx')?[p]:[]})}walk('src').filter(p=>/^[a-z]/.test(path.basename(p))).forEach(p=>console.log(p))"
node -e "const fs=require('fs'),path=require('path');function walk(d){return fs.readdirSync(d,{withFileTypes:true}).flatMap(e=>{const p=path.join(d,e.name);return e.isDirectory()?walk(p):p.endsWith('.tsx')?[p]:[]})}walk('src').filter(p=>/^[a-z]/.test(path.basename(p))).forEach(p=>console.log(p))"
Hook files not prefixed with "use"
未以"use"开头的Hook文件
node -e "const fs=require('fs');fs.readdirSync('src/hooks').filter(f=>f.endsWith('.ts')&&!f.startsWith('use')).forEach(f=>console.log('src/hooks/'+f))"
---node -e "const fs=require('fs');fs.readdirSync('src/hooks').filter(f=>f.endsWith('.ts')&&!f.startsWith('use')).forEach(f=>console.log('src/hooks/'+f))"
---Step 7 — Remove dead code
步骤7 — 移除死代码
powershell
undefinedpowershell
undefinedFind commented-out code blocks (3+ consecutive commented lines)
查找注释掉的代码块(连续3行及以上注释)
Get-ChildItem -Recurse -Include ".ts",".tsx" src | ForEach-Object {
$file = $_; $lines = Get-Content $file.FullName
$count = 0; $startLine = 0
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^\s*//') {
if ($count -eq 0) { $startLine = $i + 1 }
$count++
} else {
if ($count -ge 3) { "$($file.FullName):$startLine — $count consecutive comment lines" }
$count = 0
}
}
if ($count -ge 3) { "$($file.FullName):$startLine — $count consecutive comment lines" }
}
Get-ChildItem -Recurse -Include ".ts",".tsx" src | ForEach-Object {
$file = $_; $lines = Get-Content $file.FullName
$count = 0; $startLine = 0
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^\s*//') {
if ($count -eq 0) { $startLine = $i + 1 }
$count++
} else {
if ($count -ge 3) { "$($file.FullName):$startLine — $count consecutive comment lines" }
$count = 0
}
}
if ($count -ge 3) { "$($file.FullName):$startLine — $count consecutive comment lines" }
}
Find console.log/debug statements
查找console.log/debug语句
grep -rn --include=".tsx" --include=".ts" -E "console.(log|debug|warn|error|info)" src/
grep -rn --include=".tsx" --include=".ts" -E "console.(log|debug|warn|error|info)" src/
Find TODO/FIXME/HACK comments
查找TODO/FIXME/HACK注释
grep -rn --include=".tsx" --include=".ts" -E "(TODO|FIXME|HACK|XXX):" src/
Rules:
- `console.log` and `console.debug` must be removed before shipping (use proper error logging for `console.error`).
- Commented-out code blocks must be removed — version control preserves history.
- `TODO` and `FIXME` comments older than the current sprint should be resolved or converted to tracked issues.
- Unused imports are caught by the linter (Step 1); confirm they are gone.
---grep -rn --include=".tsx" --include=".ts" -E "(TODO|FIXME|HACK|XXX):" src/
规则:
- 上线前必须移除`console.log`和`console.debug`(`console.error`需使用正规错误日志工具)。
- 注释掉的代码块必须移除——版本控制会保留历史记录。
- 早于当前迭代的`TODO`和`FIXME`注释应被解决或转换为跟踪工单。
- 未使用的导入会被代码检查工具(步骤1)捕获;确认已移除。
---Step 8 — Verify file and export structure
步骤8 — 验证文件与导出结构
Every feature area should follow a consistent structure. Check that the app's layout matches this pattern:
src/
├── components/ # Shared presentational components
│ └── <name>/
│ ├── <name>.tsx
│ └── index.ts # re-exports the public API
├── hooks/ # Custom hooks (each file = one hook)
├── utils/ # Pure utility functions (no React)
├── contexts/ # React context providers
├── pages/ or views/ # Route-level components
└── types/ # Shared TypeScript typesFlag:
- Business logic sitting directly in page components (should be in hooks)
- Utility functions living inside component files (should be in )
utils/ - Types defined inline in component files when they are used across multiple files (should be in )
types/ - Missing barrel files for component directories (makes imports verbose)
index.ts
每个功能区域应遵循一致的结构。检查应用布局是否符合以下模式:
src/
├── components/ # 共享展示组件
│ └── <name>/
│ ├── <name>.tsx
│ └── index.ts # 重导出公共API
├── hooks/ # 自定义Hook(每个文件对应一个Hook)
├── utils/ # 纯工具函数(无React依赖)
├── contexts/ # React上下文提供者
├── pages/ or views/ # 路由级组件
└── types/ # 共享TypeScript类型标记以下问题:
- 业务逻辑直接写在页面组件中(应移至Hook)
- 工具函数存放在组件文件内(应移至)
utils/ - 跨多个文件使用的类型在组件文件内定义(应移至)
types/ - 组件目录缺少桶文件(会导致导入语句冗长)
index.ts
Step 9 — Report findings
步骤9 — 报告发现结果
Produce a structured report grouped by category:
| Category | File | Line | Issue | Recommendation |
|---|---|---|---|---|
| TypeScript | | 18 | | Import and use |
| Size | | — | 340 lines, mixes fetch and render logic | Extract |
| DRY | | 45, 62 | Identical date formatter | Extract to |
| Naming | | — | File name does not start with | Rename to |
| Dead code | | 88 | | Remove |
If no issues are found in a step, state "No issues found" for that step. Do not skip steps silently.
生成按类别分组的结构化报告:
| 问题类别 | 文件路径 | 行号 | 问题描述 | 修复建议 |
|---|---|---|---|---|
| TypeScript | | 18 | 使用 | 从 |
| 组件大小 | | — | 共340行,混合了数据获取与渲染逻辑 | 提取 |
| DRY原则 | | 45, 62 | 存在相同的日期格式化函数 | 提取至 |
| 命名规范 | | — | 文件名未以 | 重命名为 |
| 死代码 | | 88 | 存在 | 移除该语句 |
若某一步未发现问题,需明确标注“未发现问题”,不得跳过步骤不说明。
Done
完成
Summarize the total number of findings by category and list the highest-impact items to address first. Any type and lint error must be treated as blocking — list these separately.
any按类别总结发现的问题总数,并列出需优先处理的高影响项。所有类型和代码检查错误必须视为阻塞性问题——单独列出这些问题。
any