Pull to refresh

Comments 73

Удачи и приятного рефакторинга!

Это, должно быть, шутка.
Я по долгу службы как раз занимаюсь таким вот переписыванием по живому одного проекта. Это нечто. Поддержка того, что еще работает на старых скриптах, перевод на новые, поддержка старых и очень старых (а так же очень очень старых) данных, при изменяющихся требованиях к ним. Т.е. вчера формат номера телефона, например, был свободным, а сейчас к нему появилась кучка требований. Очень много мороки и очень мало видимого снаружи результата. В общем мало приятного совсем.
Еще и недокументированные костыли бывают…
Недокументированные? Документации вообще нет никакой. Не думаю, что это редкость.
Конечно, процесс рефакторинга непростой. Но я надеюсь, у вас и других коллег, кто столкнулся с такой задачей, все пройдет успешно!
UFO just landed and posted this here
Приятно или нет оценка всё же субъективная. Но могу вам рассказать ситуацию ещё похуже: нужно рефакторить код форка динамически развивающегося проекта, постоянно вбирая из оригинала новую функциональность, багфиксы и т. п., не имея никакого влияния на код оригинала.
UFO just landed and posted this here
Вы, наверное, хотели сказать: «Переводите ещё» =)
goto — новое оружие в руках быдлокодеров.
goto — выше «добра» и «зла» ;)
use Symfony\Component\DependencyInjection\ContainerBuilder;

$container = new ContainerBuilder();
$container->register('mailer', 'Mailer');


И по сути отбрасываем всю простоту и легкость динамических языков и получаем Java, только ещё и раз в 30 медленней… И кто после этого быдлокодер?
UFO just landed and posted this here
Хм… :)

$ find . | grep -E 'php|phtml|inc$' | wc -l
8071

$ find . | grep -E 'php|phtml|inc$' | xargs cat | wc -l
1180995


И вроде как-то вполне неплохо себе без неймспейсов всё работает… Странно, да :)?
UFO just landed and posted this here
Количество точно не значит качество. Вот у вас в строчке, которой вы меряетесь, ошибка, напимер:
$ echo phphphphxxxxx | grep -E 'php|phtml|inc$'
phphphphxxxxx
Вот у вас в строчке, которой вы меряетесь, ошибка:

Да, прошу прощения, действительно ошибся :). На результат это особо не влияет — вместо 8071 получается 8059 PHP-файлов…

Количество точно не значит качество.

Согласен. Более того, я считаю, что такое небольшое количество кода в Badoo говорит как раз о его высоком качестве.
Nginx + Varnish + Memcached


Казалось бы при чем тут PHP и Dependency Injection Container :)
На самом деле — нет. Не делают. Varnish и Memcached это уже оптимизация, а не средства из коробки. Не все проблемы скорости можно решить кешем. Для порталов — отличное решение, а для сервисов — Memcached и Varnish ничем не помогут.
UFO just landed and posted this here
Ну для 90% задач MySQL хватает. Он более универсален.

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

То есть да, на больших проектах, особенно в dev-режиме оно будет работать медленно. И это раздражает.
Преимущества динамических языков к развязыванию зависимостей отношения мало имеют и преимущества никуда не теряются.
Чтобы не быть голословным, вот как можно нормально реализовать Dependency Injection в PHP.
gist.github.com/1936860

Особенность этого подхода, в том, что мы вводим абстракции только когда они становятся необходимыми, а не изначально, когда в них смысла нет. Т.е. работает эволюционный подход.
Я вот только недавно узнал про такую штуку как DI, мол, это так круто и ZF2 и Symfony 2 его используют, и многие другие. А вы говорите что это плохо. И youROCK говорит что мы теряем простоту не жостко типизированного PHP.

И поэтому у меня вопрос.
А почему абстракции — это плохо? Усложняют понимание кода? Так вроде для того их и вводят, чтобы не знать о деталях. Вот из той статьи, где абстранции вводятся компилируя шаблоны — разве это проще? А когда будет не 3 класса, а 300 — конфиг будет, наверно, сложным.

Вот автор той статьи пишет: «When you develop you should not think on any injection or configuration». Вот разве мы думаем о том, какой там storage? У нас есть интерфейс и мы им пользуемся. Я не понимаю чем DI и DIC усложняют проект.
Сам по себе DI в PHP не обязательно реализовывать таким методом, который принят в Symfony, в том-то и прикол. На конференции РИТ++ в этом году был доклад про то, как делать нормальный и удобный DI в динамических на примере Perl, и вот там реализация была очень простая и удобная.

