Skip to content

[Quality] 可维护性: 代码质量问题合集 - Bare Except、重复键、硬编码路径、代码重复 #17

@newtontech

Description

@newtontech

概述

对 PyMultiWFN 代码库进行全面的可维护性审查后,发现多个影响代码质量和长期维护的问题。以下是详细的分类问题清单。


🔴 高优先级问题

1. Bare Except 子句 (10处) - 严重

问题: 使用裸 except 子句会捕获所有异常,包括系统级异常(如 KeyboardInterrupt、SystemExit),这会掩盖真正的错误并使调试变得不可能。

文件位置及代码:

pymultiwfn/io/parsers/factory.py (4处)

# Line 182
except:
    pass  # Skips WFN format detection errors

# Line 204
except:
    pass  # Skips MOL format detection errors

# Line 240
except:
    pass  # Skips GRO format detection errors

# Line 261
except:
    pass  # Skips all content detection errors

pymultiwfn/density/topology.py (1处)

# Line 221
except:
    pass  # Skip if optimization fails

pymultiwfn/vis/display.py (2处)

# Lines 74, 520
except:
    pass

pymultiwfn/orbitals/localization.py (2处)

# Lines 115, 175
except:
    pass

pymultiwfn/electrostatics/potential.py (1处)

# Line 286
except:
    pass

修复建议:

# 替换前
except:
    pass

# 替换后
except SpecificException as e:
    logger.warning(f"Operation failed: {e}")

2. 字典重复键 - 高

文件: pymultiwfn/io/parsers/factory.py 第56-58行

代码:

PARSERS: Dict[str, Type] = {
    # ...
    ".gjf": GJFLoader,  # Line 56
# ...
".gjf": GJFLoader,  # Line 58 - 重复键!
}

问题: 字典中有重复的 .gjf 键,第二个会覆盖第一个,可能导致意外的行为。

修复建议:

PARSERS: Dict[str, Type] = {
    # Coordinate formats
    ".xyz": XYZLoader,
    ".pdb": PDBLoader,
    # ... 其他格式
    ".gjf": GJFLoader,  # 只保留一个
    ".com": GJFLoader,  # Gaussian input files
}

3. 硬编码文件路径 (46+处) - 高

问题: 大量环境特定的路径硬编码在源代码中,导致代码无法在不同系统上运行。

具体示例:

test_overlap_properties.py (第8行)

sys.path.insert(0, "/home/yhm/software/PyMultiWFN")

debug_shells.py (第10行)

wfn_path = "/home/yhm/software/PyMultiWFN/consistency_verifier/examples/H2_CCSD.wfn"

feishu_demo.py (第293行)

doc_file_path = "/tmp/pymultiwfn_mulliken_analysis.md"

consistency_verifier/comprehensive_test_system_v2.py (第30、32行)

PROJECT_DIR = Path("/home/yhm/software/PyMultiWFN")
MULTIWFN_BIN = "/home/yhm/software/PyMultiWFN/Multiwfn_3.8_bin_Linux_noGUI/Multiwfn"

修复建议:

# 使用环境变量或配置文件
import os
from pathlib import Path

PROJECT_DIR = Path(os.getenv("PYMULTIWFN_DIR", Path.home() / "software/PyMultiWFN"))
TEMP_DIR = Path(os.getenv("TEMP_DIR", "/tmp"))

4. 代码重复 - DRY 原则违反

问题: 两个文件中实现了几乎完全相同的 Mayer 键级计算逻辑。

文件1: pymultiwfn/analysis/bonding/mayer.py (第7-129行)
文件2: pymultiwfn/analysis/bonding/bondorder.py (第16-127行)

重复代码示例:

