Perl 26:bless 不替你验证日志记录
前 25 篇用散列引用传递已经校验过的记录。报表若需要一个对象接口,最先要问的不是怎么写 bless,而是传给构造器的四个字段究竟由谁验证:bless 只把引用关联到一个包,不检查散列结构,更不会把 DEBUG 变成允许的日志等级。
LogTool::Record->new($fields) 首先要求普通散列引用,time、level、service、message 四个键都存在且已定义,再限制 level 为 INFO、WARN 或 ERROR。这里的 message => '' 合法;删掉 message 或换成 undef 才是不满足构造契约。执行构造 INFO 的正例,STDOUT 为 INFO\n、STDERR 空、退出 0;把等级换成 DEBUG,STDOUT 空,STDERR 为 invalid record level\n,裸 perl -e 退出 255。完整命令与金标见 examples/perl-language/evidence/26-31.md。
1 | |
new 中的 bless { map { $_ => $fields->{$_} } ... }, $class 建立新的散列,再使其成为传统 Perl 对象。报表的 report_rows 把已经解析的字段交给构造器,取 level 计数,不让对象自己重新读文件。注意这个构造器只保障上述局部不变量;它不对传入时间字段复验日历,原始 TSV 的完整校验仍在 read_records。练习:把 message 从空串改成 undef,能否继续构造?不能;可以通过测试中的 eval 捕获构造错误,而不是忽略异常再报成功。参考冻结的 Perl 5.38.2 官方 pod/perlobj.pod 的 bless 与方法章节,以及 examples/perl-language/lib/LogTool/Record.pm。
本轮补课把“对象接口”继续推进到 LogTool::Course::Aggregator:它只有 new、add($record)、rows 三个入口,rows 返回按 level 排序的散列行 {level,count},不包含总数。LogTool::report_rows 仍输出旧的二维数组格式,是为了保持 CLI 和旧 TAP 兼容;总数仍由调用方传入输出策略。t/course-engineering.t 已把单进程聚合、TSV 输出、JSON Lines 输出分别断言,避免把同号文章里的旧二维数组当成新聚合器的 API。









