Вы наверняка думаете, что писать на php — это просто. И «hello, world» выглядит примерно так так:

<?php
echo 'Hello, world!';

Конечно, чего еще ожидать от языка с низким порогом входа. Ну да, именно так и было раньше. Много лет назад. Но теперь, в 2017 году никто так уже не делает. Давайте рассмотрим, почему, и попробуем построить наше более реалистичное hello-world приложение по шагам, а их, скажу сразу, получилось не мало.


> Полный исходный код «hello,world» можно посмотреть здесь.

Для начала надо осознать тот факт, что без фреймворка сейчас приложения никто не делает. Если вы пишете вручную "echo 'hello, world'", то обрекаете проект на говнокод на веки вечные (кто потом этот велосипед за вас переписывать будет?). Поэтому возьмем какой-нибудь современный, распространенный в мире фреймворк, например Symfony.

Но прежде, чем его устанавливать, надо бы создать базу данных. Зачем базу данных? Ну не хардкодить же строку «hello, world» прямо в тексте программы!

База данных


В 2017 году принято использовать postgresql. Если вы вдруг еще не умеете его устанавливать, я помогу:

sudo apt-get install postgresql

Убунта при установке создаст юзера postgres, из под которого можно запустить команду psql с полными правами на базу.

sudo -u postgres psql

Теперь создадим юзера базы с паролем (придумайте какой-нибудь посложнее).

 CREATE ROLE helloworlduser  WITH PASSWORD '12345'  LOGIN;

И саму базу:

 CREATE DATABASE helloworld  OWNER helloworlduser;

Также надо убедиться, что в pg_hba.conf у вас разрешены коннекты к базе с localhost (127.0.0.1). Там должно быть что-то вроде этого:

host    all             all             127.0.0.1/32            md5

Проверим соединение:

psql -h localhost -U helloworlduser helloworld

после ввода пароля должно пустить в базу. Сразу создадим таблицу:

CREATE TABLE greetings (
     id int,
     greeting text,
     primary key(id)
);

INSERT INTO greetings 
(id, greeting) 
VALUES 
(1, 'Hello, world!');

Ну, супер, с базой всё. Теперь перейдем к фреймворку

php-фреймворк


Надеюсь, что в 2017 году у всех стоит composer на компьютере. Поэтому сразу перейдем к установке фреймворка

 composer create-project symfony/framework-standard-edition  helloworldphp

При установке он сразу спросит параметры соединения с базой:

host: 127.0.0.1
database_name: helloworld
database_user: helloworlduser
database_password: 12345

остальное по умолчанию/по усмотрению.

Надо только в конфиге config.yml поменть драйвер на driver: pdo_pgsql. (У вас ведь установлено php-расширение pdo_pgsql ?)

Проверим, что всё более менее работает, запустив

cd helloworldphp
bin/console server:start 

Симфони запустит свой собственный сервер, который слушает порт 8000 и на нем можно дебажить код. Таким образом в браузере по адресу http://localhost:8000/ должно быть что-то вроде «Это симфони, блаблабла».

Уфф! Казалось бы всё, контроллер уже есть, подправить вьюху, создать модель и понеслась, хелло ворлд уже близко!

Но… нет. Извините, но не в 2017-ом. В этом году все делают SPA (single page application).
Php-программист в 2017 году не может обойтись без js и верстки, теперь мы все full stack, а значит и helloworld должен быть соответствующий.

Ну ладно, ладно, еще бывают чистые php-бекенд-разработчики, но давайте возьмем более общий случай

JavaScript и его многочисленные друзья


Поэтому находим в симфони вьюху (а дефолтная вьюха лежит в app/Resources/view/default/index.html.twig) и стираем там всё, заменяя на:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="root"></div>
<script src="js/bundle.js"></script>
</body>
</html>

Т.е. всё будет лежат в bundle.js: сжатые javascript файлы прямо вместе со стилями и всем, чем нужно.
Как нам создать этот бандл? Нужно написать приложение и настроить webpack для сборки.

Webpack (или его аналоги) нам все равно бы понадобились, мы же не будем писать код на чистом javascript в 2017-году, когда typescript явно в тренде. А typescript надо как-то преобразовать в обычную js-ку. Это удобно делать, используя webpack.

Разумеется, на чистом typescript тоже никто не пишет. Нужен какой-то фреймворк. Одна из самых модных связок сейчас — это react + redux. А для верстки, так и быть, будем использовать старый добрый олдскульный bootstrap (через sass, конечно же).

Нам понадобится куча js-библиотек. У вас ведь стоит nodejs и npm? Убедитесь, что у вас свежий npm и установите пакеты:

npm init 

в зависимостях (в файле package.json) пропишем примерно такое:

"dependencies": {
 "@types/react": "^15.0.11",
 "@types/react-dom": "^0.14.23",
 "babel-core": "^6.23.1",
 "babel-loader": "^6.3.2",
 "babel-preset-es2015": "^6.22.0",
 "babel-preset-react": "^6.23.0",
 "bootstrap-sass": "^3.3.7",
 "css-loader": "^0.26.1",
 "node-sass": "^4.5.0",
 "react": "^15.4.2",
 "react-dom": "^15.4.2",
 "react-redux": "^5.0.2",
 "redux": "^3.6.0",
 "resolve-url-loader": "^2.0.0",
 "sass-loader": "^6.0.1",
 "style-loader": "^0.13.1",
 "ts-loader": "^2.0.0",
 "typescript": "^2.1.6",
 "url-loader": "^0.5.7",
 "webpack": "^2.2.1",
 "@types/node": "^7.0.5"
}


И выполним

npm install

и еще нужно установить:

npm install webpack -g

чтобы была доступна команда webpack.

Увы, это еще далеко не всё. Так как у нас typescript, еще надо создать файл tsconfig.json, примерно такой:

tsconfig.json
{
  "compilerOptions": {
    "module": "es6",
    "moduleResolution": "node",
    "sourceMap": false,
    "target": "esnext",
    "outDir": "web/ts",
    "lib": [
      "dom",
      "scripthost",
      "es5",
      "es6",
      "es7"
    ],
    "jsx": "react"
  },
  "include": [
    "frontend/**/*.ts",
    "frontend/**/*.tsx"
  ]
}


С конфигами пока что ок, теперь займемся нашим приложением на typescript.

Сначала создадим компонент для отображения нашего текста:

// файл frontend/components/Greetings.tsx
import * as React from 'react';

export interface GreetingsProps {
    text: string;
    isReady: boolean;
    onMount();
}

class Greetings extends React.Component<GreetingsProps, undefined> {

    componentDidMount() {
        this.props.onMount();
    }

    render() {
        return (
            <h1>{this.props.text}</h1>
        );
    }
}

export default Greetings;

Наше SPA будет подгружать текст надписи через Rest API. React — это просто view-компоненты, а нам еще нужна логика приложения и управление состоянием.

Так что будем использовать redux, а также пакет для связи redux и react (react-redux). Поэтому надо будет еще создать компонент, который будет создавать наш компонент Greetings с нужными properties, и сможет сообщить хранилищу (store) состояния, что появилось новое действие (получены данные для отображения).

Disclaimer: я только начал изучать redux, поэтому наверняка тут есть за что «бить по рукам».

Выглядит этот компонент, допустим, примерно так:

// файл frontend/components/App.tsx
import * as React from 'react';

import {connect} from 'react-redux'
import Greetings from './Greetings';


const mapStateToProps = (state) => {
    return state;
}

const mapDispatchToProps = (dispatch) => {
    return {
        onMount: () => {
            fetch("/greetings/1").then((response) => {
                return response.json();
            }).then((json) => {
                dispatch({type: 'FETCH_GREETING', text: json.greeting})
            });
        }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Greetings);

Ну и точка входа приложения, создание redux-стора, диспатчера и т.д. Тут всё сделано немного по рабоче-крестьянски, но для хелловорлда сойдет, пожалуй:

// подгружает стили  bootstrap
import 'bootstrap-sass/assets/stylesheets/_bootstrap.scss';

import * as React from 'react';
import * as ReactDOM from "react-dom";
import {Provider} from 'react-redux';
import App from './components/App';
import {createStore} from 'redux';

const app = (state = {isReady: false, text: ''}, action) => {
    switch (action.type) {
        case 'FETCH_GREETING':
            return Object.assign({}, state, {isReady: true, text: action.text});
    }
    return state;
}

const store = createStore(app);

ReactDOM.render(
    <Provider store={store}>
        <App/>
    </Provider>,

    document.getElementById("root")
);

Примерно здесь происходит следующее:

  • Первоначальное состояние системы — {isReady: false, text: ''}.
  • Создан reducer под названием app, который умеет обрабатывать действие FETCH_GREETING и возвращать новое состояние системы.
  • Создан store для обработки состояний.
  • Всё отрендеривается в элемент, который мы прописали во вьюхе <div id="root"></div>

Ах да, совсем забыл. Конфиг вебпака:

webpack.config.js
const webpack = require('webpack');
const path = require('path');
const ENVIRONMENT = process.env.NODE_ENV || 'development';

let config = {
    context: path.resolve(__dirname, "frontend"),
    entry: './index.tsx',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, "web/js")
    },
    resolve: {
        extensions: [ ".js", ".jsx", '.ts', '.tsx']
    },
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: [{
                    loader: 'babel-loader',
                    query: {
                        presets: ['es2015', 'react']
                    }
                }, {
                    loader: 'ts-loader'
                }]
            },

            {
                test: /\.woff($|\?)|\.woff2($|\?)|\.ttf($|\?)|\.eot($|\?)|\.svg($|\?)/,
                loader: 'url-loader'
            },

            {
                test: /\.scss$/,
                use: [
                    {
                        loader: "style-loader"
                    },
                    {
                        loader: "css-loader"
                    },
                    {
                        loader: "resolve-url-loader"
                    },
                    {
                        loader: "sass-loader"
                    }
                ]
            }
        ]
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify(ENVIRONMENT)
        })
    ],
    node: {
        process: false
    }
};

if (ENVIRONMENT == 'production') {
    config.plugins.push(
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                drop_console: false,
                warnings: false
            }
        })
    );
}

module.exports = config;


Теперь мы можем запустить webpack или NODE_ENV=production webpack (чтобы получить минифицированную версию bundle.js)

Pomodoro


Не знаю как вы, а я уже задолбался писать этот hello, world. В 2017 году надо работать эффективно, а это подразумевает, что надо делать перерывы в работе (метод Pomodoro и т.д.). Так что, пожалуй, прервусь не надолго.

[прошло какое-то время]

Давайте продолжим. Мы уже умеем подгружать код с /greetings/1 на стороне javascript, но php-часть еще совершенно не готова.

Doctrine


Уже потрачено много времени, а в php-коде не создано ни одной сущности. Давайте исправим положение:

<?php

// src/AppBundle/Entity/Greeting.php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="greetings")
 */
class Greeting
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    private $greeting;

    public function getId()
    {
        return $this->id;
    }

    public function getGreeting()
    {
        return $this->greeting;
    }
}

Супер. Осталось совсем чуть-чуть.

REST


Надо сделать-таки простенький REST API, который может хотя бы отдать json по запросу GET /greetings/1

Для этого в контроллере (файл src/AppBundle/Controller/DefaultController.php) добавим метод с роутом:

    /**
     * @Route("/greetings/{id}")
     */
    public function greetings($id)
    {
        $greeting = $this->getDoctrine()->getRepository("AppBundle:Greeting")->find($id);
        return new JsonResponse(['greeting' => $greeting->getGreeting()]);
    }

Всё, можно запускать. На экране отображается «Hello, world!». Внешне он, конечно, выглядит почти также как результат <?php echo «hello, world» ?> (если не считать бутстраповского шрифта), но теперь это современное приложение по всем канонам. Ну, скажем так, почти по всем канонам (не хватает тестов, проверок ошибок и много чего еще), но я уже задолбался это делать :)

Выводы


В последнее время сильно участились споры «зачем нужен php, если есть java». Уж не знаю, кто прав, а кто нет, холивары — дело такое. Но в каждом споре один из аргументов в пользу php — это простота для новичков. Как мне кажется, этот аргумент уже давно не валиден, что я и хотел показать этой статьёй. Новичку все равно придется кучу всего узнать и 100500 конфигов настроить: фреймворки (очень похожие на фреймворки java), базы данных, linux, javascript со всем своим зоопарком, верстка, http-протокол, различный тулинг и многое-многое другое. Даже если это не SPA.

