Вы можете думать о веб-сервисе как об интерфейсе или API. Вы клиент этого интерфейса, API. Если интерфейс меняет вас как клиента, необходимо адаптировать ваш вызов. Нет хорошего способа справиться с этим. Обычно те, кто предоставляют API, должны поддерживать его стабильность и предлагать способы перехода на более новые версии и так далее. Но я полагаю, что вы не можете запросить это у службы погоды, о которой идет речь. Теперь, чтобы справиться с частой сменой интерфейса, вы можете сделать следующее: - создать свой собственный интерфейс, который определяет данные, которые вы хотите вернуть, это уровень абстракции. - закодируйте свой клиент в соответствии с вашим интерфейсом, к которому у вас есть контроль над изменениями, - осуществите реализацию ваших интерфейсов, запросив метеорологическую службу 1 или метеорологическую службу 2. Это всего лишь отображение данных. Метеослужбы 1 и 2 могут быть совершенно разными службами, или вы можете думать об одной и той же службе с разными версиями. Ни один из ваших клиентских кодов не должен изменяться, только это отображение будет меняться при изменении URL.
Это решение помогает вам легко переключаться между упомянутыми реализациями. То, что я описал, является решением ООП вашей проблемы, поэтому вам нужно будет использовать язык ООП, чтобы иметь полиморфное поведение.
Что касается последнего пункта, который вы можете выбрать, чтобы представить свой сервис (интерфейс, о котором я говорил выше) как сервис REST.
Я предпочитаю не использовать префикс в интерфейсах:
префикс повреждает удобочитаемость.
Используя интерфейсы в клиентах стандартный лучший способ программировать, таким образом, названия интерфейсов должны быть максимально краткими и приятными. Классы с реализацией должны быть более ужасными для воспрепятствования их использования.
При изменении от абстрактного класса до интерфейса конвенции кодирования с префиксом я подразумеваю переименование всех случаев класса---не хороший!
Есть ли действительно различие между:
class User implements IUser
и
class UserImpl implements User
, если все мы говорим о, соглашения о присвоении имен?
Лично я предпочитаю не предшествовать интерфейсу с I
, поскольку я хочу кодировать к интерфейсу, и я полагаю что быть более важным с точки зрения соглашения о присвоении имен. Если Вы называете интерфейс IUser
затем, каждый потребитель того класса должен знать IUser
. При вызове класса UserImpl
затем, только класс и контейнер DI знают о Impl
, часть и потребители просто знают, что они работают с User
.
С другой стороны, времена я был вынужден использовать Impl
, потому что лучшее имя не представляет себя, были немногочисленны, потому что реализация становится именованной соответственно к реализации, потому что это - то, где это важно, например,
class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO
Может быть несколько причин, Java обычно не использует конвенцию IUser.
Часть Объектно-ориентированного подхода - то, что Вам не придется знать, использует ли клиент интерфейс или класс реализации. Так, даже Список является интерфейсом, и Строка является фактическим классом, метод мог бы быть передан они оба - не имеет смысла визуально отличать интерфейсы.
В целом, мы на самом деле предпочтем использование интерфейсов в клиентском коде (предпочтите Список ArrayList, например). Таким образом, не имеет смысла заставлять интерфейсы выделиться как исключения.
соглашение о присвоении имен Java предпочитает более длинные имена с фактическими значениями к префиксам венгерского стиля. Так, чтобы код был максимально читаем: Список представляет список, и Пользователь представляет пользователя - не IUser.
Существует также другая конвенция, используемая многими проектами с открытым исходным кодом включая Spring.
interface User {
}
class DefaultUser implements User {
}
class AnotherClassOfUser implements User {
}
мне лично не нравится "I" префикс по простой причине что дополнительная конвенция. Таким образом, если я принимаю это, IIOPConnection означает интерфейс для IOPConnection? Что, если класс не имеет "I" префикса, сделайте я затем знаю не интерфейс.. ответ здесь не, потому что конвенции не всегда сопровождаются, и управление на основе политик ими создаст больше работы, которую сохраняет сама конвенция.
Bob Lee сказал однажды в презентации:
точки точка интерфейса, если у Вас есть только одна реализация.
так, Вы начинаетесь с одной реализацией т.е. без интерфейса. позже Вы решаете, ну, в общем, существует потребность в интерфейсе здесь, таким образом, Вы преобразовываете свой класс в интерфейс.
затем это становится очевидным: Ваш исходный класс был вызываемым пользователем. Ваш интерфейс является теперь вызываемым пользователем. возможно, у Вас есть UserProdImpl и UserTestImpl. при разработке приложения хорошо, каждый класс (кроме тех, которые инстанцируют Пользователя), будет неизменно и не заметит, что внезапно они передаются интерфейс.
, таким образом, это разбирается-> Интерфейсная Пользовательская реализация UserImpl.
В C# это
public class AdminForumUser : UserBase, IUser
, Java сказал бы
public class AdminForumUser extends User implements ForumUserInterface
Из-за этого, я не думаю, что конвенции почти как важные в Java для интерфейсов, так как существует явное различие между наследованием и интерфейсной реализацией. Я сказал бы, просто выбирают любое соглашение о присвоении имен, которое Вы хотели бы, пока Вы последовательны и используете что-то, чтобы показать людям, что это интерфейсы. Не сделали Java за несколько лет, но все интерфейсы просто были бы в их собственном каталоге, и это было конвенцией. Никогда действительно имел любые проблемы с ним.
По моему опыту, "I" конвенция относится к интерфейсам, которые предназначаются для обеспечения контракта классу, особенно когда сам интерфейс не является абстрактным понятием класса.
, Например, в Вашем случае, я только ожидал бы видеть IUser
, если единственный пользователь, которого Вы когда-либо намереваетесь иметь, User
. Если бы Вы планируете иметь различные типы пользователей - NoviceUser
, ExpertUser
, и т.д. - я ожидал бы видеть User
интерфейс (и, возможно, AbstractUser
класс, который реализует некоторую общую функциональность, как get/setName()
).
я также ожидал бы интерфейсы, которые определяют возможности - Comparable
, Iterable
, и т.д. - чтобы быть названными как этот, и не как IComparable
или IIterable
.
После хороших принципов OO должен Ваш код (до практического/возможного), зависят от абстракций, а не реальных классов. Например, обычно лучше записать метод как это:
public void doSomething(Collection someStuff) {
...
}
, чем это:
public void doSomething(Vector someStuff) {
...
}
, Если Вы следуете за этой идеей, затем я поддерживаю, что Ваш код будет более читаемым при предоставлении имен интерфейсов как "Пользователь" и "BankAccount" (например), а не "IUser", "UserInterface" или другие изменения.
единственные биты кода, который должен заботиться о фактических реальных классах, являются местами, где реальные классы создаются. Все остальное должно быть записано с помощью интерфейсов.
, Если Вы делаете это, затем "ужасные" имена реального класса как "UserImpl" должны быть безопасно скрыты от остальной части кода, который может весело продолжить использовать "хорошие" имена интерфейса.
Действительно ли это - более широкое соглашение о присвоении имен в каком-либо реальном смысле? Я нахожусь больше на стороне C++, и не действительно на Java и потомках. Сколько сообществ языка использует меня конвенция?
, Если у Вас есть независимое от языка соглашение о присвоении имен стандарта магазина здесь, используйте его. В противном случае пойдите с соглашением о присвоении имен языка.
Как сказал другой автор, обычно предпочтительно, чтобы интерфейсы определяли возможности, а не типы. Я бы не стал «реализовывать» что-то вроде «User», и именно поэтому «IUser» часто не нужен описанным здесь способом. Я часто рассматриваю классы как существительные, а интерфейсы как прилагательные:
class Number implements Comparable{...}
class MyThread implements Runnable{...}
class SessionData implements Serializable{....}
Иногда прилагательное не имеет смысла, но я бы все равно использовал интерфейсы для моделирования поведения, действий, возможностей, свойств и т.д., ... не типов.
Кроме того, если вы действительно собирались создать только одного пользователя и называть его пользователем, тогда какой смысл иметь интерфейс IUser? И если у вас будет несколько разных типов пользователей, которым необходимо реализовать общий интерфейс, что добавление «I» к интерфейсу спасет вас при выборе имен реализаций?
Я думаю, что более реалистичный пример мог бы помочь быть тем, что некоторые типы пользователей должны иметь возможность войти в определенный API. Мы могли бы определить интерфейс входа в систему, а затем иметь родительский класс «User» с суперклассами SuperUser, DefaultUser, AdminUser, AdministrativeContact и т. Д., Некоторые из которых будут или не будут реализовывать интерфейс входа (Loginable?) По мере необходимости.