PHP

Несмотря на многочисленные попытки отговорить меня от данной затеи, я все же продолжу как и планировал. Каждый комментарий предыдущей части, я прочитал и учел. Встретил как собственные пожелания некоторых людей, так и настоятельные рекомендации не крутить собственный велосипед. Мне понравились комментарии ainu и Fesor, на мой взгляд — очень конструктивное мнение о том, чего не хватает в CMS & Framework на сегодняшний день. К примеру реализация задачи по быстрому и простому способу создания блога для человека, которому довольно сложно объяснить как им пользоваться — чрезвычайно сложна по своей природе. А поскольку подобные задачи появляются все чаще и чаще, я и решил заняться вплотную данной идеей.

Вы можете себе представить насколько удобно можно реализовать интеграцию социальных сетей, API Аналитики и прочих «сладостей» нынешних возможностей мира информационных технологий для конечного пользователя? Насколько простым и интуитивным можно сделать интерфейс информационных ресурсов? Я могу довольно долго продолжать описывать мои идеи и цели, но пока это происходит, прогресс не идет, а значит время тратится впустую. Ко всему этому мы дойдем в следующих частях моей серии статей, а пока — по делу.

Иерархия поддиректорий проекта


  • engine
    • Service
    • System

  • module
    • Module
    • ...

  • public
    • Downloads
    • ...

  • view
    • Theme
    • ...



Очень часто работая с крупными проектами встречал огромное количество папок содержащих тот, или иной «жизненно важный» компонент работающей системы. Чего нельзя сказать к примеру о Django / Symfony. Каждая их папка отвечает за собственный автономный в той или иной мере компонент, изначально подразумевающий выполнение определенных целей. То же самое можно сказать о многих других фреймворках, но сейчас не об этом.

Папка engine будет содержать системные классы, а также сервисы обеспечивающие выполнение той или иной задачи.

Папка module включает в себя контроллеры с описанием роутинга, конфигурационными файлами, файлами кеша, трейтами.

Папка public содержит файлы, к которым предполагается непосредственный доступ со стороны клиента посредством выдачи сервером напрямую. Иными словами — файлы для скачивания пользователями.

Папка view будет содержать в себе папки тем оформления со всеми необходимыми компонентами в виде каскадных стилей, скриптов, исходников sass, картинок и прочего видимого медиаконтента.

Архитектура


В прошлой статье, меня увлекли в незнании паттернов проектирования. В свое оправдание могу сказать что паттерны проектирования уместны не во всех ситуациях. К примеру используя MVC/HMVC, я бы с легкостью смог спроектировать WEB-Приложение на PHP. Но если взять тот же Pattern Facade или Observer, общая картина становится не такой уж очевидной, хотя и представить ее можно.

Для более наглядного объяснения чего я хочу добиться, приведу пример реализации авторизации пользователя на Django (Python):
def auth_controller(request):
    user = authenticate(username=request.POST['username'], password=request.POST['password'])
    if user.is_active:
        login(request, user)

Да я опустил множество мелких деталей, но не упустил важнейшего чего и хочу добиться. Такие вещи как авторизация / регистрация, должны реализовываться в момент, что и показала нам группа разработчиков Django. В случае если сервисы CMS будут спроектированы по шаблону Facade, можно будет добиться довольно хороших результатов. Все проверки, эскейпы и валидации в таком случае, должны проходить не в контроллере, что я довольно часто наблюдаю, а в сервисе, где данные будут отфильтрованы, а результат будет сообщен, как только задача будет выполнена — контроллеру, где и продолжится программный цикл. Такие мелкие на первый взгляд вещи в сотни раз облегчат, ускорят и позволят избежать элементарных ошибок, которые мы так часто делаем из-за невнимательности или незнания процесса обработки входных данных и правильного цикла выполнения задачи. Поэтому я пришел к выводу, что паттерн Фасад будет наиболее правильным в плане реализации сервисов своей CMS.