Upd. Статья уходит в глубокий минус, но я не собираюсь менять мнение. Оно примерно такое:
1) SPA всё больше проникает в наш мир, и надо это уметь, хотя бы в общих чертах.
2) Без фреймворков не построишь хорошее современное приложение.
Поделиться с друзьями
-->

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


  1. DeLuxis
    20.02.2017 11:02
    +16

    Вы смешали frontend (где действительно избыточно много абстракций) и backend.
    Достаточно было создать модель и вывести «Hello world!» из базы во вьюхе через контроллер.


    1. varanio
      20.02.2017 11:05
      +1

      Согласен, получилось скорее hello, world SPA. Но сейчас SPA со страшной силой шагает по планете. Зайдите в любую современную админку банка и т.д. — там будет реакт. Мне кажется, надо уметь хотя бы хелловорлд всего этого дела.


      1. jobanaro
        21.02.2017 01:03
        +1

        SPA должен умереть…


        1. Fesor
          21.02.2017 01:22
          +4

          отчего же? Это же волшебно когда UI на клиенте это не статическая страничка а луп отрисовывающий стэйт! А если еще и выстроен как композиция реюзабельных компонентов, ух… А бэкэнд stateless и в целом не зависит от UI особо, крути верти как хочешь. Дикий простор для творчества. Для определенного процента проектов можно вообще без бэкэнда обходиться благодаря всяким там firebase-ам и похожим сервисам. Идеально для CRUD-like приложений, да и с кодогенерацией для UI и реюзом оного как-то получше дела обстоят.


          Конечно же это не для всех проектов/команд подходит… И надо фронтэнды уметь, с чем сейчас тугова-то у людей. То есть свои жирные минусы несомненно есть...


      1. questpc
        21.02.2017 11:24

        Мне не нравится JSX из-за смешивания логики (кода) и шаблона. В Knockout.js, который я использую, логика отдельно, шаблон data-bind отдельно. Это позволяет использовать общий шаблон с разными JS классами, что очень удобно. Никаких транспилеров и кучи node.js приложений не нужно, все работает на ES5 без какой-либо прекомпиляции. Сам Knockout.js очень небольшой и содержит все что нужно.

        SPA плохи двумя вещами — слабой индексацией в поисковиках и глюками старых браузеров. Я больше использую AJAX компоненты чем чистое SPA. Хотя для админки SPA действительно хорош — там не нужна индексация и вряд ли кто зайдет старым браузером.


        1. varanio
          21.02.2017 11:55
          +1

          Я раньше также думал. Пока не попробовал.

          В JSX есть логика, но это только view логика.

          Когда вы в handlebars пишете

            {{#if author}}
              <h1>{{firstName}} {{lastName}}</h1>
            {{/if}}
          


          ведь это тоже смешение тегов с логикой отображения. Просто в jsx наоборот, смешивается логика с тегами. Что дает определенные преимущества: не надо сочинять свой шаблоноязык, а использовать чистый js.

          Разумеется, бизнес-логику нельзя пихать в react-компонент, ни в коем случае. Для бизнес-логики надо юзать redux (или еще какой-нибудь flux), обмениваясь с компонентами событиями и т.д.


          1. VolCh
            21.02.2017 12:06

            Разумеется, бизнес-логику нельзя пихать в react-компонент, ни в коем случае.

            Нельзя смешивать в одном компоненте бизнес-логику и логику отображения. Разделять вполне можно.


          1. vintage
            26.02.2017 00:23
            -1

            Когда вы в handlebars пишете

            Так не пишите, оставьте шаблоны простыми.


        1. Fesor
          21.02.2017 12:03
          +2

          из-за смешивания логики (кода) и шаблона.

          Twig/Nunjucks/Jinja2


          <ul>
          {% for item in list %}
             <li>{{ item}}</li>
          {% else %}
             <li class="empty">List is empty :(</li>
          {% endfor %}
          </ul>

          Angular


          <ul>
            <li *ngFor="let item of list">{{item}}</li>
            <li class="empty" *ngIf="!list.length">List is empty :(</li>
          </ul>

          React JSX


          render: function() {
              return (
                  <ul>
                    {this.props.list.map(item => <li>{item}</li>)}
                    {this.props.list.length == 0 &&
                       <li class="empty">List is empty :(</li>
                    }
                  </ul>
                )
              }

          Knockout.js


          <li data-bind="foreach: list">
             <span data-bind="text: $data"></span>
          </li>
          <li class="empty" data-bind="if: pets().length == 0">List is empty :(</li>

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


          все работает на ES5 без какой-либо прекомпиляции.

          Я уже не могу писать просто на es5 без всяких бабелев… к хорошему быстро привыкаешь.


          SPA плохи двумя вещами — слабой индексацией в поисковиках и глюками старых браузеров.

          На счет браузеров — согласен, хотя с каждым годом ситуация меняется в лучшую сторону. Ну а по поводу индексации — приведу пример. angular-universal. Server-side рендринг в пол пинка (ну как. относительно конечно).


          1. questpc
            21.02.2017 12:10

            Тем не менее в случае knockout / angular мы имеем самый минимум логики в шаблонах (конечно можно запихнуть в data-bind JS-код на несколько строк, только это даже человеку не любящему красоту кода будет очевидно выглядеть плохо), а react как-бы поощряет запихивать побольше кода в шаблон. Понятно что хороший программист будет сдерживать себя.

            И еще момент с наследованием этого дела. В ES5 и тем более в ES6 можно прототип метода у потомка заменить и пожалуйста — тот же шаблон knockout.js с другим кодом. В то же время в популярном Vue.js с наследованием оказались огромные проблемы вообще не рекомендуют использовать. Хотя на мой взгляд UI без наследования это нон-сенс.

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

            На react может конечно и надо переходить так как спрос на него огромен, хотя идеологически коробит меня от него, привыкнуть ко всему можно. Куча уже существующего кода на Knockout.js работает и вроде как непонятно зачем. Разве что из-за денег.


            1. Fesor
              21.02.2017 12:15
              +1

              Тем не менее в случае knockout / angular мы имеем самый минимум логики в шаблонах

              присмотритесь. Количество логики ровно одинаковое. Разница лишь в синтаксисе. Причем в этом плане у jsx есть преимущество перед knockout — не надо изучать новый синтаксис — все работает на обычном js. Как и в underscore templates например и куче других шаблонизаторов.


              es5 хорош тем что быстрее проект разворачивать

              yoman, кучи скафолдингов, шаблоны проектов и т.д. решают эту проблему. А за счет es2015+ скорость разработки и удешевление поддержки быстро окупает эти вещи.


              На react может конечно и надо переходить

              В целом я фанат ангуляра так что… я не перейду)


          1. Ronnie_Gardocki
            21.02.2017 13:15
            +2

            React версию можно отрефакторить до такого:

            render() {
                let {list} = this.props;
                return (
                    <ul>
                        {list.map(item => <li>{item}</li>)}
                        {!list.length && <li className="empty">List is empty :(</li>}
                    </ul>
                  )
            }
            


            1. Fesor
              21.02.2017 15:20

              да, так поприятнее. Тогда разница вообще ничтожна.


          1. vintage
            26.02.2017 00:50

            $mol:


            $my_pets $html_ul
                Pet_row!index $html_li
                    sub /
                        <= pet_name!index     No_pet $html_li
                    sub /
                        <= no_pet_messsage @ \Not pets :(

            sub() {
                if( this.items().length === 0 ) return [ this.Empty() ]
                return this.pets().map( ( name , index )=> this.Pet_row( index ) )
            }
            
            pet_name( index : number ) {
                return this.pets()[ index ]
            }

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


            1. vintage
              26.02.2017 01:19

              Не this.Empty(), а this.No_pet(), конечно же. И с наследованием тут всё хорошо (прям отлично). И нет, это не "самопиар", а объяснение, как та же проблематика может быть решена лучше.


              1. varanio
                26.02.2017 07:01

                Ваш пример не особо лучше. Вы все равно изувечили html, напихав туда свой язык. Как и в других шаблонизаторах


                1. vintage
                  26.02.2017 09:52

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


            1. Fesor
              26.02.2017 14:07

              На таком простом примере преимуществ не видно

              А на каком будет видно и в чем заключается преимущество? Мы уже как-то дискутировали на эту тему — ваш вариант возможно и имеет свои плюсы, но не годится для большинства людей.


              1. vintage
                26.02.2017 22:12

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


                При разделении композиции и логики вы просто пишете, например:


                $my_app $mol_view
                    as_card true
                    sub / <= Card $mol_card
                        sub / <= Info $mol_labeler
                            title <=  info_title @ \Your salary
                            content / <= Salary $my_currency
                                value <= salary null

                А потом добавляете отдельно любой сложности логику:


                sub() {
                    return [ this.as_card() ? this.Card() : this.Info() ]
                }


                1. Fesor
                  26.02.2017 23:03
                  +1

                  На любом более-менее реальном.

                  То есть вывести список — не реальная задача?


                  Ну, банальная задача: в зависимости от флага заворачивать содержимое в дополнительную обёртку.

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


                  1. vintage
                    27.02.2017 09:50

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


                    Так тут родитель (блок $my_app) и управляет всеми своими элементами (Card, Info, Salary).


                    1. VolCh
                      27.02.2017 10:37

                      Вывести список строк в одиночном теге — не реальная

                      Очень реальная. Пример — вывести табличку с заголовком строки в виде ФИО клиента и одним из столбцов через запятую номера заказов.


                      1. vintage
                        27.02.2017 11:28

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


                        1. VolCh
                          27.02.2017 11:49

                          Сложно по бумаге кликать.


                          1. vintage
                            27.02.2017 11:56

                            Версия для печати — очень частный случай.


                            1. VolCh
                              27.02.2017 12:03

                              Большинство отчётов не нуждаются в интерактивности, даже если формально не печатаются.


                              1. vintage
                                27.02.2017 12:29

                                У нас ровно противоположная статистика.


                                1. VolCh
                                  27.02.2017 13:02

                                  У нас отчёты — это отчёты. Если отчёт подробный, то там всё и так есть. Если агрегированный, значит детали никого не интересуют. Были попытки получить интерактивность у отчётов, но и показали другой инструмент и сказал, что это то, что нужно.


                                1. Fesor
                                  27.02.2017 18:28
                                  +2

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


                                  В целом же как по мне ваш варинт излишне сложен если сравнивать его с любым другим.


                                  1. vintage
                                    27.02.2017 20:35

                                    Значит ваша выборка "реальных случаев" не может быть репрезентативной.

                                    А какая может? Будет чудесно, если вы приведёте ссылку на репрезентативную статистику.


                                    Да и вывести ссылку — не сильно сложная проблема

                                    Я говорил про не только ссылку.


                                    "Мутация" контейнера детьми я расцениваю больше как какой-то костыль

                                    Тут нет никакой мутации контейнера. Тут вывод либо одного компонента, либо другого. И это вполне штатная ситуация для нормального инструмента.


                                    В целом же как по мне ваш варинт излишне сложен если сравнивать его с любым другим.

                                    Реализуйте мой пример по проще :-)


                                    1. Fesor
                                      27.02.2017 23:27
                                      -1

                                      Реализуйте мой пример по проще :-)

                                      <my-card *ngIf="asCard()"></my-card>
                                      <my-info *ngIf="asInfo()"></my-info>

                                      Если я правильно понимаю о чем ваш пример.


                                      1. vintage
                                        28.02.2017 08:39

                                        Нет, типичная реализация того же на Ангуляре будет выглядеть так:


                                        <my-card *ngIf="asCard()">
                                            <my-info>много тегов</my-info>
                                        </my-card>
                                        <my-info *ngElse>копипаста</my-info>


                                        1. Fesor
                                          28.02.2017 10:25
                                          +1

                                          типичная реализация того же на Ангуляре будет выглядеть так:

                                          Эм...


                                          1. в Angular нет ngElse. Это атрибут элемента, он ничего не знает о соседях.
                                          2. Вся "копипаста" выносится в отдельный компонент. И компонент-родитель будет рулить какой выводить и с какими параметрами.

                                          Ну то есть мэйнстрим подход, UI как композиция UI компонентов.


                                          1. vintage
                                            28.02.2017 17:43

                                            1. Тем более, значит ещё и условие повторить надо.
                                            2. Ну то есть вводится специальный компонент со своим конфигом, с пробрасыванием всех параметров. И это не потому, что требуется декомпозиция в этом месте, а потому, что шаблонизатор настолько дубовый, что не способен переставить блок в другое место.


                                            1. Fesor
                                              28.02.2017 19:46
                                              -1

                                              1. не то что бы повторить, у вас должен быть красивый и удобный метод во вью модел который проверяет это условие, и там где надо просто надо добавить отрицание. Логика провери же будет инкапсулирована.


                                              2. Шаблонизатор не должен быть умным. Вся логика во вью модели, а шаблоны просто шаблоны. Ну и да, "умный" компонент-контейнер выгоднее "умного" универсального компонента. Это как раз более качественный уровень декомпозиции.

                                              Почему я считаю что такой подход "удобнее" — потому что, как вы заметили тут в комментариях, далеко не все разработчики компетенты. И их нужно ограничивать. А это значит надо делать компоненты максимально тупыми и выносить из них логику. Такие компоненты и тестить удобнее, и в целом приятно работать.


                                              1. vintage
                                                28.02.2017 20:23
                                                +1

                                                1. Суть от этого не меняется — нужно повторить вызов метода. А если надо будет привязаться к другому методу, то оба вызова надо будет поправить.


                                                2. Именно, поэтому в "шаблонах" вообще не должно быть логики, а в презентере можно уже использовать полноценный язык программирования, не ограничиваясь директивами.

                                                От того, что вы разобьёте один компонент на два сильносвязанных, вы никому жизнь не облегчите, а только усложните. Выносить в отдельный компонент имеет смысл лишь переиспользуемую логику.


                                                1. Fesor
                                                  28.02.2017 23:43
                                                  -1

                                                  А если надо будет привязаться к другому методу, то оба вызова надо будет поправить.

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


                                                  Именно, поэтому в "шаблонах" вообще не должно быть логики

                                                  так ее и нет, вся логика в презентерах.


                                                  От того, что вы разобьёте один компонент на два сильносвязанных

                                                  компоненты не могут быть "сильносвязанными". Они либо имею связи/зависимости либо нет.


                                                  1. vintage
                                                    01.03.2017 09:06

                                                    В одно месте вам нужно написать "asCard()", в другом "!asCard()". А если нужно первый блок показать при выполнении условий А и Б, второй — Б и В, а третий — А и С? Да, вы можете создать отдельные методы вида "isFirstBlockShowing", но:


                                                    1. так мало кто сделает.
                                                    2. писанины будет ещё больше.

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


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


                                                1. VolCh
                                                  01.03.2017 07:38
                                                  +1

                                                  Выносить в отдельный компонент имеет смысл лишь переиспользуемую логику.

                                                  Очень спорное утверждение, противоречащее многим общепринятым принципам проектирования типа того же принципа единственной ответственности.


                                                  1. vintage
                                                    01.03.2017 08:52

                                                    Компонент, созданный лишь для того, чтобы его можно было помещать в разные места, — не несёт какой-то уникальной ответственности.


                                                    1. Fesor
                                                      01.03.2017 09:18
                                                      -1

                                                      не несёт какой-то уникальной ответственности.

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


                                                      На моей памяти подобного небыло. Были компоненты занимающиеся отображением, весьма тупые, и компоненты-контейнеры, которые максимум разруливали какие компоненты показывать, но не занимались отображением непосредственно.


                                                      Ангуляр не фосирует вынос логики, а наоборот поощряет её написание прямо в шаблоне.

                                                      в целом — да, но можно во вью модели логику подублировать всегда. У разработчиков всегда будет возможность сломать инкапсуляцию и продублировать логику. С этим надо бороться другими способами.


                                                      Могут. Выделяя как попало компоненты вы получаете такие вложенные

                                                      Есть такая проблема. Нужна нормальная декомпозиция, а многие разработчики почему-то этого не умеют.


                                                      1. vintage
                                                        01.03.2017 09:29

                                                        Ок, пусть это будет карточка товара: Фотка, название, описание, цена, список тегов. На всех страницах товары показываются такими карточками, но на некоторых страницах карточка должна быть ссылкой, а на некоторых — нет.


                                                        1. VolCh
                                                          01.03.2017 09:59

                                                          Решение в лоб


                                                          ProductCard = (product) => 
                                                            <div>
                                                              <ProductImage value={product.image}/>
                                                              <ProductName value={product.name}/>
                                                              <ProductDescription value={product.description}/>
                                                              <ProductPrice value={product.price}/>
                                                              <ProductTags value={product.tags}/>
                                                            </div>;
                                                          
                                                          LinkableProductCard = ({product}) => <a href={product.link}><ProductCard product={product}></a>;


                                                          1. vintage
                                                            01.03.2017 10:14

                                                            Замечательно, тольво вы забыли прокинуть alt в картинку, title в ссылку, завернули теги в ссылку (они ведь тоже должны быть ссылками), в стоимость не прокинули валюту (которую надо оформлять другим цветом), плюс у вас появился совершенно лишний див. А уж про прокидывание правильных классов для навешивания стилей я вообще молчу. Ну и, конечно, создали пяток совершенно лишних компонент, которые нигде не будут использоваться кроме как тут.


                                                            1. VolCh
                                                              01.03.2017 10:32
                                                              -1

                                                              Всё строго по ТЗ :) Единственное замечание которое принимаю сходу — title в ссылку, но только как фичереквест. О всём остальном вы не можете судить по этому фрагменту, не зная схемы объекта product. А div не лишний, а несёт семантическую нагрузку — отделяет карточку продукта от остального документа, делает её самостоятельным элементов, на который, в числе прочего, можно ссылаться в файлах стилей. И компоненты лишними не считаю, даже если они не будут переиспользоваться — они улучшают поддерживаемость кода. Вот захотели вы валюту указывать — я джуну скажу "там есть элемент ProductPrice — добавь наименование валюты", а без компонентов придется "там есть семиэтажный Product, поройся в нём, найди часть, где цена выводится и добавь наименование валюты"


                                                              1. vintage
                                                                01.03.2017 14:13
                                                                +1

                                                                ТЗ изменилось. Сколько вам времени потребуется на рефакторинг всего проекта под новые требования, описанные в предыдущем сообщении?


                                                                Вы на имя тега будете ссылаться в файлах стилей?


                                                                Для отображения валют в разных местах имеет смыл создать компонент CurrencyValue. Отображать ProductPrice вне ProductCard было бы странно.


                                                                1. VolCh
                                                                  01.03.2017 15:08

                                                                  title для ссылки откуда брать? product.name или product.link.title? Если первое, то до десяти минут, включая деплой на стейдж- сервер. Если второе — ждём бэкенедеров и плюс 10 минут.


                                                                  Пока в проекте только одно место, где нужно отображать. Появится второе — будем смотреть что в них общего.


                                                                  1. vintage
                                                                    01.03.2017 19:45

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


                                                                    1. VolCh
                                                                      01.03.2017 20:38

                                                                      карточка должна быть ссылкой

                                                                      Согласно ТЗ и реализовано. Никаких "внутри" в ТЗ нет. Ели опять ТЗ меняется, то уточните, что значит "внутри". И почему не могу завернуть ссылку в ссылку?


                                                                      1. vintage
                                                                        01.03.2017 21:50

                                                                        1. VolCh
                                                                          02.03.2017 06:36

                                                                          1. vintage
                                                                            02.03.2017 08:39

                                                                            image


                                                                            1. VolCh
                                                                              02.03.2017 08:43

                                                                              Работает?


                                                                              1. vintage
                                                                                02.03.2017 08:58

                                                                                Нет, работать оно будет либо в режиме XHTML, либо если вы создаёте DOM скриптом. О каком-либо изоморфном рендеринге HTML в таком случае придётся забыть.


                                                                                1. VolCh
                                                                                  02.03.2017 09:07

                                                                                  В ТЗ что-то было про изоморфный рендеринг? По умолчанию у нас обеспечивается только функциональность в актуальной стабильной версии Chrome, что фиксируется в коммерческом предложении на внедрение и SLA, ну в Firefox потестим чтобы вёрстка не плыла глобально, а практически весь body генерируется скриптами, клиенту отдаётся минимальная статическая страница.


                                                                                  1. vintage
                                                                                    02.03.2017 09:54

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


                                                                                    Вы когда к стоматологу приходите — тоже выкатываете ему подробное тз или всё же рассчитываете на его профессионализм и понимание что и для чего он делает и к каким последствиям это приведёт?


                                                                                    1. VolCh
                                                                                      02.03.2017 11:07

                                                                                      Не за нами написанным, за вами.


                                                                                      1. vintage
                                                                                        02.03.2017 14:22

                                                                                        У вас видимо очень продвинутые заказчики, раз сами пишут вам ТЗ :-)


                                                                                        1. VolCh
                                                                                          02.03.2017 15:41

                                                                                          Мне не важно кто пишет, наши заказчики или наши аналитики, главное, что я не пишу.


                                                                                  1. Fesor
                                                                                    02.03.2017 13:36

                                                                                    В ТЗ что-то было про изоморфный рендеринг?

                                                                                    Справедливости ради, вот эти "в тз небыло" немного напрягают. А как же protected variations?


                                                                                    1. VolCh
                                                                                      02.03.2017 13:54

                                                                                      Небольшие (с точки зрения заказчика) могут полностью перевернуть подход к разработке. Навскидку, для изоморфного рендеринга React-"шаблонов" я вообще никаких оценок дать не могу — знаю, что некоторые люди это как-то делают, вероятно с помощью http-сервера на NodeJS. Всё. Есть ли у React различия между рендерингом в DOM и в http-ответ я не знаю, в этом направлении в компании вообще ничего не делалось никогда. И вообще, может из-за требования изморфного рендеринга нужно будет полностью пересмотреть бэкенд часть. Ну или оставить PostgreSQL, но выпилить из проекта PHP и меня вместе с ним.


                                                                                      Обеспечивать во фронтенд коде совместимость с каким-то сервером, которого разработчик в глаза не видел — это не мелочь, которую можно опустить в ТЗ по принципу "это же очевидно, вы же профессионалы"


                                                                                      1. vintage
                                                                                        02.03.2017 14:25

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


                                                                                        1. VolCh
                                                                                          02.03.2017 15:40

                                                                                          Для такой задачи я увеличу сроки на месяц, даже если оценю её чисто для фронта на час. И то с большими рисками не уложиться.


                                                                                          1. vintage
                                                                                            02.03.2017 16:54

                                                                                            А я увеличу на неделю и уведу у вас заказчика :-Р


                                                                                1. Fortop
                                                                                  02.03.2017 16:38

                                                                                  Вы нам лучше объясните какой плюс заказчику от изоморфного рендеринга :)


                                                                                  1. vintage
                                                                                    02.03.2017 17:00

                                                                                    Ну, там разные тезисы: генерация html-писем, индексирование поисковиками и прочими роботами, поддержка отключённых скриптов и браузеров не поддерживающих скрипты, экспорт в хтмл, быстрый показ страницы, экономия батарейки клиентского девайса.


                                                                                  1. Fesor
                                                                                    02.03.2017 19:53
                                                                                    +1

                                                                                    Ну например "хотите чтобы ваш круто интернет-магазин вообще поисковиками индексировался" или "хотите чтобы конверсия не падала от того что апа загружается у пользователей 5 секунд".


                                                                                    Продать изоморфность весьма просто. И в целом это не требует каких-то больших эфортов если делать нормально.


                                                                                    @vintage я вот только ваш кейс с "а тепер весь блок продукта стал ссылкой" немного не понял. Мне всегда казалось что делать блоки ссылками — не хорошо, и как правило была бы ссылка где-то внутри блока а какой-то декоратор над контейнером уже бы превращал весь блок в ссылку. Это как бы и кейс изоморфности покрывает, и делать легко и просто, и нет конфликтов со спецификациями.


                                                    1. VolCh
                                                      01.03.2017 09:46

                                                      ListItemsOrNoItems = ({items}) => items.length !== 0  ? <ListItems items={items}/> : <NoItems/>;
                                                      
                                                      ListItems ({items}) => <ul>{items.map((item) => <ListItem item={item}/>)}</ul>;
                                                      
                                                      ListItem = ({item}) =>  <li>{item}</li>;
                                                      
                                                      EmptyList = () => <p>No items</p>;
                                                      

                                                      У каждого компонента ровно одна собственная уникальная ответственность. Будет она переиспользоваться где-то, может будет дублироваться — дело десятое. Главное — декомпозиция ответственностей и обязанностей.


                                                      1. vintage
                                                        01.03.2017 10:11

                                                        Замечательно. А если мне нужен ListItemsOrNoItems, но с другими ListItems и NoItems?


                                                        1. VolCh
                                                          01.03.2017 10:18

                                                          Что-то вроде
                                                          ListItemsOrNoItems = (items, AbstractListItems, AbstractNoItems) => items.length !== 0 ? <AbstarctListItems items={items}/> : <AbstarctNoItems/>;


                                                          и вызов codehtml


                                                            <ListItems items={items}  AbstractListItems={ListItems} AbstractNoItems={NoItems/} />

                                                          P.S. что-то разметка глючит


                                                          1. vintage
                                                            01.03.2017 10:21

                                                            Очень наглядно, спасибо.


                                                            1. VolCh
                                                              01.03.2017 10:33

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


                                                              1. vintage
                                                                01.03.2017 14:15

                                                                Чудесно, особенно когда таких опциональных компонентов больше 2.


                                                                1. VolCh
                                                                  01.03.2017 15:09

                                                                  Это же XML по сути.


                                                                  1. vintage
                                                                    01.03.2017 19:46

                                                                    ListItemsOrNoItems = (items, AbstractListItems, AbstractNoItems) => items.length !== 0 ? <AbstarctListItems items={items}/> : <AbstarctNoItems/>;

                                                                    Это лапша. И в жизни это так не работает, так как вы не прокидываете параметры в в создаваемые тут компоненты.


                                                                    1. VolCh
                                                                      01.03.2017 20:40

                                                                      Присмотритесь — прокидываю. И в чем лапша?


                                                                      1. vintage
                                                                        01.03.2017 21:58

                                                                        Вы прокидываете один единственный параметр — items.


                                                                        1. VolCh
                                                                          02.03.2017 06:37

                                                                          От количества параметров что-то зависит? Тем более их можно группировать в объекты типа options


                                                                          1. vintage
                                                                            02.03.2017 08:25

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


                                                                            1. VolCh
                                                                              02.03.2017 08:49

                                                                              Чем оно не переиспользуемо? Вывод списка элементов или элемента, замещающего пустой список — типовая задача и данный сниппет её решает. Передачу дополнительных параметров (что обычно для таких задач не требуется, стили или инлайнятся/импортятся в конкретных элементах, или через контекст передается тема) для дочерних элементов можно реализовать разными способами, например через…


                                                                              1. vintage
                                                                                02.03.2017 09:06

                                                                                Договаривайте уж. Через контекст? Глобальную переменную? Урл?


                                                                                1. VolCh
                                                                                  02.03.2017 09:16
                                                                                  +1

                                                                                  Это не многоточие русского языка, а рест оператор джаваскрипта/джейэсикс :)


                                                                                  1. vintage
                                                                                    02.03.2017 10:01

                                                                                    что ж вы сразу-то этого не сделли? Давайте посмотрим какой код у вас получится.


                                                                                    1. vintage
                                                                                      02.03.2017 10:21

                                                                                      Для сравнения, у меня получился такой.


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


                                                                                      1. varanio
                                                                                        02.03.2017 11:15

                                                                                        На реакте написаны facebook, сбербанк, тинькоф, слак. Я думаю, что, исходя из этого, можно утверждать, что любые проблемы решаются, так или иначе. Такой ли список рендерить, сякой и т.д.


                                                                                        1. vintage
                                                                                          02.03.2017 14:29

                                                                                          Разница в стоимости этого решения и стоимости его поддержки. Тинькоф — вообще чудесный пример — орава разработчиков сделала тормозной сайт, где некоторые страницы рендерятся по 4 секунды :-)


                                                                                    1. VolCh
                                                                                      02.03.2017 11:08

                                                                                      Не видел необходимости. KISS


                                                                                      1. vintage
                                                                                        02.03.2017 14:31

                                                                                        Теперь она появилась, не заставляйте иеня упрашивать вас написать полноценное переиспользуемое решение, которое можно применять в реальных ситуациях, а не только в комментариях на Хабре :-)


                                                                                        1. VolCh
                                                                                          02.03.2017 15:45

                                                                                          Не заставляйте меня делать продакшен решение в комментариях на хабре по неясным для меня критериями переиспользуемости.


                                                                                          1. vintage
                                                                                            02.03.2017 17:03

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


                                                                                            1. VolCh
                                                                                              02.03.2017 17:24

                                                                                              Сформулировать требования к переиспользуемости много времени займёт. Навскидку, рассматривать ли возможность замены тегов ul, li и т. п.


                                                                                              1. vintage
                                                                                                02.03.2017 18:59

                                                                                                Разумеется :-)


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


        1. VolCh
          21.02.2017 12:05
          +1

          SPA
          слабой индексацией в поисковиках

          Как правило, приложение, в отличии от сайтов и порталов, не нуждается в индексации.


  1. DamirFelix
    20.02.2017 11:02
    +9

    А если я не знаю PHP, хочу его изучить, мне сразу начинать с фрейморвка? Мне кажется более логично изучить голый PHP.


    1. varanio
      20.02.2017 11:07

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


      1. DamirFelix
        20.02.2017 11:15
        +4

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


        1. stepmex
          20.02.2017 11:24
          +19

          Сперва приходилось писать свой фреймворк. А потом на нём писать веб-приложение.


        1. VolCh
          20.02.2017 11:32
          +1

          тысячами разработчиками писались одни и те же вещи, часто с одними и теми же ошибками. Попробуйте написать такое же (желательно так же с объектом Greeting, получаемым из базы, а не массивом или stdClass) приложение на голом PHP и количество кода вас неприятно удивит. Или в коде будут грубые ошибки.


          1. linux_art
            20.02.2017 23:41

            Строчек 5-6 займет? :)


            1. wrewolf
              21.02.2017 10:52
              +1

              Ага, но только реализация класса Greeting (без учета взаимеодействия с БД)


              1. linux_art
                21.02.2017 19:30
                +1

                Это только при условии, что стоит цель усложнять код. В ином случае готовый json получается 1 запросом из базы и делать из него внутренний обьект php вообще надобности нету ;)


                1. wrewolf
                  21.02.2017 19:46
                  +1

                  При условии не усложнять объект и база лишнии, пишем константу в коде, но это выше выяснили.


                1. VolCh
                  21.02.2017 22:32

                  Не только. Условием может быть моделирование предметной области, в которой есть сущность "Приветствие".


                  1. Fesor
                    21.02.2017 22:53

                    скорее всего это будет VO


                    1. VolCh
                      21.02.2017 23:20
                      +2

                      Надо побеседовать с экспертами :)


      1. ellrion
        20.02.2017 11:24
        +6

        Это смотря какое приложение. Да и фреймворки разные есть. Тут больше важно что нужно знать современные концепции и стандарты современного веб приложения. Вот composer — да; PSR'ы; Неймспейсы; Автолоадинг; Система контроля версий; Единая точка входа; Паблик директория; Роутинг; Шаблонизация; Query builder. Остальное имхо опционально.


        И если уж говорить о самой статье, то замените symfony на laravel и react на vue. И статья выйдет короче)


      1. psFitz
        20.02.2017 11:35
        +8

        Что за бред?
        Часто видел когда люди сразу начинали учить cms или фреймворк и потом даже не понимали где cms, а где сам php.


      1. Fesor
        20.02.2017 18:52
        +1

        голого php хватит для реального приложения

        Его то хватит, вопрос в стоимости решения и покрываемых кейсах.


      1. alexlcdee
        21.02.2017 15:13

        Пожалуй, стоит подбирать инструмент подходящий под задачу, а не бездумно хватать фреймворк, если задача запросто решается без него.
        Брать фреймворк для вывода hello world — извращение.


        1. VolCh
          21.02.2017 15:42

          Как минимум, нужно ещё подумать как задача будет изменяться в обозримом будущем.


          1. alexlcdee
            21.02.2017 16:08

            Вероятность того, что задача «Hello World» менять не будет несколько выше, чем вероятность её изменения, на мой взгляд. Если задача «Hello World» должна будет вырасти дальше за пределы, собственно вывода на экран надписи «Hello World», то проще код вывода «Hello World» выкинуть и решить задачу с нуля отдельным проектом за отдельную сумму.

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


            1. VolCh
              21.02.2017 16:15

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

              Да ладно не желают. Желают, но узнав сколько оно стоит (или в случае внутреннего заказчика — сроки), то свои аппетиты умеряют. Но возможность развития закладывать нужно практически всегда, особенно если заказчик уже рассказал о своих будущих хотелках.


              1. alexlcdee
                21.02.2017 16:42

                Да ладно не желают. Желают, но узнав сколько оно стоит (или в случае внутреннего заказчика — сроки), то свои аппетиты умеряют.

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


                1. VolCh
                  21.02.2017 17:38

                  Разработчики не желают? Да нам дай волю, мы ИИ в хелловорлд запихаем, не то что СУБД с фреймворком :), да менеджеры нудят "строки-сроки".


                  1. alexlcdee
                    21.02.2017 17:40

                    Видимо я в душе менеджер, а не кодер :)
                    Ну или просто сферический лентяй


    1. vlreshet
      20.02.2017 11:25
      +2

      ИМХО, следует сначала учить чистый PHP, потом попробовать написать свой фреймворк (все должны через это пройти, чтобы исчезло желание писать велосипеды), и только потом пробовать уже существующие фреймворки.


      1. Fesor
        20.02.2017 18:49
        +1

        потом попробовать написать свой фреймворк

        Тут можно напороться на проблему "а что писать то". Ну то есть мы хотим на практике поучиться — это похвально. Но как новичку определить что он делает что-то дельное? Мы же таким образом можем вредные привычки сформировать у человека.


        1. VolCh
          21.02.2017 08:58

          Может выложить свое творчество на Хабр — тут очень доброжелательно ему объяснят, что он делает не так.


          1. wrewolf
            21.02.2017 10:54
            +4

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


            1. Fesor
              21.02.2017 11:00
              +1

              В целом есть еще чатики всякие, тостеры и подобное. Ну то есть получать фидбэк сейчас есть где. Другой вопрос что… то о чем я писал немного о другом.


              Допустим вы решили написать свой фреймворк но понятия не имеете что в нем должно быть… У вас еще нет конкретных задач которые решает фреймворк, и делать мы его будем в отрыве от реальности. И пихать туда будем кучу всего просто посмотрев на других, не разобравшись почему там так и зачем. И скорее всего ближайшее код ревью будет не через неделю а через месяц минимум. А на таких масштабах "конструктивно" уже сложно.


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


              Ну и под "прикладными задачами" я подразумеваю не бложики, а что-то интереснее. Например — клоны инстаграммов, твиттеров. Какие-то утилитки. Хороший пример в чатиках проскакивал — человек отрабатывал навыки на примере тулы для генерации чейджлогов из git log.


              1. wrewolf
                21.02.2017 12:15

                Я это понимаю. Но мой коментарий был к VolCh.
                П.С.
                Я сам писал фреймворк, да и сейчас сталкиваюсь с несколькими самописными.
                Но они все написаны с целью решать определенные задачи.


      1. Koshelenok
        21.02.2017 08:28

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


        1. VolCh
          21.02.2017 08:58
          +4

          Паттерны почти бесполезно изучать, если на практике не сталкивался с проблемами, которые они решают.


      1. michael_vostrikov
        21.02.2017 20:25

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


        1. Fesor
          21.02.2017 22:31
          +1

          еще нюанс — следует попробовать поработать хотя бы с двумя фреймворками. Чтобы посмотреть разные подходы.


          1. VolCh
            21.02.2017 22:33

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


            1. Fesor
              21.02.2017 22:55

              точно не ассемблер… эрланг например.


    1. Fesor
      20.02.2017 18:47

      Мне кажется более логично изучить голый PHP.

      А еще было бы неплохо поучиться тесты писать до момента когда надо фреймворк брать. Ну и не стоит на голом пыхе заниматься коммерческой разработкой (если у вас нет достаточно опыта).


      А так да, знание фреймворка не убережет вас от незнания языка. Логику мы все ж на php пишем.


    1. questpc
      21.02.2017 11:25

      Советую изучить Python вместо PHP. Не смотря на то что PHP в последних версиях взял очень много из Питона, по легкочитаемости кода и красоте синтаксиса уступает последнему. Python по сути это тот же PHP, но лучше. Особенно если 3.x и с использованием Jinja2.


  1. A-Stahl
    20.02.2017 11:05
    +4

    >надо осознать тот факт, что без фреймворка сейчас приложения никто не делает.
    Вот поэтому о PHP и JavaScript многие такого плохого мнения — на каждый чих свой фреймворк. Все они разные. Все велосипедные и…
    >кто потом этот велосипед за вас переписывать будет?


    1. RubaXa
      20.02.2017 13:03
      -4

      Дело не JavaScript, а разнообразии платформ и браузеров.


    1. VolCh
      20.02.2017 13:07

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


  1. janson
    20.02.2017 11:18
    +23

    И всё же, hello world на PHP выглядит именно так:

    <?php
    echo 'Hello, world!';
    


    1. f3ath
      20.02.2017 11:21
      +53

      он выглядит вот так:

      Hello, world!
      

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


      1. dmitryredkin
        21.02.2017 14:57
        +2

        Просто автор- все еще master programmer, а вы — уже гуру


  1. shurupkirov
    20.02.2017 11:21
    +11

    не увидел обвеса статьи в "sarcasm"


  1. f3ath
    20.02.2017 11:24
    +31

    Автор умничал-умничал и в итоге написал всю бизнес-логику прямо в контроллер. Молодец.


    1. VolCh
      20.02.2017 11:35
      +3

      Доставание объекта из репозитория не бизнес-логика. Здесь бизнес-логики по сути нет вообще, только бизнес-данные.


      1. marenkov
        22.02.2017 00:06
        -1

        В 2017 прямое обращение к репозиторию и сущности из контроллера — это oldschool.
        Надо было создать сервис greetings, который орудует приветствиями, а в контроллере извлечь его из контейнера и запросить у него нужное приветствие.

            /**
             * @Route("/greetings/{id}")
             */
            public function greetingAction($id)
            {
                $greetingsManager = $this->get('greetings'); 
                $greeting = $greetingsManager=>get($id);
                return new JsonResponse(['greeting' => $greeting]);
            }
        


        1. Delphinum
          22.02.2017 00:18

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

          class GreetingController{
            private $greetingService;
          
            public function __construct(GreetingService $greetingService){
              $this->greetingService = $greetingService;
            }
          
            ...
          }
          


          1. Fesor
            22.02.2017 00:23
            +1

            для контроллеров удобнее через дабл диспатч… ух жду symfony 3.3… смогу убрать свои кастыли для этого. В целом нет ничего зазорного не делать контроллеры сервисами.


            1. Delphinum
              22.02.2017 00:46

              для контроллеров удобнее через дабл диспатч

              Не знаю как это.
              В целом нет ничего зазорного не делать контроллеры сервисами

              Откуда же им взять состояние, чтобы не быть сервисами?


              1. Fesor
                23.02.2017 01:52
                +1

                Не знаю как это.

                Это когда зависимости для метода прокидываются как аргументы этого метода:


                // вместо такого
                public function doSomething()
                {
                    $this->someData = $this->dependency->someCalculations($this->someData);
                }
                
                // так
                public function doSomethingCooler(MyDependency $dependency)
                {
                    $this->someData = $dependency->someCalculations($this->someData);
                }

                Хорошо подходит для экшенов контроллеров и если вы хотите какую-то логику опрокинуть в сущность чтобы не плодить геттеров и не ломать инкапсуляцию.


                Откуда же им взять состояние, чтобы не быть сервисами?

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


                А при помощи дабл диспатча мы можем полностью устранить необходимость в экшенах контроллера юзать сервис локаторы и тем самым получить практически тот же профит что и от controller-as-service но без гемороя.


                1. Fortop
                  23.02.2017 10:41

                  А кто мешает сейчас писать в режиме 1 action = 1 controller?

                  Получается именно то самое поведение, которое вам хочется.

                  PSR-7 middleware фреймворки реализуют именно то, что вы хотите.
                  Например Zend Expressive


                  1. Fesor
                    23.02.2017 14:04

                    А кто мешает сейчас писать в режиме 1 action = 1 controller?
                    Получается именно то самое поведение, которое вам хочется.

                    далеко не то же. Зачем мне ажно целый класс который выглядит так:


                    class RegisterUserAction
                    {
                        private $handler;
                        private $loginManager;
                    
                        public function __construct(RegisterUserHandler $handler, LoginManager $loginManager, Flusher $flusher)
                        {
                              $this->handler = $handler;
                              $this->loginManager = $loginManager;
                              $this->flusher = $flusher;
                        }
                    
                        /**
                         * @Route("/users", methods={"POST"})
                         */
                        public function __invoke(Request $request)
                        {
                             $user = $this->handler->__invoke($this->mapRequestData($request));
                             $this->flusher->flushChanges();
                    
                             return $this->loginManager->login($user);
                        }
                    }

                    если я могу сделать так:


                    public function registerUserAction(Request $request, RegisterUserHandler $handler, LoginManager $loginManager)
                    {
                        $user = $handler($this->mapRequestData($request);
                        $this->flushChanges();
                    
                        return $loginManager->login($user);
                    }

                    Ну то есть кода меньше, делает одно и то же. Это же контроллеры, там нет логики, даже логики уровня приложения. Оно просто связывает HTTP и приложение. Вот если бы можно было полностью от HTTP отвязаться на уровне фронтконтроллера, у меня остались бы только хэнделеры и контроллеры бы юзались как адаптеры например для совместимости со старыми версиями API. Но увы я пока не придумал эффективного способа.


                    PSR-7 middleware фреймворки реализуют именно то, что вы хотите.

                    Не то же самое. Повторюсь — я пробовал, на 100% не выходит. Проблема обычно с http реквестом или с flush-ем доктрины. Все равно нужна какая-то одна штука на запрос которая будет связывать все вместе. Проблему частично решает graphql но это если он нам подходит.


                    1. marenkov
                      23.02.2017 14:43

                      Вот если бы можно было полностью от HTTP отвязаться на уровне фронтконтроллера, у меня остались бы только хэнделеры и контроллеры бы юзались как адаптеры например для совместимости со старыми версиями API. Но увы я пока не придумал эффективного способа.

                      Может это вдохновит вас на идею https://habrahabr.ru/post/280512/


                      1. Fesor
                        23.02.2017 15:05

                        Это хорошо подходит когда вы не любите фронтэндщиков.


                        CommandBus это хорошо, это прикольно, это весело. Но это не значит что HTTP запрос который дергает шину команд ничего не должен возвращать. А если вам надо что-то вернуть — надо знать что возвращать.


                        p.s. Практикую CQRS на проектах, так что вдохновиться увы не могу и думал над этим не один месяц. Отказаться от контроллеров является непрактичной затеей. Делать экшены контроллеров как классы практично только если у вас логика в контроллерах.


                    1. Delphinum
                      23.02.2017 14:52

                      Зачем мне ажно целый класс который выглядит так

                      А почему бы не реализовать делегирующий контроллеру middleware?


                      1. Fesor
                        23.02.2017 15:06

                        и будет по мидлвэру на действие. То есть адаптеры такие небольшие. То есть… контроллеры.


                        1. Delphinum
                          23.02.2017 15:17

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


                          1. Fortop
                            23.02.2017 16:50

                            Чем он формально будет отличаться от контроллера?

                            Вы контроллер можете инстанцировать через фабрики. Зачем там middleware?


                            1. Delphinum
                              23.02.2017 17:08

                              Дело не в инстанциировании, а в подготовке запроса и ответа. Тут все зависит от задачи. К примеру у вас есть требование: «при запросе с расширением .json, должен возвращаться ответ в формате JSON, а без расширения, в формате HTML» — можно конечно реализовать два контроллера, которые будут одинаково обрабатывать Request, одинаково запрашивать у слоя домена, но по разному формировать Reponse, а можно просто добавить в Pipeline Middleware, который на основании Request будет оборачивать полученные от одного контроллера данные в разные форматы (JSON или HTML).


                              1. Fortop
                                23.02.2017 17:59
                                +2

                                В моем понимании разные форматы это рендеринг в разные View

                                Соответственно постпроцессинг запросов в middleware у вас потом ответ куда отдаёт?


                                1. Delphinum
                                  23.02.2017 20:12

                                  В моем понимании разные форматы это рендеринг в разные View

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

                                  Про JSON/HTML это был общий пример использования Middleware Pipeline, по тому же принципу, к примеру, можно организовать ACL расположив слой проверки перед контроллером в виде Middleware.


                                  1. Fortop
                                    24.02.2017 13:33

                                    Зачем?

                                    Если у меня приложение поддерживает несколько форматов рендеринга, то я это свяжу на этапе роутинга например.

                                    Или в самом контроллере анализируя пришедший из роутинга параметр формата буду подключать необходимые View.
                                    Эдакий Context switch.

                                    Суть в том, что никому другому знать о том поддерживает ли контроллер разные форматы не нужно.

                                    Вот ACL это неплохой пример post-routing события.
                                    Информации для принятия решения к этому времени уже достаточно


                                    1. Delphinum
                                      24.02.2017 14:24

                                      Или в самом контроллере анализируя пришедший из роутинга параметр формата буду подключать необходимые View.
                                      Эдакий Context switch.

                                      В том то и суть, что Middleware Pipeline позволяет вынести из контроллера часть логики, инкапсулировав ее в других классах. Разделение ответственности и все такое. Я не настаиваю, просто обсуждаю один из вариантов решения.


                              1. VolCh
                                23.02.2017 18:31

                                Как правило, для HTML нужно возвращать больше данных.


                                1. Delphinum
                                  23.02.2017 22:16

                                  В том то и прелесть, для HTML можно добавить дополнительный Middleware.


                                  1. Fesor
                                    23.02.2017 22:30

                                    То есть мы можем воспринимать контроллеры как еще один адаптер, еще один мидлварь. И у нас будет адаптер (мидлварь) которая на основе правил маршрутизации будет выбирать нужный. Пока не вижу ни разницы в подходах ни профита. Я лишь выбираю способ с которым удобнее. В PHP удобнее класс-контроллер с несколькими экшенами и дабл диспатчем. В JS удобнее функции-адаптеры которые выступают как мидлвари.


                                    1. Delphinum
                                      23.02.2017 23:50

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

                                      Выбирать нужный что?

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


                                      1. Fesor
                                        24.02.2017 11:41

                                        Разница между обычным контроллером и пачкой Middleware

                                        Я опять же не понимаю о чем спор. Мидлвари или просто слой адаптеров — это хорошо, но это совершенно отдельный вопрос. Он не решает необходимости иметь некий мидвар на конце цепочки который бы соответствовал одному http запросу. А наличие перед этим мидлварем цепочки, каждый элемент которой делает что-то одно — это просто логично.


                                        1. Delphinum
                                          24.02.2017 14:29

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

                                          и будет по мидлвэру на действие. То есть адаптеры такие небольшие. То есть… контроллеры

                                          Резюмировать мой ответ можно так: не обязательно дробить Middleware по штуке на действие.


                                          1. Fesor
                                            24.02.2017 22:08
                                            +1

                                            не обязательно дробить Middleware по штуке на действие.

                                            Не обязательно. По факту мы можем реализовать:


                                            • мидварь для всех операций записи, которые не возвращают результата отличного от "все хорошо" (ошибки — это другое, это можно разрулить отдельной мидлварей).
                                            • мидлварь для всех операций чтения, которые возвращают какой-то результат.
                                            • по мидлварю на любую комбинацию запись + чтение на запрос.

                                            То есть в общем и целом мы стоим перед выбором — либо у нас роуты будут разбросаны по всей системе (потому что тут можно без контроллера, а тут без контроллера будет сложно) либо у нас всегда будет тонкий слой адаптеров между HTTP и приложением, по экшену на юзкейс.


                                            1. Delphinum
                                              27.02.2017 15:21

                                              потому что тут можно без контроллера, а тут без контроллера будет сложно

                                              Fesor, не понял причину разброса роутов по системе. Чем плох вариант вроде:
                                              [
                                                'route' => '/article/update/:id',
                                                'middleware' => [
                                                  SessionMiddleware::class,
                                                  AclMiddleware::class,
                                                  ControllerDelegatorMiddleware::class,
                                                ],
                                                'controller' => ArticleController::class,
                                                'action' => 'updateAction',
                                              ]
                                              

                                              Возможно проблема в том, что вы конфигурируете роуты только на уровне контроллеров?


                                              1. Fesor
                                                27.02.2017 18:29

                                                Возможно проблема в том, что вы конфигурируете роуты только на уровне контроллеров?

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


                                                1. Delphinum
                                                  27.02.2017 18:38

                                                  Что менее удобно

                                                  Ну это уже слишком субъективно, чтобы обсуждать )


                                      1. vintage
                                        26.02.2017 12:20

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


                                        1. Delphinum
                                          27.02.2017 15:29

                                          проверять права, даже если они фактически не понадобятся

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

                                          В крайнем случае, что вам мешает исключить конкретные Middleware из очереди для конкретного контроллера?


                                          1. vintage
                                            27.02.2017 16:16

                                            Пользователь запрашивает текст статьи. Если статья опубликована — выдаём её без вопросов. Если в черновиках, то проверяем, что пользователь — автор или админ. Жонглирование мидлварями тут ничем не поможет. Удобно это делать на уровне модели, в момент обращения к которой, идёт автоматическая проверка по тем правилам, что соответствуют конкретной сущности.


                                            1. VolCh
                                              27.02.2017 16:36

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


                                              1. vintage
                                                27.02.2017 20:58
                                                +1

                                                Удобнее вообще не разделять серверную логику на M и V и C, ибо этот паттерн предназначен для интерактива с пользователем, а схема "запрос-ответ" не интерактивна, а строго последовательна.


                                                Более продуктивный подход — организовывать все сущности в виде "ресурсов", к которым можно обратиться через любой протокол (http, udp, ws, ssh) через соответствующие адаптеры.


                                                Зачем вам множество правил доступа?


                                                Ограничения прав имеет чуть ли не наибольшую бизнес ценность.


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


                                                1. VolCh
                                                  28.02.2017 06:50
                                                  +1

                                                  На многих серверах система "запрос-ответ" уже не используется в чистом виде. Как минимум есть всякие пуш-технологии. Да и сам запрос можно рассматривать как событие UI, причём не важно пользователь его инициировал, кликнув ссылку или другой сервер.


                                                  А мне ресурсный подход мало нравится, больше сервисный, он универсальней — сервис может обеспечить CRUD-доступ к ресурсу, а может делать гораздо более сложные вещи. И, главное, бизнес обычно оперирует процессами, а не сущностями.


                                                  Не мне, бизнесу. Постоянно новые требования. Но эти требования обычно к основной бизнес-логике не относятся. И бизнес-ценности особой не имеет, в плане что не приносит прибыли, защищают от потерь, нужны как неизбежное зло, но прибыли не приносят. Мировая практика показывает, что неразрывное связывание объектов прав доступа (это не только сущности) и описания самих прав (особенно императивное) крайне редко приносит пользу. Различные ACL, хранимые и обрабатываемые отдельно более эффективны как в плане удобства их манипулированием, так и в плане улучшения основной логики — мухи отдельно, котлеты отдельно.


                                                  Что является атрибутом, а что нет, определяется не разработчиком приложения, а экспертами предметной области. И даже если эксперты настаивают на том, что право доступа неотъемлемый атрибут сущности или экземпляра процесса, то разработчик может их разбить и связать 1:1, чтобы облегчить свои задачи, например не хранить в базе данных код определения прав с последующим его интерпретацией.


                                                  1. vintage
                                                    28.02.2017 09:05

                                                    На многих серверах система "запрос-ответ" уже не используется в чистом виде.

                                                    В рамках REST это в любом случае остаётся — запрос ответ. Даже в схеме "запрос от одного сервера, ответ другому". Нет сохраняющегося состояния вьюшки — нет MVC. Комбинацию клиент+сервер уже можно рассматривать как MVC, точнее на клиенте MVC, но модель синхронизируется с мастер-моделью на сервере.


                                                    И, главное, бизнес обычно оперирует процессами, а не сущностями.

                                                    Чем бизнес оперирует — то и есть сущность.


                                                    И бизнес-ценности особой не имеет, в плане что не приносит прибыли, защищают от потерь, нужны как неизбежное зло, но прибыли не приносят.

                                                    Всё же хотелось бы более конкретный пример. Если есть требование, например, что автор может редактировать статью, то проще, производительнее и надёжней просто проверить авторство (причём это можно делать даже на клиенте, без обращения к серверу), чем городить обращение к ACL и обеспечивать каждого автора правами на созданные ими статьи, а когда логика прав меняется — перетрясать ACL.


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


                                                    1. VolCh
                                                      28.02.2017 09:33

                                                      В рамках REST это в любом случае остаётся — запрос ответ. Даже в схеме "запрос от одного сервера, ответ другому". Нет сохраняющегося состояния вьюшки — нет MVC. Комбинацию клиент+сервер уже можно рассматривать как MVC, точнее на клиенте MVC, но модель синхронизируется с мастер-моделью на сервере.

                                                      Я рассматриваю клиент-сервер как MVC, в котором V и C размазаны между клиентом и сервером. Что между клиентом и сервером есть односторонний синхронный канал "запрос-ответ" — деталь реализации, обусловленная протоколом обмена. Что на клиенте может быть дублирование модели и свое MVC — деталь реализации.


                                                      Чем бизнес оперирует — то и есть сущность.

                                                      Очень отличается от классического определения сущности в моделировании предметных областей. Как минимум, бизнес оперирует сущностями и процессами, в которые сущности вовлечены. Например, сущности "клиент" и "договор" вовлечены в процесс "заключение договора".


                                                      Всё же хотелось бы более конкретный пример. Если есть требование, например, что автор может редактировать статью, то проще, производительнее и надёжней просто проверить авторство (причём это можно делать даже на клиенте, без обращения к серверу), чем городить обращение к ACL и обеспечивать каждого автора правами на созданные ими статьи, а когда логика прав меняется — перетрясать ACL.

                                                      ACL просто как пример. Проверять авторство — да, но в слое проверке прав доступа писать


                                                       $userCanEdit = ($article->author === $user) || $user->hasGroup('admin', 'moderator') || $user->hasPermission('edit_any_article') || ($user->birthDate ==  new \DateTime('1975-05-03')); 

                                                      а не в методе Article::isEditableBy(User $user) то же самое — слишко сильная связанность с User получается.


                                                      И способ хранения и сущности, и прав особого значения не имеет для бизнеса, как правило.


                                                      1. vintage
                                                        28.02.2017 18:15

                                                        Как минимум, бизнес оперирует сущностями и процессами, в которые сущности вовлечены. Например, сущности "клиент" и "договор" вовлечены в процесс "заключение договора".

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


                                                        не в методе Article::isEditableBy(User $user) то же самое — слишком сильная связанность с User получается.

                                                        И что в этом плохого?


                                                        И способ хранения и сущности, и прав особого значения не имеет для бизнеса, как правило.

                                                        Формат хранения определяет мышление :-)


                                                        1. VolCh
                                                          28.02.2017 18:48

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

                                                          Сущность — вещь, процесс — действие.


                                                          И что в этом плохого?

                                                          На любой чих службы безопасности и т. п. нужно менять бизнес-логику. На любое изменение сущности пользователя нужно менять бизнес-логику.


                                                          Формат хранения определяет мышление

                                                          Я вообще стараюсь не думать о хранении пока не определюсь с объектной моделью. Выбор из SQL, noSQL или вообще в какого-то веб-хранилища последний этап.


                                                          1. vintage
                                                            28.02.2017 19:21

                                                            Сущность — вещь, процесс — действие.

                                                            А что толку от этого переименовывания? Суть остаётся та же. Действие, как и любая вещь, обладает состоянием, связями с другими вещами. Как и любые вещи, действия складываются в различные коллекции. Даже процессорные потоки — это не более чем особые структуры. Что уж говорить про собственно процессы.


                                                            На любой чих службы безопасности и т. п. нужно менять бизнес-логику. На любое изменение сущности пользователя нужно менять бизнес-логику.

                                                            И? Если вы перенесёте эту функцию из файла А в файл Б, связанный с первым как 1-к-1, что-то сильно изменится?


                                                            Выбор из SQL, noSQL или вообще в какого-то веб-хранилища последний этап.

                                                            А с какими типами СУБД вы работали? Ну, помимо реляционных и словарных.


                                                            1. VolCh
                                                              28.02.2017 19:55

                                                              Действие не обладает состоянием. Оно либо есть, либо его нет. Можно условно считать, что состоянием действия является супепозицией состояний всех вовлеченных сущностей, но это только условность.


                                                              С большой вероятностью у нас будет не два файла, связанных 1-1, а множество, связанных с Б (пользователем) многие-к-одному. И при размещении логики проверки прав преимущественно в сущностях (все их там разместить скорее всего не получится, если молотком не вбивать), при изменении сущности пользователя нужно будет менять все сущности модели.


                                                              dBase к каким относится? ) А так из экзотики xBase и Db4o немного крутил.


                                                              1. vintage
                                                                28.02.2017 20:36

                                                                Действие не обладает состоянием. Оно либо есть, либо его нет.

                                                                Процесс обладает состоянием. Например, текущая стадия.


                                                                при изменении сущности пользователя нужно будет менять все сущности модели.

                                                                Зачем? Реализуйте тот же интерфейс.


                                                                dBase к каким относится? ) А так из экзотики xBase и Db4o немного крутил.

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


                                                                1. VolCh
                                                                  01.03.2017 08:06

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


                                                                  Речь об изменении интерфейса сущности пользователя.


                                                                  Я приверженец подхода по которому система хранения должна минимально влиять на объектную модель. Посмотрю, может быть некоторые мои модели удобнее будет хранить в ней, чем в реляционных или документных.


                                                                  1. vintage
                                                                    01.03.2017 09:19

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

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


                                                                    Речь об изменении интерфейса сущности пользователя.

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


                                                                    1. VolCh
                                                                      01.03.2017 10:13

                                                                      1. (подчинённый создал список в системе и начал заполнять) у сущности "список товаров на списание" статус "новый"
                                                                      2. (подчиненный отправил на рассмотрение руководителю) у сущности "список товаров на списание" статус "на рассмотрении"
                                                                      3. (руководитель рассмотрел) у сущности "список товаров на списание" статус "утвержден" или "отклонен"
                                                                      4. (бухгатер оформил) у сущности "список товаров на списание" статус "утвержден" и с ней связана бухгалтерская проводка

                                                                      Этап процесса однозначно определяется состоянием сущности "список товаров на списание" и наличием связанной с ней проводки. Причём связь может быть односторонней — только проводка ссылается на список. А собственного состояния у процесса и нет. Каждый этап должен иметь результат в виде создания, изменения или удаления каких-то сущностей.


                                                                      1. vintage
                                                                        01.03.2017 10:21

                                                                        Причём связь может быть односторонней — только проводка ссылается на список.

                                                                        Ссылка — это тоже состояние. Вам не кажется странным, что у вас тут две сущности, связанные 1-к-1 и которые всегда существуют в паре? Что вы выиграли от такого условного разделения "процесса списания", на "проводку" и "список товаров" (который на самом деле не список, а полноценный документ с подписантами, количеством, ценами и прочей требухой — почему бы не назвать этот документ "проводкой"?)?


                                                                        1. VolCh
                                                                          01.03.2017 10:45

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


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


                                                                          1. vintage
                                                                            01.03.2017 14:20

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


                                                                            1. VolCh
                                                                              01.03.2017 15:14

                                                                              Простой — это разные выделенные контексты. Оперативный документооборот и бухгалтерский учёт. Нет смысла создавать бухгалтерские проводки "в планах" на каждый чих, особенно если 90% из них руководством не утверждается. Ну а если в требованиях априори есть, что в процессе утверждения список товаров может измениться и необходимо хранить первоначальную заявку, то мы очень сильно усложним систему, не разделив эти слаюосвязанные и в реальной жизни сущности.


                                                                              1. vintage
                                                                                01.03.2017 19:49

                                                                                99% утверждаются. 1% уточняется и потом всё же утверждается. Первоначальная никого не интересует, но после утверждения изменяться состав списка не должен.


                                                    1. Fesor
                                                      28.02.2017 10:26

                                                      В рамках REST это в любом случае остаётся — запрос ответ.

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


                                                      В целом подход запрос-ответ хорошо ложится на MVA.


                                                      1. vintage
                                                        28.02.2017 18:19

                                                        Я проспал statefull революцию?


                                                        1. Fesor
                                                          28.02.2017 19:49
                                                          +1

                                                          graphql + subscribe пиарят, все чаще вэбсокеты для мобилок юзаются с доставкой ивентов на сервер вместо стэйта… Не уверен что это "революция" но тенденция есть.


                                                          Ну и в целом есть нюансы, можно сделать stateless сервер (легко скейлить) с подпиской на изменения данных используя websockets.


                                                          1. vintage
                                                            28.02.2017 20:41

                                                            Вебсокеты батарейку кушают, поэтому лучше всё же централизованные пуши.


                                                            Полноценный subscribe я мало где видел. Но подписки — это очень уж ограниченное состояние. Я бы сказал statefew.


                                                            1. Fesor
                                                              28.02.2017 23:52
                                                              +1

                                                              Вебсокеты батарейку кушают, поэтому лучше всё же централизованные пуши.

                                                              Батарейку они кушать могут только за счет проверки соединения (ping/pong). В библиотеках типа socket-io вы можете сами выставлять "частоту" проверок. Ну а в бэкграунде на всяких там iOS у вас всеравно нет выбора — надо юзать пуши.


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


                                                              Но подписки — это очень уж ограниченное состояние. Я бы сказал statefew.

                                                              Ну так это же хорошо :)


                                            1. Delphinum
                                              27.02.2017 17:09

                                              Эмм… А вашей модели «Статьи» нужно знать, что есть такие юзеры, как админы?


                                              1. vintage
                                                27.02.2017 21:01
                                                +1

                                                Да, и "Админы" — это тоже модель.


                                                1. Delphinum
                                                  27.02.2017 21:04
                                                  +1

                                                  Ну хз, я стараюсь модели максимально ограничить в знаниях. ACL по админам и авторам точно не реализовываю через уведомление Статьи о том, что в ее окружении существуют некие пользователи, которые и не авторы, но тоже важны. Зачем об этом знать Статье? (вопрос риторический)


                                                  1. vintage
                                                    27.02.2017 21:37
                                                    +1

                                                    Доменная модель естественным образом представляется в виде графа, где все узлы друг с другом перелинкованы. Пользователь логически "знает" о всех своих статьях точно также как и статья "знает" о своём авторе. Да, это не вписывается в реляционную модель, где связь многие-ко-многим эмулируется через поиск по индексу. Если же вы попробуете использовать графовую субд, то перестанете удивляться тому, что многие сущности знают друг о друге. Статья знает об авторе, пользователь о своих группах, группа о ролях, роли… о статьях :-)


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


                                                    1. Delphinum
                                                      27.02.2017 21:59

                                                      Статья то не «знает» о таких пользователях, как «Админ». Более того, Статье вообще незачем «знать» о ACL-Ролях. Под «знать» я понимаю не наличие ссылки, а скорее возможность одного объекта использовать другой в своей деятельности.


                                                      1. vintage
                                                        27.02.2017 22:07

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


                                                        1. Delphinum
                                                          27.02.2017 22:15

                                                          А зачем Статье рассказывать о правах? Статья это не ACL, у нее другие обязанности.


                                                          1. vintage
                                                            27.02.2017 22:19

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


                                                            1. Delphinum
                                                              27.02.2017 22:28

                                                              Возможно я плохо понимаю вашу задачу, но при чем тут визуализация Статьи? ) Если пользователь пытается открыть статью, действуют правила ACL, если же нужно не показывать ссылку на статью в GUI, то достаточно воспользоваться Спецификацией при выборке.


                                                              1. vintage
                                                                27.02.2017 23:06

                                                                Задача показать кнопку "редактировать" только автору и админу.


                                                                1. Delphinum
                                                                  27.02.2017 23:09

                                                                  Да все тем же ACL:

                                                                  <?php if($this->acl($currentUser, $article, 'edit')): ?>
                                                                    <a href="#">Редактировать</a>
                                                                  <?php endif; ?>
                                                                  


                                                                  1. vintage
                                                                    27.02.2017 23:10
                                                                    +1

                                                                    У меня SPA.


                                                                    1. Delphinum
                                                                      27.02.2017 23:20

                                                                      Не важно (можно вынести полностью или частично ACL во frontend, или сообщить во frontend, что можно делать с ресурсами), цель отделить «котлеты» от «мух».


                                                                      1. Fesor
                                                                        27.02.2017 23:31

                                                                        можно вынести полностью или частично ACL во frontend

                                                                        то есть… продублировать реализацию?


                                                                        1. Delphinum
                                                                          27.02.2017 23:41

                                                                          Все зависит от вашей фантазии и возможностей.


                                                                    1. Fesor
                                                                      27.02.2017 23:30

                                                                      HATEOAS?


                                                            1. VolCh
                                                              28.02.2017 06:54

                                                              Это не у статьи проверки, это у пользователей. :) Посмотрите на реальность — у документов нет систем проверки прав, есть комплекс мер, которые мешают не авторизованному пользователю получить доступ к совсекретному документу, но сам документ лишь чистая информация.


                                                      1. Fesor
                                                        27.02.2017 23:30

                                                        Более того, Статье вообще незачем «знать» о ACL-Ролях.

                                                        Сильно зависит от задачи. Частенько именно "статья" сможет сказать кто ее может редактировать. Например только ее автор. Эта информация доступна только ей.


                                                        Но не надо пытаться "обобщить" все на счете.


                                                        1. Delphinum
                                                          27.02.2017 23:48

                                                          Например только ее автор

                                                          Меня смущает не то правило, что про автора, а то, что про Админа. Статье не нужно знать о наличии Ролей в приложении.


                                                        1. VolCh
                                                          28.02.2017 07:01

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


                                                          1. vintage
                                                            28.02.2017 09:13

                                                            1. VolCh
                                                              28.02.2017 09:41
                                                              +1

                                                              Судя по первому взгляду там не запись знает, кто её может редактировать, а система проверки прав доступа решает по метаданным, сохраненной в одной записи с основными данными. И я сильно удивлюсь, если в этой СУБД нет суперпользователя, который может отредактировать запись, даже если его нет в метаданных записи. В любом случае не похоже, что там хранится полноценный объект, а не, максимум, его данные и метаданные.


                                                              1. vintage
                                                                28.02.2017 18:47

                                                                Пользователь там — это просто запись типа OUser в БД. Если входишь под таким пользователем и обращаешься к restricted записям, то срабатывает повешенный на них хук, проверяющий права. Хук наследуется от суперкласса ORestricted и к неунаследованным от него записям не применяется. Так что фактически это объект со своим состояним и поведением.


                                                                Ну, и да, всегда можно войти администратором кластера и воротить что угодно, но это к бизнес-модели уже не относится :-)


                                                                1. VolCh
                                                                  28.02.2017 19:33

                                                                  Так что фактически это объект со своим состояним и поведением.

                                                                  Не согласен. Поведение (проверка прав) не принадлежит записи, из записи только иногда (например если юзер не суперюзер) берутся данные для выбора той или иной стратегии поведения для системы проверки прав доступа. Не называем же мы объектом сишную структуру, которую читает какая-то функция. Смысл объекта — поведение вместе с данными, а не снаружи.


                                                                  1. vintage
                                                                    28.02.2017 20:46

                                                                    Покажите мне хоть один компилируемый ООП язык, где методы принадлежат объектам :-D Везде методы — это отдельно лежащие функции, которым в качестве контекста передаётся ссылка на структуру. Обычно в самом объекте максимум, что хранится — это ссылка на таблицу виртуальных методов.


                                                                    В случае ORestricted — у записи есть ссылка на её класс, у класса — на супер класс, на суперклассе навешан хук. Та же таблица виртуальных методов, только в профиль.


                                                                    1. Fesor
                                                                      01.03.2017 00:01
                                                                      +1

                                                                      Покажите мне хоть один компилируемый ООП язык, где методы принадлежат объектам

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


                                                                      Это я пытаюсь донести что вы предлагаете снять один из уровней абстракций. В ООП важным является поведение объекта. Да, само по себе поведение это просто функции которые лежат отдельно и есть некая таблица вызовов. При вызове в рантайме подставляется контекст.


                                                                      Вот только ООП оно не про объекты. "Все есть объект". Это не значит что у всего должен быть класс, это буквально означает что "любая штука есть объект". Скаляры — объекты, просто в некоторых языках у них нет поведения. Даже в языках вроде Erlang мы можем под объектом со своим стэйтом и поведением понимать тред. И треды между собой будут обмениваться сообщениями. И можно подменять треды в рантайме (late binding).


                                                                      То есть совершенно не важно что вы называете объектом. Важно то, что статически, на уровне исходников, у вас стэйт и обработка этого стэйта будут максимально рядом. Инкапсуляция и data-abstraction. А как оно там в рантайме — нам не особо интересно с практической точки зрения. Семантический разрыв и все такое.


                                                                    1. VolCh
                                                                      01.03.2017 08:15

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


                                                                      Вы делаете что-то вроде Record::findById(1)->read(): record, когда получаете отлуп от системы управления правами или делаете Record::findById(1): record? Если второе, то проверкой права на чтение данных записи занимается не запись. Если первое, то как ограничить право, чтобы клиент не узнал о существовании записи в одних случаях, и узнал но не мог прочитать — в других.


                                                                      1. vintage
                                                                        01.03.2017 09:36

                                                                        Логически и в OrientDB хук принадлежит записи :-)


                                                                        Если нет права на чтение, то запись просто не будет найдена в поисковых запросах. Если у вас есть её идентификатор, то будет отлуп при попытке чтения её данных.


                                                                        1. VolCh
                                                                          01.03.2017 10:53

                                                                          Каждая запись знает, что есть суперюзер и его надо пускать всегда?


                                                                          Кем не будет найдена, если проверка прав осуществляется в записи? Сначала найдётся для движка, а потом сама удалится при попытке движка отдать её? Или, всё таки, движок её найдёт, увидит, что пользователь не в ACL записи и не суперадмин и исключит из результатов? А если надо различать ситуации "не найдена" и "нет прав доступа" при общем запросе типа "вывести список всех сотрудников, а также их оклады если пользователь является начальником сотрудника"?


                                                                          1. vintage
                                                                            01.03.2017 14:29

                                                                            Хук скорее всего знает, да.


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


                                                                            Очевидно, оклады должны лежать в отдельных записях с отдельными правами. В OrientDB минимальная гранулярность прав — объект. Я на уровне приложения реализовывал уже гранулярность до конкретных свойств.


                                                                            1. VolCh
                                                                              01.03.2017 15:18

                                                                              для пользователя "объект сам знает кто как может с ним работать".

                                                                              Если движок пропускает записи, с которым пользователь не может работать, а не даёт отлуп на всю выборку, то не объект, а движок знает.


                                                                              В OrientDB минимальная гранулярность прав — объект.

                                                                              Тогда для очень многих схем управления доступом он не подойдёт. Очень часто права ограничиваются к полям объектов и нередко в зависимости от состояния этой, а то и других сущностей.


                                                                              1. vintage
                                                                                01.03.2017 19:51

                                                                                Движок спрашивает у объекта.


                                                                                Сложную логику вам и ACL не заменит. Только код.


                                    1. oxidmod
                                      24.02.2017 10:38

                                      Вы извините конечно, но чем вас не устраивает один класс-экшен с внедрением через конструктор? У вас лимит на количество классов? оО


                                      1. VolCh
                                        24.02.2017 11:21

                                        А чем вас не устраивает класс из нескольких экшенов? У вас лимит на количество методов в классе? :)


                                        1. oxidmod
                                          24.02.2017 11:33

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


                                          1. Fesor
                                            24.02.2017 11:48
                                            +1

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

                                            не совсем. Я борюсь с lack of cohesion. У меня есть по классу на экшен приложения, по классу на юзкейс. А контроллеры лишь являются адаптером между HTTP и этим "юзкейсом". Мне проще сделать один класс с 5-ю экшенами связанными по смыслу, а поскольку всем 5-ти экшенам нужны разные зависимости инъектить их через конструктор как-то не очень выгодно.


                                            так как в аргументах смешиваются зависимости и непосредсвтенно аргументы.

                                            А что, аргументы уже не являются зависимостями? Да, это зависимость по данным, но смысл примерно тот же. Грубо говоря у вас будет "запрос" + 1-2 зависимости для обработки этого запроса. Почти всегда. Крайне редко вам понадобится что-то сложнее.


                                            1. oxidmod
                                              24.02.2017 12:46

                                              Но дабл диспатч привязывает вас к контейнеру который умеет в дабл диспатч. Зачем это нужно?


                                              1. Fesor
                                                24.02.2017 22:10

                                                Но дабл диспатч привязывает вас к контейнеру который умеет в дабл диспатч.

                                                Нет, дабл диспатч привязывает меня к мидлвари которая достаточно умная что бы сделать $container->get(Foo::class) и заполнить аргументы метода. А делать свои имена сервисов умеют все.


                                                Если что — контейнер симфони этого не умеет из коробки. У меня есть ~80 строк кода которые добавляют эту функциональность + кэширование.


                                        1. Fortop
                                          24.02.2017 13:39

                                          Тем что при слабой связности вы будете иметь раздутый конструктор для всех зависимостей. При том что в самих action все одновременно они не требуются.

                                          Вот для случаев описанных ниже

                                          один класс с 5-ю экшенами связанными по смыслу,

                                          Можно.

                                          Я только не совсем понимаю почему они связаны между собой, а зависимости при этом у всех разные…
                                          Из чего и возникает потребность получать зависимости непосредственно при вызове action


                                          1. Delphinum
                                            24.02.2017 14:35

                                            Я только не совсем понимаю почему они связаны между собой, а зависимости при этом у всех разные…

                                            Поддерживаю. Видимо связываются они не общими механизмами или границами доступа, а правилами роутинга или чем то подобным.


                                          1. Fesor
                                            24.02.2017 22:16

                                            Я только не совсем понимаю почему они связаны между собой, а зависимости при этом у всех разные…

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


                                            есть у меня например ресурс /accounts/{id}. Он содержит в себе операции над этими ресурсами:


                                            • PUT /accounts/{id} — создание аккаунта
                                            • GET /accounts/{id} — детали аккаунта
                                            • POST /accounts/{id}/withdrawn — вывод средств

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


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


                                            1. Fortop
                                              27.02.2017 14:44

                                              image

                                              Вот вариант когда отдельные классы на каждый тип действия
                                              И естественно фабрики для них примерно так выглядят

                                                          App\Action\User\Register::class => function (ContainerInterface $container) {
                                                              return new \App\Action\User\Register(
                                                                  $container->get(RouterInterface::class),
                                                                  $container->get(TemplateInterface::class),
                                                                  // прочие зависимости
                                                              );
                                                          },
                                                          App\Action\User\Login::class => function (ContainerInterface $container) {
                                                              return new \App\Action\User\Login(
                                                                  $container->get(RouterInterface::class),
                                                                  $container->get(TemplateInterface::class),
                                                                  // прочие зависимости
                                                              );
                                                          },
                                              
                                              


                                              1. Fesor
                                                27.02.2017 18:32
                                                +1

                                                 - Invoices
                                                   - Handler
                                                       - PurchaseProductHandler
                                                       - TransferMoneyHandler
                                                       - PayTheInvoiceHandler
                                                   - Model
                                                   - Infrastructure
                                                   - Http
                                                - Orders
                                                   - Handler
                                                      - AskForRefundHandler
                                                      - ...

                                                У меня примерно так. Но все равно нужны контроллеры, а "хэндлеры" это просто application-level сервисы, реализация отдельных юзкейсов. Директории верхнего уровня описывают ограниченные контексты (Bounded Context).


                                      1. Fesor
                                        24.02.2017 11:44

                                        У вас лимит на количество классов? оО

                                        У меня лимит на количество кода не приносящего пользы. Чем меньше — тем лучше. У меня лимит на количество кода в экшене контроллера.


                              1. Fesor
                                23.02.2017 18:34

                                Увы в реальности так красиво выходит только на очень простых задачах. В остальных случаев хоть какой-то адаптер нужен для каждого конкретного UI. То что мы потом сверху можем через контент негошиейшен разруливать делать json или html — это мелочи.


                          1. Fesor
                            23.02.2017 18:33
                            +1

                            А флаш где делать? Мне его надо сделать между "сделал дело" и "сделал выборку для респонса".


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


                            1. Delphinum
                              23.02.2017 22:24

                              Да где угодно. Если есть слой сервисов, то думаю в нем, если нет, можно в контроллере или даже можно реализовать специальный Middleware для этих целей. Вариантов куча.


                              1. Fesor
                                23.02.2017 22:29

                                Если есть слой сервисов, то думаю в нем,

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


                                Через такие штуки как AOP мы можем это разрулить (декорация или ивенты неудобно).


                                можно реализовать специальный Middleware для этих целей. Вариантов куча.

                                В этом случае для каждой бизнес транзакции нам нужна мидлваря а при таком раскладе у вас разница между контроллером и мидлварем невилируется. Я вообще не понимаю о чем спор. Покажите мне код который не требует наличия контроллеров, а я скажу что это либо "тоже самое" либо "вот вам причины почему это неудобно".


                                1. Delphinum
                                  23.02.2017 23:55

                                  а я думаю в том месте, которое регламентирует границы бизнес транзакции

                                  Вполне себе вариант.
                                  Покажите мне код который не требует наличия контроллеров

                                  Выбирайте любой — http://stackphp.com/middlewares/
                                  Понятно, что это можно добавить в контроллер и на выходе мы получим, как бы контроллер, но эти решения проще компоновать.


                                  1. Fesor
                                    24.02.2017 11:50
                                    +1

                                    повторю еще раз — мидвари это просто цепочка адаптеров. контроллер = адаптер на границе приложения и UI layer. Вы можете делать все так что бы "контроллер" был лишь одним из элементов цепочки мидварей.


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


                                    1. Delphinum
                                      24.02.2017 14:51

                                      Таки я вас не призываю отказываться от контроллеров.


                    1. Fortop
                      23.02.2017 15:01

                      Ну то есть кода меньше, делает одно и то же.

                      Это в том случае если зависимости типичны для группы action.
                      Ну так и сделать наследование никто не мешает — некий CommonAction

                      А если нет?
                      Не совсем понял, кто и когда в вашем примере делает инъекцию зависимостей в методы action?
                      Router?

                      Проблема обычно с http реквестом или с flush-ем доктрины. Все равно нужна какая-то одна штука на запрос которая будет связывать все вместе.

                      Все это что? Запрос и работу с моделями доктрины?


                1. marenkov
                  23.02.2017 12:08

                  Это когда зависимости для метода прокидываются как аргументы этого метода:

                  Сейчас работаю в проекте на Zend. Там все так сделано. Пекло пекельное.
                  Когда у метода одна зависимость, как в вашем примере, еще ничего, а представьте пример с 5-ю зависимостями плюс собственными аргументами метода. Каждый вызов такого метода — простыня из аргументов. Да и объявление выглядит уродливо.


                  1. Fesor
                    23.02.2017 14:05

                    а представьте пример с 5-ю зависимостями

                    у меня есть правило — у любой штуки не должно быть более 3-х зависимостей. Если у вас их больше — вам нужно подумать больше над декомпозицией.


                  1. Fortop
                    23.02.2017 14:51

                    Зависимости в конструктор.

                    Если всего много и объекты сложный, то создаётся фабрика.
                    Или builder для инжекции зависимостей.

                    А параметры идут уже непосредственно при вызове


                1. Delphinum
                  23.02.2017 14:44

                  Хорошо подходит для экшенов контроллеров

                  Я предпочитаю контроллеры вида:
                  public function *Action(Request, Response, [$next]){
                    ...
                  }
                  

                  Потому такое мне не очень подходит )
                  Поясню свою мысль

                  Честно говоря не понял вашу мысль ) По моему мнению контроллеры зависят не от фреймворков, а от семантики запросов/ответов.


        1. Fesor
          22.02.2017 00:23
          +1

          в 2017-ом году сервисы менеджеры сущностей являются моветоном. Хотя и в нулевых так было...


              /**
               * @Route("/greetings/{id}", requirements={"id": "\d+"}, methods={"GET"})
               */
              public function greatingAction(int $id, Greater $greater)
              {
                  return $this->json([
                      'greating' => $greater->greet(),
                  ]);
              }


          1. Delphinum
            22.02.2017 00:41

            Зачем вам здесь $id?


            1. Fesor
              23.02.2017 01:53

              забыл опрокинуть его в сервис Greater.


          1. marenkov
            22.02.2017 00:44
            +1

            int $id в параметрах лишний, он автоматически будет преобразован в Greater $greater
            А так да, это самый правильный вариант. Хоть для новичков и многовато магии.


            1. Fesor
              23.02.2017 01:53

              нууу я не сторонник идей что бы сущность попадала в контроллер (хотя так часто делаю ибо ленивый), ну а в моем примере Greater это сервис. И да, у меня симфони так умеет)


          1. marenkov
            22.02.2017 14:18

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


            1. VolCh
              22.02.2017 15:54

              Сервисы домена


    1. ksgr
      20.02.2017 15:06
      +11

      Да он просто задолбался уже.


  1. knekrasov
    20.02.2017 11:24
    +10

    Полагаю, что требования к Hello world звучат примерно так «нужно уметь выводить надпись Hello world». Точка.
    Даже помня, что «выводить» можно теоретически не только в консоль, реализация слишком усложнена.
    Откуда у вас взялись REST, Postgres и куча фреймворков? Где тогда load balancing, горячий кэш данных и (конечно же!) MongoDB? Усложнять так усложнять!


    1. alix_ginger
      20.02.2017 12:34
      +1

      Полагаю, что требования к Hello world звучат примерно так «нужно уметь выводить надпись Hello world». Точка.

      Надо быть готовым, что в последствии нужно будет выводить надпись «Good evening world» или «Good morning world» в зависимости от времени суток, на выбранном языке, а потом дать возможность пользователю самому выбрать свое приветствие, и так далее.


      1. Delphinum
        20.02.2017 12:42
        +4

        Не забывайте о дизайне! Кому нужно некрасивое приложение?! Без Sass и Compass это не современное PHP Hello world!


      1. knekrasov
        20.02.2017 16:01
        +1

        И, видимо, уметь получать последний вариант текста из какой-нибудь Кафки или ZMQ. Ну и уметь масштабироваться, а то мало ли, вдруг мощностей не хватит.

        Только вот обычно цель hello world познакомиться с базовыми возможностями языка/платформы, а не предугадать все грабли, на которые придется наступить в «реальной» жизни (кстати, реальность тоже у всех разная). Такое нагромождение сложности у здравомыслящего новичка вызовет только рвотный рефлекс.


      1. Fafhrd
        21.02.2017 11:38
        +1

        Это уже изменение в ТЗ и последующий рефакторинг.


    1. D01
      20.02.2017 19:41
      +7

      Вы забыли админку, через которую надо будет в первый раз ввести Hello world!


    1. pa3ot
      20.02.2017 22:31
      +19

      Незаслуженно забыли о микросервисах. Очевидно же, что вывод Hello нужно реализовать в сервисе приветствий (Greeting), а вывод World нужно делегировать сервису геолокации.


      1. varanio
        20.02.2017 22:35
        +3

        ахаха
        Сажусь писать следующую статью ))


  1. lehha
    20.02.2017 11:27
    +6

    Сейчас тяжело найти нормального программиста, который умеет писать на ГОЛОМ PHP! Нет, движок у проекта есть, но модули почти на 80% состоят из обычного функционального программирования. Попросишь написать небольшую фичу, так он привязывает еще тонну файлов фреймворка.

    Это относится как к Frontend, и в большей степени к Backend — где одни демоны, кроны и консоли.

    Если программист может решить задачу на голом php, то он сможет и разобраться в фреймворке. А вот наоборот — не суждено.


    1. ellrion
      20.02.2017 11:28
      +1

      Крайне спорное утверждение


    1. rsvasilyev
      20.02.2017 11:51
      +19

      Может потому что нормальные программисты не хотят сидеть и допиливать проект из «80% обычного функционального программирования», которое на самом деле процедурное?)


      1. lehha
        20.02.2017 12:46
        +3

        А чего допиливать? Например, проекту более 5 лет, он не падает после yum update, нет каких-либо зависимостей, нет отсутствия обратной зависимости. 100% кода в бэкенде такое, выглядит красиво, работает стабильно, дебажится стандартными инструментами, нет скрытой логики.

        Frontend действительно стоить держать в современном виде, но главное не зарываться. Сайт Тинькофф-банка грузится сотней запросов к серверам (бесит). Сайт старого банка — двумя запросами. Скорость не в пользу Тинькова…


        1. Fesor
          21.02.2017 09:46
          +1

          выглядит красиво

          весьма субъективная метрика.


          работает стабильно

          А насколько хорошо расширяется? Есть ли статистика регрессий в коде?


          нет скрытой логики.

          Неужели нет ни одной глобальной переменной?


          1. lehha
            21.02.2017 10:33

            Расширять бизнес-логику приложения, которое не меняется годами — не нужно. Если необходимо запилить в приложении с названием «калькулятор» вызов такси Убер (или Умер), то это неправильно поставленная задача.

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


            1. VolCh
              21.02.2017 10:51

              Расширять бизнес-логику приложения, которое не меняется годами — не нужно.

              Даже не знаю сочувствовать или завидовать. Что программист-то делать должен с этим приложением? Многолетние баги фиксить? Микрооптимизациями заниматься? На новые версии PHP переводить?


              1. lehha
                21.02.2017 11:12

                Не трогать это приложение :) Заняться другими вещами, например, новым приложением «Умер» )))

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


                1. VolCh
                  21.02.2017 12:10

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


    1. VolCh
      20.02.2017 12:37
      +3

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


      1. Delphinum
        20.02.2017 12:48
        +2

        Значит вы не «нормальный программист» и вас легко найти, тяжело потерять, ну и все в таком духе )


        1. VolCh
          20.02.2017 13:09

          Понятие "нормальный программист" сильно изменилось даже за то время, что я пишу на ПХП как основном языке (а это без малого лет 20).


    1. rkosolapov
      21.02.2017 07:11
      +1

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


  1. ellrion
    20.02.2017 11:29
    +15

    Автор, В 2017 держать под гитом .idea моветон)


    1. varanio
      20.02.2017 11:35

      да, забыл добавить в .gitignore )


      1. ellrion
        20.02.2017 11:46
        +3

        Есть мнение что помещать в .gitignore тоже моветон) Нужно в .git/info/exclude. Но это конечно спорно


        1. varanio
          20.02.2017 12:01
          +4

          Век живи, век учись. Спасибо.


        1. Delphinum
          20.02.2017 12:54
          +7

          Есть мнение, что лучше для этого использовать пользовательский файл исключений:
          ~/.gitconfig

          [core]
              excludesfile = ~/.gitexclude
          

          ~/.gitexclude
          .idea/
          


          1. happyproff
            20.02.2017 13:27
            +2

            Поддерживаю! .idea это часть окружения конкретного разработчика, а не проекта.


            1. iborzenkov
              20.02.2017 14:34
              +2

              Вообще-то проекта. Из локального там только workspace.xml и tasks.xml.
              И если его правильно (https://www.gitignore.io/api/phpstorm) игнорить, то можно таскать настройки стилей кода и прочие вкусности в проекте, а не настраивать все время.
              Общие настройки хранятся в ~/.PhpStorm/config по дефолту.


              1. Delphinum
                20.02.2017 14:39
                +2

                Открою вам секрет — в хороших проектах «настройки стилей кода» применяются на уровне git push hook'ов, и являются уровнем инфраструктуры разработки, а не частью проекта.

                Зачем мне, как разработчику не использующему PhpStorm, таскать к себе ваши настройки стилей кода, применимые только в контексте PhpStorm? )


                1. VolCh
                  20.02.2017 14:54
                  +1

                  являются уровнем инфраструктуры разработки, а не частью проекта.

                  Принятая/согласованная/утвержденная инфраструктура разработки неотъемлемая часть проекта. Пускай лучше вы лишний раз скачаете не нужные вам файлы, чем 90% команды будут "переводить" стайл-гайд на "язык" настроек продуктов джетбрэйнс, а то и вычислять стайл-гайд по реджектам от хуков.


                  1. Delphinum
                    20.02.2017 14:59

                    Принятая/согласованная/утвержденная инфраструктура разработки

                    90% команды будут «переводить» стайл-гайд на «язык» настроек продуктов джетбрэйнс, а то и вычислять стайл-гайд по реджектам от хуков

                    Если уж в проекте приняли, согласовали и утвердили инфраструктуру, то должны были заодно и подготовить для всех участников окружение для быстрой развертки и работы в контексте этой инфраструктуры. Можно пойти конечно пойти путем: «запуште все в репу, это быстро и просто» — а можно маленько поднапрячься и сделать по хорошему.


                    1. VolCh
                      20.02.2017 15:05

                      ./idea в репе — часть этого окружения.


                      1. Delphinum
                        20.02.2017 15:07

                        Так себе аргумент. С тем же успехом можно хранить в репе образ ОСи, на которой должен работать проект )


                        1. iborzenkov
                          20.02.2017 15:18
                          +4

                          Ну так в папочке (docker || ansible || provision ||… ) оно обычно и лежит.


                          1. Delphinum
                            20.02.2017 15:22

                            Конфиги PhpStorm тоже обычно лежат в .idea, но это ведь не означает, что их надо пушать в репу )


                    1. iborzenkov
                      20.02.2017 15:12
                      +2

                      Вот именно — напрячься и сделать по хорошему, запушив после этого в репу то что нужно.
                      В частности и настройки IDE если 90% пользуются ей. Там можно не только стиль кода, там например могут быть уже преднастроенные параметры запуска тестов локально, vagrant или docker, деплой на тестовые сервера. Разумеется это никак не заменяет скажем билд сервера с запуском тестов, анализаторов и форматеров кода, взаимодействие с которыми кстати тоже можно в эти конфиги сохранить.


                      1. Delphinum
                        20.02.2017 15:13

                        А зачем в репу пушить? Распространять решения можно не только через git.


                        1. VolCh
                          20.02.2017 15:24
                          +1

                          А зачем распространять не через уже существующее средство распространения решений среди команды?


                          1. Delphinum
                            20.02.2017 15:27

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


              1. ellrion
                20.02.2017 14:42

                Это если в команде договор использовать продукт от jetbrains. Смысла так сильно ограничивать команду я лично не вижу. А если же у вас не проект а библиотека, то .idea уж точно быть не должно не в репозитории не в .gitignore


        1. batyrmastyr
          20.02.2017 22:55
          -4

          Есть мнение, что в 2017 году всё чаще нужен меркурий )


        1. vintage
          26.02.2017 11:37

          Есть мнение, что развёртывание проекта должно производиться одной командой и не должно никак затрагивать другие проекты. Поэтому всякие node_modules и .DS_Store помещают в .gitignore, чтобы ни у кого не было с ними проблем. Всего строчка в .gitignore, а одной головной болью меньше. Будьте прагматичными, а не фанатичными.


          1. Fesor
            26.02.2017 14:08

            .DS_Store лучше в глобальный гитигнор.


            1. vintage
              26.02.2017 22:18

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


              1. Fesor
                26.02.2017 23:06

                Так что чем меньше будет инструкция по развёртыванию окружения

                Ну так я и не буду просить разработчика на arch добавлять .DS_Store в глобальный гитигнор. Это его дело. Так что мануал как раз уменьшится, а добавить вообще все что может закоммитить недостаточно компетентный разработчик, это у вас сил не хватит.


                А вот когда на ревью придет реквест с закоммиченным .DS_Store разработчику придет вот эта ссылка.


                1. vintage
                  27.02.2017 09:53
                  +1

                  Вы будете писать по мануалу для каждой оси? А на собственно код-то время останется? :-)


                  Уже есть бойлерплейты для гитигнора со всякой ерундой, которую обычно не надо версионировать.


                  1. VolCh
                    27.02.2017 10:39

                    А для IDEA и ко есть плагинчик, который генерирует гитигнор для всякой ерунды в пару кликов, только выбрать используемую ерунду, начиная с самой IDE :)


                  1. Delphinum
                    27.02.2017 15:36

                    Зачем «по мануалу для каждой оси»? Fesor предлагает бить по рукам, если разраб попробует запушать левую зависимость в репу. В результате и мусора не будет, и разрабы научатся думать головой.


                    1. vintage
                      27.02.2017 16:17

                      Чтобы не тратить каждый раз по 10 минут на объяснение почему и как нужно делать, а потом напоминать, когда у них меняется система.


                      1. Delphinum
                        27.02.2017 17:19

                        Ну если работа ведется с очень уж далекими разрабами и лень подготавливать окружение, то, наверно, можно сделать «лишь бы работало»


                        1. vintage
                          27.02.2017 21:05

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


                          1. Delphinum
                            27.02.2017 21:16
                            +1

                            Засовывать в .gitignore не относящиеся к проекту файлы это не «работа с моим кодом», это скорее решение вида: «народу много, а я ленивый, сделаю максимально быстро и чтоб работало»


                            1. vintage
                              27.02.2017 21:39

                              Больше прагматизма, меньше идеологии — рекомендую.


                              И нет ничего плохого в том, чтобы быть ленивым. Если бы не лень, мы бы до сих пор на ассемблере писали.


                              1. Delphinum
                                27.02.2017 22:10

                                Я уже много раз наступал на грабли своей лени, потому выработал для себя простое правило: «Если действию есть правильная альтернатива, то лучше не полениться сегодня, чем страдать завтра» — ведь Закон Мерфи никто не отменял.


                                1. vintage
                                  27.02.2017 22:20

                                  Вы будете страдать от лишней строчки в gitignore?


                                  1. Delphinum
                                    27.02.2017 22:35

                                    Конечно. У проектного .gitignore вполне определенные цели, как и у git в целом, зачем возлагать на механизм задачи, которые он не должен решать. Можно ведь воспользоваться подходящим инструментом изначально, тем более если речь идет о большом проекте с множеством меняющихся разработчиков.


                                    1. vintage
                                      27.02.2017 23:09

                                      Это был риторический вопрос. И так понятно, то ни у кого никаких страданий по этому поводу не будет. Тоже мне камень преткновения.


                                      1. Delphinum
                                        27.02.2017 23:14

                                        ни у кого никаких страданий по этому поводу не будет

                                        Ну вот он я, и я страдаю, когда вижу в .gitignore что то вроде .idea ) Иногда мы практикуем такое (чаще всего в унаследованных проектах), но я понимаю, что это не хорошо, от чего и страдаю. Когда мне надоедает страдать, я выпиливаю не хорошие решения.


                                        1. vintage
                                          28.02.2017 09:16

                                          Могу лишь позавидовать тому, как удалась ваша жизнь, раз страдаете от такой ерунды :-)


                                          1. Fesor
                                            28.02.2017 10:32

                                            Я немного не понимаю вашу позицию… Попробую просумировать


                                            1. Мы не можем знать под какой осью и в каком редакторе работает разработчик (это к вопросу об инструкциях про глобальный гитигнор)
                                            2. Мы должны добавить все в свой gitignore, при том что мы все еще не знаем под какой осью и в каком редакторе работает разработчик.

                                            То есть… я пока не понимаю что именно вы предлагаете в контексте этого вопроса.


                                            Мой же вариант — не делать ни того ни того. У всех моих разработчиков настроен глобальный гитигнор. Если мне приходят PR в github и там закоммичено что-то что не должно коммититься — он получит ссылку на доку про глобальный гитигнор и настроит его себе либо удалит файлы из коммитов.


                                            Эффортов — ноль (ну или почти ноль), гитигнор чистый и там только то что относится к проекту, не надо писать километровые доки (они уже написаны).


                                          1. Delphinum
                                            28.02.2017 13:15

                                            В этом есть свои плюсы и минусы )


                                    1. VolCh
                                      28.02.2017 07:08

                                      Цели в проекте .gitignore и git в целом определяет руководство проекта, а не разработчики git. Есть хороша известная возможность у инструмента "из коробки", хорошо подходящая к задачам проекта. Почему бы её не использовать, а не искать другие инструменты или другие возможности у имеющихся? Вот вы страдаете от .idea в игноре, а я страдаю от неё в проекте. Какой ещё способ можете предложить, чтобы новый разработчик случайно не закоммитил каталог .idea? Крайне желательное требование — способ должен быть неотрывно связан с репозиторием.


                                      1. Delphinum
                                        28.02.2017 13:25

                                        Цели в проекте .gitignore и git в целом определяет руководство проекта, а не разработчики git

                                        И это не хорошо. Вы можете гвозди и мотыгой забивать, но есть куда более удачный инструмент для этой задачи. Так же и у git с gitignore, они создавали для решения определенного круга задач. Да, с их помощью можно решить и некоторые смежные задачи, но нужно ли поддаваться желанию «сделать проще»?

                                        Почему бы её не использовать, а не искать другие инструменты или другие возможности у имеющихся? Вот вы страдаете от .idea в игноре, а я страдаю от неё в проекте. Какой ещё способ можете предложить, чтобы новый разработчик случайно не закоммитил каталог .idea?

                                        В git не случайно заложено несколько уровней исключения. «Уровень пользователя» как раз позволяет разработчикам исключить из всех своих проектов не относящиеся к ним данные. Вот представьте, что вы фрилансер и каждую неделю у вас по 1-2 новых проектов. Плюс к этому, вы пишите собственные пакеты «на будущее», и храните их, к примеру, на github. Вам нужно для каждого проекта заботиться о заполнении его локального gitignore файла, когда можно один раз заполнить такой же файл, но на уровне пользователя. Согласитесь, это намного проще и удобнее, потому что правильно.

                                        Аналогично дело обстоит с группой разработчиков. Fesor верно заметил, что при изучении коммита разраба всегда можно указать ему на его же ошибки, в том числе относящиеся к окружению. Это просто для вас, и понятно для разраба.

                                        Крайне желательное требование — способ должен быть неотрывно связан с репозиторием

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


                  1. Fesor
                    27.02.2017 18:33

                    Уже есть бойлерплейты для гитигнора со всякой ерундой, которую обычно не надо версионировать.

                    А вы предлагаете сразу для всех осей и IDE запихнуть в gitignore?


                    я указал ссылку где есть ссылки на бойлерплейты и описание что зачем и куда) Как по мне ссылки на этот док достаточно.


                    1. vintage
                      27.02.2017 21:14

                      Всё, что актуально для проекта.


                      По вашей ссылке много чего предлагают в игнор засунуть, не всё это в конкретном проекте должно игнорироваться. Например, в каком-нибудь проекте *.sql могут быть необходимы. Человек скопипастит этот бойлерплейт и огребёт проблем на ровном месте. Всё же мейнтейнеру виднее какие файлы в проекте нужны, а какие — нет.


                      1. Fesor
                        27.02.2017 23:32

                        Всё же мейнтейнеру виднее какие файлы в проекте нужны, а какие — нет.

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


                        1. VolCh
                          28.02.2017 07:09

                          Главное, чтобы разрушать репозиторий не пришлось, если в него утекли чувствительные к разглашению данные.


    1. VolCh
      20.02.2017 11:37

      workspace.xml точно моветон, остальное — дело вкуса и соглашений в команде


  1. crabkakcrab
    20.02.2017 11:44
    +43

    Создавать таблицу без миграции в 2017.


    1. varanio
      20.02.2017 11:44
      +8

      да, фейл


  1. Atreides07
    20.02.2017 11:46
    +1

    Простите за оффтоп, но как же раздражают многочисленные "в 2017 году". Т.е. в 2016 можно было говнокодить по страшному и резко, меньше чем за 2 месяца все прозрели и стали писать абсолютно по другому?


  1. berezuev
    20.02.2017 11:49
    +25

    Примерно из той же оперы


    1. evil_kabab
      21.02.2017 23:00
      +1

      Они заминусили правильный ответ?! Тролли


  1. Falseclock
    20.02.2017 11:59
    -3

    Не согласен с автором. Любой нормальный программист должен пройти этап эволюции от говнокода до написания собственных фреймворков. А не использовать готовые, которые сводят на нет суть программирования.


    1. lair
      20.02.2017 12:01
      +9

      Я надеюсь, вы не используете готовые высокоуровневые языки, которые сводят на нет суть программирования? Только машинный код?


      1. Falseclock
        20.02.2017 12:10
        +2

        Если брать в пример использование PHP как основного языка для веб приложений, то за последние годы мы пришли к тому, что это программисты это те, кто умеет настраивать CMS и сайт готов, позиционируя себя опытным разработчиком.

        Типичный пример. Мне надо было сделать интеграцию самописной CRM системой с 1С по REST\OData через HTTP-сервис, который появился недавно в платформе 1С. И что вы думаете? Я обзвонил сотни программистов, поговорил в живую с десятком и не нашел того, кто это может сделать. Они только и делали круглые глаза, даже не представляя себе, что это возможно.

        Две недели упорного труда и сам реализовал то что мне нужно не имея никакого опыта программирования в 1С.

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


        1. Sky4eg
          20.02.2017 12:16
          +3

          Ну вы прям утрируете. Где вы находили эти сотни программистов которые не умеют работать с REST и не способных потратить пару вечеров на ознамление с новой ачивкой для себя?


          1. Source
            20.02.2017 13:36
            +4

            А я верю Falseclock, приходилось несколько лет назад искать 1С-программиста… у них от словосочетания "HTTP-запрос" нервный тик начинается… и про то, что данные можно передавать не только через расшаренные XML-файлы, они даже слышать не хотят. Возможно есть исключения, но вживую не приходилось встречать.


            1. lair
              20.02.2017 13:48
              -1

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

              [...]

              приходилось несколько лет назад искать 1С-программиста

              Хм.


              1. Source
                20.02.2017 16:23
                -2

                Вы невнимательно прочитали комментарий Falseclock… Цитирую:


                Типичный пример. Мне надо было сделать интеграцию самописной CRM системой с 1С по REST\OData через HTTP-сервис, который появился недавно в платформе 1С.

                Две недели упорного труда и сам реализовал то что мне нужно не имея никакого опыта программирования в 1С.

                Я понял его мысль так, что бездумное использование CMS/CMF может довести уровень среднестатистического PHP-шника до уровня среднестатистического 1C-ника. Типа делай как в туториале и ни шагу в сторону.


            1. raidhon
              20.02.2017 14:12
              +2

              В данный момент работаю над сервисом где всё, а это куча сайтов, мобильный сервис на node.js, мобильные приложения и даже телеграм бот отправляет или получает какие нибудь данные от сервера 1С.
              Да и вообще все сходиться на 1С там все хранится и все оттуда запрашивается.
              Не могу сказать что я в восторге, так как раз я занят тем что пишу( скорее уже поддерживаю так как уже написал ) сервис на node.js и телеграм бота с мобильными приложениями.
              Но вся эта система работает ( ещё и на Windows server ) уже без малого полтора года и 1С программист понимает с полуслова что мне нужен ответ в формате json определенной структуры.
              Так что программист программисту рознь.


              1. Source
                20.02.2017 16:27

                Тут спору нет, все люди разные и распределение квалификации очень широкое. Просто есть мнение, что Вам повезло, найти квалифицированного 1С-программиста не такая уж простая задача.


                1. raidhon
                  20.02.2017 18:32

                  Ну тут я никого не искал, мне просто предложили проект.
                  1С программист уже присутствовал в приложении к проекту.
                  В остальном вы правы думаю компании просто повезло.

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


          1. el_gato
            20.02.2017 15:15

            Cмех смехом, а я периодически ловлю себя на мысли что не помню как аякс запрос на js написать без jQuery.


            1. Source
              20.02.2017 16:29

              Ну так, хотя бы помните, что это можно сделать… значит доку нагуглите за пару минут )


            1. justboris
              20.02.2017 16:36
              +1

              window.fetch


              fetch('/api/endpont')
                 .then(response => response.json())
                 .then(json => console.log(json))


              1. lair
                20.02.2017 16:47
                +4

                This is an experimental technology

                И эти люди говорят нам про фреймворки.


                1. justboris
                  20.02.2017 16:56

                  Читаем дальше


                  Because this technology's specification has not stabilized, check the compatibility table for usage in various browsers.

                  Поддерживается везде, кроме IE (в Edge уже есть). Достаточно, для того чтобы хотя бы попробовать


                  1. lair
                    20.02.2017 17:00
                    +2

                    Понятно, намек на XHR прошел мимо.


                    1. varanio
                      20.02.2017 17:05

                      в любом случае надо использовать fetch. Если нужна поддержка старых IE, то добавлять полифил, да и всё


                      1. RubaXa
                        20.02.2017 17:20

                        Ага, а потом нам требуется прогресс download/upload и fetch отправляется мусорку.


                      1. lair
                        20.02.2017 17:34
                        +2

                        … полифилл самому написать или готовый взять?


                      1. vintage
                        26.02.2017 21:52

                        Не надо, как и уже устаревшие "обещания". Сейчас в тренде реактивное программирование.


                        1. Fesor
                          26.02.2017 23:07

                          мне казалось async/await, frp это весело и прикольно и в большинстве случаев не нужно.


                          Да и как вы там говорили, не всегда компетентные разработчики достаются которые знают что такое frp и как его готовить.


                          1. vintage
                            27.02.2017 10:04

                            Я ничего не говорил про FRP. OORP готовить настолько просто, что с этим справится даже джуниор. А вот async/await, frp — лишние сложности на ровном месте.


                            1. Fesor
                              27.02.2017 18:35
                              -1

                              async/await сложности? Их умеет любой джуниор дотнетчик


                              1. vintage
                                27.02.2017 21:40

                                По сравнению с их отсутствием — да, сложности.


                                1. VolCh
                                  28.02.2017 07:10

                                  колбэк хелл проще?


                                  1. vintage
                                    28.02.2017 09:18

                                    Нет, проще — синхронный код.


                                    1. VolCh
                                      28.02.2017 09:45
                                      +1

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


                                      async/await как раз способ сочетать простоту написания синхронного кода с реальной асинхронностью.


                                      1. vintage
                                        28.02.2017 19:10

                                        image


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


                                        async-await всё же не обеспечивает распараллеливание — нужно позаботиться об этом самостоятельно.


                                        1. Fesor
                                          28.02.2017 19:51
                                          +1

                                          const responses = await multipleRequests
                                              .map(request => this.preformRequest(request));


                                          1. vintage
                                            28.02.2017 20:53

                                            Вы забыли завернуть это в Promise.all. О чём и речь.


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


                                            1. Fesor
                                              01.03.2017 00:09
                                              -1

                                              Вы забыли завернуть это в Promise.all. О чём и речь.

                                              признаю, есть такой момент.


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

                                              А в вашем случае разве не происходит примерно такого же? Ну то есть вам же как-то надо приостановить выполнение кода, как это у вас происходит?


                                              1. vintage
                                                01.03.2017 09:51

                                                В том-то и дело, что нет. То же самое можно было бы переписать так:


                                                @ $mol_mem()
                                                header() {
                                                    return $mol_locale.text( this.toString() + '.header()' )
                                                    // там где-то в глубине дёргается файл с локализованными текстами на нужном языке.
                                                }
                                                
                                                @ $mol_mem()
                                                sources() {
                                                    const treeContent = $mol_file.relative( 'quine.view.tree' ).content()
                                                    const tsContent = $mol_file.relative( 'quine.view.ts' ).content()
                                                    return `${ treeContent }\n\n${ tsContent }`
                                                }
                                                
                                                @ $mol_mem()
                                                content() {
                                                    const header = this.header()
                                                    const sources = this.sources()
                                                    return `# ${ header }\n\n${ sources }`
                                                }

                                                И все 3 файла будут загружены параллельно.


                                                Приостановка делается просто — кидается исключение. $mol_mem() заворачивает метод в атом, который это исключение ловит, а наружу светит Proxy, который кидает это исключение лишь при попытке доступа к содержимому результата. Таким образом исполнение продолжается, но в момент, когда мы начинаем работать с результатом, исполнение метода прерывается, если результат ещё не получен.


                                                1. Fesor
                                                  01.03.2017 19:06
                                                  +1

                                                  Приостановка делается просто — кидается исключение.

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


                                                  1. vintage
                                                    01.03.2017 20:04

                                                    Тут имитируются волокна.


          1. D01
            20.02.2017 19:47
            +1

            Большинство программистов 1С, ничего, кроме 1С не знают… Многие даже сетевой адаптер настроить не могут (IP-адрес ввести и т.п.), а Вы REST :-)


          1. Fesor
            20.02.2017 19:58

            Где вы находили эти сотни программистов которые не умеют работать с REST

            Вот у меня специфика работы — апишки. И я на собеседованиях обычно не особо спрашиваю про rest просто по одной простой причине — 9/10 обычно начинают про http рассказывать. И для меня разработчик уже неплохо шарит в теме если говорит что оба POST и PUT могут быть использованы как для создания ресурсов так и для их обновления. Да что там, уже хорошо если аббревиатуру REST смогут расшифровать и рассказать как они это все дело понимают (не важно правильно или нет).


            То что люди не знают про OData например это меня ничуть не удивляет.


        1. lair
          20.02.2017 12:16
          +2

          Если брать в пример использование PHP как основного языка для веб приложений, то за последние годы мы пришли к тому, что это программисты это те, кто умеет настраивать CMS и сайт готов, позиционируя себя опытным разработчиком.

          Программист — это тот, кто решает задачу заказчика с необходимым качеством (и прочими критериями выполнения). CMS, фреймворк — это не имеет значения.


          А уж кто как себя позиционирует — так это личное дело каждого.


          решать задачи не прибегая к готовым решениям — другое. Это и есть путь нормального эволюционного процесса хорошего программиста.

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


          1. Falseclock
            20.02.2017 12:20
            -1

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


            1. lair
              20.02.2017 12:21
              +9

              Вы уже разобрались, как работает интерпретатор PHP? До какого уровня вниз?


            1. VolCh
              20.02.2017 12:43

              Фреймы — заботливые обертки для моего кода, берущие на себя десятки рутинных задач, которые раньше у меня ходили из проекта в проект. С фреймом я занимаюсь решением бизнес-задач, а не роутингом, валидацией форс и объектов, работой с БД и прочим, что для решения бизнес-задач если не необходимо, то крайне желательно, но решением не является.


              1. Falseclock
                20.02.2017 12:58
                +2

                да никто не против фреймов… вопрос развития программиста от хеллоу ворлд, до написания своих фреймов. Зайдите на Тостер. Там сотни программистом спрашивают дурацкие вопрос, почему, например, постгрес не коннектит к базе на Node.js. Он не в курсе как вообще сделать отладку и найти проблему. Ни логи на сервере почитать, ни включить дебаг режим.


                1. Tantacula
                  21.02.2017 08:28

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


                  1. Fafhrd
                    21.02.2017 11:55
                    +1

                    У меня за 20 лет вопросы на «форумах» возникали раз 5. Но решение находил быстрее, чем там отвечали, и в итоге понимал, что смалодушничал и не хватило терпения в решении вопроса.
                    Сейчас же на некоторых ресурсах новые персонажи умудряются плодить темы по 5 раз за день, несмотря на фреймворки и их документацию ибо видео-уроков нет ^_^


                  1. evil_kabab
                    21.02.2017 23:13

                    А я с детства никогда не просил о помощи. Попросил — расписался, что ты ребенок, а не мужик. Есть гугл и там есть все ответы. Только сегодня молодежь даже попытки не делает, сразу просят помощи, не гуглят


                    1. AFakeman
                      01.03.2017 00:34
                      +1

                      Ага, и на первой странице гугла нередко выпадают вопросы на SO, где как раз можно почитать полезный и развернутый ответ, который бы не был написан, если бы кто-то не «расписался в том, что он ребенок».


                  1. Fesor
                    21.02.2017 23:56
                    +1

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


                    Когда мы пишем код и что-то работает не так, у нас есть два варианта:


                    • просмотреть код глазами и попытаться его выполнить в голове
                    • выполнить код, подключить дебаггер, расставить бряки, глянуть как меняется стэйт и что вообще происходит.

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


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


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


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


                    1. Delphinum
                      22.02.2017 00:23

                      Это же наблюдение можно спроецировать и на любую современную IDE, если очень захотеть.


                      1. Fesor
                        23.02.2017 22:34

                        Можно, и более того — так оно и есть. Есть даже шутка — автокомплит это замечательная вещь которая позволяет создавать вещи вроде AbstractSomethingFactoryFactory. То есть возможность пользоваться оной плохо сказывается на необходимости думать над именованием и интерфейсами.


                        Но это не является причиной НЕ использовать IDE или автокомплит. Просто надо думать что делаешь.


                    1. codemax
                      23.02.2017 10:11

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

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

                      Случаев, когда при использовании дебагера один и тот же разработчик думает над последствиями своего решения меньше, а в ином случае — больше, я пока не встречал. Впрочем, это тоже только мои наблюдения :)


                    1. MikailBag
                      23.02.2017 21:55

                      Как без дебаггера вы найдете ошибку в написании алгоритма?


                      1. Fesor
                        23.02.2017 22:32

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


        1. Delphinum
          20.02.2017 13:44

          решать задачи не прибегая к готовым решениям — другое

          Вы не задумывались, что есть еще третий вариант: «знать кишки готовых решений» — ?


          1. Falseclock
            20.02.2017 13:46

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


            1. Delphinum
              20.02.2017 13:49
              +2

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


              1. oxidmod
                20.02.2017 13:57

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


                1. varanio
                  20.02.2017 13:59

                  Фреймворк особенно полезен для работы в команде. Например, проект на Yii, наняли новичка, который умеет Yii — и он всё знает, где модели, где контроллеры, как работать с базой и т.д.


                  1. Fafhrd
                    21.02.2017 11:57

                    Угу, а в итоге всё-равно получаются супер-классы с километровыми методами.


                1. Delphinum
                  20.02.2017 13:59
                  +1

                  У нас уже давно есть несколько скелетонов на все случаи жизни, в том числе для «давайте запилим прототип побыстрей».

                  composer create-project github.com/tiny-skeleton /var/www/prototype
                  


                  и дизайнеры/верстальщики уже накидывают скелет для демонстрации клиенту.


      1. evil_kabab
        21.02.2017 23:05

        Немного некорректный пример. Фреймворки для PHP написаны на PHP. Высокоуровневые языки написаны по большей части на низкоуровневых.
        Я в 88 году столкнулся с бк 0010, производительности на бейсике не хватало, ну так я быстро изучил ее ассемблер. На редкость простой и понятный…


        1. lair
          21.02.2017 23:12

          Немного некорректный пример. Фреймворки для PHP написаны на PHP. Высокоуровневые языки написаны по большей части на низкоуровневых.

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


          1. evil_kabab
            21.02.2017 23:20
            +1

            Примерно так. Высокоуровневые языки избавляют нас от необходимости писать на асм. Симфони и Ларавел вас от PHP не избавят.
            Я помню ужасный MFC и win32api и книжку Петзольда. Не хочу спорить, но предпочитаю без фреймворков работать.


            1. VolCh
              21.02.2017 23:24
              +1

              Высокоуровневые языки избавляют нас от необходимости прямой манипуляции низкоуровневыми абстракциями типа адресов и ячеек памяти, фреймворки избавляют нас от необходимости манипулировать высокоуровневыми абстракциями типа текстов HTTP или SQL запросов, сводя их к абстракциями ещё более высокого уровня.


            1. lair
              22.02.2017 00:42

              Высокоуровневые языки избавляют нас от необходимости писать на асм. Симфони и Ларавел вас от PHP не избавят.

              И как это связано с "сутью программирования"?


              1. iit
                23.02.2017 13:56

                <sarcasm>Суть программирования — это как суть пустоши, только суть программирования</sarcasm>


  1. f0rk
    20.02.2017 12:04
    +1

    del


  1. Pjeroo
    20.02.2017 12:51
    +2

    А еще собрать это всё в контейнер при помощи jenkins или teamcity и доставить на бой.


    1. ellrion
      20.02.2017 12:55
      +3

      Точно, вопрос деплоя и окружения же никак не затронут. "Нужно больше золота инфы"


    1. garex
      20.02.2017 14:08

      travis.yml куда ж без него


  1. Rastishka
    20.02.2017 13:16
    +1

    Статья:

    «Hello, (real) world!» на php в 2017 году

    Раздел:
    JavaScript и его многочисленные друзья


    1. varanio
      20.02.2017 13:22

      Вы верно ухватили суть статьи. Именно в этом и состоит смысл. Что голый php без всего — это конь в вакууме.


      1. Rastishka
        20.02.2017 14:30
        +1

        Нет, если бы статья называлась «SPA «Hello, (real) world!» в 2017 году» или «Web «Hello, (real) world!» в 2017 году»
        вопросов бы не было.

        А так получается в проекте нужны JS бандлеры, JS транспилеры и JS линтеры, а плохой при этом PHP.


        1. Delphinum
          20.02.2017 14:34
          +1

          плохой при этом PHP

          Автор не обвиняет PHP, автор намекает, что современный PHP — это не обязательно говнокод.


          1. Rastishka
            20.02.2017 16:41
            +2

            Автор намекает что современный PHP не говнокод, а node.JS, бандлер JS, таск менеджер JS, JS траспилер и JS линтер?

            Современный PHP такой Javascript…


            1. Delphinum
              20.02.2017 16:53
              +2

              По большому счету да ) И в чем то автор прав.


  1. master65
    20.02.2017 13:20
    -1

    -


  1. krocos
    20.02.2017 13:31
    +1

    А еще в 2017 docker есть…


    1. mgremlin
      20.02.2017 17:33
      +1

      Докер бы сильно упростил деплой, что плохо коррелирует с основной идеей статьи 8-)


      1. batyrmastyr
        20.02.2017 23:06

        Но ведь можно сделать свой образ (точнее четыре + docker-compose) в котором скомпилируем всё из исходников. Можно даже собственное ядро линукса собрать для полного счастья.


        1. mgremlin
          20.02.2017 23:25

          Лично для меня докер — это упрощение, хоть как его собирай.
          Вот что с ним будет на боевом сервере — это уже большой вопрос 8-)
          но поднять новый для себя сервис сначала на локальной дев-машине, а потом на серваке с докером значительно проще. Даже если до того много лет пользовался bare server — к хорошему быстро привыкаешь. Если бы докер сделал легкий доступ из контейнера к локалхосту — уверен, многие бы пользовались.

          Докерный сетап в проде лично я вынужден был разобрать из-за ряда неразрешимых проблем. Но часть контейнеров оставил бы с удовольствием 8-) тот же сфинкс — задолбался его настраивать на железе. А в контейнере он заводился в 5 сек…


          1. Fesor
            20.02.2017 23:28

            Если бы докер сделал легкий доступ из контейнера к локалхосту

            А зачем и чем он сложен? Если надо по быстрому например поднять базу данных на локалхосте (например тесты погонять)


            docker run --rm -d -p 5432:5432 --name tests-db postgres

            И вуаля. У нас поднята база на локалхосте.


            psql -h localhost -u postgre

            Другого вида доступов и не нужно особо. В этом же смысл изоляции.


            1. VolCh
              21.02.2017 07:37

              Обычному разработчику изоляция как таковая от докера не нужна, а вот доступы нужны.


            1. mgremlin
              21.02.2017 10:00
              +2

              смысл в наоборот: чтобы процесс, запущенный в докере, имел доступ наружу. например, ваш постгре поднят на железе, и был доступен внутри стороннего контейнера. Приведен пример — сфинкс, при условии, что его «базовая база» не стартует другим контейнером в compose, а выше, на localhost.

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

              полетит — можно нанять админа и настроить уже все по-человечески. А вот корячиться самому…

              еще пример: хотите вы попробовать какой-нибудь модуль nginx. image_filter, например. В родном докерном образе он включен по дефолту и запускается это все с полтычка. А поставить в систему, на localhost? В новой бунте, например, старая версия, где ничего не работает. Хочешь поменять на самую новую версию — начинаются пляски с бубном, в лоб не ставится. Все можно сделать, конечно, но если с каждой софтиной плясать — охренеешь. А если еще твой хлеб не в этом… То ли дело докер: 10 строк в compose, чистая система, 5 минут работы — все шикарно! На первый взгляд.

              Но, повторюсь, все бонусы докера рушатся его безобразной работой с сетью и накоплением ошибок в проде. Там без высококвалифицированного админа его использовать невозможно (/мне не удалось 8-). А вот для разработки — сказочно.


  1. BoneFletcher
    20.02.2017 13:41
    +1

    Для контроллеров отдающих json рекомендую использовать аннотацию ToJsonResponse:

        /**
         * @Route("/greetings/{id}")
         * @ToJsonResponse()
         */
        public function greetings($id)
        {
            $greeting = $this->getDoctrine()->getRepository("AppBundle:Greeting")->find($id);
            return ['greeting' => $greeting->getGreeting()];
        }
    

    Отличие в том, что в случае ошибки вернется корректный json, а не html-код:

    STATUS 500 Internal server error
    {
        message : 'Exception message'
    }
    


    1. faost
      20.02.2017 14:18

      Лучше сразу использовать http://symfony.com/doc/current/bundles/FOSRestBundle/index.html


  1. velafrys
    20.02.2017 14:03
    +2

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


    1. ellrion
      20.02.2017 14:38
      +1

      Мы видимо с вами разные статьи прочли. Автор неоднозначно говорит, что данные инструменты не только имеют место быть, но и в связи с требованиями рынка (и возможно моде) должны быть знакомы и применяться разработчиками.


      1. velafrys
        20.02.2017 14:42

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


  1. AlexLeonov
    20.02.2017 14:06

    Дочитал до

    Php-программист в 2017 году не может обойтись без js и верстки

    понял, что статья — полная чушь.
    Спасибо, что поставили эту фразу пораньше в тексте, сэкономили мое время.


    1. varanio
      20.02.2017 14:11
      +1

      Не за что.

      Только вы откройте, пожалуйста, hh и посмотрите. Не менее 3 вакансий из 4 требуют знание js или указывают, что это «будет плюсом».


      1. wladyspb
        20.02.2017 18:59

        Не имею ничего против знания js, css, html — в работе нужно понимать, как работают граничащие технологии. Однако на вакансии «требуется PHP программист для работы с вёрсткой, дизайном, базой данных и сервером» — советую бежать как от огня.


      1. AlexLeonov
        21.02.2017 16:06

        Для меня сочетание в резюме «PHP+HTML+JS+CSS» это скорее минус, показывающий, что человек сам не знает, чего хочет в профессии.

        И да, на PHP я пишу 13 лет. И все эти годы прекрасно обходился без JS и вёрстки. Что я делаю не так?


        1. VolCh
          21.02.2017 16:11
          +1

          Почти 20 лет пишу на PHP и редко когда было что JS и вёрстка меня вообще не касалась. Даже когда в команде есть отдельные фронтендеры, то "почему-то" меня ставят лидом команды и я принимаю их задачи.


        1. varanio
          21.02.2017 16:33
          +2

          > это скорее минус
          Почему минус? Это реалии рынка, что js надо знать, отсюда и резюме со знанием js. Всё логично.

          > И да, на PHP я пишу 13 лет. И все эти годы прекрасно обходился без JS и вёрстки. Что я делаю не так?
          Вы не подходите под большинство вакансий, куда могли бы попасть с вашим опытом php. Кроме того, это довольно странно, на мой взгляд, не интересоваться смежными областями. Хирург узко специализирован, но он должен уметь проводить реанимацию, например.


          1. AlexLeonov
            22.02.2017 14:14
            +1

            Почему «не интересоваться смежными областями»? Я интересуюсь.

            Например интересуюсь, как написать на PHP многопоточный неблокирующий код, как собрать ZTE под RHEL, интересуюсь вопросом, как на один инстанс postgres класть 10 000 insert-ов в секунду, не положив этот инстанс, интересуюсь, как автоматизировать деплой php-приложения на несколько десятков тестовых стендов и запустить (опять же в несколько потоков) толстую пачку тестов…

            Это не смежные области?

            Ну неинтересен мне JS и фронт, не люблю я их — что же делать-то?


            1. Fesor
              23.02.2017 01:59
              +1

              Это не смежные области?

              нет, это все бэкэнд и чуть-чуть ops. Очень тесно переплетенные темы.


              Ну неинтересен мне JS и фронт, не люблю я их — что же делать-то?

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


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


  1. garex
    20.02.2017 14:07
    -1

    Anton Merge branch 'master' of github.com:anton-okolelov/helloworldphp

    Далее не читал, но осуждаю.


    Вот более правильные версии хеловорлда ))


    https://github.com/DQNEO/php-HelloWorldEnterpriseEdition
    https://gist.github.com/lolzballs/2152bc0f31ee0286b722


  1. ju5tify
    20.02.2017 14:26
    -2

    composer create-project symfony/framework-standard-edition

    А так все хорошо начиналось
    Сажаскрыл


    1. varanio
      20.02.2017 14:30

      Вам не нравится composer, symfony или standard-edition? :)


      1. ju5tify
        21.02.2017 15:02

        Ну конечно же, Symfony.
        Зазывать в увлекательный мир PHP c помощью Symfony — это как привезти иностранца в Москву и начать экскурсию с Бутово. Или начать знакомство с США с Детройта вместо Манхэттэна.
        Что ждет новичка, который решит встретить новый день с Symfony?
        Его ждут аннотации (нативная конструкция в PHP, как всем известно). Его ждут бездонные контейнеры, тормзная Доктрина, мерзкий YAML, сопли из сервисов, которые инжектируются в другие сервисы третьми сервисами. Его ждут еще более тормозные бандлы от Knp, FriendsOfSymfony и прохих мастеров своего дела.
        И самое главное — его ждет наглухо упоротое комьюнити из хомячков Фабьена, каждый из которых точно знает Как? Надо? Делать? согласно святым скрижалям Великого Мастера.
        Его ждет боль. Его ждет агония.


        1. varanio
          21.02.2017 15:20
          +1

          Ну не знаю. Мне нравится Symfony. Он лучший по расширяемости, по SOLID и т.д. Очень часто можно компоненты из Symfony встретить в самых разных пакетах composer. На них даже другие фреймворки целиком построены. Потому что он абсолютно гибкий. И правильно написан по всем канонам ООП.


          1. ju5tify
            22.02.2017 17:44
            -1

            по всем канонам

            Речь идет о слепленной из говна и палок поддержке несуществующих в PHP аннотаций?
            Или о маниакальном фетише DI, благодаря которому чужой код превращается в нечитаемое месиво настолько, что приходится обвешиваться анализаторами XML и YAML барахла в многочисленных васяно-бандлах.
            Ах да, у церкви св. Фабьена же свои каноны.


            1. VolCh
              22.02.2017 18:39

              Речь идет о слепленной из говна и палок поддержке несуществующих в PHP аннотаций?

              Ваше дело использовать их или нет. У нас частичный запрет — нельзя использовать в модели, можно в контроллерах и сервисах приложения.


              Или о маниакальном фетише DI, благодаря которому чужой код превращается в нечитаемое месиво настолько, что приходится обвешиваться анализаторами XML и YAML барахла в многочисленных васяно-бандлах.

              Ваше дело ставить васяно-бандлы или нет.


  1. maxzuber
    20.02.2017 14:33
    +1

    При наличии composer, поставьте fxp/composer-asset-plugin, чтобы исключить ось nodejs — npm — bower.


  1. divanus
    20.02.2017 14:40
    -3

    Можно, я так, в сторонке постою?


  1. mortimoro
    20.02.2017 14:40
    -4

    Тема сисек не раскрыта.


    1. mortimoro
      20.02.2017 18:48
      -3

      Либо мой нанотонкий юмор не был понят, либо кто-то здесь не любит сиськи… Чтоб вам всю жизнь смотреть на сиськи через футболочку как на картинке в начале статьи, занудные старикашки! О_о


      1. acerrusm
        20.02.2017 23:42
        -1

        Спасибо. Посмеялся


  1. xaja
    20.02.2017 14:41
    +2

    Starting a basic website in 2014:

    1. Install Node
    2. Install Bower
    3. Pick CSS framework
    4. Pick responsive approach


    47. Write some HTML


    — I Am Devloper (@iamdevloper) October 2, 2014


    1. ellrion
      20.02.2017 14:44

      ну вот в в 2017(условно) пункт 2 уже выкинули) но добавили webpack)


      1. MikailBag
        20.02.2017 22:39

        и 100500 loader'ов и plugin'ов)


  1. Mithgol
    20.02.2017 14:50
    +1

    Если Node.js и npm установлены, то тогда PHP вообще не очень нужен, ведь можно поверх ставить web-сервер (например, Express.js) и шаблонизатор (например, Handlebars.js) и далее на них сайт подымать. (Я пишу это отчасти иронически — но не более, чем наполовину.)


    1. Delphinum
      20.02.2017 14:54
      +1

      Боюсь спросить, что вы предложите узнав, что в качестве ОСи сервера будет выбрана одна из BSD?


      1. batyrmastyr
        20.02.2017 23:13

        >brew info node.js
        node: stable 7.5.0 (bottled), HEAD
        Platform built on V8 to build network applications

        Возможно я вас не так понял, но проблемы не вижу.


        1. Delphinum
          20.02.2017 23:20

          Вы меня не так поняли. То был сарказм. Если коротко, то:

          Если Node.js и npm установлены, то тогда PHP вообще не очень нужен

          Можно передернуть как:
          Если под сервер используется BSD, то тогда PHP вообще не очень нужен, лучше использовать TreeFrog Framework


          1. VovanZ
            20.02.2017 23:30

            А какая связь между BSD и TreeFrog Framework?


            1. Delphinum
              20.02.2017 23:32

              Охх… Не важно, будем считать, что моя шутка не удалась )


    1. VolCh
      20.02.2017 15:03

      Я вообще ставлю Node.js между фронтендом на React и Symfony.


  1. vasilyev
    20.02.2017 15:29
    +2

    А ваши настройки шторма мне зачем? Или с гитыгнором в 2017 вы еще не разобрались?


    1. varanio
      20.02.2017 15:31
      +5

      Выше уже упоминали. Я просто забыл убрать.
      В 2017 принято читать коменты прежде чем постить новые ))


  1. spaceinvaider
    20.02.2017 15:30
    +1

    аналогичный «Hello word» в java мире, Enterprise Edition
    https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition
    наверное автор хтел создать нечно подобное для php стека


    1. Delphinum
      20.02.2017 15:33

      Для php стека нечто подобное уже давно создано, автор лишь хотел показать это.


  1. pvasili
    20.02.2017 17:30

    Вместо того, чтобы вынести мусор автор переклеил обои, сменил мебели, переехал в другую страну (со сменой документа) и потом заказал через интернет клининговой компании вынести мусор в квартире на другом континенте. А мог бы просто вынести пакет :)


  1. roboter
    20.02.2017 17:34
    -1

    Интересно в каком году в PHP view будет лежать в одной папке с controller.
    разделение по фитчам а не типам файлов.


    1. oxidmod
      20.02.2017 17:50

      А PHP заставляет делать по другому?


    1. Delphinum
      20.02.2017 18:17

      Бывает, что на первом этапе (подготовка прототипа для заказчика) проект выглядит так:

      backend/
        config/
        vendor/
        templates/
      

      Фронтендщики побыстрому накидывают шаблоны, а уже после одобрения клиентом в проект вкручиваются контроллеры, мидлевары, модель и прочее.

      Бывает даже так, что после демонстрации прототипа заказчику ТЗ меняется настолько, что от контроллеров вообще отказываются.


    1. VolCh
      20.02.2017 18:18

      Как хотите так и складываете. Не нравится стандартное размещение файлов в Symfony — переопределяется лёгким движением руки.


      1. roboter
        20.02.2017 20:18

        да понятно что всё можно, мне интересно что модно.


        1. Delphinum
          20.02.2017 20:39
          +1

          2017 — не модно
          2к17 — модно


          1. zevilz
            21.02.2017 11:10
            +1

            2kXVII


  1. phil192
    20.02.2017 20:24

    Отличная статья, если нужно уничтожить тех придурков, которые сулят обучить программированию за 2 часа.


    1. f0rk
      20.02.2017 20:44
      +3

      А где тут программирование вообще?


  1. kalsarikannito
    20.02.2017 20:42

    Зачем на это тратить время ?


    1. TonyLorencio
      20.02.2017 22:25

      Если вы пишете вручную "echo 'hello, world'", то обрекаете проект на говнокод на веки вечные (кто потом этот велосипед за вас переписывать будет?).


  1. VovanZ
    20.02.2017 22:24
    +1

    Что-нибудь слышали про KISS?


    1. Fesor
      20.02.2017 23:25
      +1

      "Make everything as simple as possible, but not simpler"

      Альберт Эйнштейн.


      В целом тут больше YAGNI подходит как по мне. С KISS легко спутать "просто" и "легко".


  1. ZoomLS
    21.02.2017 03:35

    В итоге, получилось столько js, что спрашивается, а зачем тут нужен php?
    Можно на самой node.js быстренько накатать простой сервер для «hello word» или сделать «npm install express», и создать всё ещё быстрее. Без шуток.


    1. VolCh
      21.02.2017 07:38

      Как насчёт DataMapper в ноде сейчас, появилось что-то готовое к продакшену?


      1. ZoomLS
        22.02.2017 00:16

        Что-то вроде такого https://www.npmjs.com/package/node-data-mapper? Но я не пробовал.


        1. VolCh
          22.02.2017 16:58

          Что-то вроде, надо покрутить будет на досуге. С год назад достойной альтернативы Doctrine не было.


  1. Alex_T666
    21.02.2017 07:01
    +2

    ТОЛСТО!!!


  1. ideological
    21.02.2017 07:03
    +2

    А habrahabr тоже на каком-то фреймворке написан?


  1. Gosha_say
    21.02.2017 07:05

    Ну вообще писать hello world на PHP не выгодно ввиду отношения ресурсоёмкости к его полезности, так что на PHP — hello word лучше не писать вообще


  1. lexofein
    21.02.2017 09:29

    Каждый раз когда вижу такие посты, вспоминаю историю про кучу проектов, которые клепали как умели, вместо того чтобы пытаться изучить все и вся. Один из самых ярких примеров дота. Была статья на хабре, в которой речь зашла о том что первая дота была примером лютейшего говнокода и ее очень критиковали разработчики вк3 карт за это. Где теперь разработчики со своим идеально вылизанным кодом, а где теперь дота говорить надеюсь не нужно.


    1. Delphinum
      21.02.2017 12:36

      Первые версии доты клепались на Warcraft'овском конструкторе карт, а если вы не знаете, то в этом конструкторе используется «программирование мышкой». В итоге конструктор компилирует ветвление if/else примерно так:

      function if_foo takes string returns boolean
        проверка
      endfunction
      
      function then_foo takes function returns nothing
        тогда
      endfunction
      
      function else_foo takes function returns nothing
        иначе
      endfunction
      

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

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

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


  1. Enapiuz
    21.02.2017 10:14
    +1

    То есть вы берете симфони (далеко не самый простой и дружелюбный фреймворк), в довесок к нему берете реакт (тоже не самый очевидный и дружелюбный фреймворк), обмазываетесь тайпскриптом, делаете на этом всем hello world и удивляетесь, что у вас куча оверхеда?
    Конечно, если вам нужно что-то маленькое, то можно либо взять маленький фреймворк, либо быстро состряпать из готовых компонентов свой, взять тот же fastroute и вот приложенька с API готова.
    А если приложение ваше будет большим, то и симфони не будет таким монстром на его фоне, а скорее всего упростит жизнь.
    Тут как всегда просится уже набившая оскомину фраза "для каждой задачи свой инструмент".


    1. VolCh
      21.02.2017 10:44

      Причём для реакта берётся далеко не самая стандартная обвязка, да и для симфони многое пишется руками из того, что автоматизировано либо в symfony, либо в bin/console, а про create-react-app не слышали.


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


      1. varanio
        21.02.2017 11:14

        Отвечу сразу обоим )

        Видимо мне надо было назвать статью как-то по-другому. Типа «заготовка для SPA c php». Но теперь уж поздно.

        > То есть вы берете симфони (далеко не самый простой и дружелюбный фреймворк)
        Что там недружелюбного, в симфони-то? С ним как раз всё норм, и времени не заняло совсем. С конфигами к webpack было в 100 раз больше проблем.

        > в довесок к нему берете реакт (тоже не самый очевидный и дружелюбный фреймворк)
        Насколько я вижу, сейчас есть два топовых направления: React+что-то или Angular. Ну, я выбрал React+redux

        >обмазываетесь тайпскриптом
        Вот тут вы не правы на 100500%. Typescript в мире javascript — это как бриллиант в куче г. Строгая типизация, interface и т.д. Особенно для реакта помогает. Когда задаешь interface для props, то тебе IDE не дает ошибиться
        при использовании этого react-компонента. Без интерфейсов вообще сложно строить ООП.
        При этом никакого особого оверхеда по сути нет, так как все равно обмазываться webpack-ом приходится и его конфигами.

        >Причём для реакта берётся далеко не самая стандартная обвязка
        Обвязка — это redux, вы имеете в виду? Тут да, возможно надо было бы что-то попроще взять. Без чистых функций и т.д. Но redux интересен лично мне, кроме того, я знаю пару крупных контор, котрые его используют в продакшене и радуются. Поэтому решил взять его.

        > да и для симфони многое пишется руками из того, что автоматизировано
        Создание сущности по таблице? Ну да, но там сущность на несколько строк, разницы особо нет

        > про create-react-app не слышали.
        не слышал, посмотрю


        1. VolCh
          21.02.2017 12:19
          +1

          Вот тут вы не правы на 100500%. Typescript в мире javascript — это как бриллиант в куче г. Строгая типизация, interface и т.д. Особенно для реакта помогает. Когда задаешь interface для props, то тебе IDE не дает ошибиться
          при использовании этого react-компонента. Без интерфейсов вообще сложно строить ООП.
          При этом никакого особого оверхеда по сути нет, так как все равно обмазываться webpack-ом приходится и его конфигами.

          Вы описываете плюсы статической типизации, но для JS она не ограничивается Typescript, притом что Typescript требует именно полноценного компилятора, а другие типа Flow требуют, максимум, простого плагина к babel, а то и просто типі в комментариях указіваются.


          Обвязка — это redux, вы имеете в виду? Тут да, возможно надо было бы что-то попроще взять. Без чистых функций и т.д. Но redux интересен лично мне, кроме того, я знаю пару крупных контор, котрые его используют в продакшене и радуются. Поэтому решил взять его.

          Не только, но и его тоже. Но поскольку мы говорим прежде всего о пхп-разработчике, то редакс для него библиотека с соверешнно чуждой парадигмой. Хранить стейт в умных компонентах или использовать ООП-"сторы" типа MobX куда ближе к PHP и Symfony.


          Создание сущности по таблице? Ну да, но там сущность на несколько строк, разницы особо нет

          Создание таблицы по сущности


          не слышал, посмотрю

          обязательно посмотрите


          1. varanio
            21.02.2017 17:59

            Flow посмотрю


          1. vintage
            26.02.2017 22:41

            Typescript требует именно полноценного компилятора, а другие типа Flow требуют, максимум, простого плагина к babel

            Вы так говорите будто полноценное хуже неполноценного.


            1. Fesor
              26.02.2017 23:09

              Вы так говорите будто полноценное хуже неполноценного.

              вы извращаете слова, никто не говорил про "неполноценные" компиляторы.


              В целом если вы завязали проект на TypeScript вы от него никуда не денетесь. Это своего рода вендор-лок, пусть я и не думаю что это очень плохо в данном случае. С Flow все намного более демократично.


              1. vintage
                27.02.2017 11:11

                C Flow всё демократично только если прятать типы в комментариях. Но раз мы говорим про "плагин к babel", то это явно не тот случай.


            1. VolCh
              27.02.2017 07:10
              +1

              С точки зрения управления проектом, компилятор — новый тип сущности, вводимый в процесс сборки, а плагин к бабел — ещё один экземпляр существующего типа. И вообще можно обойтись без него, описывая типы в комментариях на манер jsdoc


              1. vintage
                27.02.2017 11:12
                -1

                Сам babel — лишняя сущность при использовании ts.


                jsdoc крайне скупо описывает семантику и её крайне плохо понимают ide.


                1. VolCh
                  27.02.2017 11:56

                  Почему лишняя? Тайпскрипт умеет импортировать в Джс например цсс-файлы? тайскрипт умеет компилировать в ES5+/ES2015-, то есть для браузеров, которые, скажем, 80% фич ES2015 умеют, а 20 нет? Когда в последний раз крутил, то выбор таргетов был строго ограничен и пришлось выбрать ES2015 и оставшиеся 20% компилить бабелем. Альтернатива — таргет ES5 совсем не радовала.


                  Я про флоу типы в комментариях, а не в коде на манер тс.


                  1. vintage
                    27.02.2017 12:01
                    -1

                    Тайпскрипт умеет импортировать в Джс например цсс-файлы?

                    И зачем заниматься такими извращениями?


                    тайскрипт умеет компилировать в ES5+/ES2015-, то есть для браузеров, которые, скажем, 80% фич ES2015 умеют, а 20 нет?

                    Конечно. Если вы про генераторы, то нет, такой говнокод он не генерирует.


                    1. VolCh
                      27.02.2017 12:07

                      Про модульность не слышали? Про изоляцию CSS компонента от окружения?


                      Specify ECMAScript target version: "ES3" (default), "ES5", "ES6"/"ES2015", "ES2016", "ES2017" or "ESNext".

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


                      1. vintage
                        27.02.2017 12:33

                        Про модульность не слышали? Про изоляцию CSS компонента от окружения?

                        Для этого не нужно вкомпиливать стили в скрипты. Впрочем, я сторонник более наглядного БЭМ. Фанатичная изоляция особой пользы не приносит.


                        Или отсекай больше пользователей, чем рассчитывал, или грузи большинству кучу ненужного ему кода.

                        Или не используй модные фичи сомнительной ценности.


                        1. VolCh
                          27.02.2017 13:09

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


                          "модные фичи сомнительной ценности" как-то слабо применимо к фичам, включенным в стандарт языка и уже поддерживаемым последними стабильными версиями сколь-нибудь популярных браузеров. Просто не все обновляются.


                          1. vintage
                            27.02.2017 13:14

                            Не нужно, но это удобно

                            Совершенно не удобно. Сорсмапы — штуки до сих пор не надёжные. А для уникальности генерируются имена с хешами. БЭМ же нужен не только для решения конфликтов, но и для понимания что к чему относится.


                            "модные фичи сомнительной ценности" как-то слабо применимо к фичам, включенным в стандарт языка

                            То, что они включены в стандарт языка — лишь дань моде. Префиксы в css, Object.observe, application cache — тоже были стандартами и где они теперь?


  1. vladalivan
    21.02.2017 11:04

    Помню, в далеком 2002 году я начал изучать PHP с фреймворка Smarty, и долго делал все через задницу, пока не понял, что чистый PHP как фрейворк гораздо лучше чем Smarty.


    1. Source
      21.02.2017 11:49
      +1

      iirc, Smarty — это шаблонизатор, а не фреймворк.


      1. vladalivan
        21.02.2017 11:55

        Ну, да, сорри. Я к тому, что не всегда нужно стрелять из пушки по воробьям.


    1. AnjeyTsibylskij
      21.02.2017 12:09

      Так Smarty это не фреймворк, это шаблонизатор


  1. dimaborisovsky
    21.02.2017 11:16

    А флуда то за сутки накопилось не мало. Значит статья людям действительно понравилась!


  1. zevilz
    21.02.2017 11:17

    Эх. До чего докатились в 2017…


  1. Mexis
    21.02.2017 11:38

    Люблю такие статьи. Как раз такие статьи напоминают мне, что пора браться за ум и научиться использовать фрейворки. Я фронтендист, но частенько «хардкодю».
    Спасибо!


  1. KeLsTaR
    21.02.2017 11:53
    +1

    А мне лично статья понравилась, жду чего-то в таком же духе для Java))


  1. Denius
    21.02.2017 12:29

    Отвел душу, автор — СПАСИБИЩЕ!


  1. CodeDriller
    21.02.2017 12:39
    +1

    Стрелять из пушки по воробьям так же глупо, как изобретать велосипед заново. (с)
    Я хочу сказать, что сначала ставится и анализируется задача, а только потом под эту задачу выбираются наиболее подходящие для нее инструменты. Это важнейший инженерный принцип! А у Вас так получается, что Вы сначала подобрали себе набор наиболее модных и навороченных инструментов, а потом спрашиваете, что будем с этим делать. Хорошие системы не делаются таким образом.


  1. maxnemo
    21.02.2017 13:22

    Если вы пишете вручную «echo 'hello, world'», то обрекаете проект на говнокод на веки вечные (кто потом этот велосипед за вас переписывать будет?).

    Столько заморочек, чтобы написать пару слов hello world…


  1. dreamworker
    21.02.2017 13:35
    +2

    Вся эта статья характеризуется одним предложением: «синдром преждевременной оптимизации»


  1. OlegZorin
    21.02.2017 14:23
    +2

    Фремворки, абстракции, паттерны это все хорошо и это все правильно — надо знать и уметь применять.

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

    Если задача стоит только написать HW, то я сделаю наитивно echo 'HW';. На кой сюда совать ООП, MVC и еще кучу всякой-всячины? В частности, зачем тут БД и симфони (да и вообще любой другой фрейиворк)?

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

    Мое личное мнение — код должен быть максимально простом, но при этом он должен удовлетворять требованиям системы в целом. Тогда этот код проще сопровождать и сложнее сломать.

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

    С автором соглашусь в одном — нужно владеть как можно большим числом инструментов. Но также надо уметь правильно ими пользоваться.


    1. MikailBag
      21.02.2017 19:56
      +2

      Тут не нужен даже php)


      echo "Hello, World!" > /web/server/static/path/index.html

      И все)


      1. OlegZorin
        22.02.2017 06:49

        Вообще да, соглашусь.

        Однако, статья называется «Hello (real) world» на php. Значит у нас возникает первое ограничение системы — язык php. ))

        А вообще, я бы считал эту статью неким «пятничным стебом» и пародией на статью про JS и JS-сообщество (https://habrahabr.ru/post/312022/).


        1. MikailBag
          22.02.2017 21:34

          Причем настолько же безосновательным стебом.
          Любой живой язык постепенно обрастает кучей библиотек и фреймворков.
          На плюсах тоже хелловорд с ассемблерными вставками написать можно)


    1. zhigalin
      22.02.2017 19:15

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

      Микроскопом он забит, микроскопом.

      varanio Вы передали читателям сообщение прямо противоположное тому что хотели сказать, поздравляю.


  1. RidRock
    21.02.2017 14:24
    +2

    Предположим, автор захотел написать Hello world! на листке бумаги.
    1. Описываем долгий процесс получения бумаги (опилки-целлюлоза во все поля).
    2. Описываем долгий процесс создания авторучки (упуская при этом возможность использования гусиного пера).
    3, Описываем долгий процесс получения чернил (сок ягод?).
    4. Описываем долгий процесс изучения и написания буковок.
    5. PROFIT!
    Зы: Без обид)


  1. 14types
    21.02.2017 16:55
    +2

    Преподаватель по ООП говорил: делайте то, что просят, ни больше ни меньше.
    Для вывода «Hello,world!» даже HTML разметки не надо.


  1. ld100
    21.02.2017 17:43
    +1

    Думаю, критики в комментариях было бы гораздо меньше, если бы в примере был не hello world, а что-то чуточку более приближенное к реальности, вроде «блога за 15 минут».


    1. Fesor
      21.02.2017 17:54

      «блога за 15 минут».

      1. идем на medium.com
      2. регаем аккаунт.

      Ну или для изысканных


      1. Идем на github pages
      2. делаем дела.


  1. Al373
    21.02.2017 20:06
    -3

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


    1. VolCh
      21.02.2017 22:34

      Забыли тег "сарказм"?


  1. ideological
    21.02.2017 22:36

    Всё очень просто.

    Если это веб-студия и они пишут 100500 сайтов — то им очень нужен php фреймворк. Жизненно необходим.
    Потому что они с ума сойдут разбираться в костылях разных. Нанимаешь чуваков знающих выбранный фреймворк и вот куча визиток и интернет-магазинов.

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


    1. VolCh
      21.02.2017 22:49

      Да ладно? Для визиток и интернет-магазинов как раз фреймворк не нужен, нужна CMS, а то и вообще генератор статики.


      А вот для сервисов и нестандартных проектов фреймворки очень помогают работать именно над нестандартной частью, не тратя время на всякие роутинги и маппинги базы данных (из поста именно они использованы).


    1. Fesor
      21.02.2017 22:58
      +1

      Если же приходится писать сервис или нестандартный проект какой

      то сразу находится миллион стандартных задач:


      • логи
      • кеширование
      • надо как-то с базой работать, нужны либки под тот подход который мы хотим юзать
      • надо как-то с http работать
      • надо как-то очереди делать
      • надо как-то управлять зависимостями
      • Аутентификация, авторизация
      • надо как-то с <впишите-модную-технологию> работать...

      Ну то есть вся инфраструктура проекта. Можно брать full-stack фреймворки или микрофреймворки и дополнять компонентами по вкусу… Порой приходится дописывать что-то свое когда "жмет". Бизнес логика же обычно не должна зависеть от подобных вещей. Кучи принципов и правил не просто так понапридумывали.


  1. vtvz_ru
    22.02.2017 00:04
    +1

    Несмотря на то, что это не «Hello, World на PHP», но вполне реалистично описывает современную ситуацию. Помню времена, когда был только jQuery и голый CSS… Сейчас порог вхождения для всего web стека намного выше, чем раньше. Хотя создание сложных вещей стало намного проще, но разобраться во всем этом разнообразии разобраться не могу до сих пор


  1. Rathil
    23.02.2017 02:56

    Ну не скажите. Мы сейчас пилим достаточно большой продукт, а точнее переписываем его, сейчас около 1М строк. Переписываем на микросервисы и не используем особо фреймворк. Было решено взять фалкон, но только для малого числа функционала (DI, валидаторы). Так что пишут сейчас без фреймворков. Пишут.


    1. Fesor
      23.02.2017 03:21

      Было решено взять фалкон

      Так что пишут сейчас без фреймворков.

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


      1. Rathil
        23.02.2017 12:58

        Ну как Вам ответить, все зависит от того, что Вы подразумеваете под понятием «использовать фреймворк». Если бы мы взяли просто готовую либу, не из фреймворка и использовали ее, Вы бы все равно сказали, что мы используем стороннюю готовую либу, а это почти тоже самое! Просто нам подошёл именно тот интерфейс и тот функционал, вот мы и взяли фалкон и используем его как либу, а не фреймворк. Полностью заврапили те части, что мы используем, своими интерефейсами и полетели…


  1. Skit25
    23.02.2017 03:24
    +1

    Про postgresql, ваши слова бы да хостерам в уши. Если бы хостеры поставили постгрес, на ряду с мускулем, было бы супер! А так — мускуль. Хотя на локалке, чтобы не отставать использую постгрес, благо фреймворк в 21 веке позволяет менять драйвер, одним словом в конфиге.


  1. aureliano_b
    23.02.2017 12:16
    +1

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

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

    Сильно абстрагированные фреймворки вопреки бытующему в среде «корпоративных менеджеров» мнению, не упрощают, а напротив — радикально усложняют разработку и поддержку (см статью, собственно). Это новая религия (слаба роботам, не особо популярная в среде профессиональных разработчиков, как это может показаться после чтения Хабры) возникла из иллюзорных желаний непременной монетизации любого созданного за 15 минут кода, с легкой руки Google и иже.

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

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

    Тем же, кто действительно любит писать код и стремится постичь «Дао» этого ремесла могу посоветовать фундаментальную монографию Дональда Кнута фывфывфыThe Art of Computer Programming.

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


    1. varanio
      23.02.2017 12:34
      +2

      Вы когда-нибудь вообще работали в команде?
      Вы когда-нибудь делали SPA-приложение без фреймворка?

      Как php, так и js-код без фреймворка в большой команде имеет тенденцию к нарастанию запутанности. Я это видел много раз. И вот именно это говнищще приходится потом переделывать с нуля. В отдельных случаях, при наличии сильного техлида, образовывается некоторая поддерживаемая структура, но это по сути фреймворк! Только велосипедный!!! Но это редкость, обычно всё скатывается в говнокод.

      И наоборот: я много раз наблюдал, как человек впервые видел проект например на Yii и сразу начинал писать код, потому что знал Yii.

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

      И отдельным пунктом совершенно непонятно как Кнут со своими сортировками и деревьями и т.д. может помочь с проектированием поддерживаемого приложения в команде.


    1. VolCh
      23.02.2017 13:50
      +1

      Если вы действительно настолько индокринированы и реально подходите к проектированию и работе так, как описано в статье, мой вам совет: оставьте это ремесло, программирование не для вас.

      Процентов 80 новых проектов я начинаю с подобных шагов: поднять базу постгрес, развернуть симфони с доктриной для бэка и вебпак с реактом для фронта. Полчаса максимум. И начинаю проектировать и программировать бизнес-логику и интерфейсы, не отвлекаясь на алгоритмы Кнута для валидации формочек, роутинга и маппинга объектной модели на базу данных.


  1. gerashenko
    23.02.2017 18:17
    +1

    Статья отражает и мое впечатление об изменениях в сфере веб-разработки за последние 10 лет. Вряд ли описанные шаги являются пособием для новичков, но они хорошо показывают то, как изменились требования к соискателям. Времена, когда знания PHP было достаточно, ушли. Для развертывания приложений сейчас требуется выполнить столько всевозможных настроек и установок, что начинаешь ощущать себя админом, возможно, Docker и решает частично этот вопрос, но он же порождает новые конфиги. Сами приложения теперь включает в себя множество подязыков и языки на языках. Да можно сделать сборку и пользоваться ей, но она устаревает уже через полгода. С легкостью прыгнуть с проекта на проект не получается, нужно смотреть список задействованных технологий. И проблема здесь не в средствах разработки, не в том фреймворке, который вы выберете, а в требованиях к конечным продуктам. Планка выросла. Мне это напоминает игровую индустрию, раньше игру мог написать один человек, сейчас такая игра никому уже не будет интересна, есть исключения, но это будет не та игра, которые сейчас выпускаются корпорациями.


  1. Lorien_Elf
    24.02.2017 14:37

    Кого-то удивляет, что в ближайшие два десятилетия 99% программистов будут заменены ИИ? :)


  1. stargazr
    24.02.2017 18:04

    Получилась статья о том, что современные инструменты веб-разработки не заточены для написания хелловорлдов.
    Замечательно! Продолжайте в том же духе. Ждем разоблачений про использование современных Java IDE для ведения заметок, или про видеоконференции по электронной почте.


    1. f0rk
      24.02.2017 19:17

      И ведение деловой переписки через Snapchat :)


      1. MikailBag
        24.02.2017 21:12

        И скрипты на ассемблере.


  1. vdonich
    25.02.2017 06:14

    Эй, что за REST API? Это что за 200x?
    Websocket! Web Worker!


    1. varanio
      25.02.2017 06:18

      Websocket на php? Мсье знает толк


      1. Fortop
        25.02.2017 13:47
        +2

        Я вам открою Америку.

        http://socketo.me

        Пользуйтесь.


  1. JDBaha
    26.02.2017 14:57
    -1

    Изучение пхп следует начать с:


    1. Изучения синтаксиса
    2. Изучения одного из популярных фреймворков
    3. Поднятия собственного движка

    В современных фреймворках куча всего лишнего, всевозможные хелперы, обработчики, орм. Кому они нужны, если отдача простой статической страницы на таком фреймворках занимает 70мс? (тестил на локалке, Yii2).
    Doctrine бесполезен в 95% случаях. Куча предобработки в запросах и ради чего? Потому что, возможно, в будущем я перенесу проект на другую SQL бд. Этого не случится в 95%ах случаев. А если и перейдете то далеко не факт что это будет sql поддерживающая бд.
    Я поднял свой mvc движок, для своего маленького проекта. И страница отдается за 30мс без запросов к бд. При этом там есть нормальный роутинг, актив рекорд, автолоад классов и удобная подрубка сторонних библиотек.
    Фреймворки в большинстве случаев слишком универсальны. За что вы платитесь производительностью


    1. Fesor
      26.02.2017 16:24
      +2

      Изучение пхп следует начать с:

      а как по мне когда люди начинают идти по такому пути, где-то упускаются следующие понятия:


      • декомпозиция — проектирование системы сверху вниз. Обычно разработчики почему-то строят систему снизу вверх (то есть на скорую руку выбирают нижние кирпичики, например схему базы данных и уже потом лемят оттуда).
      • data abstraction — это когда мы делаем сначала методы. описываем поведение, а уже потом думаем о данных (если упрощать)
      • инкапсуляция — это та штука которая позволяет улучшить реюз абстракций (не кода позволю себе заметить), позволит DRY-ить код, и в целом улучшит понимание что происходит.
      • полиморфизм — это та штука которая уменьшает количество if-в в коде и в целом позволяет юзать "похожие вещи" как одни и те же.

      В целом фреймворки или написание своего "движка" тут не помогут от слова совсем.


      Куча предобработки в запросах и ради чего? Потому что, возможно, в будущем я перенесу проект на другую SQL бд. Этого не случится в 95%ах случаев.

      Давайте немного поговорим о "смене БД". Это дурацкий пример, полностью согласен. Если у нас на проекте была выбрана MySQL то мы от нее вряд-ли сможем далеко убежать. Более того, делать совсем без SQL не выйдет в большинстве задач. Рано или поздно появляется native sql для того что бы максимально эффективно использовать выбранную СУБД.


      НО! Вместо смены СУБД на всем проекте мы всегда можем добавить вторую! Просто потому что можем упереться в лимиты СУБД или просто потому что в другой СУБД что-то есть из коробки. Тут уже ORM или любые абстракции от хранилища (DAO вам должно понравится судя по всему) сильно экономят время.


      В целом достаточно просто что бы SQL не был размазан по всему проекту и лежал изолированно где-то. А как вы это делаете — это уже детали. Например любители доктрины часто размазывают DQL по всему проекту или EntityManager юзают не только там где надо но вообще везде. Это тоже плохо и противоречит идеи Doctrine.


      Я поднял свой mvc движок, для своего маленького проекта. И страница отдается за 30мс без запросов к бд.

      Symfony3 + Doctrine 2.5 + выборка из базы = 20ms. Что я делаю не так? Скорость ответов важна, но это лишь значит что мы берем что-то медленное и стандартное а потом оптимизируем узкие места. То есть мы экономим 5x на времени разработки (чтобы вы понимали, во фреймворках покрыты многие кейсы о которых вы даже думать не будете, но если будете вам придется все это реализовать самостоятельно), и потом оптимизируем только то что медленно работает. Например в случае доктрины можно гидрацию данных оптимизировать или на SQL.


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


      Проблема с фреймворками и разработчиками в основном заключается в том, что большинство даже не пытается разбираться "а зачем там что и как работает".


      1. JDBaha
        26.02.2017 17:22

        30мс — это тоже у меня на локалке. Я думал будет понятно, простите.
        Если говорить о проектировании систем то лучше уж почитать Фаулера.
        И мне кажется добавление еще одной бд входит в эти 5%. В Doctrine я и в правду не захотел разбираться, как и в симфони. Из коробки симфони у меня на локалке отдает страницу за 200мс, кажется это был второй симфони. После я естественно начал гуглить оптимизацию производительности. Понял что там предстоит нешуточная работа и бросил все это дело.


        1. Fesor
          26.02.2017 18:32
          +1

          30мс — это тоже у меня на локалке.

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


          Если говорить о проектировании систем то лучше уж почитать Фаулера.

          Фаулера почитать стоит конечно, а еще Роберта Мартина, Кента Бэка, Алестера Коберна и других хороших людей. Но их почему-то не читают. Ну и опять же на каком этапе читать то из тех что вы озвучили?


          И мне кажется добавление еще одной бд входит в эти 5%.

          Повторюсь — "абстракция от базы данных" это не для смены оной, а что бы игнорировать наличие оной когда вы бизнес логику описываете. Это не значит что вы не можете делать все через plain sql, просто все операции с базой должны быть изолированы в отдельных штуках. ORM аля Doctrine просто предоставляет вам один из способов делать это быстро и удобно. Ну то есть в большинстве случаев вы не будете проектировать схему базы данных, вы будете работать только с объектной моделью. То что этот инструмент несет в себе высокий уровень скрытой сложности — это да. И авторы к третьей версии собираются выпилить весь "сомнительный" функционал который позволял делать стремные вещи.


          1. JDBaha
            26.02.2017 19:28

            Повторюсь — «абстракция от базы данных» это не для смены оной, а что бы игнорировать наличие оной когда вы бизнес логику описываете

            Это выглядит как ненужный слой, по своей сути дающий profit лишь в редких ситуациях. Ну ладно… у каждого свое видение одного и того же


            1. Fesor
              26.02.2017 23:14

              Ну ладно… у каждого свое видение одного и того же

              Я пока плохо представляю ваш вижен. Давайте на каком-нибудь маломальски простом примере:


              Есть например у нас необходимость давать пользователю скидку, если он накупил товаров за календарный месяц на >$100. Можете описать как бы вы делали, куда ложили бы sql, как выглядел бы код?


              p.s. Специально выбирал примеры для которых ORM плохо подходит. Мне интересно именно как вы сделали бы подобное в вашем случае. Куда бы положили эту проверку, делили бы как-то и т.д. Где был бы SQL.


              1. JDBaha
                27.02.2017 08:29

                Тоже самое, только без абстрагирования от бд

                class User extends \app\system\model\ActiveRecord
                {
                
                    public function haveDiscount()
                    {
                        return 100 < Util::getTransactionHistorySumByPeriod($this->id, strtotime('-1month'));
                    }
                ...
                }
                
                ...
                class Util
                {
                
                    public static function getTransactionHistorySumByPeriod($iId, $iStart, $iEnd = null)
                    {
                        $sEnd = $iEnd === null ? date('d-m-Y H:i:s') : date('d-m-Y H:i:s', $iEnd);
                        $sStart = date('d-m-Y H:i:s', $iStart);
                
                        return \app\system\Registry::get('db')->add('SELECT SUM(value) AS total')
                            ->add('FROM transactions')
                            ->add('WHERE "id" = :id AND "created_at" > :start AND "created_at < :end')
                            ->execute([':id' => $iId, ':start' => $sStart, ':end' => $sEnd])->fetch('total');
                
                    }
                }
                


                1. VolCh
                  27.02.2017 10:45

                  У вас всё таки есть слой, изолирующий бизнес-логику от хранилища, назвали вы его правда Util, но суть не меняется — даже если заменить SQL базу на NoSQL, а то и вообще на облачное хранилище с ptotobuf интерфейсом, то ничего в классе User не поменяется, только в слое Util нужно будет что-то менять.


                  Другое дело, что если нужно будет вывести список всех клиентов с пометкой есть ли у них право на скидку, то или получим ситуацию 1+N запросов, или нужно будет писать ещё один метод в слое изоляции.


                1. Fesor
                  27.02.2017 18:39
                  +1

                  Вот если вы переименуете Util в TransactionHistoryDao какой-нибудь, или просто TransactionHistory будет то же что и у меня в проектах с доктриной а не "еще одной реализацией AR". Ну и логику тогда можно было бы ложить в сущности.


                  Я не зря написал что описанная мной задача решается с ORM плохо, просто потому что задача выходит за пределы OLTP (Online-Transaction Processing).


            1. VolCh
              27.02.2017 07:19

              Как по мне, то это самый нужный слой в сколь-нибудь серьёзном приложении. А так-то, да, можно SQL-запросы в PHP-шаблоны складывать.


    1. VolCh
      27.02.2017 07:11

      Doctrine бесполезен в 95% случаях.

      актив рекорд

      То есть вам не понравилась Doctrine и вы изобрели свою ORM?


    1. Delphinum
      27.02.2017 15:42
      +1

      В современных фреймворках куча всего лишнего

      В 3 версии ZendFramework вообще ничего нет, компонуем только то, что нужно в проекте.

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

      Эмм… А зачем все это, когда есть composer со встроенным генератором autoload?


      1. Lordz
        28.02.2017 09:12
        -1

        А зачем нужны 5 классов «встроенного autoload» если в конце он все равно вызывается spl_autoload_register?
        Ну это еще ладно… можно объяснить унификацией подключения сторонних библиотек.

        Но в чем круть от писанины автора: «return new JsonResponse(...)», вместо return json_encode(...) ?!
        А если этот никчемный класс (JsonResponse) порождается 100 раз в секунду?

        ЗЫ. Давайте не забывать, что PHP — язык рожденный умирать! А OOP — это всегда медленно…
        PHP + OOP = «hello, Highload»
        Предлагаю переименовать публикацию :-)


        1. VolCh
          28.02.2017 09:53

           return json_encode(...) 

          А статус ответа, а заголовки? Да банальный 'application/json', его как возвращать? Ну и унификация: JsonResponse — частный случай Response, какой-нибудь миддлваре всё равно какой из Response вернули, допишет свой заголовок, а какая-то только к JsonResponse что-то допишет или наоборот удалит что-то.


          OOP — средство уменьшения сложности. Не бесплатное, да.


        1. Fesor
          28.02.2017 11:06

          А зачем нужны 5 классов «встроенного autoload» если в конце он все равно вызывается spl_autoload_register?

          Давайте рассуждать. У нас есть spl_autoload_register который позволяет нам сделать цепочки автозагрузчиков. Почему нам важны цепочки? Потому что разные модули нашего проекта, не важно наши они или third-party, могут иметь свои правила автозагрузки (например у вас есть старый модуль из эпохи php5.0 бэз нэймспейсов и новый красивый из эпохи 7.0). Это упрощает использование модулей. Мы просто подключаем автозагрузчик модуля и "едем дальше" вместо того что бы каждый раз вкручивать его в проект.


          Далее, почему писать свой автозагрузчик плохая идея в большинстве случаев. Что мы можем написать сами за 1 минуту? Скорее всего это будет тупая функция которая тупо по имени класса будет импортировать какой-то файл.


          Что мы можем сделать с composer за одну минуту. Описать PSR-4 автозагрузку или прописать инклуды, и вызвать команду composer dump --optimize --no-dev --classmap-authoritative. Что дает нам эта команда:


          • опция --optimize и --classmap-authoritative позволит нам составить классмэп (какой класс в каком файле искать), что бы не нужно было вычислять это каждый раз и трогать лишний раз файловую систему. Максимально эффективный способ.
          • опция --no-dev выкинет все зависимости которые нам требуются для разработки (phpunit например или тэсты) из мэпы классов.
          • если у нас миллион зависимостей и узким местом становится инициализация классмэпа, есть другая стратегия, которая позволяет использовать apcu и кэш в рантайме. Для маленьких проектов это не самый эффективный вариант, а вот для большших может быть спасением.

          И все это вы получаете… просто так из коробки. Подходит как для маленьких так и для больших проектов. Эфортов разработчика — минимум. Так почему бы не юзать?


          Но в чем круть от писанины автора: «return new JsonResponse(...)», вместо return json_encode(...) ?!

          скорее вместо:


          header('Content-Type: application/json');
          echo json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
          fastcgi_finish_request();

          Раз уж вы о производительности заботитесь. Что будет быстрее, записать в поток 2 раза по 100 байт или 1 раз 200? И сколько это по времени если сравнивать с инстанцированием объектов?


          ну и опять же, JsonResponse хэндлит еще и варианты для jsonp (вдруг кто-то тут еще под ie6 пишет), что руками делать уже ой как не удобно.


          А если этот никчемный класс (JsonResponse) порождается 100 раз в секунду?

          разница между простым вызовом json_encode будет ажно целый порядок, 10^-4 ms vs 10^-5 ms. Экономия на спичках.


          ЗЫ. Давайте не забывать, что PHP — язык рожденный умирать! А OOP — это всегда медленно…

          рожденный ползать летать не может? С тех пор как PHP родился его нутро пару раз переписывали уже. В данный момент он вполне себе может не умирать. Да, пока плохо с инфраструктурой, но если у нас например запросы на чтение (а их обычно большинство), выборки какие-нибудь, можно взять react или php-pm и радоваться жизни.


          Некоторые для этих целей берут nodejs например (то есть запись происходит в php, там формируется набор событий. строится проекция на какую-нибудь монгу или эластику, а node через graphql отдает данные).


          А OOP — это всегда медленно…

          Не совсем так. Медленно — динамическая диспетчеризация, когда вам надо в рантайме соответствия искать кто кого вызывает. Эти вещи решаются различными инлайн кэшами на уровне интерпретатора (JIT, который обещают впилить в php8, вполне способен на подобные оптимизации). А все остальное — не отличается по производительности.


          А хайлоад… это надо быть в top 100 по нагрузкам ресурсов что бы "ООП" стало узким местом. Намнооого чаще узким местом становится кривая архитектура.


          1. Lordz
            01.03.2017 00:07

            рожденный ползать летать не может?

            В том то и дело, что PHP отлично летает… по крайней мере до тех пор пока ему булыжник на шею не цепляют.
            Концепция «рожден чтобы умирать» это от того что PHP — скриптовый язык, который изначально задумывался для веба, и чтобы следовать простому процессу: получить запрос, обработать его, отобразить вывод и умереть.


            1. VolCh
              01.03.2017 08:21
              +1

              задумывался

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


        1. lair
          28.02.2017 11:32

          А OOP — это всегда медленно…

          Я боюсь, что StackOverflow с вами не согласится.


        1. Delphinum
          28.02.2017 13:32

          Мне кажется, вы болеете «преждевременной оптимизацией» )


  1. RonBarhash
    28.02.2017 15:18

    Статья в стиле «Страшилка для Джунов» :) После статьи осталось впечатление, что в авторе еще до сих пор живет истеричный джуниор :). А после слов: «Не будем хардкоддить… а лучше запихнем все в постгрес», хочется окатить Вас холодной водой!!! Это не уровень ведущего разработчика, и мне искренне жаль вашего работодателя.
    Вы из простой задачи сделали монстра. Привычка полить из пушки по воробьям очень пагубна. Если уж так хотелось использовать базы то, могли бы взять что-то полегче SQLite например или что-то современное, для REST есть куча микро-феймворков… про SPA даже говорить не хочется. У каждого подхода есть свое применение. И лепить популярные технологии во все проекты могут позволить себе только джуниоры, ведь им нужно многому учиться и практиковаться. Ах да, по поводу техники POMODORO, в ней основная идея разбивать рабочий процесс на равные доли (рекомендуется по 25 минут с 5-минутными перерывами и т.д.) Вами он как то странно описан :D Было бы очень интересно услышать от автора, почему он лично считает, в чем преимущества использования фреймворков в разработке :)


    1. varanio
      28.02.2017 15:29

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

      Но! В остальном никакой истерики тут нет. Следующий новый проект я начну именно так, как описано здесь. Ну, может redux заменю на что-то попроще.


      1. RonBarhash
        28.02.2017 17:19

        Я лично, ничего против не имею в том, чтобы использовать Постгрес+Симфони в проектах… Но к статье самой есть :) Я от нее ожидал Вашей интерпритации это задачи с использованием современных технологий, которые используются в 2017 году при разработке на PHP. А в статье много времени рассуждения о базе данных и фронтенде и «ничего» о современном PHP. Хотелось увидеть карикатуру на «Мона Лизу» от совренного художника, а оказалось «Суровые будни — 2017» :D


    1. VolCh
      28.02.2017 15:53

      С другой стороны подобный стэк может быть корпстандартом, на котором по умолчанию начинаются новые проекты без особіх требований. Наш, например, не сильно отличается, из глобального только таблицы ручками не создаём и create-react-app используем для фронта.