×
¥
查看详情
🔥 会员专享 文生代码 其它

代码智能重构

👁️ 631 次查看
📅 Nov 24, 2025
💡 核心价值: 一键智能重构代码,更规范、更高效,轻松提升代码质量!

🎯 可自定义参数(5个)

编程语言
编写代码所使用的编程语言
代码内容
需要进行重构的完整代码或关键模块内容
重构目标
代码重构的主要目标方向
编码规范
代码需要遵循的编码规范标准
关键模块/方法
指定希望重点优化的函数、类或模块

🎨 效果示例

重构说明

  • 目标达成

    • 可读性提升:将计时器、网络请求与渲染逻辑分离,命名规范统一,结构更清晰。
    • 可维护性增强:引入可复用的 useDebounce 钩子、集中化的 API 层 searchApi、统一的 performSearch 方法,避免重复代码。
    • 可测试性提高:searchApi 与 useDebounce 为纯函数/无副作用模块,便于独立单元测试;请求取消和错误处理逻辑明确。
  • 主要问题与修复

    1. 定时器泄漏与闭包问题:原代码使用 var timer,未随组件生命周期清理,且闭包捕获旧 kw。改为 useDebounce + useEffect 触发搜索,避免泄漏与不一致。
    2. 直接操作 DOM:移除 useEffect 中的 document.getElementById,改用条件渲染显示提示信息。
    3. 事件名错误:修复按钮事件名为 onClick。
    4. key 不稳定:不再使用 Math.random,优先 item.id,其次 item.name,最后索引作为兜底。
    5. 并发与竞态:引入 AbortController,避免快速输入导致的竞态与内存泄漏。
    6. 错误与状态管理:统一 loading、error 管理;在 finally 中收敛状态。
    7. ESLint 规范:使用 const/let、箭头函数、早返回、可选链、安全的 encodeURIComponent。
  • 针对关键模块/方法

    • SearchForm.onChange → handleChange:仅负责更新输入状态,不做副作用。
    • SearchForm.useEffect:监听去抖后的关键字 debouncedKeyword,触发搜索并处理取消。
    • SearchForm.reload → handleReload:复用 performSearch,保证与自动搜索逻辑一致。

重构后的代码(符合 ESLint) import React, { useState, useEffect, useCallback } from 'react';

// 可测试的纯 API 方法 export async function searchApi(query, options = {}) { const url = /api/search?q=${encodeURIComponent(query)}; const res = await fetch(url, options); if (!res.ok) { throw new Error(Request failed with status ${res.status}); } const data = await res.json(); return Array.isArray(data?.data) ? data.data : []; }

// 通用的去抖 Hook function useDebounce(value, delay = 300) { const [debouncedValue, setDebouncedValue] = useState(value);

useEffect(() => { const id = setTimeout(() => setDebouncedValue(value), delay); return () => clearTimeout(id); }, [value, delay]);

return debouncedValue; }

export default function SearchForm() { const [keyword, setKeyword] = useState(''); const [items, setItems] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null);

// 去抖后的查询关键字(使用 trim 避免空格触发请求) const debouncedKeyword = useDebounce(keyword.trim(), 300);

// 统一的搜索执行函数,便于复用与测试 const performSearch = useCallback( async (query, signal) => { setLoading(true); try { const result = await searchApi(query, { signal }); setItems(result); setError(null); } catch (err) { // 取消请求不认为是错误 if (err?.name !== 'AbortError') { setError(err?.message || '搜索失败,请稍后重试'); } } finally { setLoading(false); } }, [] );

// 自动搜索:监听去抖后的关键字变化 useEffect(() => { if (!debouncedKeyword) { setItems([]); return; } const controller = new AbortController(); void performSearch(debouncedKeyword, controller.signal); return () => controller.abort(); }, [debouncedKeyword, performSearch]);

// 原 onChange 逻辑重构:仅更新输入值 const handleChange = useCallback((e) => { setKeyword(e.target.value); }, []);

