Страница 1 из 2

Суффикс для интерфейсов

Добавлено: 2019.07.04, 19:52
samdark
В Yii 1.1 интерфейсы именовались как `IName`. В Yii 2 используется `NameInterface`. В Yii 3 я попробовал убрать суффикс. Получились имена вроде ErrorRenderer.

Что вы думаете на эту тему?

Re: Суффикс для интерфейсов

Добавлено: 2019.07.04, 20:05
chungachguk
Думаю, что лучше без суффиксов. Потому как если есть класс реализации интерфейса, то это будет что-то конкретное, завязанное на какое-то особенное поведение, а значит в его название можно будет об этом упомянуть. Если такого сделать не получается, значит интерфейс не сильно-то и нужен.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.04, 21:19
Loveorigami
Дело привычки, но я за суффикс.

Иначе:
ErrorRenderer implements ErrorRenderer
ErrorException implements ErrorException
и тд...
Где интерфейс, а где класс?

-----------

1. ErrorRenderer implements ErrorRendererInterface
в шторме легче найти или класс, или интерфейс.

2. psr именует как LoggerInterface

https://github.com/php-fig/log/tree/master/Psr/Log

Re: Суффикс для интерфейсов

Добавлено: 2019.07.05, 06:34
chungachguk
Loveorigami писал(а):
2019.07.04, 21:19
Дело привычки, но я за префикс.

Иначе:

ErrorRenderer implements ErrorRenderer

Где интерфейс, а где класс?
К примеру здесь интерфейс можно было назвать Renderable и сделать класс его реализующий ErrorRenderer. По-большому счёту, интерфейс это просто маркер, указывающий, что в данном классе есть какая-то функциональность. К тому же один класс необязательно должен реализовывать только один интерфейс, может и десяток реализаций в себе иметь, и в своём именовании не должен быть зависим от названия интерфейса.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.05, 09:22
dimsog
Понятное дело, что во всех книгах говорят используйте *able, Runnable, Throwable и так далее. Но RequestInterface, DataObjectInterface и так далее. Я за Interface на конце.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.05, 12:56
NeverDie
Я тоже за суффикс. А если без, то как же psr?
https://www.php-fig.org/bylaws/psr-naming-conventions/

Re: Суффикс для интерфейсов

Добавлено: 2019.07.05, 13:25
BrusSENS
Я тоже не понимаю, как может быть без суффикса, если 3 мажор следует PSR

Re: Суффикс для интерфейсов

Добавлено: 2019.07.05, 14:39
samdark
Ссылка выше не на стиль кода для внешних проектов, а на внутренний документ PHP-FIG, стандартизирующий именование в рамках самих PSR-документов.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.05, 15:20
Loveorigami
samdark писал(а):
2019.07.05, 14:39
Ссылка выше не на стиль кода для внешних проектов, а на внутренний документ PHP-FIG, стандартизирующий именование в рамках самих PSR-документов.
... коими потом будут пользоваться во всех PSR совместимых пакетах

https://github.com/php-fig/log/blob/mas ... erface.php

Вы же Yii3 для чего на пакеты разнесли? Чтоб никто не мог понять, что там внутри? ;)

Через пол-года эдак напишите (не заходя внутрь), что из этого интерфейс https://github.com/yiisoft/yii-web/tree ... rorHandler
Не говоря уже о тех, кто видит это впервые.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.05, 17:32
samdark
Итого пока будем с суффиксом: https://github.com/yiisoft/docs/blob/ma ... erfaces.md

Решение до релиза можно поменять.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.07, 14:41
skynin
часто
В мире Java
интерфейс
SomeEntity
реализация
SomeEntityImpl // метят суффиксом реализацию

В C#
интерфейс
ISomeEntity // метят префиксом интерфейс
реализация
SomeEntity

-- интерфейс это просто маркер, указывающий
так то оно так...

но, приходится читать в коде
instanceof SomeEntity

и гадать, если одинаковые названия
так что проверяем то - класс или интерфейс?

тот же вопрос с указанием типа в параметрах метода
скролить вверх, смотреть какой use?

