Java Leaky Проверка абстракции - PullRequest
4 голосов
/ 24 февраля 2009

Я обдумываю идею написания программы для проверки "дырявые абстракции" в Java. Одна область, которая сразу же пришла в голову, за исключением:

public class X
{
    // this one is fine, Readers throw IOExceptions so it is 
    // reasonable for the caller to handle it
    public void parse(final Reader r)
        throws IOException
    {
    }

    // This one is bad.  Nothing in the API indicate that JDBC 
    // is being used at all.
    public void process()
        throws SQLException
    {       
    }
}

Обратите внимание, я не хочу аргумент относительно относительных достоинств проверенных / непроверенных исключений. То, что я ищу, - это другие примеры (не обязательно для обработки исключений), которые есть у людей, которые также могут быть разумно обнаружены путем изучения исходного кода или файлов классов.

Мне известны чекстайл, findbugs и PMD, и AFAIK ни один из них не занимается этим (и я не против вставлять чеки в один из этих инструментов, а не писать свои).

Есть ли еще примеры утечек абстракций, о которых вы можете подумать, которые можно статически проверить?

EDIT:

Причина, по которой второй является плохим, заключается в том, что метод генерирует исключение, когда клиент не может знать, что используется JDBC (например, это может быть что угодно). Таким образом, «дырявая абстракция» заключается в том, что используется JDBC. Если базовый механизм изменился на что-то другое (скажем, JPA, который является другой библиотекой абстракции базы данных), то исключения также должны будут измениться. Таким образом, базовая библиотека базы данных просочилась.

Ответы [ 4 ]

2 голосов
/ 24 февраля 2009

Поскольку я не обнаружил вопрос в исходном посте, я буду бродить.

Любой такой инструмент должен был бы заставить пользователя сообщать ему, какие исключения квалифицируются как непротекаемые для данного класса, а все, что отсутствует в таком списке, будет утечкой.

Это всего лишь исключения. Насколько я понимаю, дырявые абстракции относятся к гораздо большему. Учтите это:

class Client
{
    private Integer ID;

    public Integer ID() { return this.ID; }
}

Это квалифицируется как утечка? Если позже мне нужно будет представить идентификатор как Long, то это так. Вы можете исправить такой сценарий так:

class Client
{
    private ClientID ID;

    public ClientID ID() { return this.ID; }
}

class ClientID
{
    private Integer value;

    public ClientID(String id) { this.value = Integer.parseInt(id); }

    public String asString() { return value.toString(); }

    ... other methods that don't reveal value's type here ...
}

Это решило бы утечку из Client, но теперь вы запускаете инструмент на ClientID. Это протекает?

Это может стать еще сложнее, если вам придется исследовать методы, которые не являются простыми получателями. Что, если у ClientID был метод, который выполнил некоторую математическую операцию над своим ID (потакает мне) и вернул Integer. Это утечка? Означает ли это утечку, что значение является целым числом?

Так что я не уверен, что это запах кода, который машина может легко уловить.

2 голосов
/ 24 февраля 2009

Зв

Как определить, если API утечка деталей реализации или не поддерживает тот же уровень абстракции.

Вы, вероятно, можете посмотреть этот разговор . В нем объясняется, как выглядят и разрабатываются хорошие API-интерфейсы (из хороших практик можно вывести, что является плохими)

Например

Функциональность должна быть легко объяснима. Если это жесткое имя, то, как правило, плохой дизайн.

Из этого вы можете обнаружить, что если методы или возвращаемые параметры дают подробные инструкции, они не соответствуют уровню абстракции.

Например, метод высокого уровня

 -initProcess(): SGN_MTL

Может быть утечка деталей реализации возвращаемого значения.

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

Например, в вашем методе было бы нормально использовать SQLExceptions, если сам код является реализацией уровня JDCB.

Другим источником, где вы можете увидеть больше этих тем, является этот список. http://www.jetbrains.com/idea/documentation/inspections.jsp

См. Пункты в разделе "Абстракция", т.е.

  • Переменная экземпляра конкретного класса: отчет, когда тип переменной экземпляра объявлен как конкретный класс, а не как интерфейс.

Классический пример:

 private ArrayList list;

когда будет лучше

 private List list;
0 голосов
/ 24 февраля 2009

Мысль о другом. Наличие открытого члена, который имеет дело с закрытым типом.

class Foo { ... } // local to the package

public class Bar
{
    class Car() { ... }

    public Bar(Foo f) { ... }

    public Car star() { ... }
}

Бар и звезда будут дырявыми. Вы можете видеть конструктор Bar b, но вызывать его можно только из того же пакета, что и класс Bar. Вы можете вызвать метод star, но можете использовать только возвращаемое значение как Object.

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

0 голосов
/ 24 февраля 2009

Вы можете рассмотреть возможность распространения вашего примера для проверки нарушений на Принцип замены Лискова . Некоторые скажут, что класс, реализующий интерфейс, должен выдавать только те же исключения, которые определены интерфейсом.

Если бы вы могли проанализировать использование объекта, было бы неплохо предложить использовать более общий тип (например, метод требует SQLConnection, когда будет делать IDBConnection).

...