Задать вопрос
  • Зачем задавать приватный модификатор доступа для свойств класса?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    У вас очень логичный вопрос на счет сеттера: сеттер полностью уничтожает задумку с инкапсуляцией. Правильно это называется "семантическое нарушение инкапсуляции" — то есть как-бы мы инкапсулировали, но по факту назад открыли прямую запись в свойство напрямую. Все доводы "ну мы можем в сеттере валидировать" не корректны

    Правильным способом будет не использовать сеттеры. Вот моя статья на эту тему:
    https://habr.com/ru/post/469323/

    Более подробно: каждый класс нужно проектирвовать так, чтобы данные внутри были максимально связаны. Например каждый метод работать должен в хорошем случае с максимальным числом полей класса, тогда у него высокий cohesion... В тоже время снаружи наужно работать с максимальн омалым числом метода, тогда будет низкая связанность (coupling). Это пара принципов из GRASP.
    Когда вы делаете сеттеры и геттеры, то у вас данные внутри между собой почти никак не взаимодействут: с геттером работают снаружи, с сеттером работаю снаружи — весь класс нараспашку, а в нем в 100% случаев появляются данные, которые вместе не должны находиться и никак не связаны — анрушена и абстракция и инвариант и много чего еще...

    Про инвариант отдельно: например есть платеж, у него есть значение, с которым платеж инициирвоан (initValue), есть значение холда (holdAmount) и есть значение чарджа на списание (chargeAmount)
    Когда вы работаете с платежом, контролируя ивнариант в самом классе, то ваш каждый метод првоеряет др значения и позволяет перейти к др состоянию... методов будет 2-3, все инкапсулировано и безопасно.

    Например:
    class Payment {
         pub func charge(amount int) void {
              if (this.holdAmount < amount && this.initAmount < amount) {
                   throw new PaymentException('Unavailable charge amount')
              }
    
               if (this.status === PaymentStatus:finish) {
                   throw new PaymentException('Payment already fisnished')
              }
    
              this.chargeAmount = amount
              this.holdAmount -= amount
              this.status = PaymentStatus:finish
         }
    }


    Тут в одном методе полные проверки и класс сам контролирует все состояние внутри, также соблюдается закон Деметры. У даннго кода высокий cohesion (из GRASP), тк внутри идет плотная работа с внутр данными (значит они корректно тут закроекны) и низкий coupling ( с теми данными для данного кейса только один метод работы, все внутри)

    Когда вы раскроете сеттерами и геттерами, то ваше состояние становится непредсказуемо и полагается только на то, что снаружи точно подумали об инварианте (нет)
    Ответ написан
    18 комментариев
  • Зачем задавать приватный модификатор доступа для свойств класса?

    Adamos
    @Adamos
    class VeryOpenOne
    {
    public $property;
    }
    $voo = new VeryOpenOne();
    $name = 'pro' . 'perty';
    $voo->$name = 'Пытаясь отрефакторить тот класс, ' .
      'ты хрен найдешь, что в этой строчке меняется эта переменная. ' .
      'Никакое самое умное IDE не поможет';
    Ответ написан
    1 комментарий
  • Как создать локальную базу данных?

    Adamos
    @Adamos
    файл с расширение .db

    Это, скорее всего, база SQLite.
    Ответ написан
    Комментировать
  • Как создать локальную базу данных?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    На mysql не создают такой файл.
    Mysql - это отдельная программа, которая хранит данные в своих собственных файлах.
    "Создавать" её не надо. На хостинге она уже есть, дома она обычно тоже уже есть, в составе какого-нибудь набора - XAMPP, MAMP и пр.
    Если никаких наборов нет, то скачать и установить Mysql с офсайта.

    После этого вся работа с БД будет производиться через SQL.
    Лучше это делать через нормальный клиент, типа PHPStorm, Workbench и так далее. В крайнем случае - phpmyadmin, но это конечно очень уродливая программа.
    Настроить программу на соединение с сервером БД и выполнять в нем команды SQL.
    Например, создать database - это типа такой каталог, в котором лежат таблицы - CREATE DATABASE mydb;
    И вот это mydb потом указывать в параметрах подключения PDO.
    Ответ написан
    Комментировать
  • Возможно ли получить данные со второй html странички с помощью одного js скрипта?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    HTML предназначен для отображения данных, не для хранения.

    Хранить данные можно, например в json формате. Структуру можно прописать прямо на странице в теге script, или подгружать аяксом внешний json файл.
    Ответ написан
    2 комментария
  • На каком движке работает сайт? Как сделать такой же?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Такой сайт можно сделать на любом движке. Для этого достаточно знать основы вёрстки и уметь кликать мышкой в админке любой CMS.
    Ответ написан
    Комментировать
  • Дают ли выигрыш ссылки на элементы массива и на поля объектов в PHP?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    С точки зрения памяти не даёт, потому что в РНР и так очень оптимальное управление памятью.
    В частности, при присвоении значений переменным применяется принцип copy-on-write. Объекты же и так всегда копируются по ссылке.

    С точки зрения "вычислять адрес промежуточного объекта" - я никогда не слышал о таких проблемах. Судя по всему, это явно не является узким местом для динамически интерпретируемого языка.
    В любом случае, учитывая copy-on-write, исходно это снова будет опять ссылка.

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

    0xD34F
    @0xD34F Куратор тега JavaScript
    После кого надо удалить элементы: const selector = '#point';.

    Удаляем:

    const elem = document.querySelector(selector);
    const parent = elem?.parentNode;
    const elems = [...parent?.children ?? []];
    const index = elems.indexOf(elem);
    elems.slice(-~index || elems.length).forEach(n => parent.removeChild(n));
    
    // или
    
    for (
      const el = document.querySelector(selector);
      el?.nextElementSibling;
      el.nextElementSibling.remove()
    ) ;
    
    // или
    
    document.querySelectorAll(`${selector} ~ *`).forEach(n => n.outerHTML = '');
    Ответ написан
    Комментировать
  • Как сделать рандомный цвет фона при наведении для каждого элемента?

    0xD34F
    @0xD34F Куратор тега JavaScript
    По событию mouseover перезаписывайте css-переменную, отвечающую за цвет:

    document.querySelector('.shopWrapper').addEventListener('mouseover', function() {
      const color = `#${Math.random().toString(16).slice(2, 8).padEnd(6, 0)}`;
      this.style.setProperty('--random-color', color);
    });
    Ответ написан
    1 комментарий
  • Как произвести сравнение и вывести результаты сравнения объектов в массиве?

    0xD34F
    @0xD34F Куратор тега JavaScript
    arr.map(n => {
      const ids = Object
        .values(n.childrenHash.reduce((acc, m) => ((acc[m.hash] ??= []).push(m.id), acc), {}))
        .filter(m => m.length > 1);
    
      return {
        ...n,
        childrenHash: ids.length ? ids : null,
      };
    })
    Ответ написан
    5 комментариев
  • Как изменять нумерацию div при добавлении и удалении?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Перестаньте заниматься ерундой и замените div'ы на ol + li.

    Ну или хотя бы через css сделайте.
    #itemInner {
      counter-reset: bullshit-counter;
    }
    .row {
      counter-increment: bullshit-counter;
    }
    .row::before {
      content: counter(bullshit-counter) "!!!";
    }

    А если всё-таки намерены продолжать говнокодить, то...
    ...долой счётчик itemLength, устанавливайте значения заново после каждой вставки/удаления:

    itemInner.find('.item-num').text(i => i + 1);
    Ответ написан
  • Можно ли через регулярные выражения вставить в текст символ?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Регулярные выражения не нужны:

    const insert = (str, substr, ...indices) => [ 0 ]
      .concat(indices)
      .filter(n => 0 <= n && n <= str.length)
      .sort((a, b) => a - b)
      .map((n, i, a) => str.slice(n, a[i + 1]))
      .join(substr);
    
    // или
    
    const insert = (str, substr, ...indices) => indices
      .sort((a, b) => b - a)
      .reduce((acc, n) => (
        0 <= n && n <= str.length && acc.splice(n, 0, substr),
        acc
      ), [...str])
      .join('');
    
    // или
    
    const insert = (str, substr, ...indices) =>
      ''.concat(...Array.from(
        { length: -~str.length },
        function(_, i) {
          return substr.repeat(this[i] ?? 0) + str.charAt(i);
        },
        indices.reduce((acc, n) => (acc[n] = -~acc[n], acc), {})
      ));

    Но, конечно, можно и с ними:

    const insert = (str, substr, ...indices) => indices
      .filter(n => 0 <= n && n <= str.length)
      .sort((a, b) => a - b)
      .reduce((acc, n, i) =>
        acc.replace(RegExp(`(?<=^.{${n + i * substr.length}})`), substr)
      , str);

    Как использовать:

    // ваш случай
    const str = insert(`${number}`, '-', 3, 5, 8, 10);
    
    // вставлять можно больше одного символа
    insert('abc', ' --> ', 1, 2) // 'a --> b --> c'
    
    // можно по одному индексу несколько раз делать вставку
    insert('abc', '~', 0, 0, 0) // '~~~abc'
    
    // за границы строки вставка не выполняется,
    // за исключением позиции сразу же после конца строки
    insert('abc', '!', -1, 3, 4) // 'abc!'
    Ответ написан
    Комментировать
  • Как практиковать ООП?

    AgentSmith
    @AgentSmith
    Это мой правильный ответ на твой вопрос
    Только опыт и практика.
    Пиши как можно больше.
    Со временем будешь понимать, что год назад ты писал плохо и можно переписать намного лучше с применением ООП и шаблонов проектирования, которые освоил.
    Других советов нет.
    Никаких курсов и уроков.
    Ответ написан
    1 комментарий
  • Как сделать изменение цвета текста при скролле?

    RAX7
    @RAX7
    Ответ написан
    Комментировать
  • Стоит ли адаптировать сайт под IE 10 в 2022-м году?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Под такие верстать, которые клиент заказывает.
    Ответ написан
    Комментировать
  • Зачем нужна инкапсуляция в ООП?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Попробуйте учебники читать, а не видео смотреть. Все принципы ООП, сам ООП и другие парадигмы, а также шаблоны проектирования существуют для управления сложностью. Понять всё это проще всего тогда, когда столкнулся с десятилетнем легаси в проекте с большой командной.
    Ответ написан
    Комментировать
  • Зачем нужна инкапсуляция в ООП?

    DollyPapper
    @DollyPapper
    Инкапсуляция вообще является (ИМХО) главным принципом из 4. Инкапсуляция + абстракция. Вы не поняли её основную идею. Инкапсуляция это объдинение в одной сущности данных (не обязательно в общем-то) и действий которая эта сущность может предоставить. Инкапсуляция + абстракция представляю собой в общем более общий принцип - сокрытие информации/сложности, и один без другого не сильно то полезен. Не путать с модификаторами доступа (public, private и тд). Этот принцип идет скрозь всю историю развития языков программирования и собственно является главной движущей силой их развития. Вот пример из реальной жизни: есть у вас микроволновка. Она имеет +- 2 нопки: выставить время, выставить мощность. Это интерфейс микроволновки, который доступен конечному пользователю. Всё что вам нужно знать, чтобы приготовить себе похавать - 1)на какой мощности это хавать, нужно готовить 2) сколько это нужно делать по времени. При этом очевидно внутри микроволновки происходит та самая сложность, микросхемы гоняют электрический ток, магнетрон изучает электромагнитные волны, всякая разная физика происходит и вот это вот всё. Итого: вся эти физика и электротехника инкапсулирована в объект микроволновки (инкапсулирована так, что мы не можем добраться до её внутреннего устройства, это важно. Т.е. мы не можем сами соединить проводки, поменять электрическую цель, чтобы себе похавать сделать, разработчик этой электропечки не дал нам даже потенциальную возможность это сделать легально. Можно конечно разобрать устройство и проделать все эти манипуляции, но это уже это на совести того самоделкина, кто это делает). Итого: мы имеем интерфейс из двух кнопок и получаем от обьекта микроволновки услугу - приготовить пожрать. Как там внутри это реализовано, нам не важно. Это и есть инкапсуляция + абстракция = сокрытие информации/сложности.
    Более программистский пример: есть такая структура данных - Стек. Хотя по факту это не структура данных, а абстрактный тип данных. Советую этот термин загуглить, это важная составляющая в понимании ООП.
    Представим, что стек это такой обьект который предоставляет услуги, по типу как мы представляли себе обьект микроволновки. Что нам нужно знать про стек, чтобы им пользоваться? Публичный интерфейс. Т.е. есть класс Stack с публичными методами push(), pop(), viewTopStack() (посмотреть первый элемент стека, без его удаление из самого стека). Всё, можно пользоваться. Как он внутри эти элементы хранит, простой ли это массив, или связный список, на сколько эффективно он там внутри работает - нам не важно. Это важно тому, кто предоставил нам в пользование данный класс. Мы знаем, что вызвав viewTopStack мы посмотрим первый элемент стека, вызвав push - положим что-то в стек, вызвав pop получим первый элемент, удалив его из стека (по аналогии: мы знаем что чтобы притоговить пожрать, нужно выставить в микроволновке время и мощность, на выходе получив наше адово хрючево). Если подытожить - инкапсуляци + абстракция, (еще раз настою на том, что порознь их нельзя рассматривать, это две тесно связанные концепции которые имеют практический смысл только в синергии) это механизм борьбы со сложностью, не только в программировании, вообще везде, в любой человеческой деятельности. В этом их смысл. Если ваши абстракции плохие -> ваш код сложный -> ваш код плохой (говнокодом его еще называют в сообществе программистов).
    Почитать на эту тему можно следующее: Р.Мартин - Чистая архитектура (начать с глав про SOLID прицнипы), С.Макконел - Совершенный код (главу про классы обязательно, остальное желательно (очень желательно)), там в общем-то вам расскажут то что я вам сейчас рассказал, только более подробно, по больше примеров и дадут обоснование сложности, назвав борьбу с ней - Главным техническим императивом. Шлифануть это книгой банды четырех. Сами паттерны не обязательно начинать учить (да и рано вам еще), но вот введение и часть про программирование на основе интерфейса, а не реализации - самое оно, это дополнит картину.

    UPD: тот факт, что мы в классе стек собрали его функционал (функции pop,push,...) обьединенные одной общей темой и есть факт инкапсуляции.
    Ответ написан
    Комментировать
  • Почему тут TypeError у map?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    А зачем там str и что вы имели ввиду, написав это?
    Просто уберите.

    function camelize(str) {
        return str
            .split('-')
            .map(function(word, index) {
                if (index == 0) {
                    return word;
                } else {
                    return word[0].toUpperCase() + word.slice(1);
                }
            })
            .join('')
    }
    
    let str = prompt('Введите текст через дефис');
    alert(camelize(str));


    Можно и покороче

    function camelize(str) {
        return str
            .split('-')
            .map((word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1))
            .join('')
    }
    
    let str = prompt('Введите текст через дефис');
    alert(camelize(str));


    const upper = (word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1);
    function camelize(str) {
        return str
            .split('-')
            .map(upper)
            .join('')
    }
    
    let str = prompt('Введите текст через дефис');
    alert(camelize(str));


    const upper = (word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1);
    const camelize = str => str.split('-').map(upper).join('');
    
    let str = prompt('Введите текст через дефис');
    alert(camelize(str));
    Ответ написан
    1 комментарий
  • Почему тут TypeError у map?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    alert(camelize(str));
    надо же передать аргумент в функцию..

    и зачем тут .str в .str.join('') – уберите, оставьте только .join('')
    Ответ написан
    Комментировать
  • Стоит ли адаптировать сайт под IE 10 в 2022-м году?

    bingo347
    @bingo347
    Crazy on performance...
    С 15 июня IE в принципе больше не работает, можно не поддерживать.
    Safari как был болью похлеще IE, так ей и остается.
    А так подавляющее большинство браузеров сегодня основаны на Chromium, ну и Firefox еще есть немного.
    Ответ написан
    Комментировать