// 原 reload 重构:复用统一搜索方法 const handleReload = useCallback(() => { const query = keyword.trim(); if (!query) return; void performSearch(query); }, [keyword, performSearch]);

const showPrompt = !keyword.trim() && !loading; const getItemKey = (item, index) => item?.id ?? item?.name ?? String(index);

return (

<button type="button" onClick={handleReload} disabled={!keyword.trim() || loading} > 搜索

  {showPrompt && <span>请输入关键字</span>}
  {error && <p role="alert">错误:{error}</p>}

  {loading ? (
    <p>加载中...</p>
  ) : (
    <ul>
      {items.map((i, idx) => (
        <li key={getItemKey(i, idx)}>{i?.name ?? '-'}</li>
      ))}
    </ul>
  )}
</div>

); }

测试建议

  • searchApi:使用 jest/vi 模拟 fetch,验证正常返回与非 2xx 状态抛错。
  • useDebounce:用 fake timers 验证去抖延迟与清理。
  • SearchForm:
    • 输入变化后 300ms 触发一次请求,快速输入应只触发最后一次。
    • 空输入显示“请输入关键字”,不会发起请求。
    • 错误时展示错误信息;卸载时不会内存泄漏(AbortController 生效)。
    • 点击搜索按钮与自动搜索行为一致。

重构后的代码(report.py)

from future import annotations

import csv import heapq import json import logging from dataclasses import dataclass from pathlib import Path from typing import Iterable, List, Optional, Sequence

配置日志,便于调试与测试时观察行为

logging.basicConfig(level=logging.INFO) logger = logging.getLogger(name)

@dataclass(frozen=True) class Item: """结构化的数据项,提升类型安全与可读性。""" id: str name: str score: float

@dataclass class ReportConfig: """报告生成配置。threshold 预留(当前逻辑未使用)。""" limit: int = 1000 threshold: float = 0.7

def load_data(csv_path: str | Path, json_path: str | Path) -> List[Item]: """ 从 CSV 和 JSON 文件加载数据。 - CSV 每行格式: id,name,score - JSON 为对象列表,支持键: id, n(name), s(score) - 对异常行进行忽略并记录日志 """ items: List[Item] = []

# 读取 CSV
csv_path = Path(csv_path)
if csv_path.exists():
    with csv_path.open("r", encoding="utf-8", newline="") as f:
        reader = csv.reader(f)
        for row_num, row in enumerate(reader, start=1):
            if not row or len(row) < 3:
                logger.debug("Skip CSV row %d: insufficient columns", row_num)
                continue
            raw_id, raw_name, raw_score = row[0], row[1], row[2]
            try:
                score = float(raw_score)
            except ValueError:
                logger.debug("Skip CSV row %d: invalid score '%s'", row_num, raw_score)
                continue
            items.append(Item(id=str(raw_id).strip(),
                              name=str(raw_name),
                              score=score))
else:
    logger.warning("CSV file not found: %s", csv_path)

# 读取 JSON
json_path = Path(json_path)
if json_path.exists():
    with json_path.open("r", encoding="utf-8") as f:
        try:
            raw_list = json.load(f)
        except json.JSONDecodeError as exc:
            logger.error("Invalid JSON file '%s': %s", json_path, exc)
            raw_list = []

    if isinstance(raw_list, list):
        for idx, obj in enumerate(raw_list, start=1):
            if not isinstance(obj, dict):
                logger.debug("Skip JSON item %d: not a dict", idx)
                continue
            raw_id = obj.get("id")
            raw_name = obj.get("n", "")
            raw_score = obj.get("s", 0)
            try:
                score = float(raw_score)
            except (TypeError, ValueError):
                logger.debug("Skip JSON item %d: invalid score '%s'", idx, raw_score)
                continue
            items.append(Item(id=str(raw_id).strip(),
                              name=str(raw_name),
                              score=score))
    else:
        logger.warning("JSON root is not a list: %s", json_path)
else:
    logger.warning("JSON file not found: %s", json_path)

