При разработке любого вида интерфейса кода, будь то элегантный объектно-ориентированный пакет или один из тех уродливых классов «Service», к которым мы так привыкли, очевидно, что он должен быть настолько расширяемым, насколько это возможно, и требовать как можно меньшего обслуживания , Это относится, конечно, к входным и выходным параметрам (возвращаемым типам), особенно если рассматриваемый код не может быть изменен его клиентами.
Вопрос в том, как мы можем иметь гибкие параметры, если они состоят из тупых моделей get / set? Каждый раз, когда требуется новое поле / атрибут, кто-то будет стучать в вашу дверь, чтобы обновить ваш интерфейс, потому что в противном случае он не сможет отправить или получить все необходимые данные.

Возьмите приведенный ниже пример:
|
1
2
3
4
5
6
|
public interface People extends Iterable<Person> { Person fetch (int id); boolean insert (Person person); //...} |
Предположим, что наш Person — это класс get / set, имеющий firstName , lastName и id . Когда пользователю этого интерфейса потребуется получить или отправить больше атрибутов, которые он не сможет, он попросит вас сначала изменить модель Person а затем добавить логику в ваш код для обработки этих атрибутов.
Решением этой проблемы является Полиморфизм, один из наиболее распространенных принципов ООП — он сделает наши параметры «прозрачными» и более удобными в обслуживании. Предполагая, что наши данные представлены в формате JSON, я бы изменил интерфейс People :
|
1
2
3
4
5
|
public interface People extends Iterable<Person> { Person fetch (int id); boolean insert (JsonObject person); //...} |
Есть два больших изменения: Person на самом деле является интерфейсом, расширяющим javax.json.JsonObject и в то же время анимирующим некоторые части базового json или, может быть, все — таким образом, если People.fetch(...) изменяется и возвращает больший JsonObject , новые значения будут доступны автоматически через JsonObject.getString(...) , пока мы не добавим больше метода чтения в интерфейс Person .
Второе изменение — это ввод, который ожидает метод insert(...) . Теперь он требует необработанного JsonObject по той же причине: если инкапсулированный сервис решит ожидать больше значений, пользователь просто добавит их в JsonObject . Это может звучать как уродливое решение, так как они могут использовать его так:
|
1
2
3
4
5
6
7
8
|
People people = ...people.insert( Json.createObjectBuilder() .add("id", 1) .add("firstName", "John") .add("lastName", "Doe") .build()); |
Вышесказанное довольно уродливо, создание JsonObject означает дублированную логику. Однако пользователь должен понимать, что он может реализовать интерфейс PersonInput extends JsonObject — вся эта логика построения будет в конструкторе реализации PersonInput , в то время как вызовы people.insert(...) будут выглядеть следующим образом:
|
1
2
3
4
|
People people = ...people.insert( new PersonInput(1, "John", "Doe")); |
Относительно входного параметра JsonObject остается еще один вопрос: как клиент должен знать, какие значения предоставить? Это та часть, где JavaDocs вступает в игру: все это должно быть тщательно задокументировано в JavaDoc метода. Я думаю, вы можете назвать это хорошим компромиссом: пользователь должен немного изучить, прежде чем использовать ваш метод, но, с другой стороны, разделение очень удобно для вас обоих.
Точный подход, описанный выше, я использовал при разработке docker-java-api . Большинство методов, которые создают что-то на сервере, ожидают JsonObject качестве входных данных и возвращают интерфейсы, расширяющие JsonObject (см., Например, Containers.create (…) и Container ) — таким образом, если API Docker будет развиваться, требуя различных входов Json или верните разные Jsons, мне не обязательно менять какие-либо модели в ближайшее время.
PS Надеюсь, вы заметили, что ключевое слово в этой статье — «интерфейс». Это еще один пример того, почему интерфейсы являются очень важными инструментами, которые должен использовать любой объект.
|
Опубликовано на Java Code Geeks с разрешения MIhai Andronache, партнера нашей программы JCG. Смотрите оригинальную статью здесь: Полиморфные данные ввода / вывода Мнения, высказанные участниками Java Code Geeks, являются их собственными. |