• Как не пускать на сайт при включенном adblock/ublock и прочее?

    @d-stream
    Готовые решения - не подаю, но...
    Большая часть пользователей адблокеров просто тут же покидает сайты-попрошайки, если их попрошайничество хоть как-то мешает. Бывают конечно редкие сайты-исключения, на которых блокировщики отключают.
    Но чтобы этого добиться - надо быть ресурсом типа хабра или Майкрософта.
    Ответ написан
    14 комментариев
  • Как можно использовать ненужный Intel Celeron?

    RadiationX
    @RadiationX
    Front-End разработчик
    1.Брутальный IT брелок из процессор.
    2.Поставить на него железную банку(от кофе например), включить компьютер и поставить на какой-нибудь стресс-тест. Т.е использовать как кипятильник для воды.
    3.Сделать какой-нибудь сервер. Допустим домашнее файловое хранилищи, веб-сервер и т.д и т.п
    4.Отдать нуждающимся.
    5.Опять-же сделать какой-нибудь сервер, найти школоту, которая будет платить какие-нибудь деньги за "аренду" сервера.
    Ответ написан
    Комментировать
  • Как работает подход Unit of Work?

    @Flying
    Unit of Work - это паттерн определяющий логическую транзакцию т.е. атомарную синхронизацию изменений в объектах, помещённых в объект UoW с хранилищем (базой данных).

    Если обратиться к исходному описанию этого паттерна у Мартина Фаулера - то видно что объект, реализующий этот паттерн отвечает за накопление информации о том какие объекты входят в транзакцию и каковы их изменния относительно исходных значений в хранилище. Основная работа производится в методе commit() который отвечает за вычисление изменений в сохранённых в UoW объектах и синхронизацию этих изменений с хранилищем (базой данных).

    Паттерн Unit of Work как правило не является полностью самостоятельным, он обычно тесно связан с паттерном Identity Map, задача которого - сохранение карты созданных объектов, взятых из хранилища с тем чтобы гарантировать что одна единица информации из хранилища представлена ровно одним экземпляром объекта данных в приложении. Это позволяет избежать конфликтов изменений т.к. не допускает ситуации когда два объекта, представляющих один и тот же элемент данных в хранилище, изменены по-разному. Информация из Identity Map используется в методе commit() паттерна Unit of Work для вычисления разницы между исходными данными и накопленными изменениями.

    Поскольку для вычисления разницы (и, соответственно, определения того что и каким образом должно быть изменено в хранилище) необходимо знать какие данные и как именно хранятся в объектах - как правило необходима также реализация паттерна Metadata Mapping, описывающего связь между содержимым хранилища (к примеру таблицами и столбцами базы данных) и классами / свойствами объектов.

    Также, если данные в хранилище не являются независимыми (к примеру связи между таблицами в базе данных) - может потребоваться реализации ряда паттернов, отвечающих за сохранение информации о связях между данными (это паттерны раздела Object-Relational Structural Patterns в каталоге паттернов).

    Подводя итог: сам по себе Unit of Work довольно прост в своём внешнем интерфейсе, но реализация его корректной работы требует предоставления множества дополнительных данных, поэтому миниатюрных примеров привести не могу.

    Если говорить о PHP - то лучшей реализацией этих паттернов на PHP безусловно является Doctrine ORM. В частности в разделе Working with Objects документации Doctrine можно найти хорошее описание и множество примеров использования паттернов, описанных выше.
    Ответ написан
    6 комментариев
  • Как работает подход Unit of Work?

    voronkovich
    @voronkovich
    Попробую привести очень примитивный пример. Допустим, мы делаем простое приложение для микроблоггинга. Каждая сущность будет иметь вид:

    class Tweet
    {
        private $id;
        private $content;
    
        public function __construct(int $id, string $content)
        {
            $this->id = $id;
            $this->content = $content;
        }
    
        public function getId(): int
        {
            return $this->id;
        }
    
        public function getContent(): string
        {
            return $this->content;
        }
    
        public function setContent(string $content): void
        {
            $this->content = $content;
        }
    }


    Схема данных:

    CREATE TABLE tweets (
        id INTEGER PRIMARY KEY,
        content VARCHAR(255) NOT NULL
    )


    Следующая реализация UnitOfWork будет иметь несколько ограничений:
    1. Она умеет работать только с Tweet;
    2. Она умеет только загружать сущности и сохранять произведённые в них изменения.
    class UnitOfWork
    {
        private $connection;
        private $identityMap;
        private $data;
    
        public function __construct(\PDO $connection)
        {
            $this->connection = $connection;
            $this->identityMap = [];
            $this->data = [];
        }
    
        public function find(int $id): Tweet
        {
            if (isset($this->identityMap[$id])) {
                return $this->identityMap[$id];
            }
    
            $query = $this->connection->prepare('SELECT * FROM tweets WHERE id = ?');
            $query->execute([ $id ]);
    
            if (false === $data = $query->fetch()) {
                throw new \Exception(\sprintf('Tweet with id "%d" not found.', $id));
            }
    
            $id = (int) $data['id'];
    
            // Исходные данные сохраняются для того, чтобы в дальнейшем вычислить изменения.
            $this->data[$id] = $data;
    
            $tweet = new Tweet($id, $data['content']);
    
            $this->identityMap[$id] = $tweet;
    
            return $tweet;
        }
    
        public function commit(): void
        {
            // Вообще говоря, лучше вычислить все изиенения, создать один "большой" запрос
            // и выполнить его внутри транзакции, но для простоты мы сделаем для каждого
            // изменения отдельный запрос
            $query = $this->connection->prepare('UPDATE tweets SET content = ? WHERE id = ?');
            foreach ($this->identityMap as $tweet) {
                if ($tweet->getContent() !== $this->data[$tweet->getId()]['content']) {
                    $query->execute([ $tweet->getContent(), $tweet->getId() ]);
                }
            }
        }
    }


    Полный пример можете скачить и посмотреть тут: https://gist.github.com/voronkovich/d35cdcdf6eb09e...
    Ответ написан
    1 комментарий
  • Имеет ли смысл собирать мощную рабочую станцию на 771 сокете из б/у комплектующих?

    optemist
    @optemist
    1. 64-х битную семерку запустить сможете, в крайнем случае Server 2008. Про МакОсь не скажу, не знаю, но вроде были Маки Про на ксеонах, так что сможете попробовать прикрутить хакинтош.

    2. В перещете на мощность пока выиграете, а потом проиграете на возможности апгрейда. Хотя тут еще и скорость памяти может подпортить ситуацию.

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

    4. Но для фана, я бы сам с удовольствием собрал такую железку! :)
    Ответ написан
    5 комментариев
  • PUT & POST при написании API

    MrMig
    @MrMig
    PUT должен быть идемпотентной операцией, т.е. несколько одинаковых последовательных пут-запросов на один урл (и с одинаковыми параметрами) не должны создавать новых объектов.

    POST, в свою очередь, может создавать новые объекты при последовательных запросах на один урл.
    Другими словами, POST нужно использовать для обращения к «производящим фабрикам».

    Первая подручная статья, в которой это объясняется: на английском.

    И да, PUT можно сравнить с INSERT… OM DUPLICATE KEY UPDATE.
    POST — это чистый INSERT.
    Ответ написан
    1 комментарий
  • Что такое ElasticSearch?

    AlexXYZ
    @AlexXYZ
    O Keep Clear O
    Знаете, я с вами соглашусь, что хорошую вводную по Elastic трудно найти. Пока сам не переварил доков и не набил шишек многие элементарные понятия оставались для меня неясными. Поэтому вот моя вводная: Elastic можно использовать как NoSQL БД, только надо быть внимательным, т.к. всё-таки его основная задача поиск, а не удовлетворение функций БД. Например, если вы не настроили хранение исходных данных, а только индексацию, то свои данные вы уже не извлечёте из него. НИКОГДА. Только отдельные выражения, удовлетворяющие условиям поиска. Всё, тупик. Так же нельзя повторно индексировать уже загнанные в него данные. Т.е. перед загрузкой данных надо грамотно настроить индексацию, т.к. перестроить индекс, как это делается в реляционной БД невозможно. Нужно придумать новую схему индексации и перезалить данные в Elastic. Именно поэтому основное использование Elastic - как дополнение к существующей БД из которой данные можно перезалить по одному или полностью в Elastic (можно, конечно сделать схему Elastic->Elastic, но тоже есть нюансы).
    Ещё пару слов про схему. Это ЛОЖЬ, что в Elastic нет схемы данных. Она как раз есть и ооочень жёсткая. Жёсткая до того, что однажды определив, вы не сможете её поменять. Изначально Elastic оказывает медвежью услугу, разрешая вам дополнять схему по-умолчанию, но когда вы разберётесь с этой темой, то можете обнаружить, что Elastic "понастроил" такого у себя внутри, что остаётся только охреневать и переделывать всё явно, отказавшись от его "услуг" по автоматическому добавлению полей в схему.
    Так же в Elastic очень непросто строить сложные запросы на поиск и агрегатные запросы. Совершенно неинтуитивно. Но если освоитесь, то будет вам счастье. )))
    Несмотря за такие "страшные" вещи - Elastic классная система и по производительности агрегатных запросов не уступает платной версии MSSQL в поиске в многопроцессорных системах (проверял на одинаковых аппаратных конфигурациях с 16 ядрами). Так что если вам хочется большую скорость в агрегатных запросах и главное - это бесплатность, то берите и осваивайте Elastic. Мощности и возможности у него огромные. Но... нужно потратить приличные усилия на изучение.
    Ответ написан
    1 комментарий
  • Что нужно уметь, чтобы я справедливо мог вписать git в резюме?

    bask
    @bask
    Этого достаточно.
    Но придерживаться Git Flow крайне рекомендую.
    Здесь простым языком и по-русски:
    https://proglib.io/p/git-github-gitflow/
    Ответ написан
    1 комментарий
  • Как правильно тестировать api?

    В данном случае я обычно использую тестовую sqlite in memory базу, в phpunit.xml добавив:

    <env name="DB_CONNECTION" value="sqlite"/>
    <env name="DB_DATABASE" value=":memory:"/>


    После в тесте всегда сбрасывать и накатывать данные в БД при каждом запуске:

    use RefreshDatabase;

    Дальше используя фабрики создаем записи в тестовой БД. Как пример:

    $task = factory(\App\Task::class)->create([
         'archive' => false
    ]);


    Отправляем запрос на наш URL (у Вас это будет /api/post). Опять таки для примера:

    $response = $this->get('/current_tasks');

    И в результате проверяем нужные данные, например, что ответ от сервера пришел со статусом 200 и что результатом должен быть ответ в формате JSON и именно те данные, которые мы ранее поместили в тестовую БД:

    $response->assertStatus(200)
              ->assertJson([$task->toArray()]);


    Здесь подробнее посмотрите про все ассерты: https://laravel.com/docs/5.6/http-tests
    Ответ написан
    5 комментариев
  • Хороший пример структурированного CSS файла?

    delphinpro
    @delphinpro Куратор тега CSS
    frontend developer
    Вот реальный файл
    /*!
     * Main styles
     *
     * @author     delphinpro <delphinpro@gmail.com>
     * @copyright  copyright © 2018 delphinpro
     * @license    licensed under the MIT license
     */
    //==
    //== Config & mixins
    //== ======================================= ==//
    $DEV_MODE: true;
    @import "vrhythm.cfg.scss";
    @import "grid.cfg.scss";
    @import "../../node_modules/bs-grid-system/source/scss/bs-grid";
    @import "../../node_modules/vrhythm/source/mixins/rhythm";
    @import "main.cfg.scss";
    @import "mixins.scss";
    @import "../../node_modules/tiny-slider/src/tiny-slider";
    //==
    //== Global styles
    //== ======================================= ==//
    @import "webfonts.scss";
    @import "vendor/normalize";
    @import "base/global.scss";
    @import "base/grid-system.scss";
    @import "base/page.scss";
    @import "base/site.scss";
    @import "base/table.scss";
    @import "base/input.scss";
    @import "base/uploadbox.scss";
    @import "base/buttons.scss";
    @import "base/checkbox.scss";
    @import "base/radio.scss";
    @import "base/radio-button.scss";
    @import "base/radio-panel.scss";
    @import "base/controls-group.scss";
    @import "base/form-field.scss";
    @import "base/auto-height.scss";
    @import "base/transitions.scss";
    //==
    //== Blocks
    //== ======================================= ==//
    @import "blocks/availability.scss";
    @import "blocks/availability-details.scss";
    @import "blocks/back-link.scss";
    @import "blocks/benefit-block.scss";
    @import "blocks/block-heading.scss";
    @import "blocks/breadcrumb.scss";
    @import "blocks/btn-close.scss";
    @import "blocks/callback-link.scss";
    @import "blocks/checked-list.scss";
    @import "blocks/ci.scss";
    @import "blocks/clear-link.scss";
    @import "blocks/document-list.scss";
    @import "blocks/download-link.scss";
    @import "blocks/email-link.scss";
    @import "blocks/entry-item.scss";
    @import "blocks/expert-consult.scss";
    @import "blocks/goods-attributes.scss";
    @import "blocks/heading.scss";
    @import "blocks/icons.scss";
    @import "blocks/info-text.scss";
    @import "blocks/logo.scss";
    @import "blocks/paginate.scss";
    @import "blocks/phone-link.scss";
    @import "blocks/phone-with-icon.scss";
    @import "blocks/phone.scss";
    @import "blocks/popular-links.scss";
    @import "blocks/price.scss";
    @import "blocks/print-link.scss";
    @import "blocks/section.scss";
    @import "blocks/service-description.scss";
    @import "blocks/services.scss";
    @import "blocks/share-block.scss";
    @import "blocks/show-all.scss";
    @import "blocks/smenu-box.scss";
    @import "blocks/smenu.scss";
    @import "blocks/tags.scss";
    @import "blocks/unordered-list.scss";
    @import "blocks/worktime.scss";
    @import "blocks/zoom.scss";
    //==
    //== Blocks
    //== ======================================= ==//
    @import "blocks/about-us-section.scss";
    @import "blocks/article-section.scss";
    @import "blocks/benefits.scss";
    @import "blocks/carousel.scss";
    @import "blocks/cart.scss";
    @import "blocks/delivery-map.scss";
    @import "blocks/delivery-partners.scss";
    @import "blocks/delivery.scss";
    @import "blocks/footer.scss";
    @import "blocks/header.scss";
    @import "blocks/help-me.scss";
    @import "blocks/load-more.scss";
    @import "blocks/nav-catalog.scss";
    @import "blocks/nav.scss";
    @import "blocks/navbar.scss";
    @import "blocks/news-section.scss";
    @import "blocks/panel.scss";
    @import "blocks/params-panel.scss";
    @import "blocks/payment-block.scss";
    @import "blocks/search.scss";
    @import "blocks/catalog-table.scss";
    @import "blocks/catalog-grid.scss";
    @import "blocks/time-range.scss";
    //==
    //== Components
    //== ======================================= ==//
    @import "components/spin.scss";
    @import "components/selector.scss";
    @import "components/tabs.scss";
    @import "components/hamburger.scss";
    @import "components/fixed-bar.scss";
    @import "components/step-indicator.scss";
    @import "components/complete-screen.scss";
    @import "components/ordering.scss";
    @import "components/order-complete.scss";
    @import "components/summary.scss";
    @import "components/goods.scss";
    @import "components/basket-contains.scss";
    @import "components/basket-goods.scss";
    @import "components/basket.scss";
    @import "components/icon-complete.scss";
    @import "components/big-order-form.scss";
    @import "components/feedback-form.scss";
    @import "components/modal.scss";
    @import "components/vue-scrollbar.scss";
    @import "components/mobile-menu.scss";
    @import "components/gallery.scss";
    //==
    //== Page specific classes
    //== ======================================= ==//
    @import "pages/home.scss";
    @import "pages/articles.scss";
    @import "pages/catalog.scss";
    @import "pages/product.scss";
    @import "pages/terms.scss";
    @import "pages/services.scss";
    @import "pages/news.scss";
    @import "pages/feedback.scss";
    @import "pages/page404.scss";
    //==
    //== Helpers & other classes
    //== ======================================= ==//
    @import "base/helpers.scss";
    @import "base/printer.scss";
    Ответ написан
    5 комментариев
  • И все-таки PHP 7 быстрее Python 3?

    Да, быстрее. Он быстрее даже HHVM (пусть и ненамного). Вдумайтесь - интерпретируемый (пусть и из байт-кода) язык быстрее компилируемого! Воистину, PHP Team состоит из гениев чуть менее, чем полностью.

    Язык, за которым будущее всего www.
    Ответ написан
    2 комментария
  • Как пробросить USB порт в VirtualBox (Windows 7)?

    maashina
    @maashina Автор вопроса
    Короче сам я разобрался. Сначала необходимо определить номер порта в которую подключаете флешку (с помощью какой-нибудь проги). Потом просто создаете фильтр в виртуалбоксе с необходимым портом.
    Ответ написан
    1 комментарий
  • Структура проекта на React?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    В components/header + вложенность, все как вы описали в вопросе.

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

    так же разные подходы по организации были у людей, выполнивших второе тестовое задание (видео и текст). В комментах у видео есть репозитории, можете ознакомиться.
    Ответ написан
    Комментировать
  • PHP ORM для бизнес приложений?

    artemylapko
    @artemylapko
    Symfony, Doctrine developer. Немного js и python.
    Doctrine. Возможно в начале будет не очень легко, нужно только выбросить из головы всякие active record и т.д. Но когда вникнешь в суть, уйти от доктрины не сможешь.
    Ответ написан
    6 комментариев
  • Какие файлы и папки WordPress можно отправить на GitHub?

    Olek1
    @Olek1
    Файлы в которых хранятся пароли в открытом виде, пути и т.д.
    Кэш какойто и тому подобное
    Скачайте гдето найдите gitignore файл для вордпресса и почитайте его откройте в блокноте
    Ответ написан
    3 комментария
  • Минификация php?

    402d
    @402d
    начинал с бейсика на УКНЦ в 1988
    А что мешает попробовать? 10 строк кода рекурсивного обхода папок проекта. Вот только результат будет незначительным или вообще отрицательный. По памяти точно хуже.
    Ответ написан
    1 комментарий
  • Минификация php?

    latteo
    @latteo
    На митапе по magento 2, core разработчик фреймворка говорил, что медленная скорость исполнения это плата за гибкость и кучу абстрактных слоев. А самый лучший подход по ускорению - это full page cache и Varnish.

    Пол года назад, когда мне довелось поработать с этим фреймворком, я собрал самые замечательные глюки с производительностью. К примеру mega menu, который пихают во многие темы, увеличивал FTTB в 2 раза даже если он не используется, но прописан в di. Индус, который работал с апи mega menu, замедлил еще почти в 2 раза.
    Вкл какого-то вида минификации в глубинах админки, тоже давало почти двойное замедление. Но вроде бы уже пофиксили.
    Вкл/выкл настроек в админке через раз приводило сайт в нерабочий вид, с необходимостью сделать rm файлов кеша через консоль и запуск еще нескольких консольных команд magento.

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

    В общем, ваш вопрос интересен с точки зрения исследователя, но бесполезен в контексте реального ускорения сайта.
    Ответ написан
    1 комментарий
  • Закон Деметры. Нужен ли?

    ConConovalofff
    @ConConovalofff
    Сегодня прочитал об этом законе и сделал для себя следующие выводы:

    Закон не нацелен на улучшение читаемости или эстетичности кода. Наоборот, красота кода теряется, а структура класса обрастает проксирующими функциями-пустышками, портя читаемость класса.

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

    К примеру, представим 2 разные ситуации:
    1. В проекте игнорируется закон Деметры. Класс b включен в классы a, c и d. Каждый класс инстанцируется в разных участках кода по 10 раз каждый и применяется a.b.Method(), c.b.Method() и d.b.Method()
    2. В проекте применяется закон Деметры. Класс b включен в классы a, c и d. Каждый класс инстанцируется в разных участках кода по 10 раз каждый и применяется a.Method(), c.Method() и d.Method()

    При замене класса 'b' на класс 'z':
    В 1-ом случае нам придется изменить код в 30 местах где используется a.b.Method().
    Во 2-ом случае нам потребуется изменить код в 3-ех методах классов a, c и d.

    Следуя этому правилу, я думаю будет логичен следующий код:
    $user = new User('Paul')
    $comments = $user->getCommentsOfLastPost()


    В классе User:
    function getCommentsOfLastPost()
    {
        $posts = new Posts()
        $posts->getCommentsOfLastPostUser($this)
    }

    и т.д.

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

    Я уловил суть?
    Ответ написан
    1 комментарий
  • Закон Деметры. Нужен ли?

    everzet
    @everzet
    Допустим вы хотите купить молоко:

    дом->лестница->машина_Opel->магазин->кассир_Люба->купить_молоко();

    Так как вы уважающий себя software developer который не видит смысла в законе Деметры, вы это скорее всего напишете в 10 разных местах системы.

    2 недели назад вы продали свой Opel и купили BMW. Вы теперь должны в 10 разных местах поменять код на:

    дом->лестница->машина_BMW->магазин->кассир_Люба->купить_молоко();

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

    дом->лестница->велосипед->магазин->кассир_Люба->купить_молоко();

    Через пару дней Любу уволили и на работу взяли нового кассира Клаву? Меняем в 10 разных местах код на:

    дом->лестница->велосипед->магазин->кассир_Клава->купить_молоко();

    Через другую пару дней в вашем доме поставили лифт и вы не хотите бегать по лестнице за молоком? Меняем в 10 разных местах код на:

    дом->лифт->велосипед->магазин->кассир_Клава->купить_молоко();

    Мораль: этих всех замен можно мыло бы избежать, если бы для покупки молока вы использовали абстракцию:

    магазин->купить_молоко();
    Ответ написан
    8 комментариев
  • Чем обусловленна высокая стоимость книг проф направленности в электронном виде?

    klen
    @klen
    Ммм, в капиталистическом обществе цена товара не определяется трудозатратами и себестоимостью, а лишь исключительно спросом и коньюктурой рынка. Она стоит 250 рублей потому, что ее покупают за 250 рублей. Перестанут покупать, цены упадут.
    Ответ написан
    1 комментарий