3 ms·
There's a reason why Torvalds said, "Talk is cheap. Show me the code."[1] Quite often when people write about abstract concepts in software that violate well-kn
by thangalin 10y ago
There's a reason why Torvalds said, "Talk is cheap. Show me the code."[1] Quite often when people write about abstract concepts in software that violate well-known principles, they cannot come up with concrete examples that show a good time to break form. Because they are few and far between.
Take URLs for an example.
> Here I may be deeply concerned about SSL
On web pages, instead of codifying "http://" http://" and "https://" https://" everywhere (a form of duplication), it is possible to drop the protocol to use "//"; the browser will fetch subsequent files using the security of the original page. (Mixing secure and insecure content is an architectural mistake.)
An application shouldn't be concerned with HTTP vs HTTPS. In Java, that concern is made transparent by HttpURLConnection (and its subclass of HttpsURLConnection), for example.
> a chunk of ten or twenty lines that are identical
When seemingly identical chunks of code are repeated, they can often be abstracted and parameterized. Lambda expressions help reduce duplicated code snippets. Of course, when I say "parameterized" I don't mean "pass in a metric ton of parameters" as there are techniques for shortening long parameter lists (such as multiple methods and the builder pattern).
Lines 70 to 89 are an example of duplicated code[3] (here are four lines, but you get the idea):
this.namespacesAware = xmlNode.getAttribute("namespacesaware");
this.prunetags = xmlNode.getAttribute("prunetags");
this.hyphenReplacement = xmlNode.getAttribute("hyphenreplacement");
this.booleanAtts = xmlNode.getAttribute("booleanatts");
These should be a map of properties rather than a volley of String instance variables:
private String namespacesAware;
private String prunetags;
private String hyphenReplacement;
private String booleanAtts;
It might not seem like much duplication at first, until you look at the code that uses those parameters[4]:
final String namespacesAware = BaseTemplater.evaluateToString(elementDef.getNamespacesAware(), null, context);
if (namespacesAware != null) {
properties.setNamespacesAware(CommonUtil.isBooleanTrue(namespacesAware));
} else {
properties.setNamespacesAware(false);
}
final String hyphenReplacement = BaseTemplater.evaluateToString(elementDef.getHyphenReplacement(), null, context);
if (hyphenReplacement != null) {
properties.setHyphenReplacementInComment(hyphenReplacement);
}
final String pruneTags = BaseTemplater.evaluateToString(elementDef.getPrunetags(), null, context);
if (pruneTags != null) {
properties.setPruneTags(pruneTags);
}
final String booleanAtts = BaseTemplater.evaluateToString(elementDef.getBooleanAtts(), null, context);
if (booleanAtts != null) {
properties.setBooleanAttributeValues(booleanAtts);
}
The entire code block could be reduced to one line of code had properties been used instead of instance variables. (Maybe a loop and two lines of code, but either way the duplication could be easily mitigated.)
Without seeing source code examples, it is extraordinarily difficult to identify problems in the code and explain how the code could be improved. Hence the Torvalds quote.
> the same abstraction is just pain
Sometimes code is poorly designed, not designed for extensibility, or has hard-coded assumptions that should be exposed as properties. Take line 52 of the HtmlToPlainText class[2]:
private static final int maxWidth = 80;
That one line forced duplicating the entire class, which was otherwise perfect for my needs. But the class did not expose behaviour to change the maximum width of a line. An incorrect assumption was made at the design level: 80 characters ought to be enough.
The correct solution would be to make it an attribute and send a pull request to the author. :-)
[1]: https://lkml.org/lkml/2000/8/25/132 https://lkml.org/lkml/2000/8/25/132
[2]: http://grepcode.com/file/repo1.maven.org/maven2/org.jsoup/jsoup/1.6.3/org/jsoup/examples/HtmlToPlainText.java http://grepcode.com/file/repo1.maven.org/maven2/org.jsoup/js...
[3]: https://sourceforge.net/p/web-harvest/code/HEAD/tree/trunk/webharvest-core/src/main/java/org/webharvest/definition/HtmlToXmlDef.java https://sourceforge.net/p/web-harvest/code/HEAD/tree/trunk/w...
[4]: https://sourceforge.net/p/web-harvest/code/HEAD/tree/trunk/webharvest-core/src/main/java/org/webharvest/runtime/processors/HtmlToXmlProcessor.java https://sourceforge.net/p/web-harvest/code/HEAD/tree/trunk/w...