Правильное использование интерфейсов

Статус
В этой теме нельзя размещать новые ответы.

esase

Новичок
Хотел бы узнать у знающих людей следующее:

Нужно на ли на каждый класс натягивать интерфейс, для того чтобы создать некую абстракцию даже если реализация интерфейса ну будет превышать одного раза?

почему спрашиваю? Во многих постулатах (SOLID к примеру) написано нужно использовать абстракцию вместо конкретных реализаций. Но я честно говоря не
вижу выгоды использования интерфейсов повсюду, одно дело когда мы можем сделать несколько реализаций некого функционала отображенным в интерфейсе и быть уверены, что все эти реализации будет иметь функции заявленные в интерфейсе.
Но бывают классы которые мало вероятно будут иметь больше одной реализации.
 

fixxxer

К.О.
Партнер клуба
Не нужно. При необходимости, введение интерфейса - это простейший рефакторинг, который можно сделать средствами IDE.

Но мыслить надо в любом случае интерфейсами: набор публичных методов класса и есть его интерфейс.
 

HraKK

Мудак
Команда форума
Нужно) Потому что это хорошая привычка и помогает перестроить мышление.
 

fixxxer

К.О.
Партнер клуба
HraKK, нужно понимать, когда нужно. С таким безоговорочным "нужно" щас кто-нибудь пойдет со счастливым лицом клепать какой-нибудь UserCommentsModelInterface :)

Интерфейсы должны быть простыми, указывающими на какое-то конкретное ability - а такие при проектировании loosely coupled приложения неизбежно появятся сами по себе.
 

HraKK

Мудак
Команда форума
fixxxer, пусть это хорошо. Когда человек сможет осознанно понять что ему не нужен этот интерфейс, только тогда пусть не пишет его. Я встречал мало приложений в которых переизбыток интерфейсов, а вот недостаток - повсеместно.
 

fixxxer

К.О.
Партнер клуба
Интерфейс, копирующий фактический публичный интерфейс класса со всеми разнообразными методами - это вовсе не интерфейс, это какая-то фигня. Ну разве что класс очень простой:)

Мне нравится подход к интерфейсам в языке go. Там вообще нет ключевого слова implements (впрочем, там и классов нет, есть сложные типы). Но есть интерфейсы и соглашения по именованию методов. Проверка на implements делается при компиляции "по факту" - если в метод, который хочет FooableInterface параметр, передается некоторый bar, который фактически реализует интерфейс FooableInterface, значит, все хорошо. В комбинации с соглашениями по именованию и строгой типизацией это позволяет (да и что уж там - заставляет, типизация-то строгая) прописывать интерфейсы в нужный момент.
 

HraKK

Мудак
Команда форума
Я против того чтоб прописывать в нужный момент, так получаются не осознанные интерфейсы, а вынужденные.
 

HraKK

Мудак
Команда форума
Плюс, есть такая вещь как лень. Лично я с ней боролся очень просто - на каждый чих создавал интерфейс, потом абстрактный класс, потом только класс нужный мне. Даже, если знал что мне это не понадобится. Зато я точно знал, что, если мне где-то понадобится интерфейс или абстрактный класс, я не поленюсь и напишу. Но это уже чисто моя особенность.
 

esase

Новичок
Давайте на примере есть класс утилита с со списком статичных методов

PHP:
<?php
namespace Application/Utility;

class FileSystem
{
    /**
    * Check  directory
    *
    * @param string $path
    * @return boolean
    */
    public static function isDirectoryEmpty($path)
    {
        return (($files = scandir($path)) && count($files) <= 2) ? true : false;
    }

    /**
    * Get the file's  name
    *
    * @param string $fileName
    * @param string $removeExtension
    * @return string
    */
    public static function getFileName($fileName, $removeExtension = true)
    {
        $file = self::getFileInfo($fileName)->getFileName();

        if ($removeExtension && null != ($extension = self::getFileExtension($file))) {
            $file = preg_replace('/.' . preg_quote($extension) . '$/i', '', $file);
        }

        return $file;
    }
  ..........
}
как я используя его :

PHP:
<?php
namespace Application\Controller;

use Application\Utility\FileSystem;

class SettingAdministrationController
{
      public function indexAction() {
        if(FileSystem::isDirectoryEmpty('test')) {
          // create a new one
        }
      }
}
Вопрос нафига мне интрефейс для моего класса утилиты ?? по подробнее плиз
 

esase

Новичок
Плюс, есть такая вещь как лень. Лично я с ней боролся очень просто - на каждый чих создавал интерфейс, потом абстрактный класс, потом только класс нужный мне. Даже, если знал что мне это не понадобится. Зато я точно знал, что, если мне где-то понадобится интерфейс или абстрактный класс, я не поленюсь и напишу. Но это уже чисто моя особенность.
Дела далеко не в лени, а разумности тело движений
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Плюс, есть такая вещь как лень. Лично я с ней боролся очень просто - на каждый чих создавал интерфейс, потом абстрактный класс, потом только класс нужный мне. Даже, если знал что мне это не понадобится. Зато я точно знал, что, если мне где-то понадобится интерфейс или абстрактный класс, я не поленюсь и напишу. Но это уже чисто моя особенность.
По мне так это и есть программистская лень: вместо обдумывания и планирования - фигачить по шаблону везде одинаково.
 

