При разработке любого вида интерфейса кода, будь то элегантный объектно-ориентированный пакет или один из тех уродливых классов «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, являются их собственными. |