直接用通用setter易出问题,因其割裂赋值与业务含义,导致校验缺失、副作用遗漏;应改用具业务语义的方法(如rename_to()),内聚校验、副作用与异常处理,并严格遵循const正确性与移动语义。

为什么直接用 set_name() 这类通用 setter 容易出问题
业务逻辑一变,set_name() 就可能既允许非法值(比如空字符串、超长名),又不触发关联动作(比如同步更新缓存、校验权限、记录审计日志)。它把“赋值”和“业务含义”割裂开了,结果是调用方得反复查文档或翻源码才能知道:这个 set_name() 到底允不允许 null?改完要不要手动调 update_index()?
用有业务语义的方法命名,比如 rename_to() 或 assign_primary_contact()
方法名本身就要回答“谁在什么场景下做这件事”。不是“设一个值”,而是“执行一个业务动作”。
-
rename_to(const std::string& new_name)—— 暗示这是对已有实体的重命名,可内置非空、长度、重复性校验,自动触发日志和索引更新 -
assign_primary_contact(User& user)—— 不仅检查user是否活跃,还可能解绑旧联系人、发送通知、更新聚合状态 - 避免
set_前缀;如果必须保留兼容接口,让它抛异常或标记为[[deprecated]]
把校验和副作用收进方法体,而不是靠调用方拼凑
通用 setter 往往只做赋值,把责任甩给上层。而业务方法应该“要么全成功,要么不发生”。
- 校验失败时直接抛
std::invalid_argument或自定义异常(如NameTooLongError),不留下半截脏状态 - 副作用要明确:比如
promote_to_admin()内部调用add_role("admin")+invalidate_session(),不暴露中间步骤 - 若需绕过校验(如迁移脚本),提供带
_unsafe后缀的内部方法,而非开放裸字段访问
注意 const 正确性和移动语义的配合
业务方法不是纯函数,但也不能随意破坏封装。比如 transfer_ownership(Owner&& new_owner) 应该接受右值引用,避免拷贝敏感资源;而 is_eligible_for_promotion() 这类判断方法必须是 const。
立即学习“C++免费学习笔记(深入)”;
- 修改状态的方法不加
const;只读判断一律加const,否则无法在const对象上调用 - 传参优先用
const&或&&,别默认传值——尤其当参数是std::string或自定义大对象时 - 返回值如果是新状态(如
create_archived_copy()),考虑返回std::unique_ptr或移动构造的对象


