return items

def normalize(items: Iterable[Item]) -> List[Item]: """ 规范化数据: - name 去空格并转为小写 - score 若 > 1 则按百分比缩放为 /100 - 保持按规范化后的 name 去重(与原代码语义保持一致,且 O(n)) """ normalized: List[Item] = [] seen_names: set[str] = set()

for item in items:
    normalized_name = item.name.strip().lower()
    normalized_score = item.score / 100.0 if item.score > 1 else item.score

    if normalized_name in seen_names:
        continue

    seen_names.add(normalized_name)
    normalized.append(Item(id=item.id, name=normalized_name, score=normalized_score))

return normalized

def dedup_and_sort(items: Sequence[Item], limit: int, cache: Optional[List[str]] = None) -> List[Item]: """ 去重并选出 Top-K: - 按 id 或 name 去重(任一重复则跳过) - 使用最小堆进行 Top-K 选择,复杂度 O(n log k),提升性能 - 结果按 score 降序;同分数时按出现顺序稳定 - 可选收集去重后的 id 到 cache(不再使用全局变量) """ seen_ids: set[str] = set() seen_names: set[str] = set()

# 堆中元素为 (score, order, Item),最小堆保留当前前 K 项
heap: List[tuple[float, int, Item]] = []

for order, item in enumerate(items):
    if item.id in seen_ids or item.name in seen_names:
        continue

    seen_ids.add(item.id)
    seen_names.add(item.name)

    if cache is not None:
        cache.append(item.id)

    score = item.score
    if len(heap) < limit:
        heapq.heappush(heap, (score, order, item))
    else:
        # 比堆顶更优则替换(更高分或更早出现)
        top_score, top_order, _ = heap[0]
        if score > top_score or (score == top_score and order < top_order):
            heapq.heapreplace(heap, (score, order, item))

# 将堆内容转为按 score 降序、order 升序的列表
heap.sort(key=lambda t: (-t[0], t[1]))
return [t[2] for t in heap]

def main() -> None: config = ReportConfig() ids_cache: List[str] = []

data = load_data("data.csv", "more.json")
data = normalize(data)
rows = dedup_and_sort(data, limit=config.limit, cache=ids_cache)

for r in rows:
    print(f"{r.id},{r.name},{r.score}")

if name == "main": main()

重构说明

  • 性能优化

    • 去重由原来的 O(n^2) 改为使用集合 O(n)。
    • Top-K 采用最小堆(heapq),复杂度 O(n log k),避免对全量数据排序,提高在大量数据且 limit 较小(如 1000)时的性能。
    • 使用 csv 模块和 json.load 流式读取,避免不必要的字符串拼接和内存开销。
  • 可维护性增强

    • 引入 dataclass(Item、ReportConfig),数据结构清晰,类型更安全。
    • 去除全局可变状态(原始的全局 cache、cfg),通过参数与返回值传递,降低耦合。
    • 增加日志与错误处理,对异常输入有明确行为与可观测性。
  • 可读性提升

    • 增加函数与类的文档字符串,解释行为与约束。
    • 采用 PEP8 命名与结构,清晰的分层(load_data、normalize、dedup_and_sort、main)。
    • 明确的类型注解使接口直观。
  • 可测试性提高

    • 函数均为纯函数或副作用受控(cache 通过参数提供),利于单元测试。
    • normalize、dedup_and_sort 可直接针对输入列表进行测试;load_data 可使用临时文件或模拟对象测试。
    • 通过日志辅助测试异常分支与边界情况。
  • 行为保持与差异说明

    • normalize 保持原始逻辑:按规范化后的 name 去重,并进行 score 归一化(>1 则 /100)。
    • dedup_and_sort 保持原始去重规则:id 或 name 任一重复则跳过;排序按 score 降序。
    • cfg.threshold 在原代码未使用,现作为 ReportConfig 的保留字段,未改变行为。需要启用阈值过滤时,可在 dedup_and_sort 中添加相应过滤逻辑。
  • 其他

    • I/O 使用 Path 与上下文管理器,避免资源泄露。
    • 输出格式保持不变:id,name,score。

