Anti-Patterns или как делать не надо

Давно собирался собрать коллекцию анти-паттернов, дабы самому просвятиться и другим помочь. Данную заметку буду периодически пополнять, по мере нахождения последних.

Итак, азы! :)

Конкатенация строк

String s = "";
for (Item i : items) {
    s += ", " + i.getText();
}

Во-первых, конкатенация строк дело плохое, т.к. при этом образуется новый объект строки. Во-вторых, конкатенация в цикле приведет к тому, что для получения единственной конечной строки образуется items.length2 новых мусорных объектов.
Вместо конкатенации необходимо использовать StringBuffer (или даже лучше StringBuilder, если не нужна "thread safe"). При этом, выражения типа stringBuffer.append("val=" + value); естественно приведут к полной бесполезности использования StringBuffer'а.


Сравнение строк
Еще один пример anti-pattern'а - это сравнение строк. Сделать это можно так:

str == "dummy"
так:
str.compareTo("dummy") == 0
или, например, так:
str.equals("dummy")

Последний вариант хоть и является более правильным, но все же не идеал. Наиболее корректный подход - это
"dummy".equals(str)

В данном случае мы избежим NullPointerException (если str == null), а также, если сравнение происходит в цикле - метод equals будет вызываться у одного и того же объекта.


URL.equals...
Не используйте для сравнения java.net.URL метод equals, т.к. последний говорит true, если сравнивыемые хосты url'ов имеют одинаковый IP адрес. Например:

URL a = new URL("http", "stremoukhov.ru", "index.php");
URL b = new URL("http", "stremoukhov.com", "index.php");

System.out.println(a.equals(b));   // Выведет true!

Вместо этого можно использовать java.net.URI


Переопределение equals()
При переопределении метода equals() необходимо помнить, что понадобится переопределить hashcode() дабы они не противоречили друг другу, а также, в реализации метода не забыть сделать проверку на instanceof (которая также обезопасит от NullPointerException):

public boolean equals(Object obj) {        
    return (obj instanceof UserType) && this.id.equals(((UserType)obj).getId());
}


Создание immutable объектов
Тут все просто - незачем создавать новый immutable-объект, теряя время и ресурсы на его инициализацию и размещение в памяти. В качестве примера можно взять обертки примитивных типов. Статический метод valueOf() будет работать гораздо быстрее.

// Как делать не надо:
Integer i = new Integer(0);  
Boolean b = new Boolean(true);

// Правильно будет:
Integer i = Integer.valueOf(0);  
Boolean b = Boolean.TRUE;


Небуфферизированные потоки
Многие разработчики читают и записывают потоки по байтам, используя стандартные FileInputStream и FileOutputStream. Например:

InputStream in = new FileInputStream(file);  
int i;  
while ((i = in.read()) != -1) {  
}  

Такой подход плох тем, что каждый вызов in.read(), а точнее, чтение каждого байта порождает обращение к JNI (Java Native Interface). Намного эффективнее будет использовать Buffered Streams:
InputStream in = new BufferedInputStream(new FileInputStream(file));  

Отправить комментарий

Image CAPTCHA
Enter the characters shown in the image.