我使用PDFBox创建了一个PDFGenerator。 PDF大约9页,实际的PDFGenerator.java是一个拥有近4k行代码的怪物,大部分代码是PDF中文本的恒定像素定位。
当前版本(v1)包括2个主要变量,即供应和排气。因此,对于每一行某物,都有供给价值和排气价值。
整个过程完美无缺,我对整个生成过程非常满意。然而现在v2已经到来,客户希望有可能创建供应或排气,或两者。
这就是我对DRY原则的问题所在。从理论上讲,两者的代码已经存在。并且当它是一个或另一个时,唯一改变的是文本的定位,现在它在2列之间居中。
示例:两者(当前正在生成)
属性.............供应.........耗尽
身高.......................... 5 ................... 0.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不在那里(因为如果必须在每个代码块之前都一样)。
我的问题是:通常最好的方法是什么?我不介意怪物是否会从4k到8k的代码行再次增长,但是如果有一种更简单(更好)的方法可以做到这一点,那我就是耳朵。
干杯:)
答案 0 :(得分:4)
查看您的代码:
pdContentStream.beginText();
pdContentStream.setFont(boldFont, BOLD_FONT_SIZE);
pdContentStream.newLineAtOffset(EXHAUST_BEGIN, currentYCoord);
pdContentStream.showText(messageSource.getMessage("pdf.exhaust", null, this.locale));
pdContentStream.endText();
我看到的仅部分是messageSource.getMessage()
的第一个参数。
所以你的重构可能会从介绍开始:
public void prepareContent(Whatever pdContentStream, String message) {
pdContentStream.beginText();
pdContentStream.setFont(boldFont, BOLD_FONT_SIZE);
pdContentStream.newLineAtOffset(EXHAUST_BEGIN, currentYCoord);
pdContentStream.showText(messageSource.getMessage(message, null, this.locale));
pdContentStream.endText();
}
然后你的主要代码归结为:
prepareContent(pdContenStream, "pdf.value.TDVentilator");
prepareContent(pdContenStream, "...
等等。然后:你可能会把这些东西放在自己的类中,你可以在其中创建pdContentStream
字段; git摆脱每个调用需要该参数。
之后应该考虑"组织"那些字符串更好。写下来没有意义:
foo("bla");
foo("blub");
相反,你推动那些像" pdf.value.TDVentilator"进入列表;然后暗示迭代列表/集合/等等,从那里获取所需的信息。
长话短说:你不会长出怪物。你甚至不允许它们存在。您展示的代码已经严重严厉违反DRY,绝对不可以容忍!