Сам же модуль, будет реализован по похожему принципу но с некоторыми нюансами. Часто случается необходимость в реализации элементарного API, что с использованием CMS — довольно громоздкая и сложная задача, если это не предусмотрено самой системой. По-этому, точкой входа каждого модуля будет родительский метод базового модуля — "request", аргументом которого будет объект, который будет содержать средства изменений результирующего набора заголовков. Таким образом, мы добьемся максимально модифицируемый и удобный интерфейс модификации ответа сервера по тому или иному запросу, что и является главной задачей нашего контроллера.

Как наглядный пример — реализация RSS:

namespace Module/News;

class RSS {
    public function request($request) {
        $request->response->headers['Content-Type'] = 'application/xml';
    }

    public function route($router) {
        $router->map('^rss\.xml$', [$this, 'feed']);
    }

    public function feed($io) {
        return $this->service('Rss', $this->service('News')->getLatest(0, 50));
    }
}

Пример довольно грубый и не показывает всю идею того что я хотел показать, но как ранее я уже упомянул — модули могут содержать traits, в которых для наглядности мы можем хранить наши контроллеры. А уж если модуль слишком объемный, ничего не мешает в роутинг передать callback вида «Module/News/Feed::xml», с того же пространства имен.

В заключение


Как всегда, жду конструктивной критики с Вашей стороны. В следующей части, учитывая комментарии к этой статье, выложу все учтенные правки, благодарности, и репозиторий Github. Всего доброго!

