【发布时间】:2023-03-10 02:35:02
【问题描述】:
请原谅这个问题的阴暗面,请允许我解释一下。
我使用 PDFBox 创建了一个 PDFGenerator。 PDF 大约有 9 页,实际的 PDFGenerator.java 是一个拥有近 4k 行代码的怪物,大部分代码是 PDF 内文本的恒定像素定位。
当前版本 (v1) 包括 2 个主要变量,一个供应和一个排气。因此,对于某物的每一行,都有一个供应值和一个排放值。
整个事情完美运行,我对整个生成过程非常满意。然而,现在 v2 已经到来,客户希望能够创建供应或排放,或两者兼而有之。
这就是我对 DRY 原则的问题所在。理论上,两者的代码都已经存在。当它是一个或另一个时,唯一改变的是文本的位置,现在它在两列之间居中。
示例:两者(当前正在生成)
属性............供应......排气
高度 ....................................5 .5
宽度 ....................................5 ..5
示例:一个或另一个
属性............供应......
高度 ....................................5....... ......
宽度 ....................................5........ .......
这是一个生成一行的块:
pdContentStream.beginText();
pdContentStream.setFont(boldFont, BOLD_FONT_SIZE);
pdContentStream.newLineAtOffset(TEXT_BEGIN, currentYCoord);
pdContentStream.showText(messageSource.getMessage("pdf.value.TDVentilator", null, this.locale));
pdContentStream.endText();
pdContentStream.beginText();
pdContentStream.setFont(boldFont, BOLD_FONT_SIZE);
pdContentStream.newLineAtOffset(SUPPLY_BEGIN, currentYCoord);
pdContentStream.showText(messageSource.getMessage("pdf.supply", null, this.locale));
pdContentStream.endText();
pdContentStream.beginText();
pdContentStream.setFont(boldFont, BOLD_FONT_SIZE);
pdContentStream.newLineAtOffset(EXHAUST_BEGIN, currentYCoord);
pdContentStream.showText(messageSource.getMessage("pdf.exhaust", null, this.locale));
pdContentStream.endText();
请记住,这类块会在整个生成过程中重复出现。现在是我的 DRY 问题出现的地方。
我想到的第一件事是将当前代码导出到仅用于生成两者的函数中,并创建(复制/粘贴)用于其中一个或另一个的第二个函数。但是大部分代码会重复这样做(少了一个块,因为我们只有一个输出变量而不是两个)。
我能想到的另一种方法是在每个代码块之前创建一个 if() ,如果这种情况则采用该代码块,如果这种情况采用该代码块。再一次,DRYness 不存在(因为相同的 if 必须出现在每个代码块之前)。
我的问题是:通常最好的方法是什么?我不介意怪物是否再次从 4k 行代码增长到 8k 行代码,但如果有更简单(更好)的方法来做到这一点,我会全力以赴。
干杯:)
【问题讨论】:
-
你不必每次都设置字体,只要它改变了。而且您不必每次都执行 beginText / endText,但请注意传递给
newLineAtOffset的偏移值是相对于前一个偏移量的。 (第一个是 0,0)。如果输出较少,则结果 PDF 文件会更小,如果您将它们存储或从 http 行发送,这是一件好事。 -
对于您的单元测试(您希望进行单元测试),我建议您对 PDF 进行渲染并比较图像结果。这样,您可以确保重构后的 PDF 保持不变。请参阅 TestPDFToImage.java 以获得灵感。
-
是的,伙计,我当然会进行单元测试咳咳 :) 有趣的事情要注意(也许它会在某个时候帮助某人)。我运行了一个经典的文件比较测试,以查看 PDF 的硬拷贝是否与生成的 PDF 相同,并且即使它们完全相同,它也会不断抛出错误。原来PDF每次都设置一个新ID,这个ID可以通过“pdfDocument.setDocumentId(1);”静态设置之后,测试没有问题通过。当然,静态 id 只是为了测试而设置的,对于部署,它是正常生成的。