Простая причина этого заключается в том, что а) интерфейсы должны быть явными, а б) реализации должны быть самодокументируемыми.
Причина этого поста в том, что в данный момент я вижу много кода, который попадает в одну из двух ловушек — либо все задокументировано, либо ничего не задокументировано.
Все задокументировано
Найдите, что не так с этим кодом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
/** * The foo class represents blah blah blah...and so on, describing the * class in such detail it's a pity the code couldn't be generated from it */ public class Foo { /** The name */ private String name; /** * Do something with this instance. */ public void doSomething() { // Get the name String localName = this .getName(); // munge the local name localName.munge(); } /** * Get the name. * @return the name */ public String getName() { // return the name return this .name; } /** * Set the name. * @param name the name */ public void setName(String name) { // set the name this .name = name; } } |
Или, другими словами, определите, что с этим правильно. Это гораздо более короткий ответ. Код полон ненужных комментариев — например, getName () получает имя — и код, который, кажется, был написан только для того, чтобы его можно было прокомментировать — например; Строка localName — this.getName (); Имена были изменены, чтобы защитить виновных, но это реальный код, который я видел в живой кодовой базе.
Что касается меня, реализации не нуждаются в комментариях на уровне кода, потому что это то, что делает код в любом случае .
Ничего не задокументировано
На другом конце шкалы находится этот маленький драгоценный камень:
1
2
3
|
public interface Parser { void parse(InputStream is) throws IOException, SQLFeatureNotSupportedException } |
Интерфейсы, с другой стороны, должны иметь четкую документацию, которая определяет, что входит, общее описание того, что должно произойти, и четкое описание того, что выходит и какие исключения могут быть выброшены. Информация на этом уровне должна указывать, допустимы ли, например, нулевые аргументы, можно ли возвращать нулевое значение, обстоятельства, при которых могут возникать определенные исключения, и так далее.
Интерфейсы должны быть явными
Интерфейсы, по моему мнению, являются контрактами, а контракты — как скажет любой кровососущий юрист — существуют, чтобы их уважали. Они не могут быть выполнены, если условия явно не установлены.
В Бельгии нет Burger Kings, поэтому, если я нахожусь в Великобритании или Нидерландах, я обычно испытываю желание иметь один. Во время моего последнего визита я заметил это в нижней части квитанции:
«Бесплатный напиток с любым гамбургером для взрослых с этой квитанцией, исключая сделку с гамбургерами, чизбургерами или королями или любые рекламные предложения»
Или, говоря по-другому …
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
/** * Get the free drink promised by the receipt. This is valid for any burger. * @param burger the burger * @param receipt the receipt * @returns the free drink * @throws InvalidBurgerException if the burger doesn't qualify for a free drink */ public Drink getFreeDrink(Burger burger, Receipt receipt) throws InvalidBurgerException { if (MealType.HAMBURGER == meal.type() || MealType.CHEESEBURGER == meal.type() || MealType.KING_DEAL == meal.type() || meal.isPromo()) { throw new InvalidBurgerException(); } return new Drink(); } |
На мой простой ум, это чертовски запутанно и противоречиво. Ваш API должен быть четким и (как мои преподаватели университета бьют меня) однозначно — например, слова «любой» и «кроме» не должны появляться в одном и том же предложении. Стремитесь к ясности — если вам кажется, что ваш API слишком сложен для четкого документирования, есть большая вероятность, что его будет раздражать. В случае выше, улучшение будет что-то вроде
01
02
03
04
05
06
07
08
09
10
|
/** * Get the free drink promised by the receipt. Not every burger qualifies for a free drink. * @param burger the requested burger. This may or may not qualify for a free drink * @param receipt the receipt containing the offer * @returns the free drink. May be null, depending on the burger */ public Drink getFreeDrink(Burger burger, Receipt receipt) { // implementation } |
Обратите внимание, что я также избавился от исключения из-за того, что был более явным.
Вывод
Как ни раздражает, документация чрезвычайно важна в правильном месте и совершенно бесполезна везде. Если все сделано правильно, они сделают ваш API более простым в использовании и обслуживании, что, как правило, хорошо.
Ссылка: Назад к основам — хорошие комментарии — это целевые комментарии от нашего партнера JCG Стива Чалонера в блоге Objectify .