提问者:小点点

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


请原谅这个问题的含混不清,请允许我解释一下。

我使用PDFBox创建了一个PDFGenerator。PDF大约有9页,实际的PDFGenerator.java是一个怪物,几乎有4k行代码,大部分代码是PDF内部文本的恒定像素定位。

当前版本(v1)包括两个主要变量,一个电源和一个排气。因此,对于每一行内容,都有一个供应值和一个排气值。

整个过程非常完美,我对整个生成过程非常满意。然而,现在v2已经推出,客户希望能够创建供应或排气,或两者兼而有之。

这就是我对干式原理的问题所在。理论上,两者的代码都已经存在。当它是一个或另一个时,唯一改变的是文本的位置,它现在在两列之间居中。

示例:两者(当前正在生成)

属性。。。。。。。。。。。。。供给耗尽

身高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();

请记住,这些类型的块在整个生成过程中重复自己。现在是我的干燥问题出现的地方。

我想到的第一件事是将当前代码导出到一个仅用于生成两者的函数中,并创建(复制/粘贴)第二个用于两者的函数。但是大部分代码会重复这样做(少了一个块,因为我们只有一个输出变量而不是两个)。

我能想到的另一种方法是在每个代码块之前创建一个if(),如果是这种情况,则取该块,如果是这种情况,则取该块。再一次,干燥是不存在的(因为相同的if必须出现在每个代码块之前)。

我的问题是:一般来说,什么是最好的方法?我不介意怪物是否会再次从4k代码行增长到8k代码行,但如果有更简单(更好)的方法,我会洗耳恭听。

干杯:)


共1个答案

匿名用户

查看您的代码:

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, "...

等等然后:您可能会将这些内容放在它自己的类中,在该类中,您将pContentStream作为一个字段;以避免每次调用都需要该参数。

之后,应该更好地“组织”这些字符串。没有必要写下:

foo("bla");
foo("blub");

相反,您将诸如“pdf.value.tdventurator”之类的值推到列表中;然后意味着迭代列表/集合/任何东西,从那里获取所需的信息。

长话短说:你不会养怪物。你甚至不允许他们存在。您显示的代码已经严重违反了DRY,绝对不能容忍!