以下为重构后的代码与说明。重构重点:

  • 引入策略模式(Strategy)处理折扣计算,消除魔法数与分支膨胀,提升可扩展性。
  • 引入仓储模式(Repository)隔离持久化,使用 PreparedStatement 防止 SQL 注入并改进资源管理。
  • 提升可维护性与性能:拆分职责、消除拼接字符串、使用 StringBuilder、封装常量、构造函数注入提升可测试性。
  • 遵循 Google Java Style:命名、常量、空指针处理、try-with-resources、早返回等。

代码

文件:app/domain/CustomerType.java package app.domain;

public enum CustomerType { VIP, NEW, STAFF, REGULAR;

public static CustomerType fromNullable(String type) { if (type == null) { return REGULAR; } switch (type.trim().toUpperCase()) { case "VIP": return VIP; case "NEW": return NEW; case "STAFF": return STAFF; default: return REGULAR; } } }

文件:app/discount/DiscountStrategy.java package app.discount;

public interface DiscountStrategy { double calculate(double amount); }

文件:app/discount/VipDiscountStrategy.java package app.discount;

public final class VipDiscountStrategy implements DiscountStrategy { private static final double BASE_RATE = 0.10; private static final double HIGH_RATE = 0.15; private static final double THRESHOLD = 1000.0;

@Override public double calculate(double amount) { if (amount <= 0.0) { return 0.0; } return amount * (amount > THRESHOLD ? HIGH_RATE : BASE_RATE); } }

文件:app/discount/NewUserDiscountStrategy.java package app.discount;

public final class NewUserDiscountStrategy implements DiscountStrategy { private static final double WELCOME_CASH = 20.0;

@Override public double calculate(double amount) { return WELCOME_CASH; } }

文件:app/discount/StaffDiscountStrategy.java package app.discount;

public final class StaffDiscountStrategy implements DiscountStrategy { private static final double RATE = 0.30;

@Override public double calculate(double amount) { if (amount <= 0.0) { return 0.0; } return amount * RATE; } }

文件:app/discount/NoDiscountStrategy.java package app.discount;

public final class NoDiscountStrategy implements DiscountStrategy { @Override public double calculate(double amount) { return 0.0; } }

文件:app/discount/DiscountStrategyFactory.java package app.discount;

import app.domain.CustomerType;

public final class DiscountStrategyFactory { private static final DiscountStrategy VIP = new VipDiscountStrategy(); private static final DiscountStrategy NEW_USER = new NewUserDiscountStrategy(); private static final DiscountStrategy STAFF = new StaffDiscountStrategy(); private static final DiscountStrategy NONE = new NoDiscountStrategy();

private DiscountStrategyFactory() {}

public static DiscountStrategy of(CustomerType type) { switch (type) { case VIP: return VIP; case NEW: return NEW_USER; case STAFF: return STAFF; case REGULAR: default: return NONE; } } }

文件:app/repository/OrderRepository.java package app.repository;

import java.sql.SQLException;

public interface OrderRepository { void save(String userId, String productId, int qty) throws SQLException;

int countByUserId(String userId) throws SQLException; }

文件:app/repository/JdbcOrderRepository.java package app.repository;

import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException;

public final class JdbcOrderRepository implements OrderRepository { private static final String SQL_INSERT = "INSERT INTO orders(user_id, product_id, qty) VALUES(?, ?, ?)"; private static final String SQL_COUNT_BY_USER = "SELECT COUNT(*) AS n FROM orders WHERE user_id = ?";

private final Connection connection;

public JdbcOrderRepository(Connection connection) { this.connection = connection; }

@Override public void save(String userId, String productId, int qty) throws SQLException { try (PreparedStatement ps = connection.prepareStatement(SQL_INSERT)) { ps.setString(1, userId); ps.setString(2, productId); ps.setInt(3, qty); ps.executeUpdate(); } }

@Override public int countByUserId(String userId) throws SQLException { try (PreparedStatement ps = connection.prepareStatement(SQL_COUNT_BY_USER)) { ps.setString(1, userId); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { return rs.getInt("n"); } return 0; } } } }