Комментарии (69)


  1. gene4000
    25.10.2015 15:05
    +5

    Уличили, а не увлекли. Сегодня вас уличили в незнании русского языка.


  1. lair
    25.10.2015 15:27
    +2

    В случае если сервисы CMS будут спроектированы по шаблону Facade, можно будет добиться довольно хороших результатов. Все проверки, эскейпы и валидации в таком случае, должны проходить не в контроллере, что я довольно часто наблюдаю, а в сервисе, где данные будут отфильтрованы, а результат будет сообщен, как только задача будет выполнена — контроллеру, где и продолжится программный цикл.

    Простите, а как вы понимаете паттерн Фасад, что вы такое пишете?

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

    (кстати, вы перепутали аутентификацию и авторизацию в вашем примере)


  1. Delphinum
    25.10.2015 15:28
    +1

    Да я опустил множество мелких деталей, но не упустил важнейшего чего и хочу добиться. Такие вещи как авторизация / регистрация, должны реализовываться в момент (чего?), что и показала нам группа разработчиков Django

    Мне кажется, или вы «забыли» самое главное слово во всем этом предложении? Так всю статью чего то не хватает.

    Можете еще раз объяснить, чем вам так понравился подход с аутентификацией в Django?


    1. VolCh
      25.10.2015 19:52
      +1

      «В момент» тут значит, скорее всего, «моментально», «быстро».


      1. Delphinum
        25.10.2015 22:21

        Тогда становится интересно, чем же такой подход отличается от любого другого фреймворка с модулем аутентификации? )


  1. caballero
    25.10.2015 18:00

    а зачем вообще смешивать APi и модули. API — должна быть отдельная часть системы, возможно со своей аутентификацией, роутингом и все такое. Если какой то метод использует данные из модуля пусть просто обратится к объектам этого модуля.
    Вообще не очень понятна цель статьи. Ну делаете CMS в которой по другому расположены папки. Новичкам, которые не имея опыта, бросаются писать свои CMS наверно будет полезно, не более того.

    Если вам нравится Django просто портируйте его на PHP один к одному.
    Уверен есть достаточно разрабов, которым нравится Django но они не могут его заюзать, например, из-за ограничений шаред-хостинга. И людям польза и вам приятно.


    1. andrewnester
      25.10.2015 21:39

      к сожалению, Python не PHP и некоторые вещи, активно используемые в Django портировать не выйдет, например, декораторы


      1. kovalevsky
        25.10.2015 22:12

        Django не видел, но загуглил и посмотрел немного, могу путать, но разве Doctrine\Annotations (http://docs.doctrine-project.org/projects/doctrine-common/en/latest/reference/annotations.html) не оно?


        1. andrewnester
          25.10.2015 22:36

          не совсем, декораторы в Python это фактически реализация паттерна «декоратор» — вы можете обернуть выполнение вашей функции/метода в какой-то декоратор. Например, в django на view функцию можно повесить @login_required и таким образом она будет доступна только для авторизованных пользователей

          В PHP так просто сделать не получится (есть решения из области AOP, но это немного не то уже)

          А аннотации в доктрине это копия аннотации из Hibernate в Java, и используется немного для другого :)


          1. Delphinum
            25.10.2015 23:03
            +4

            Например, в django на view функцию можно повесить @login_required и таким образом она будет доступна только для авторизованных пользователей
            В PHP так просто сделать не получится

            Это было крайне сложно, но похоже я справился
            class LoginViewDecorator{
              private $controller;
              
              public function __construct($controller){
                $this->controller = $controller;
              }
            
              public function view(...){
                if(Annotation::fromMethod($this->controller, 'view')->has('login_required')){
                  if(!$serviceLocator->get('user')->hasLogin()){
                    throw new RuntimeException('...');
                  }
                }
                return $this->controller->view();
              }
            }
            


            1. andrewnester
              25.10.2015 23:45

              да, я согласен, что в PHP единственной простой альтернативой является декоратор/прокси.
              Но везде, где у вас инстанцируется декорируемый класс, Вам придется обернуть этот класс декоратором. И хорошо если у Вас хорошая архитектура и такое место в коде одно :)

              но тут разговор идет о портировании джанго в пхп, и я говорил о том, что многие вещи, которые сделаны очень удобно в джанго не будут таковыми в пхп из-за ограничений самого языка и во многом портирование будет бессмыслынным, потому что это по итогу получится подобие Symfony 2/ Laravel 5


              1. Fesor
                26.10.2015 00:14

                декораторы в python ссылаются на функцию, которая может что-то сделать. Добавлять таким образом дополнительное поведение как минимум странно, так как декорируемый объект об этом поведении начинает что-то подозревать. Да удобно, но направление зависимостей как-то не в ту сторону смотрит, вы не думаете? В пайтоне такие штуки удобно использовать для DRY-га всяких второстепенных вещей вроде… логирования deprecated вызовов. Словом внутренняя кухня. Расширять таким образом поведение объектов как по мне не круто.

                Но может быть я не прав.


                1. andrewnester
                  26.10.2015 00:44

                  я может не совсем вас понял, но чем отличается это от паттерна «декоратор»

                  в нем вы так же ссылаетесь на декорируемый объект

                  насчет того, что функция начинает, что-то подозревать тоже наверное не понял вас

                  но вы правы, что основная цель их в python — это DRY. с их помощью легко можно избавиться от сквозного функционала в духе логирования/кэширования


                  1. Fesor
                    26.10.2015 01:20

                    я говорю о маленьких вещах, вроде пометки депрекейтед методов. Это реально удобно и читабельно, в PHP для этого средств действительно нет (ну как… есть, но это кастыли с phpdoc).

                    насчет того, что функция начинает, что-то подозревать тоже наверное не понял вас

                    Если вы у метода ставите какой-то атрибут что бы добавить какое-то дополнительное поведение — это я и называю «метод начинает что-то подозревать».

                    в нем вы так же ссылаетесь на декорируемый объект

                    Да, но декорируемый объект не подозревает что его декорируют. Как на счет реализации таким же способом адаптера?


                    1. andrewnester
                      26.10.2015 01:27

                      ну вот насчёт «метод подозревает» не могу согласится

                      при вызове данного метода из клиентского кода мы не знаем декорированный он или нет, точно так же как и при реализации паттерна. сам метод тоже не может получить данных о том, декорируют его или нет
                      Так каким образом именно метод может узнать декорирован он или нет?


              1. Delphinum
                26.10.2015 00:25
                +1

                Вы хотите чтоб я еще раз постарался и справился?


                1. andrewnester
                  26.10.2015 00:47

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


                  1. Delphinum
                    26.10.2015 00:59

                    Зачем портировать джанго?

                    или такой реализацией, чтобы не приходилось оборачивать инстанцируемые классы

                    Внутри там все оборачивается, просто вы этого не видите.
                    В пару строк кода
                    interface Controller{
                      ...
                    }
                    
                    abstract class Decorator{
                      protected $controller;
                    
                      public function wrap(Controller $controller){
                        $this->controller = $controller;
                      }
                    }
                    
                    class LoginActionDecorator extends Decorator{
                      public function __call($method, $args){
                        if(substr($method, -6) == 'Action'){
                          if(!ServiceLocator::get('user')->isLogin()){
                            throw new RuntimeException('Нет прав');
                          }
                          else{
                            return call_user_func_array([$this->controller, $method], $args);
                          }
                        }
                      }
                    }
                    
                    class ControllerFactory{
                      private $wrappers = [];
                    
                      public function get($className){
                        $controller = new $className;
                        foreach($this->wrappers as $wrap){
                          $controller = $wrap->wrap($controller);
                        }
                        return $controller;
                      }
                    
                      public function addWrap(Decorator $wrap){
                        array_push($this->wrappers, $wrap);
                      }
                    }
                    
                    $myControllerFactory = new ControllerFactory;
                    $myControllerFactory->addWrap(new LoginActionDecorator);
                    $controller = $myControllerFactory->get('app\Controllers\TaskController');
                    


                    1. andrewnester
                      26.10.2015 01:09

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

                      и не я предлагаю портировать джанго, я наоборот считаю это бессмыслынным


                      1. Delphinum
                        26.10.2015 01:10

                        Ну так в чем же тогда проблема? Иль вам нужно чтоб это было именно в ядре интерпретатора?


                        1. andrewnester
                          26.10.2015 01:20
                          -1

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


                          1. Delphinum
                            26.10.2015 01:24
                            -1

                            Ну языки потому и называются по разному, что у них реализации отличаются )


              1. Fesor
                26.10.2015 00:34
                +2

                портировании джанго в пхп

                Зачем, если Symfony лучше? Для PHP правильно мигрировать практики из Java/C# мира, так как семантика языка ближе. Скажем symfony это по большей части клон spring-а.


                1. andrewnester
                  26.10.2015 01:10

                  так я и не предлагал портировать, не моя идея же :) я ведь и утверждаю, что выйдет то по факту что-то около симфони или ларавел


                  1. Fesor
                    26.10.2015 01:22

                    и я не вижу в этом ничего плохого.


                1. saksmt
                  30.10.2015 08:04
                  +1

                  C symfony всё значительно сложнее, это скорее клон гибрида OSGi (концепция бандлов), Spring (концепция сервисов и архитектуры в целом) с прилеплными Pebble (местный Twig) и Hibernate/MyBatis (то, из чего выросла Doctrine), модифицированный личным восприятием Фабиена… И этот клон чертовски хорош, некоторых крутых штук в оригинале просто нет


                  1. Fesor
                    30.10.2015 11:34

                    twig это порт jinja скорее, как и pebble. Но по остальным пунктам я полностью согласен.


            1. andrewnester
              26.10.2015 00:05

              а вообще такое поведение уже сделано в Symfony :) symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/security.html


              1. Fesor
                26.10.2015 01:23
                +1

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


                1. andrewnester
                  26.10.2015 01:39

                  согласен, с точки зрения реализации отличается, но результат у @login_required и у Security один и тот же и выглядят одинаково, я говорил об этом

                  А go-aop мне не очень нравится, потому что очень сложный и выглядит реально как борьба с языком

                  на самом деле это больше мои прихоти, не знаю почему такой большой тред вышел из-за этого)

                  а как вы решаете вопросы кеширования/логирования? классы-декораторы?


                  1. Fesor
                    26.10.2015 01:49

                    классы-декораторы?

                    Именно (и не классы а объекты). Ну я совру если скажу что всегда так делаю, иногда просто смешиваю обязанности. И это нормально, потому и существует термин «технический долг».

                    но в целом такой подход упрощает сопровождение тестов и вообще делает архитектуру лучше (позволяет вносить изменения чаще и быстрее).


                    1. andrewnester
                      26.10.2015 01:57

                      полностью согласен, делаю точно также на самом деле ( в тайне мечтая о декораторах)))


          1. Delphinum
            25.10.2015 23:12

            декораторы в Python это фактически реализация паттерна «декоратор»

            Если некий объект агрегирует другой, значит он уже декоратором зовется? За управление доступом к субъекту отвечает прокси, а не декоратор.


            1. andrewnester
              25.10.2015 23:50

              в python декораторы как раз-таки «декораторы», а не «прокси» с точки зрения функции — они позволяют динамически добавлять новую функциальность

              Но соглашусь, что @login_required похож на прокси, так как управляет доступом к субъекту


              1. Fesor
                26.10.2015 00:15

                а что, прокси не могут управлять доступом к субъекту?


                1. andrewnester
                  26.10.2015 00:35

                  так вроде написал же, что могут, и этим занимаются :)


              1. Fesor
                26.10.2015 01:29

                в python декораторы это не «декораторы» в контексте GoF-ких паттернов. Это указатель на функцию высшего порядка и только. Позвольте привести маленькую но емкую цитату из документации:

                A function returning another function, usually applied as a function transformation using the wrapper syntax. Common examples for decorators are classmethod() and staticmethod().

                The decorator syntax is merely syntactic sugar, the following two function definitions are semantically equivalent:
                def f(...):
                    ...
                f = staticmethod(f)
                
                @staticmethod
                def f(...):
                    ...
                




                грубо говоря говорить о декорации тут не выходит, так как, если мы уберем синтаксический сахар, наша «декорируемая» функция будет более чем знать об этом дополнительном поведении. Это всего лишь позволяет нам сократить код и вынести дублирование в пределах модуля. Но добавление кеширования таким образом например грубо будет противоречить принципу единой отвественности.


                1. andrewnester
                  26.10.2015 01:53

                  А еще в пайтоне, функции это объекты)
                  ну я не хотел упоминать функции высшего порядка раз мы старались говорить в терминах ООП :)

                  да, я в курсе что это просто синтаксический сахар, но это не нарушает принцип единственной ответственности, f занимается своим, a staticmethod своим

                  вы же не говорите, когда оборачиваете объект бизнес-логики кэширующим декоратором, что теперь у объекта 2 ответственности — и кеширование и бизнес логика

                  так каким образом при оборочивании функции другой функцией нарушается принцип единственной ответственности?


                  1. Fesor
                    26.10.2015 02:28

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


                    1. andrewnester
                      26.10.2015 08:56

                      По поводу именно staticmethod согласен, но декораторы в python, механизм намного более мощный, чем просто реализация паттерна. Это уже специфика реализации и классов, и самих декораторов в пайтоне ( я про @staticmethod, @classmethod, @abstractmethod и тд )

                      но представьте, что мы используем декоратор cache или log. Каким образом в таком случае нарушается принцип единственной ответственности?


                1. andrewnester
                  26.10.2015 02:16

                  вообще немного не правильно с моей стороны говорить о gof паттернах в контексте функций, поэтому уж лучше рассматривать class decorators в python, вот это как раз «классические» декораторы


                  1. Fesor
                    26.10.2015 02:31

                    ну раз уж не корректно говорить о gof паттернах в контексте функций (они ж в пайтоне объекты, объекты можно декорировать), то тогда совсем не уместно сравнивать пайтоновские недо-классы (и это в хорошем смысле) с тем что в пыхе или жабе. Намного проще сравнить пайтоновские классы с оными в javascript (те что из es2015). Вот там да, можно брать пайтоновские практики и радоваться (более того, аннотации/декорацию там тоже путят в рамках es2016).


                    1. andrewnester
                      26.10.2015 09:19

                      да я и не пытался их сравнивать, в smalltalk классы тоже не такие как в java, но тем не менее паттерны применимы
                      вот и в случае с python, для программиста незнакомого с python более уместным/классическим будут выглядитт class decorators

                      А в js такое часьл называют decorator function ;)


          1. kovalevsky
            26.10.2015 09:39

            В PHP легко можно реализовать паттерн декоратор, а обернуть его в декоратор так, как как в Python/Django (аннотацией "@") можно вышеуказанной библиотекой доктрины


            1. andrewnester
              26.10.2015 09:58

              чтобы получить похожий функционал

              1) все классы содержащие эти аннотации должны создаваться через фабрики/DI контейнеры/сервис локаторы

              2) это будут не декораторы, а прокси, который будет через __call__ отлавливать вызовы, парсить аннотации, вызывать нужный код, потом вызывать метод проксируемого класса

              (именно прокси, а не декораторы, поскольку обычно мы декорируем конкретный класс объектов, а создавать для разных классов декораторы с одинаковым кодом парсинга аннотаций тоже не очень класс)

              ну и по итогу
              1) в хорошей архитектуре в большинстве случае классы так и будут создаваться, это не проблема

              2) из-за использования такого прокси теряется читаемость, да и вызывать call_user_func_array на каждый вызов оборачиваемого метода тоже не класс

              поэтому в PHP как и Fesor я предпочитаю использовать явные декораторы


              1. VolCh
                26.10.2015 22:49

                Есть ещё кодогенерация декоратов


      1. caballero
        25.10.2015 22:37

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

        Я свой фреймворк с явы портировал хотя в PHP нет например ни анонимных классов ни нормально реализованных замыканий.


        1. andrewnester
          25.10.2015 22:56

          мне вот лично очень не хватает декораторов в PHP

          вот пример, как они используются в Django
          как вы бы реализовали это в PHP?
          docs.djangoproject.com/en/1.8/topics/auth/default/#django.contrib.auth.decorators.login_required

          это не то, как фреймворк устроен внутри, это то, что он предоставляет для использования, довольно активного использования, и без это во многом теряется его удобство и простота


          1. Fesor
            26.10.2015 00:16
            +1

            мне вот лично очень не хватает декораторов в PHP

            вам не хватает аннотаций, давайте выражаться яснее. Те штуки которые вы хотите частично решает стремная штука под названием go-aop, и я не одобряю подобные тенденции и веяния. Обычный старый добрый интерфейс, отдельный объект декорирующий наш маленький объект и все хорошо.


            1. andrewnester
              26.10.2015 00:35

              согласен, не хватает аннотаций

              на самом деле, я отношусь к ним с некоторым подозрением — с одной стороны это удобный инструмент для задач в духе добавления кэширования/логирования и тд. С другой стороны, это создает сложный для отладки код

              Но я скорее за то, чтобы они были, чем не были

              ну а так с вами согласен, для многих вещей лучше подходит паттерн декоратор, да и go-aop не совсем мне нравится на самом деле


              1. Delphinum
                26.10.2015 00:40
                +1

                Могу с вами поделится реализацией аннотаций на PHP в стиле Java или JSON, если вам их так сильно не хватает


                1. andrewnester
                  26.10.2015 01:00

                  я бы с удовольствием взглянул, правда, без какой-либо иронии или сарказма
                  но я говорю вот о таких декораторах/аннотациях gist.github.com/CHH/4520200

                  а о библиотеках в духе php annotations я конечно вскурсе


                  1. Delphinum
                    26.10.2015 01:03

                    Это больше похоже на какие то костыли для обхода динамической типизации в PHP, если честно. Подозреваю что это предварительно еще компилируется?

                    а о библиотеках в духе php annotations я конечно вскурсе

                    Тогда не буду делиться ))


                    1. Fesor
                      26.10.2015 01:33

                      Этот пропозал был подготовлен в рамках обсуждения добавления в PHP нативной поддержки DbC (если я правильно помню эти обсуждения в интерналс). То есть эти «декораторы» это грубо говоря «аспекты» в контексте АОП. Возможность декларировать дополнительную логику. Вне чисто функционального языка (PHP не является функциональным языком, согласитесь) в этом нет как по мне ровным счетом никакого смысла. В Python да, это удобно для некоторых кейсов. Но не для добавления логирования/кеширования (хотя можно, но я считаю это увеличением технического долга и допустимым только при быстрой разработке)


                      1. Delphinum
                        26.10.2015 01:46

                        Благодарю за разъяснения.


  1. lavkasnov
    25.10.2015 18:09
    -3

    Иерархия папок и файлов, на мой взгляд, ввообще не имеет значения: файлы подгружаются по __autoload.

    Замечу, что CMS (как создатель своей CMS) очень сложный проект, на сегодня это 30000 строк кода — за сколько вы осилите такой объем?


    1. stychos
      26.10.2015 01:09

      По своему опыту — если есть кураж, то можно и за неделю-две. Вопрос в том, что без дoлжного изначального планирования, многое потом будет подвергаться собственной же критике и в итоге переписываться.


      1. Delphinum
        26.10.2015 01:11

        Да даже с должным изначальным планированием многое (читать — все) будет критиковаться и переписываться. Программирование это «грязная задача», тут это в порядке вещей, особенно когда на это есть время.


        1. stychos
          26.10.2015 01:12

          Ну так-то да, я свой велосипед уже пятый раз реставрирую =)


          1. Delphinum
            26.10.2015 01:14

            Мой фреймворк помог мне устроится на работу, так что время потрачено не зря )


            1. stychos
              26.10.2015 01:16

              Да и я не считаю, что такие затеи бесполезны — как минимум, свои собственные набитые шишки — они самые запоминающиеся, и выдающие наибольшую порцию персистентных практических знаний.


  1. Evgeny42
    25.10.2015 19:33
    +5

    Такие штуки надо писать втихую, чтобы никто о них не знал. Тем более когда каша в голове, а амбиции словно в космос собрался :)


  1. serginho
    25.10.2015 19:52
    +2

    Несколько советов от меня:
    1. Используй как можно больше готовых библиотек и подключай их через composer.
    Например нужен роутинг, вводишь в гитхабе в поиске php routing и смотришь какие библиотеки есть на эту тему. Поэкспериментируй с каждой, и поймешь какая наиболее подходит тебе. Писать все с нуля заколебешься. Тоже самое касается кеширования, шаблонизации, авторизации и прочего. Уже практически для всех целей есть независимые библитотеки.
    2. engine лучше тоже вынести в отдельный модуль и подключать через composer. Чтобы не копировать эту папку каждый раз в новый проект.
    3. Сейчас в основном фреймворки используют шаблон проектированияя Dependency Injection, почитай на эту тему.
    4. Раз уж ты пишешь CMS, то имеет смысл основать ее на каком-нибудь популярном фреймворке типа Laravel, Symfony, Yii. Так другим людям будет проще вникнуть в твою архитектуру, писать новые модули и т.д.
    5. Не сдавайся :)


    1. kovalevsky
      25.10.2015 20:39

      Не, там бесполезно говорить ему о Composer'e и чужих, написанных и оттестированных библиотеках. Автор в прошлой статье практически сказал, что все текущие CMS и фреймворки — фуфло. Он будет все с нуля писать. Он даже здесь докопался до Django и Symfony. Мне теперь даже стало интересно, насколько быстро его CMS, которая игнорирует все best practiсe, загнется от того, что автор не сможет безболезненно её модифицировать. А на «вторую попытку» силы вряд ли останутся.


      1. Suntechnic
        26.10.2015 00:10

        Web такая среда где игнорирование best practiсe часто залог не только выживания, но и долгого контрпродуктивного развития. Хотя не данном случае конечно. В данном случае вы абсолютны правы — все уткнется в «не сможет безболезненно её модифицировать».


  1. Zibx
    25.10.2015 20:27
    +3

    Запилили бы на rust или nim, там пока непаханое поле. А на пхп свою цмс писал каждый ещё в 2000 году.


  1. Fesor
    25.10.2015 22:39
    +6

    я все же продолжу как и планировал.

    вас не отговорить пытались от идеи написания, пишите конечно, это полезная практика. Вас от вашего плана пытались отговорить. У вас судя по тому что вы пишите банально недостаточно опыта что бы сделать что-то лучше чем то что есть сейчас.

    К примеру реализация задачи по быстрому и простому способу создания блога для человека, которому довольно сложно объяснить как им пользоваться — чрезвычайно сложна по своей природе

    Она разбивается на множество весьма простых задач, каждую из которых можно решить, предоставить решению интерфейс, предоставить стандартную реализацию (или несколько) и это позволит уже сильно быстро создать бложик. А вопрос админки это уже отдельная песня. Мне в этом плане нравится концепция выделения функционала управления этим делом в rest api сервис и отдельный независимый интерфейс. Так поддерживать все это добро будет проще.

    Вы можете себе представить насколько удобно можно реализовать интеграцию социальных сетей, API Аналитики и прочих «сладостей» нынешних возможностей мира информационных технологий для конечного пользователя?

    нынче это весьма тривиальная задача которую решают люди каждый день. И количество качественных готовых решений не равно нулю.

    Я могу довольно долго продолжать описывать мои идеи и цели

    Пока ваши идеи цели выражаются как «хочу написать CMS и при этом использовать хабр как жж-ку где буду записывать как у меня дела, при этом я не читал ни одной книжки по ООП и т.д. но эффект даннинга-крюгера дает о себе знать».

    Иерархия поддиректорий проекта

    Почему вы так пристали к иерархии директорий? Или это уже синоним архитектуры приложения?

    В свое оправдание могу сказать что паттерны проектирования уместны не во всех ситуациях.

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

    Но если взять тот же Pattern Facade или Observer, общая картина становится не такой уж очевидной, хотя и представить ее можно.


    Фасад — смотрим что значит это слово в любом словаре. Грубо говоря это шаблон проектирования, суть которой скрыть сложность реализации красивым и удобным интерфейсом. Это не та чушь которая была в Laravel 4 (хотя частично можно так сказать, ибо это упрощение доступа к контейнеру но все же...).

    Observer — есть штука которая эмитит события, есть слушатели которые на события подписаны. Что тут сложного?

    Да я опустил множество мелких деталей, но не упустил важнейшего чего и хочу добиться.

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

    Ай короче… печально это. удачи вам что-ли.


  1. xanm
    26.10.2015 10:01

    Чтобы написать что-то стоящее нужно подробно изучить уже существующие фреймворки и cms, почитать что такое ооп, почитать gang of 4, почитать Фаулера, затем попрактиковать что вы почитали. Еще более важно определиться с целью, надо знать что вы делаете и зачем. Но это лично мои советы. Я в свое время не нашел фреймворка с полноценным отделением бизнес логики от инфраструктуры и это стало целю в одном из проектов.


  1. maxru
    26.10.2015 11:22
    +4

    Никогда такого не было и вот опять.