> вы бы еще про уборщицу вспомнили, которая в теле изменила бы параметр, а в заголовке нет
А вот запросто, видел кучу кода (да и вот прямо сейчас гляжу на него) в котором в phpdoc вообще нет названий аргументов, только их типы. Поэтому phpdoc, в отличие от автокомплита, можно полноценно использовать только в идеальном мире. Да и от его *устаревания* никто не застрахован.
Для ключей массивов ни одна IDE не делает авкомплит. Отслеживать изменения в них гораздо сложнее (вручную). Нет проверки в рантайме со стороны языка (снова вручную и при вызове и в самой функции). и т.д.
> И вариант с именованными параметрами куда удобнее чем передавать массив типа $options, у которого неизвестно какие ключи.
В качестве ключей можно использовать константы класса (многословно, да). Да и потом, тут многие пишут «20 параметров слишком много», какой смысл этой «фичи» при 4-5 параметрах? Никакого.
А насчет рефакторинга — не все IDE его поддерживают (привет PDT), к сожадению. Да и изменить только название метода гораздо быстрее и проще чем проверять и изменять еще и его аргументы (имена которых, ИМХО, вообще относятся к внутренней реализации метода и не должны никаким образом влиять на вызывающий код).
Хотя бы что нужно постоянно в документацию лазить, чтобы узнать какие параметры есть. Впрочем, это отчасти решается константами класса (CreateThumbnailParams::QUALITY), но получается многословно.
> И я еще жду ответа на вопрос как разговнокодить createThumbnail
В идеально мире: создать класс Thumbnail, в конструктор передавать $source, также добавить в него методы для установки всех свойств (setCrop и т.д.) и потом вызывать create($destination).
И в случае переименовывания параметров этого метода придется переписывать весь код, который его использовал? На фиг… «default» в этом плане гораздо нагляднее.
Первый абзац порезался :( (читать сначала этот комментарий, а потом тот что выше)
Отличие у них всего одно — концептуальное: интерфейс это «поведение» без реализации; абстрактный класс — частичная реализация какого-либо поведения (конкретная реализация переложена на плечи потомков). Из этого отличия как раз и вытекают все свойства интерфейсов: реализация методов в них бессмысленна (и противоречит концепции), т.к. автоматически превращает интерфейс в абстрактный класс (обратное тоже верно — абстрактный класс содержащий только абстрактные методы можно считать интерфейсом); множественная реализация интерфейсов, в отличие от множественного наследования, разрешена т.к. не может породить конфликтов реализаций; и т.д.
На самом деле выбор того что использовать зависит от задачи, опыта и личных предпочтений разработчика. Например, в публичных библиотеках могут быть удобнее интерфейсы, т.к. они делают код стороннего приложения более независимым от конкретной реализации (= этой библиотеки) и позволяют скрыть от посторонних собственные внутренности (повышает дуракоустойчивость и понижает требования к коду). В закрытых проектах с небольшим деревом классов могут быть удобнее абстрактные классы, т.к. они позволяют избавиться от лишних сущностей (= интерфейсов) и тем самым еще более упростить код (это работает только до определенного момента, не всегда и не везде).
Ну и реальный пример: в приложении нужен платежный шлюз (ПШ), который должен уметь проводить платежи через несколько платежных систем (ПС). Вопрос как лучше реализовать?
1) Возможность расширения плагинами не предполагается: В этом случае наиболее рационально и просто реализовать класс Абстрактной ПС (АПС), от которой будут наследоваться все остальные ПС и переопределять необходимые методы (но вот часть методов логично расположить именно в АПС, поскольку они будут одинаковыми для всех ПС). Сам ПШ будет оперировать только АПС.
2) Решили дать возможность плагинам добавлять свои ПС: Можно оставить предыдущую модель, но в этом случае сторонним разработчикам придется разбираться в вашей реализации (в большом старом приложении 100% будет куча подводных камней в АПС, да и сам код, скорее всего, будет закрыт). Поэтому вместо этого логичнее вынести общие для всех ПС методы из АПС в Интерфейс ПС (ИПС) и заставить все ПС реализовывать его (фактически только АПС, которая в этом случае никуда не денется). Сам же ПШ вместо АПС станет оперировать ИПС.
ЗЫ: А данном контексте: публичный — совместно используемая библиотека; закрытый — конечный проект (код нигде повторно не используется).
> который будет редактироваться не сильно продвинутым пользователем
У вас «хорошее» мнение о большинстве PHP разработчиков :)
> IDE и автокомплит вещи не связанные.
IDE там не просто так в кавычки взято.
ЗЫ: Печальная дискуссия получилось, почему адепты json-а молчат про «json schema»? Я вот, например, только что о ней узнал (что неудивительно в виду её малой распространенности), а она как раз и является альтернативой XML схемам (но её поддержка опять же гораздо меньше).
Посмотрите немного шире — XML это целая куча технологий, например, то же описание пакетов в статичном HTML можно было бы генерировать с помощью XSLT (про документацию к схеме я молчу). Но зачем? Правильно, лучше json и еще пару велосипедов.
> Про DSL на PHP — как вы будете разбирать такие описания пакетов на центральном сервере (packagist?) не рискуя безопасностью?
Ключевое тут DSL, а значит очень узкая область применения, и, как следствие, совсем небольшой набор синтаксических конструкций => можно через tokenizer проверить чтобы присутствовали только разрешенные методы (если реализация DSL будет через методы, что, опять же, логично из-за автокомплита). Или же, может быть, можно использовать песочницу из runkit-а (не пробовал).
Ниже ashofthedream почти тоже самое написал, но если вам непонятно в виде слов, то вот код:
$thumb = new Thumbnail($source).
$thumb->setCrop($cropX1, $cropY1, $cropX2, $cropY2);
$thumb->setBackgroundColor($backgroundColor);
$thumb->setQuality($quality);
$create = $thumb->create($destination, $forceRegenerate);
if (!$create) {
// bla bla bla
}
Непонятно где вы тут семь сеттеров насчитали. На последний вопрос думаю не нужно отвечать?
А вот запросто, видел кучу кода (да и вот прямо сейчас гляжу на него) в котором в phpdoc вообще нет названий аргументов, только их типы. Поэтому phpdoc, в отличие от автокомплита, можно полноценно использовать только в идеальном мире. Да и от его *устаревания* никто не застрахован.
В качестве ключей можно использовать константы класса (многословно, да). Да и потом, тут многие пишут «20 параметров слишком много», какой смысл этой «фичи» при 4-5 параметрах? Никакого.
А насчет рефакторинга — не все IDE его поддерживают (привет PDT), к сожадению. Да и изменить только название метода гораздо быстрее и проще чем проверять и изменять еще и его аргументы (имена которых, ИМХО, вообще относятся к внутренней реализации метода и не должны никаким образом влиять на вызывающий код).
И куча проблем при рефакторинге.
> 20 параметров для функции — это слишком много.
А при небольшом кол-ве параметров функции эта «фича» совершенно лишняя.
В идеально мире: создать класс Thumbnail, в конструктор передавать $source, также добавить в него методы для установки всех свойств (setCrop и т.д.) и потом вызывать create($destination).
ЗЫ: См. чуть выше пропущенную первую часть.
Отличие у них всего одно — концептуальное: интерфейс это «поведение» без реализации; абстрактный класс — частичная реализация какого-либо поведения (конкретная реализация переложена на плечи потомков). Из этого отличия как раз и вытекают все свойства интерфейсов: реализация методов в них бессмысленна (и противоречит концепции), т.к. автоматически превращает интерфейс в абстрактный класс (обратное тоже верно — абстрактный класс содержащий только абстрактные методы можно считать интерфейсом); множественная реализация интерфейсов, в отличие от множественного наследования, разрешена т.к. не может породить конфликтов реализаций; и т.д.
Про выбор читаем выше.
Ну и реальный пример: в приложении нужен платежный шлюз (ПШ), который должен уметь проводить платежи через несколько платежных систем (ПС). Вопрос как лучше реализовать?
1) Возможность расширения плагинами не предполагается: В этом случае наиболее рационально и просто реализовать класс Абстрактной ПС (АПС), от которой будут наследоваться все остальные ПС и переопределять необходимые методы (но вот часть методов логично расположить именно в АПС, поскольку они будут одинаковыми для всех ПС). Сам ПШ будет оперировать только АПС.
2) Решили дать возможность плагинам добавлять свои ПС: Можно оставить предыдущую модель, но в этом случае сторонним разработчикам придется разбираться в вашей реализации (в большом старом приложении 100% будет куча подводных камней в АПС, да и сам код, скорее всего, будет закрыт). Поэтому вместо этого логичнее вынести общие для всех ПС методы из АПС в Интерфейс ПС (ИПС) и заставить все ПС реализовывать его (фактически только АПС, которая в этом случае никуда не денется). Сам же ПШ вместо АПС станет оперировать ИПС.
ЗЫ: А данном контексте: публичный — совместно используемая библиотека; закрытый — конечный проект (код нигде повторно не используется).
У вас «хорошее» мнение о большинстве PHP разработчиков :)
> IDE и автокомплит вещи не связанные.
IDE там не просто так в кавычки взято.
ЗЫ: Печальная дискуссия получилось, почему адепты json-а молчат про «json schema»? Я вот, например, только что о ней узнал (что неудивительно в виду её малой распространенности), а она как раз и является альтернативой XML схемам (но её поддержка опять же гораздо меньше).
А XML нельзя, да? :)
> Про DSL на PHP — как вы будете разбирать такие описания пакетов на центральном сервере (packagist?) не рискуя безопасностью?
Ключевое тут DSL, а значит очень узкая область применения, и, как следствие, совсем небольшой набор синтаксических конструкций => можно через tokenizer проверить чтобы присутствовали только разрешенные методы (если реализация DSL будет через методы, что, опять же, логично из-за автокомплита). Или же, может быть, можно использовать песочницу из runkit-а (не пробовал).