Предположим, что группа разработчиков работает параллельно над частями большого проекта. Некоторые разработчики работают над реализацией сервиса, в то время как другие работают над кодом, использующим этот сервис. Обе группы согласовали сервисный API и начали работать отдельно с учетом предположений API.
Как вы думаете, у этой истории будет счастливый конец? Ну, … — может быть ? Есть инструменты, которые могут помочь достичь этого. Одним из таких инструментов является FindBugs , поддерживаемый JSR-305 (аннотации для обнаружения дефектов программного обеспечения).
Давайте посмотрим на контракт API сервиса:
package com.blogspot.vardlokkur.services;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import com.blogspot.vardlokkur.entities.domain.Employer;
/**
* Defines the API contract for the employer service.
*
* @author Warlock
* @since 1.0
*/
public interface EmployerService {
/**
* @param identifier the employer's identifier
* @return the employer having specified {@code identifier}, {@code null} if not found
*/
@CheckForNull Employer withId(@Nonnull Long identifier);
/**
* @param specification defines which employers should be returned
* @return the list of employers matching specification
*/
@Nonnull List<Employer> thatAre(@Nonnull Specification specification);
}
Как видите, к сигнатурам метода службы добавляются аннотации, такие как @Nonnull или @CheckForNull . Цель их использования — определить требования к параметрам метода (например, параметр identifier не может быть нулевым ), а ожидания значений, возвращаемых методами (например, результат метода службы, могут быть нулевыми, и вы должны проверить это в своем коде ).
Ну и что? — спросите вы, — должен ли я сам проверить их в коде или доверить коллегам, что они будут использовать руководящие принципы, определенные этими аннотациями? Конечно, нет ? — никому не доверяйте, используйте инструменты, которые проверят предположения API, такие как FindBugs .
Предположим, что у нас есть следующий сервис API:
package com.blogspot.vardlokkur.test;
import org.junit.Before;
import org.junit.Test;
import com.blogspot.vardlokkur.services.EmployerService;
import com.blogspot.vardlokkur.services.impl.DefaultEmployerService;
/**
* Employer service test.
*
* @author Warlock
* @since 1.0
*/
public class EmployerServiceTest {
private EmployerService employers;
@Before
public void before() {
employers = new DefaultEmployerService();
}
@Test
public void test01() {
Long identifier = null;
employers.withId(identifier);
}
@Test
public void test02() {
employers.withId(Long.valueOf(1L)).getBusinessName();
}
@Test
public void test03() {
employers.thatAre(null);
}
}
Давайте попробуем проверить код в соответствии с предположениями API сервиса:
FindBugs проанализирует ваш код и переключится на перспективу FindBugs, показывая потенциальные проблемы:
![]() |
| Null передан для ненулевого параметра |
![]() |
| Возможно разыменование нулевого указателя |
Аналогичным образом, ребята, пишущие служебный код, могут проверить свою работу в соответствии с определенными предположениями API, например если вы запустите FindBugs для самой ранней версии реализации сервиса:
package com.blogspot.vardlokkur.services.impl;
import java.util.List;
import com.blogspot.vardlokkur.entities.domain.Employer;
import com.blogspot.vardlokkur.services.EmployerService;
import com.blogspot.vardlokkur.services.Specification;
/**
* Default implementation of {@link EmployerService}.
*
* @author Warlock
* @since 1.0
*/
public class DefaultEmployerService implements EmployerService {
/**
* {@inheritDoc}
*/
public Employer withId(Long identifier) {
return null;
}
/**
* {@inheritDoc}
*/
public List<Employer> thatAre(Specification specification) {
return null;
}
}
Следующая ошибка будет найдена:
Как видите, ничто не может спрятаться от FindBugs и его союзника — JSR-305;)
Еще несколько ссылочных ссылок:
- JSR-305: аннотации для обнаружения дефектов программного обеспечения
- JSR 305: серебряная пуля или не пуля вообще?



