如何在不损害 java + PDFBox 中的 DRY 原则的情况下格式化代码?
How to go about formatting code without hurting the DRY principle in java + PDFBox?
请原谅这个问题的阴暗面,请允许我自己解释一下。
我使用 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 问题出现的地方。
我想到的第一件事是将当前代码导出到一个仅用于生成两者的函数,然后创建 (copy/paste) 用于一个或另一个的第二个函数。但是大部分代码会重复执行此操作(少一个块,因为我们只有一个输出变量,而不是两个)。
我能想到的另一种方法是在每个代码块之前创建一个 if() ,如果是这种情况,则取该块,如果是,则取该块。再一次,DRYness 不存在(因为相同的 if 必须出现在每个代码块之前)。
我的问题是:通常最好的方法是什么?我不介意这个怪物是否再次从 4k 行代码增长到 8k 行代码,但如果有更简单(更好)的方法来做到这一点,我会洗耳恭听。
干杯 :)
查看您的代码:
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, "...
等等。然后:您可能会将这些东西放在它自己的 class 中,在其中您将 pdContentStream
设为一个字段;到 git 摆脱每次调用都需要该参数。
之后应该更好地研究 "organizing" 那些字符串。写下来没有意义:
foo("bla");
foo("blub");
相反,您将 "pdf.value.TDVentilator" 之类的值推送到 List 中;然后暗示迭代 lists/sets/whatever,从那里获取所需的信息。
长话短说:你不会培养怪物。你甚至不允许它们存在。您显示的代码已经 严重 违反了 DRY,绝对 不能 是可以容忍的!
请原谅这个问题的阴暗面,请允许我自己解释一下。
我使用 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 问题出现的地方。
我想到的第一件事是将当前代码导出到一个仅用于生成两者的函数,然后创建 (copy/paste) 用于一个或另一个的第二个函数。但是大部分代码会重复执行此操作(少一个块,因为我们只有一个输出变量,而不是两个)。
我能想到的另一种方法是在每个代码块之前创建一个 if() ,如果是这种情况,则取该块,如果是,则取该块。再一次,DRYness 不存在(因为相同的 if 必须出现在每个代码块之前)。
我的问题是:通常最好的方法是什么?我不介意这个怪物是否再次从 4k 行代码增长到 8k 行代码,但如果有更简单(更好)的方法来做到这一点,我会洗耳恭听。
干杯 :)
查看您的代码:
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, "...
等等。然后:您可能会将这些东西放在它自己的 class 中,在其中您将 pdContentStream
设为一个字段;到 git 摆脱每次调用都需要该参数。
之后应该更好地研究 "organizing" 那些字符串。写下来没有意义:
foo("bla");
foo("blub");
相反,您将 "pdf.value.TDVentilator" 之类的值推送到 List 中;然后暗示迭代 lists/sets/whatever,从那里获取所需的信息。
长话短说:你不会培养怪物。你甚至不允许它们存在。您显示的代码已经 严重 违反了 DRY,绝对 不能 是可以容忍的!