文件:app/service/OrderService.java package app.service;

import app.discount.DiscountStrategy; import app.discount.DiscountStrategyFactory; import app.domain.CustomerType; import app.repository.JdbcOrderRepository; import app.repository.OrderRepository; import java.sql.Connection; import java.sql.SQLException; import java.util.List;

public final class OrderService { private static final String STATUS_INVALID = "INVALID"; private static final String STATUS_OK_PREFIX = "OK:"; private static final String STATUS_ERR_PREFIX = "ERR:"; private static final String SUMMARY_SEPARATOR = "|"; private static final String SUMMARY_KV_SEPARATOR = ":";

private static final CustomerType SUMMARY_DEFAULT_TYPE = CustomerType.VIP; private static final double SUMMARY_DEFAULT_AMOUNT = 120.0;

private final OrderRepository orderRepository;

// 推荐:依赖注入仓储以提升可测试性 public OrderService(OrderRepository orderRepository) { this.orderRepository = orderRepository; }

// 兼容原构造方式:从 Connection 创建 JDBC 仓储 public OrderService(Connection connection) { this.orderRepository = new JdbcOrderRepository(connection); }

// 策略模式:根据类型委派到对应策略 public double calcDiscount(String type, double amount) { CustomerType customerType = CustomerType.fromNullable(type); DiscountStrategy strategy = DiscountStrategyFactory.of(customerType); return strategy.calculate(amount); }

// 校验与持久化解耦到仓储;使用 PreparedStatement 防注入 public String saveOrder(String userId, String productId, int qty) { if (isBlank(userId) || isBlank(productId) || qty <= 0) { return STATUS_INVALID; } try { orderRepository.save(userId, productId, qty); int count = orderRepository.countByUserId(userId); return STATUS_OK_PREFIX + count; } catch (SQLException ex) { return STATUS_ERR_PREFIX + ex.getMessage(); } }

// 渲染职责保留在服务层但使用 StringBuilder 提升性能 public String summary(List ids) { if (ids == null || ids.isEmpty()) { return ""; } StringBuilder sb = new StringBuilder(Math.max(32, ids.size() * 16)); for (String id : ids) { double discount = calcDiscount(SUMMARY_DEFAULT_TYPE.name(), SUMMARY_DEFAULT_AMOUNT); sb.append(id) .append(SUMMARY_KV_SEPARATOR) .append(discount) .append(SUMMARY_SEPARATOR); } return sb.toString(); }

private static boolean isBlank(String s) { return s == null || s.trim().isEmpty(); } }

重构说明

  • 遵循设计模式

    • 折扣计算采用策略模式(Strategy + 简单工厂)。消除了原先 calcDiscount 中的多层 if-else 与魔法数,支持后续在不改动 OrderService 的情况下扩展新折扣类型,符合开闭原则。
    • 持久化采用仓储模式(Repository)。OrderService 仅关注用例编排,不关心 SQL 细节,便于替换实现(如切换到 JPA/ORM)。
  • 可维护性增强

    • 常量命名替代魔法数(VIP 阈值与费率、固定优惠 20、状态前缀、摘要拼接符等)。
    • 职责分离:校验、折扣、持久化、渲染各自独立,单元测试更简单;OrderService 支持依赖注入,易于 mock。
    • CustomerType 枚举集中管理类型映射与合法性,避免字符串散落。
  • 性能优化

    • 使用 StringBuilder 构建 summary 字符串,避免重复拼接产生多余临时对象。
    • 使用 PreparedStatement 预编译 SQL,减少解析与防止 SQL 注入;try-with-resources 正确释放资源。
    • 折扣策略实例在工厂中复用(静态单例),避免重复创建对象。
  • 编码规范(Google Java Style)

    • 包命名小写、类与枚举命名使用 UpperCamelCase、常量大写下划线。
    • 早返回、空值保护、有限制的行宽与缩进、final/不可变语义(不可变常量、不可变依赖)。