В PHP для реализации DI достаточно сделать что-то вроде следующего:

class Something
{
     protected $Model;

    function __construct($model_class = 'Model')
    {
        $this->Model = new $model_class(...);
    }

    function doSomething()
    {
         $this->Model->....;
    }
}


Все эти конфиги, ямлы и многотонные «use Symfony\Component\DependencyInjection\ContainerBuilder;» слишком сложны и многословны, чтобы ими было легко и удобно пользоваться.
Польза DIC действительно крайне неочевидна. Ну кроме абстрактно-фабричных случаев.
Но вот остальные компоненты весьма годны.
Когда у нас 20+ сервисов в проекте, они используются двумя способами:

1. В начале кода инициализации страниц подключаются и инициализируются все нужные библиотеки.

Плюсы
Примерно все в одном месте и их легко найти и конфигурировать.

Минусы
Каждая страница подключает все библиотеки.

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

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

Минусы
* Инициализация разных сервисов в разных местах
* В разных участках кода может быть создано несколько экземпляров одного сервиса

В реальности часто оба подхода смешиваются, что еще больше все усугубляет. Тогда на помощь приходит DIC.
А вы в Баду пишете такой же простой и легкий код, как и на Обновлении остался? :)
Сформулируйте пожалуйста вопрос более четко.
Куда же четче?

Очень глупо заявлять, что вот превращают php в java, при том, что, во-первых, ОО-модель пхп дерется с джавы, о чем открыто говорят сами разработчики, во-вторых, в любых развивающихся проектах использование ООП очень даже оправдывает себя, т.к. в итоге ваша система превращается в набор независимых модулей, которые позволяют малой кровью менять функционал проекта. При условии, что вы умеете писать вменяемый ОО код, а не делать 2-3 класса с 3-4-мя статическими методами по 300-400 строчек кода каждый.
Так вот мне и интересно, Badoo очень большой проект. И у вас там все простенькими функциями написано, причем так, что возможно нормально поддерживать?
Я могу вам ответить с 80% вероятностью.

Там все перемешано, и классы и функции, нет автолоада, запросы пишутся прямо в бизнес-логике. В представлении (если оно есть) предостаточно того, чего там быть не должно. Все кешируется, что можно.
Программисты сидят не глупые. Достаточно большая команда, новички сидят в саппорте, исправляют все, что каждый день отваливается понемногу. Новичкам вникнуть в код и разобратся в проекте нужно от 2 до 6 месяцев.
Вы работали в баду? О_о
Да нет, есть MVC, функции не используются, автолоад есть и т.д. :). Кешируется действительно всё, чтобы снять нагрузку на базы.
Для меня одного слова Depency Injection, Inversion of Control и Namespace применительно к PHP, звучат вроде «Глянь какой у меня *censored* длинный» ??
А Namespace чем вас обидел? ;)
Изначально я хотел написать про DI и IoC, но в каждом файле не хочется писать такое:
<?php
use foo/bar;
use your/exception as exception;
use pdo, pdoexception;

Поэтому добавил Namespace.

И вообще, сейчас OOП применяется не по назначению довольно часто.
...в каждом файле не хочется писать такое:...
Дак никто вас не заставляет. Если в файле создается один экземпляр из foo/bar, пишите так:
$f = new \foo\bar\class();
> Как реанимировать ваш PHP-проект

Здесь можно было останавливаться и писать: выкиньие РНР, пишите на чем-то другом :)
Здесь можно было остановиться, но я не смог:
[imho]Нет ничего лучше, чтобы писать некрупные динамические сайты, чем PHP.[/imho]

Понятно, что у того ЯП есть те плюсы, но проста написания кода/развертки приложения PHP просто умиляет.

И да, я пишу на PHP, учу Python (давно уже пора) и люблю RoR (не знаю почему).
Простота написания кода — RoR
А развертка — да, согласен
Под «написанием кода» я подразумевал порог вхождения для написания чего-то вроде сайта-визитки.
опять же RoR или какой-нит sinatra :)
У меня развертка RoR на Webbynode и Heroku делается одной командой.
Даже не знаю что может быть проще )
CI, например. Вообще ничего жать не надо :)
Ну как маркетинговый слоган вполне катит, но мы то знаем, что за этим «ничего жать не надо» стоит :)
На баше не оценят, но последние 3 коммента в контексте одного диалога меня очень даже улыбнули (:
Я этого и не утверждаю :)