Итого:
1. названия интерфейса и класса реализации должны отличаться
2. для автокомлита в IDE удобней префикс, а не суффикс
3. Но раз написано Interfaces MUST be suffixed by Interface: e.g. Psr\Foo\BarInterface то и ладно, пункт 1 соблюден

Re: Суффикс для интерфейсов

Добавлено: 2019.07.08, 12:26
Nex-Otaku
1. Предлагаю убрать требование суффикса "Interface" для интерфейсов из соглашения.

2. Считаю, что этот суффикс только уродует и захламляет код. Повторение бесполезной информации в коде, затрудняет его чтение.

3. С суффиксом "Interface" усложняется рефакторинг.

Например, у нас есть компонент Cache, который используется в 500 классов системы через внедрение зависимостей. Подключается конкретный класс Cache.

Допустим, нам понадобилось реализовать новый вид кеширования. Был файловый кеш, а мы решили сделать ещё кеш в памяти, для быстрого запуска тестов.

Без суффикса, нам пришлось бы изменить только один файл - Cache. Заменив в нём ключевое слово "class" на "interface", и написав две реализации этого интерфейса, мы успешно решаем задачу.

С суффиксами, к этим действиям прибавляется переименование класса и соответственно изменение 500 связанных с ним классов.

4. Откуда взялось требование суффикса интерфейса в соглашении?

Я уверен, что такое требование перешло в соглашение из невнимательного прочтения соглашения PSR: https://www.php-fig.org/bylaws/psr-naming-conventions/

Если приглядеться внимательнее, станет ясно, что этот стандарт описывает не стандарт для кодирования, а стандарт написания самих текстов PSR. То есть это стиль документации, а не стандарт кода.

Видимо, разработчика соглашения ввёл в заблуждение заголовок "PSR Naming Conventions", и стиль не глядя был скопирован в соглашения кода.

5. В списке актуальных стандартов, разумеется, этого нет. Ни один из действующих и ни один из устаревших стандартов PSR не предлагает использовать суффиксы для интерфейсов.
См. https://www.php-fig.org/psr/

Re: Суффикс для интерфейсов

Добавлено: 2019.07.08, 12:34
Nex-Otaku
skynin писал(а):
2019.07.07, 14:41
но, приходится читать в коде
instanceof SomeEntity

и гадать, если одинаковые названия
так что проверяем то - класс или интерфейс?
Зачем гадать? Какая разница, что там? Какое это может иметь значение? Можешь описать ситуацию, в которой твои дальнейшие после "гаданий" действия различаются, в зависимости от того, класс это или интерфейс?
skynin писал(а):
2019.07.07, 14:41
тот же вопрос с указанием типа в параметрах метода
скролить вверх, смотреть какой use?
Тот же вопрос. Какое дело разработчику, класс обозначается или интерфейс? Ему важно лишь, что тип объекта соответствует ожидаемому. Есть такой-то тип, он даёт нам возможность пользоваться такими-то методами и ожидать такого-то поведения. Согласованная абстракция.
skynin писал(а):
2019.07.07, 14:41
3. Но раз написано Interfaces MUST be suffixed by Interface: e.g. Psr\Foo\BarInterface то и ладно, пункт 1 соблюден
Это написано в PSR для стиля ДОКУМЕНТАЦИИ, а не кода. К сожалению, немногие видят различие, как и показывают комментарии в этом топике.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.08, 12:48
Nex-Otaku
Loveorigami писал(а):
2019.07.04, 21:19
Дело привычки, но я за префикс.

Иначе:
ErrorRenderer implements ErrorRenderer
ErrorException implements ErrorException
и тд...
Где интерфейс, а где класс?
Если интерфейс описывает общую для нескольких классов абстракцию, то это будет выглядеть так:

Код: Выделить всё

interface Renderer { public function render():string; }

class ErrorRenderer implements Renderer {}

class HtmlRenderer implements Renderer {}


class AccessDenied implements AppException {}

class FileNotFound implements AppException {}
Если же для каждого интерфейса существует только один класс, то интерфейс в этом случае и не нужен. Достаточно указывать класс.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.08, 19:39
Loveorigami
Nex-Otaku писал(а):
2019.07.08, 12:26