兼容性与扩展建议

  • 兼容:OrderService 提供 Connection 构造与原方法签名不变,调用方无需调整即可获得更安全与更稳定的实现。
  • 扩展:若需要在 summary 中按不同类型或金额渲染,可新增重载 summary(List ids, CustomerType type, double amount) 或注入渲染策略。
  • 错误处理:当前保留原返回字符串语义。若允许,可引入 Result 类型或异常映射器以提供更丰富的错误上下文与可观测性。

示例详情

该提示词已被收录:
“程序员必备:提升开发效率的专业AI提示词合集”
让 AI 成为你的第二双手,从代码生成到测试文档全部搞定,节省 80% 开发时间
√ 立即可用 · 零学习成本
√ 参数化批量生成
√ 专业提示词工程师打磨

📖 如何使用

模式 1:即插即用(手动档)
直接复制参数化模版。手动修改 {{变量}} 即可快速发起对话,适合对结果有精准预期的单次任务。
加载中...
💬 模式 2:沉浸式引导(交互档)
一键转化为交互式脚本。AI 将化身专业面试官或顾问,主动询问并引导您提供关键信息,最终合成高度定制化的专业结果。
转为交互式
🚀 模式 3:原生指令自动化(智能档)
无需切换,输入 / 唤醒 8000+ 专家级提示词。 插件将全站提示词库深度集成于 Chat 输入框。基于当前对话语境,系统智能推荐最契合的 Prompt 并自动完成参数化,让海量资源触手可及,从此彻底告别“手动搬运”。
安装插件
🔌 发布为 API 接口
将 Prompt 接入自动化工作流,核心利用平台批量评价反馈引擎,实现"采集-评价-自动优化"的闭环。通过 RESTful 接口动态注入变量,让程序在批量任务中自动迭代出更高质量的提示词方案,实现 Prompt 的自我进化。
发布 API
🤖 发布为 Agent 应用
以此提示词为核心生成独立 Agent 应用,内嵌相关工具(图片生成、参数优化等),提供完整解决方案。
创建 Agent

🕒 版本历史

当前版本
v2.1 2024-01-15
优化输出结构,增强情节连贯性
  • ✨ 新增章节节奏控制参数
  • 🔧 优化人物关系描述逻辑
  • 📝 改进主题深化引导语
  • 🎯 增强情节转折点设计
v2.0 2023-12-20
重构提示词架构,提升生成质量
  • 🚀 全新的提示词结构设计
  • 📊 增加输出格式化选项
  • 💡 优化角色塑造引导
v1.5 2023-11-10
修复已知问题,提升稳定性
  • 🐛 修复长文本处理bug
  • ⚡ 提升响应速度
v1.0 2023-10-01
首次发布
  • 🎉 初始版本上线
COMING SOON
版本历史追踪,即将启航
记录每一次提示词的进化与升级,敬请期待。

💬 用户评价

4.8
⭐⭐⭐⭐⭐
基于 28 条评价
5星
85%
4星
12%
3星
3%
👤
电商运营 - 张先生
⭐⭐⭐⭐⭐ 2025-01-15
双十一用这个提示词生成了20多张海报,效果非常好!点击率提升了35%,节省了大量设计时间。参数调整很灵活,能快速适配不同节日。
效果好 节省时间
👤
品牌设计师 - 李女士
⭐⭐⭐⭐⭐ 2025-01-10
作为设计师,这个提示词帮我快速生成创意方向,大大提升了工作效率。生成的海报氛围感很强,稍作调整就能直接使用。
创意好 专业
COMING SOON
用户评价与反馈系统,即将上线
倾听真实反馈,在这里留下您的使用心得,敬请期待。

试用后开通会员即可无限使用

加载中...