Просто для того же Ruby простота написания выше, чем у PHP, особенно во фреймворках. За счет фич самого языка.
А я и не говорю «Выкиньте рельсы/синатру». Мне наоборот нравится, что там можно просто и без разговоров написать (поправьте, если что-то не так в коде, в руби не силен)

require 'sinatra'

get '/' do
    'Hello, Habr!'
end


Но это уже не чистый руби =)
Ну, на чистых языках мало кто пишет :) Для того же «сайта-визитки» PHP быстр и удобен только пока там одна страница :) Как только страниц две, уже начинается «include header.php», «include footer.php» и т.п., что быстро становится кашей
При использовании фрэймворка, на пхп аналогично ), хоть и чуть больше строк
require 'Slim/Slim.php';
$app = new Slim();
$app->get('/', function () {
    echo "Hello, Habr!";
});
$app->run();


Python way)
Я коллаборатор фреймворка Slim, если что.
$mailer = $this->container->get('mailer');

И ни одна IDE не угадает, инстансом какого же класса будет являться $mailer. Очень удобно, да.
PHPDoc решает это проблему.
/** @var $mailer Mailer */
$mailer = $this->container->get('mailer');
Это то понятно. Но автоматически это узнать нельзя. Да и беда сам разработчик не всегда может узнать что это за класс сюда попадает. Нужно дополнительно смотреть в конфигурацию контейнера.
PHPStorm 5 уже, вроде бы, умеет угадывать классы Symfony 2.
Это не решение, это костыль для костыля.
Предложите более удобный вариант. К примеру должен быть сервис, который умеет отправлять смс. При тестах или разработке отправлять реальные смски нельзя. Куда Вы будете его помещать?

А вообще здесь лучше обсуждать подход, а не конкретное решение. Можно сделать и так:

class MyCustomContainer extends Container
{
/**
* return iMailer
*/
public function getMailer()
{
return $this->get( 'mailer' );
}

/**
* return iAnotherService
*/
public function getAnotherService()
{
return $this->get( 'anotherService' );
}
}
Иии? А ты наверное любитель магических геттеров/сеттеров?
// файл сервиса
class TestService
{
    /**
     * @var MailerInterface
     */
    protected $mailer;

    public function __construct(MailerInterface $mailer)
    {
        $this->mailer = $mailer;
    }
}

# файл services.yml с описанием зависимостей сервисов
services:
    test_service:
        class: \TestService
        arguments: [@mailer] 

Сервис не должен ничего знать ни о контейнере, ни о геттерах для получения сервисов. У него должен быть интерфейс для внедрения зависимости, а в настройках контейнера вы уже описываете, что передать сервису. Есть еще несколько способов внедрения зависимостей, которые реализованы в Symfony 2, почитать можно здесь и здесь. А в документации можно посмотреть, что еще позволяет сделать контейнер в Symfony 2. А $mailer = $this->container->get('mailer'); это действительно костыль и плохой тон.
Это все красиво и замечательно, но покажите пожалуйста пример использования testService.
Да ну? Смотрим внимательно :)
Переводить на новую версию PHP можно только весь проект.
Странно, но я как-то не согласен с автором.
Порой для переноса аля у нас тут куча кода от разных разработчиков, где вроде все работает, но что-то поменять, исправить баг очень сложно, приходиться не пересмотреть весь код, и его хотя бы немного подготовить. Проверка такого кода и его связанности (особенно если есть приложения для моб. телефонов, партнерские програмы и т.д) вызавает большие трудности и занимает много времени.

Я остановился на том что проще каждый месяц отъедать от работающего сайта по модулю, и переписывать его на фреймворке, покрывая тестами. + Пихать в SESSION\COOKIE данные которые необходимые для модулей на старой системе.
Не понятно зачем подключать ClassLoader при использовании Composer, который внутри себя несет автолоад по psr-0 и классмап.
Тоже переписываю сейчас код, где есть куски из 90-х. Забавно читать однострочники на ~1000 символов, где и и onclick="..." и style="..." внутри html. Брр-р, дрожь по коже.

Так вот у меня есть убежденность: никакой фреймворк не решит проблем роста проекта. Фреймворк только помогает быстро стартануть. И скорее всего у вас появится свой фреймворк с нужной конкретно вам моделью компонентности, и который решает конкретно ваши задачи.
А вот в симфони можно подсматривать, да.
Sign up to leave a comment.

Articles

Change theme settings