3. С суффиксом "Interface" усложняется рефакторинг.

Например, у нас есть компонент Cache, который используется в 500 классов системы через внедрение зависимостей. Подключается конкретный класс Cache.
Думаю, не стоит приводить частные случаи и делать обобщающие выводы.

1. Что мешало изначально сделать через интерфейс?
2. Когда я открываю DI - с префиксом я вижу, где у меня класс, а где у меня интерфейс.

Код: Выделить всё

$container->set('app\cache\CacheInterface', 'app\cache\FileCache');
легко меняю

Код: Выделить всё

$container->set('app\cache\CacheInterface', 'app\cache\RedisCache');
В вашем DI будет список классов, непонятно как сконфигурированных (то ли класс, то ли интерфейс). Если я и запомню как-то это все, то каждому новому человеку в команде нужно будет дополнительно все это изучать...

Опять же повторюсь, откройте пакет https://github.com/php-fig/log/tree/master/Psr/Log, мысленно уберите там суффикс Interface. И попробуйте теперь написать свою реализацию логера. А если не известно, где лежит класс и нужно в шторме найти. Набрав LoggerI...я уже его найду. А если искать Logger (по вашему без суффикса) - мне в выдачу попадут все вперемешку - и интерфейсы, и классы...

Так что я за суффикс, однозначно. Я лучше переименую 500 классов за пару сек в шторме, зато это избавит меня от последующих трат времени при разработке.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.09, 16:37
Nex-Otaku
Loveorigami писал(а):
2019.07.08, 19:39
1. Что мешало изначально сделать через интерфейс?
KISS - Keep It Simple, Stupid.

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

Как только понадобилась вторая реализация - впору и интерфейс создать, если это опять же уместно.

Ну а если вы на всё и вся заранее плодите интерфейсы, то вы замусориваете свой проект.
Loveorigami писал(а):
2019.07.08, 19:39
2. Когда я открываю DI - с префиксом я вижу, где у меня класс, а где у меня интерфейс.

Код: Выделить всё

$container->set('app\cache\CacheInterface', 'app\cache\FileCache');
легко меняю

Код: Выделить всё

$container->set('app\cache\CacheInterface', 'app\cache\RedisCache');
В настройках контейнера в такой строке может быть только интерфейс, иначе это весьма странное переопределение классов, попахивающее "костылями". Вы часто так делаете?
Loveorigami писал(а):
2019.07.08, 19:39
В вашем DI будет список классов, непонятно как сконфигурированных (то ли класс, то ли интерфейс). Если я и запомню как-то это все, то каждому новому человеку в команде нужно будет дополнительно все это изучать...
Если код Yii плохо читается, то это решается простой обёрткой. Сделайте свой метод, и используйте его.

Код: Выделить всё

$this->setImplementation('app\cache\Cache', 'app\cache\FileCache')
Loveorigami писал(а):
2019.07.08, 19:39
Опять же повторюсь, откройте пакет ...
Именование классов в фреймворке должно зависеть от произвольных сторонних пакетов? Или оно должно быть самостоятельным?
Вы код своего проекта тоже делаете максимально зависимым от используемых библиотек и фреймворков?

Re: Суффикс для интерфейсов

Добавлено: 2019.07.09, 16:43
Nex-Otaku
Чтобы использование суффикса было осмысленным, этот суффикс должен давать дополнительную ПОЛЕЗНУЮ информацию разработчику, читающему код.

Информация полезна только тогда, когда она влияет на решения. Если читая "ага, это интерфейс", я принимаю другое решение, чем прочитав "ага, это класс", то это и есть польза. Вы можете такой пример привести, реалистичный? Попробуйте.

Если не можете - значит, эта информация только кажется вам полезной, а на самом деле такой не является.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.09, 18:35
chungachguk
skynin писал(а):
2019.07.07, 14:41
часто
В мире Java
интерфейс
SomeEntity
реализация
SomeEntityImpl // метят суффиксом реализацию

В C#
интерфейс
ISomeEntity // метят префиксом интерфейс
реализация
SomeEntity
Кстати говоря, а как с этим обстоит дело в PHP? Может стоит от этого и отталкиваться?

Re: Суффикс для интерфейсов

Добавлено: 2019.07.09, 20:21
samdark
В PHP большинство суффиксит Interface.

Re: Суффикс для интерфейсов

Добавлено: 2019.07.09, 20:49
Loveorigami
Речь шла про компонент кеша. Для которого уже есть PSR. Мы обсуждаем Yii3-пакет, а не Yii2-монолит.
Именование классов в фреймворке должно зависеть от произвольных сторонних пакетов?
1. Отвечать вопросом на вопрос - это не конструктивная дискуссия.

2. Не просто фреймворк, a PSR совместимый
https://github.com/yiisoft/docs/blob/ma ... roadmap.md

3. Эти же пакеты потом будут использовать в других проектах, и даже не Yii-разработчики. Симфони в пример.

4. Откройте любой компонент в Симфони. Первый попавшийся - https://packagist.org/packages/symfony/console (147 915 885 установок)
- открываем любой класс https://github.com/symfony/console/blob ... Logger.php
- что мы видим в use ?
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
5. Тоже для Slim - https://github.com/slimphp/Slim/tree/3. ... Interfaces

6. В laravel - там все структурировано монолитом. https://github.com/laravel/framework/tr ... /Contracts
Да, без префикса, но все интерфейсы в одном месте. Но это не путь для Yii3.

А то что вне - use Illuminate\Database\ConnectionResolverInterface - в общем, поизучайте https://github.com/laravel/framework/se ... =Interface

7. Навскидку, пару библиотек
- Doctrine https://github.com/doctrine/orm/tree/ma ... ctrine/ORM
- Guzzle https://github.com/guzzle/guzzle/tree/master/src
- Flysystem https://github.com/thephpleague/flysyst ... master/src

8. В самом PHP - https://www.php.net/manual/en/class.dat ... erface.php и др.

9. Любой принятый PSR - https://github.com/php-fig/fig-standard ... r/accepted

https://github.com/php-fig/fig-standard ... e-cache.md

Т.е. почему, если уже выработано некое негласное правило среди программистов по интерфейсам, мы должны стоять особняком только потому, что так "проще рефакторить" отдельно взятому программисту. Но рефакторить - не только поменять имя, но и переместить в другую папку. В таком случае Ваш выше упомянутый класс разве не потребует 500 изменений в других файлах? Так что Ваши аргументы меня не убедили.
Если код Yii плохо читается, то это решается простой обёрткой. Сделайте свой метод, и используйте его.
Для меня плохочитающимся кодом является такой (вопрос, на который Вы не ответили)

Код: Выделить всё

use Google\Auth\CacheTrait;
use GuzzleHttp\Event\BeforeEvent;
use GuzzleHttp\Event\RequestEvents;
use GuzzleHttp\Event\Subscriber;
use Psr\Cache\CacheItemPool;
и хорошо читающимся

Код: Выделить всё

use Google\Auth\CacheTrait;
use GuzzleHttp\Event\BeforeEvent;
use GuzzleHttp\Event\RequestEvents;
use GuzzleHttp\Event\SubscriberInterface;
use Psr\Cache\CacheItemPoolInterface;
https://github.com/googleapis/google-au ... criber.php

И далее код я могу не смотреть уже...
Информация полезна только тогда, когда она влияет на решения. Если читая "ага, это интерфейс", я принимаю другое решение, чем прочитав "ага, это класс", то это и есть польза. Вы можете такой пример привести, реалистичный? Попробуйте.
пожалуйста

Не открывая каждый класс, я уже вижу, что последних два я могу в DI заменить на свои реализации.

Не просто кеш, а CacheItemPoolInterface - а дальше я уже смотрю в DI, а какой кеш у меня в системе. А если у данного пакета нет нужной мне реализации

https://github.com/PHPixie/Cache/tree/m ... ivers/Type

Идем на пакажист и выбираем, что нравится

https://packagist.org/packages/psr/cach ... nts?page=1

https://packagist.org/packages/zendframework/zend-cache

https://github.com/zendframework/zend-c ... ge/Adapter

Или настраиваем, или смотрим пример и пишем (копируем) к себе в проект нужный адаптер.