# 两个文件中都有几乎相同的循环结构
for i in range(num_atoms):
    basis_fns_i = atomic_basis_indices[i]
    for j in range(i + 1, num_atoms):
        basis_fns_j = atomic_basis_indices[j]
        ps_ij = PS_total[np.ix_(basis_fns_i, basis_fns_j)]
        ps_ji = PS_total[np.ix_(basis_fns_j, basis_fns_i)]
        accum = np.trace(ps_ij @ ps_ji)
        bond_order_matrix_total[i, j] = accum
        bond_order_matrix_total[j, i] = accum

修复建议:
在一个文件中实现核心逻辑,另一个文件导入并可能添加特定功能:

# bondorder.py
from .mayer import _calculate_mayer_core

def calculate_mayer_bond_order(wfn):
    return _calculate_mayer_core(wfn)

5. Print 调试语句残留 (20+处) - 中

问题: 生产代码中残留大量 print 调试语句,应该使用日志模块。

pymultiwfn/io/parsers/wfn.py (第487-501行)

print(f"[DEBUG] Basis function information (first 20 of {num_basis}):")
print(f"[DEBUG] Index | Centre | WFN Type | GTO Type | Exponent")
# ... 更多 print

pymultiwfn/core/data.py (第260-262行、第296-299行)

print(
    f"Warning: Mismatch in total basis functions assigned ({total_bfs_assigned}) "
    f"vs expected ({self.num_basis}). This may indicate a parsing issue."
)

修复建议:

import logging
logger = logging.getLogger(__name__)

# 替换 print
logger.warning("Mismatch in total basis functions: %d vs %d", 
               total_bfs_assigned, self.num_basis)

6. 过多的 TODO 注释 (15+处) - 中

问题: 大量 TODO 注释表示未完成的功能,影响代码可读性。

示例:

  • pymultiwfn/io/parsers/qeparser.py:15: # TODO: Implement Quantum ESPRESSO input parsing
  • pymultiwfn/io/parsers/vasp.py:62: # TODO: Implement CHGCAR parsing
  • pymultiwfn/math/basis.py:125: # TODO: Implement G, H and Spherical/Cartesian support
  • pymultiwfn/analysis/properties/__init__.py:1: # TODO: Implement functionality

建议: 将 TODO 迁移到 Issue 跟踪系统,而不是留在代码中。


7. 类设计问题 - 重复的 Analyzer 模式

问题: 22个 Analyzer 类都实现了几乎相同的 __init__ 模式:

def __init__(self, wavefunction: Wavefunction):
    if wavefunction.coefficients is None:
        raise ValueError("Wavefunction must have MO coefficients")
    self.wfn = wavefunction
    # ... 初始化缓存变量

建议: 使用基类或混入(mixin)模式减少重复。


📊 问题统计

严重程度 问题类型 数量 影响文件
🔴 高 Bare except 子句 10处 5个文件
🔴 高 字典重复键 1处 factory.py
🔴 高 硬编码路径 46+处 30+个文件
🔴 高 代码重复 (DRY) 2处 mayer.py, bondorder.py
🟡 中 Print 调试语句 20+处 20+个文件
🟡 中 TODO 注释 15+处 10+个文件
🟢 低 重复的类模式 22个类 多个模块

🔧 修复优先级建议

  1. 立即修复: Bare except 子句(安全性和稳定性问题)
  2. 本周修复: 字典重复键、硬编码路径
  3. 本月修复: 代码重复重构、print 替换为日志
  4. 长期改进: TODO 管理、类设计优化

测试建议

修复后应运行:

# 运行所有测试
pytest

# 运行特定模块测试
pytest tests/analysis/test_bonding.py
pytest tests/io/test_parsers.py

# 代码质量检查
flake8 pymultiwfn --select=E722  # 检查 bare except
pylint pymultiwfn --disable=all --enable=W0702  # 检查异常处理

为什么这些问题重要

  1. Bare except: 隐藏错误、安全风险、难以调试
  2. 重复键: 可能导致意外的行为覆盖
  3. 硬编码路径: 代码不可移植、暴露系统信息
  4. 代码重复: 维护困难、bug 修复不一致
  5. Print 语句: 不适合生产环境、无法分级控制

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions