Какие вещи нужно иметь в виду при стремлении к хорошему классу?
Вчера я присутствовал на интервью в одной ведущей ИТ-компании. Техническое интервью было хорошим, никаких проблем, затем я перешел на другой набор раундов "Управление, дизайн и процесс". Я ответил на все, кроме вопроса ниже.
Вопрос, заданный интервьюером:
Скажем, вы разрабатываете класс, который я собираюсь использовать в своих класс, расширяя это, каковы ключевые моменты, которые вы держите в разум? Ex, класс A, который имеет метод под названием "метод A", возвращает коллекцию, скажем, "список". Какие меры предосторожности вы предпримете?
Мой ответ: следующие пункты, которые я рассмотрю, например:
- Класс и метод должны быть общедоступными.
- Метод 1 возвращает список, тогда это должно быть дженериками. Таким образом, мы можем избежать исключения класса cast
- Если этот класс будет доступен в многопоточной среде, этот метод необходимо синхронизировать.
Но интервьюер не был убежден в моих замечаниях. Он ожидал от меня другого ответа, но я не могу понять, что он задумал.
Поэтому, пожалуйста, предоставьте свои предложения.
Ответы
Ответ 1
Я бы хотел, чтобы вы придерживались принципов единственной реанимации, Open/Close и Injection Dependency Injection. Держите его без гражданства, простым и проверяемым. Убедитесь, что он может быть расширен без изменения.
Но тогда я не брал с вами интервью.
Ответ 2
Еще несколько пунктов, которые еще не были упомянуты, будут:
- Достойная документация для вашего класса, так что вам не нужно слишком углубляться в свой код, чтобы понять, какую функциональность вы предлагаете, и что такое gotchas.
- Попробуйте расширить свой класс, прежде чем передавать его кому-то другому. Таким образом, вы лично можете почувствовать боль, если ваш класс плохо разработан и тем самым может его улучшить.
- Если вы возвращаете список или какую-либо коллекцию, необходимо задать один важный вопрос: "может ли вызывающий абонент изменить возвращенную коллекцию"? Или "этот возвращенный список является прямым представлением внутреннего состояния вашего класса?". В этом случае вы можете захотеть вернуть копию, чтобы избежать звонков, которые вмешиваются в ваше внутреннее состояние, т.е. поддерживать правильную инкапсуляцию.
- Планирование видимости методов. Нарисуйте явную строку между методами
public
, protected
, package private
и private
. Убедитесь, что вы не раскрываете больше, чем хотите. Извлечение функций затруднительно. Если что-то отсутствует в вашем хорошо разработанном API, вы можете добавить его позже. Но вы раскрываете множество бесполезных публичных методов, вы действительно не можете обновлять свой API без устаревших методов, так как вы никогда не знаете, кто еще его использует.
Ответ 3
Если вы возвращаете коллекцию, первое, о чем вы должны подумать, - это защитить себя от вызывающего меняющего моего внутреннего состояния, например.
List list = myObject.getList();
list.retainAll(list2);
Теперь у меня есть все общие элементы между list1
и list2
Проблема заключается в том, что myObject может не ожидать, что вы уничтожите содержимое списка, который он вернул.
Два общих способа исправить это - взять защитную копию или обернуть коллекцию с помощью Collections.unmodifiableXxxx()
Для дополнительной паранойи, вы можете сделать и то, и другое.
Я предпочитаю обойти это, чтобы вообще не возвращать коллекцию. Вы можете вернуть счет и метод для получения n-го значения или для карты вернуть ключи и предоставить getter, или вы можете позволить посетителю каждого элемента. Таким образом, вы не открываете свою коллекцию или не нуждаетесь в копии.
Ответ 4
Вопрос очень общий, но я хочу добавить несколько пунктов:
- За исключением метода, который вы хотите открыть, вы можете использовать другие методы и переменную private. Целая точка сохраняет видимость до минимума.
- Где бы это ни было возможно сделать его неизменным, это уменьшит накладные расходы в среде mutithreaded.
- Возможно, вам захочется оценить, поддерживается ли сериализуемость или нет. Если нет, не предоставляйте конструктор по умолчанию. И если сериализуемое значение, то оцените сериализованный шаблон прокси.