如何在不损害java + PDFBox中的DRY原则的情况下格式化代码?

时间:2017-01-20 08:08:47

标签: java pdfbox dry

请原谅这个问题的耻辱,请允许我解释一下自己。

我使用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的代码行再次增长,但是如果有一种更简单(更好)的方法可以做到这一点,那我就是耳朵。

干杯:)

1 个答案:

答案 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,绝对可以容忍!