fixxxer

К.О.
Партнер клуба
esase, в твоем примере вообще класса нет. Это просто набор функций.
 
  • Like
Реакции: WMix

fixxxer

К.О.
Партнер клуба
Я против того чтоб прописывать в нужный момент, так получаются не осознанные интерфейсы, а вынужденные.
Если разрабатывать по TDD, то нужный момент будет в момент написания теста - то есть, в самом начале.
 

esase

Новичок
esase, в твоем примере вообще класса нет. Это просто набор функций.
Класс есть но с набором статических функций. Получается здесь профита использовать интерфейса нет.

Другой пример:
PHP:
<?php
namespace Application\Model;

class Base
{
public funciton saveChanges()
  {
  ......
  }
}
?>

<?php
namespace Application\Model;

class Administration extends Base
{
public funciton getItems()
  {
  ......
  }
}
?>

Реализация

[CODE]<?php

namespace Application\Controller;

class IndexController {
    public function indexAction()
    {
      $this->view = [
          'items' => $this->serviceLocator()->get('model/Administration')
      ];
    }
}[/CODE]

Чуть посложне но все же, зачем нам здесь интерфейсы на классы модели (Base and Administration) ???
 

HraKK

Мудак
Команда форума
Если разрабатывать по TDD, то нужный момент будет в момент написания теста - то есть, в самом начале.
Если. По ТДД работают 5% и явно не те кто задают такие вопросы.

По мне так это и есть программистская лень: вместо обдумывания и планирования - фигачить по шаблону везде одинаково.
Не согласен.
 

Adelf

Administrator
Команда форума
Был у меня однажды проект на C#. и Архитектор недавно видать как раз прочитал. Что нужно везде интерфейс. Это был полный абзац. Страшное дублирование кода(особенно если учесть что в интерфейспах были все свойства моделей). Кароч он был бы лучше без этой хрени.
Мое мнение - интерфйес нужен тогда, когда ты хочешь чтобы был интерфйес. Опытный программер чувствует это сам. Можно конечно формализовать. Но лепить интерфйес к контроллерам например - не надо. (Это кстати для @esase )
 

fixxxer

К.О.
Партнер клуба
Класс есть но с набором статических функций.
Это значит - класса нет. Класс - это когда можно и имеет смысл создать его инстанс. В твоем случае $instance = new FileSystem не имеет смысла, соответственно, это не класс, а зачем-то использовано ключевое слово class вместо namespace.

Интерфейс - это признак того, что объект умеет что-то делать.

Вот тебе пример:

PHP:
interface RenderableInterface {
    public function renderTo(TemplateInterface $template);
}
interface TemplateInterface {
    public function assign(string $placeholder, string $value);
    public function renderWithTemplateFile(string $template_file);
}
class NewsModel implements RenderableInterface {
    public function renderTo(TemplateInterface $template) {
        $template->assign('title', $this->title);
        $template->assign('text', $this->text);
        $template->assign('created_datetime', $this->created_datetime);
    }
}
class NewsController {
     public function actionGetById(numeric $id) {
         $newsModel = new NewsModel($id);
         $template = new HtmlTemplate(); // HtmlTemplate implements TemplateInterface
         $newsModel->renderTo($template);
         return $template->renderWithTemplateFile('news.tpl');
     }
}
Все не имеющие к делу отношения детали (что там откуда наследуются, какая где еще реализация) намеренно опущены. Несуществующие в php scalar typehints написаны для красоты. =)

Что важно - важно то, что каждый делает то, что он заявил, что он умеет и никто не лезет в чужие дела.

Интерфейс - это как раз то, что говорит, что мы можем у переданного нам объекта попросить. При этом нас не интересует, как его зовут и что он умеет еще - важно, что нам надо сделать что-то конкретное, и знать, что этот кто-то это конкретное что-то умеет.

Контроллер сам по себе вообще никуда не передается - он просто инстанциируется и у него вызывается action, потому интерфейс вообще не имеет смысла. (Могут быть интерфейсы, имеющие смысл внутри фреймворка - но снаружи, на уровне приложения, - нет).

Модель может много что уметь. Нет никакого смысла в интерфейсе NewsModelInterface, т.к. нам это без разницы. Нам важно, что она _умеет_. В данном случае она умеет отрендерится в TemplateInterface, и это мы у нее и просим. NewsModel::render, в свою очередь, интересует только то, что переданный ему объект умеет сделать assign; его не интересует, будет там html, pdf или картина маслом.
 
Последнее редактирование:

esase

Новичок
Был у меня однажды проект на C#. и Архитектор недавно видать как раз прочитал. Что нужно везде интерфейс. Это был полный абзац. Страшное дублирование кода(особенно если учесть что в интерфейспах были все свойства моделей). Кароч он был бы лучше без этой хрени.
Мое мнение - интерфйес нужен тогда, когда ты хочешь чтобы был интерфйес. Опытный программер чувствует это сам. Можно конечно формализовать. Но лепить интерфйес к контроллерам например - не надо. (Это кстати для @esase )
Нет я этого не делал если быть внимательным, с спросил нужен ли мне интерфейс для моделей которые используются в контроллере, и в чем выгода использования, как я смогу потом это дело абстрагировать...
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху