Задать вопрос
  • Для чего нужны Map и Set?

    Окей гугл, что такое "структуры данных".

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

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

    А при помощи Set ты можешь получить массив без повторов, и при этом без необходимости при каждой вставке проверять, есть ли такой элемент в массиве, или нет.
    Ответ написан
    Комментировать
  • Как в 2022 году проверяют верстку в Safari и Safari Mobile, если нет мака и нет айфона?

    Get-Web
    @Get-Web
    Front-End Developer
    На виртуальную машину VMware или VirtualBox ставишь MacOS и там с настоящего браузера Safari дебажишь без особых проблем.
    Ответ написан
    2 комментария
  • Как в 2022 году проверяют верстку в Safari и Safari Mobile, если нет мака и нет айфона?

    @Ignavus
    Можно поставить свежую MacOS на VirtualBox.
    Monterey 12.3.0 в марте ставил - взлетела нормально.
    Но вопросов с IPhone оно не снимает.
    Ответ написан
    1 комментарий
  • Что выбрать VPS или PaaS?

    @holyx
    ДевОпс Сисадмин
    cloudservicesseparation.png

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

    Если что-то специфическое нужно, то VPS и руками, если стандартное, без заморочек, то PaaS.
    Ответ написан
    1 комментарий
  • Безопасно ли хранить api ключ в .env?

    Djaler
    @Djaler
    Сеньор-помидор
    Если это фронтенд-приложение - то оно целиком публично, в нём нельзя ничего спрятать. Такие места, где используется переменные из env - считай что просто автозаменой при сборке подставляются значения.
    Ответ написан
    Комментировать
  • Безопасно ли хранить api ключ в .env?

    yarkov
    @yarkov Куратор тега JavaScript
    Помог ответ? Отметь решением.
    Ну так если он будет передаваться при запросе, то и смысла его прятать нет.
    Ответ написан
    Комментировать
  • Можно ли обновить пакеты разархивировав образ в папку?

    @pfg21
    ex-турист
    какой образ ?? зачем вносишь изменения ?? для чего собираешь ?? какая система обновляется ?? что вообще делаешь ??
    описывай яснее вопрос, не свои бессмысленные эмоции , а конкретную проблему желательно технически подброным языком.
    все ясновидцы и предсказатели давно сбежали на РЕНТВ.
    Ответ написан
    6 комментариев
  • С помощью какой программы отзеркалить видео по горизонтали?

    ffmpeg с фильтром hflip:
    SRC="/var/tmp/nu-pogodi.mp4"
    
    ffmpeg \
      -i "$SRC" \
      -vf "hflip" \
      -c:v libx264 \
      -c:a copy \
      "$SRC-flip.mp4"
    Медленная и тяжёлая часть работы тут — пережатие видео в h264. Его не избежать, к сожалению.

    Можно выполнять кодирование на GPU, но придётся компилировать ffmpeg и кодек. Вот пример. Не пробовал. Но должно ускорить.
    Ответ написан
    7 комментариев
  • Что за код на 10000 строк?

    Это минифицированный код.
    Спрашивай у автора, где исходники
    Ответ написан
    Комментировать
  • Отличия GET от POST?

    NikFaraday
    @NikFaraday
    Student full-stack Developer
    UPD: пример ниже приведён для MVC архитектуры. API выдаёт данные, а не страницы. HttpGet - это получение информации от сервера. HttpPost - отправка информации на сервер. Основная разница в тому, что Post запрос имеет тело запроса, в котором можно передавать сложные структуры. Get запрос может передавать данные через строку запроса. Так же Get запросы кешируются, в отличие от Post запросов

    HttpGet и HttpPost это два стандартных типа запроса. Так же есть HttpPut, HttpDelete и некоторые другие, основные из каких я перечислил сначала.

    Разница между HttpGet и HttpPost в очень простом виде:
    HttpGet - выдача сервером какой-то информации клиенту. Для примера, сервер отдаёт какую-то информацию, допустим, имя и логин пользователя, который зашёл на сайт, для того, что бы отобразить её где-то на странице. Так же Get запрос может отдавать целые страницы в формате HTML или других форматах. По факту, большинство страниц, что вы видите в браузере, включая эту, была передана нам в браузер от сервера путём выполнения запроса. Такая информация передаётся как HttpGet.

    HttpPost - это отправка данных на сервер. Любая. Когда вы регистрируетесь на сайте, ваши данные отправляются с использованием HttpPost запроса. Когда вы делаете изменения личной информации, обновлённые данные отправляются как HttpPost, хотя в REST API принято такой запрос помечать как HttpPut. Тут речь идёт об отправке сложных структур данных, возможно, фотографий, видео, аудио, информации о местонахождении, контактные данные. Т.е., другими словами, когда вы сервер уведомляете о какой-то новой информации.

    Стоит отметить, что редирект через url является HttpGet запросом. Если вы просто делаете переадресацию на какую-то страницу и в url передаёте id клиента (Для примера), что бы на странице сведений вывести его данные (Опять же, чисто для примера), это НЕ HttpPost запрос, это просто редирект. Потому что вы не обновляете никакую информацию. Когда вы обращаетесь к серверу с просьбой отрисовать/отрендрить страницу и передаёте туда id клиента, сервер отдаёт ответ на HttpGet запрос, который имеет разметку самой страницы.

    Иными словами, HttpGet запрос, это то, когда сервер должен отрисовать новую разметку или вернуть какие-то данные в некотором формате (В основном JSON для API). Может выполняться несколько запросов, если вы во время регистрации на сайте отправляете данные, делается сначала HttpPost запрос с отправкой ваших данных, а потом HttpGet, когда у вас рендрится новая страница, на которую вас перекинуло.

    Так же есть HttpPut - аналогия HttpPost, разницы нет почти никакой. Обычно используется для обозначения запроса на обновление информации, т.к. HttpPost должен работать как запрос на создание. Тот же пример HttpDelete - когда нужно удалить информацию.
    Ответ написан
    11 комментариев
  • В чем заключаются архитектурные ошибки моего кода?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    class Calculation():
    
      def __init__(self, calculation):
        #init
        self.calculation = calculation

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

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

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

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

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

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

    Вот тут у вас, очевидно, можно написать проще и без лишних повторений, провоцирующих ошибки:
    if i % self.inflation_indexation_period==0 and i != 0:
            if i not in range(0, self.inflation_indexation_period):
              init_indexation_inflation *= self.sales_init.inflation_indexation
            else:
              init_indexation_inflation = 1
            inflation_indexations.append(round(init_indexation_inflation, 5))
          else:
            inflation_indexations.append(round(init_indexation_inflation, 5))

    Лучше так:
    if i % self.inflation_indexation_period==0 and i != 0:
            if i in range(self.inflation_indexation_period):
              init_indexation_inflation = 1
            else:
              init_indexation_inflation *= self.sales_init.inflation_indexation
    
          inflation_indexations.append(round(init_indexation_inflation, 5))

    Функция get_inflation_indexations у вас имеет опасный побочный эффект. Она имеет префикс get_ но модифицирует контекст объекта. Это кэширование? Чем обусловлено такое поведение? Если такое делается "на всякий случай". то это плохая практика неявного внедрения побочного эффекта. Если нарочно, то такое надо документировать и корректно называть и описывать метод в докстринге.

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

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

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

    А вот здесь вообще всё плохо:
    count = 0
        revenue_list = []
        for i in total_price:
          revenue = i*total_value[count]
          revenue_list.append(revenue)
          count+=1

    count - это "количество", а вы его используете как "индекс" и никак иначе!
    i - это индекс, а вы туда суёте фактически цену!
    У вас total_price и total_value параллельные одноразмерные списки, их нужно состегнуть с помощью zip и пронумеровать с помощью enumerate (если надо, а здесь не надо!).
    Весь этот кусок понятнее, проще, короче и более питоничнее записать в такой форме:
    revenue_list = [price * value for price, value in zip(total_prices, total_values)]


    Итого вся вот эта громоздкая плохо читабельная функция:
    def get_revenue(self):
        '''Получить итоговую выручку'''
        total_price = []
        for i in self.get_inflation_indexations():
          price = self.sales_init.price*i
          total_price.append(price)
    
        total_value = []
        for i in self.get_value_indexations():
          value = self.sales_init.sales_volume*i
          total_value.append(value)
    
        count = 0
        revenue_list = []
        for i in total_price:
          revenue = i*total_value[count]
          revenue_list.append(revenue)
          count+=1
    
        return revenue_list

    Легко и читабельно для питониста заменяется на вот такую:
    def get_revenue(self):
        '''Получить итоговую выручку'''
        indexations = self.get_inflation_indexations()
    
        init_price = self.sales_init.price
        total_prices = [init_price * x for x in indexations]
    
        init_volume = self.sales_init.volume
        total_values = [init_volume * x for x in indexations]
    
        return [price * value for price, value in zip(total_prices, total_values)]


    И везде не стоит использовать параллельные счетчики, используйте итераторы, распаковку, зипы, енумервторы и функциональный стиль, ведь он сокращает код и делает его проще.

    Что это за ерунда:
    def get_interest_expenses(self):
        '''процентные расходы'''
        interest_expenses_list = []
        return interest_expenses_list


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

    Вот такое вообще жесть: self.get_revenue()[count]
    Отчего не сохранить в промежуточную переменную?!

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

    Удачи.
    Ответ написан
    3 комментария
  • Как поступить с заказчиком?

    @vism
    А заказчик то причем.
    Это ты оценил проект
    Это ты продолбал уточнения по ТЗ
    Заказчик не должен разбираться в том, как тебе ТЗ составить. Ты должен добиться верного полного ТЗ для тебя. Чтоб ты оценил верно.

    Заказчик вобще не знает что ты там делал, ему сказали цену, он согласился.

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

    Щас ты ведёшь себя как строители-кидалы. Которые берутся за ремонт квартиры/стройку дома, а посреди процесса говорят - доплачивай ещё 30% или уйдём. Уйдём = сгнивший дом.

    Вобщем если у тебя ещё осталось что-то честное и человечное, прими свою отвественность, доделай проект и дальше продумывай свои действия и решения наперёд, продумывай риски и страхуйся от них.
    Но не будь, не будь очередным кидалой, который объяснил себе почему "он прав".

    P.S.
    Если этот проект
    https://qna.habr.com/q/1159728
    То вобще стыдно должно быть от таких мыслей.
    Заказчик то ждет от вас хорошую работа наверное, а вы на нём учитесь. Вы уйдёте, а он потеряет и время, и деньги. Мде...
    Ответ написан
    Комментировать
  • Как поступить с заказчиком?

    SeaInside
    @SeaInside
    16 лет пилю все эти штуки
    Вы ведь сами понимаете, что это ваш косяк, а не заказчика? А чего ему за него платить?

    Мне прям вспомнилась ситуация, когда я пришёл к стоматологу вылечить кариес (пусть будет 2 000 рублей), мне рассверлили весь зуб и заявляют "батюшки, да тут же пульпит!" (12 000 рублей).
    Помогите Маше найти фразу для стоматолога, которая позволила бы сохранить хорошие отношения.

    И вот вы сейчас, по прошествии 2 месяцев, оставите заказчика один на один с незавершённым проектом, в котором никто не разберётся (то есть по сути ни с чем) - то вы поступаете как чудак. Я же вижу по тексту, что понимаете.
    А сюда вы за индульгенцией пришли? :)

    Хотите "сохранить отношения" - доделывайте как есть, в будущем будете мудрее.

    Если совсем невмоготу - возвращаете оплату целиком и сильно извиняетесь (можно даже сверху накинуть).
    В таком случае о хороших отношениях говорить не приходится, но послевкусие хотя бы как от порядочного человека.

    Два совета на будущее:
    1) Перезакладывать стоимость и время разработки;
    2) Если понимаешь, что всё идёт не по плану/пропал интерес / слишком сложно / некомфортно / whatever - сказать об этом сразу и отказаться от проекта, так всегда получается честнее

    Опыт всегда стоит дорого, а 53 000 рублей - ну не самая большая цена его получения :)
    Ответ написан
    8 комментариев
  • Что за программа на скриншоте?

    Geminix
    @Geminix
    Фуллстек nuxt, .net разработчик
    Resolume arena 6
    Ответ написан
    Комментировать
  • Как корректно настроить политику CORS на Laravel 9 (localhost)?

    iMedved2009
    @iMedved2009
    Не люблю людей
    В 'allowed_origins' указать те домены с которых будут разрешены запросы. Я так понимаю у вас это admin.site.ru.
    Ответ написан
    Комментировать
  • Почему js делает неправильный hex?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    В UTF-8 есть правила. Поэтому не всякая бинарная строка является валидной UTF-8-строкой.
    spoiler
    Вот вам упрощённый пример. Представим, что вы переводите не в UTF-8, а в ASCII, и что главным правилом является нулевой восьмой бит. Пусть изначальная hex-строка будет FA. При переводе в ascii алгоритм видит, что это какая-то ошибка и решает исправить её, заменив на 7A (символ "z"). Далее при переводе в hex вы уже получаете 7A, а не FA, потому что информация о восьмом бите утеряна.

    Можете попробовать так. Возможно, это и решит вашу проблему X:
    var hex = "354d413043b4b440e1510b00";
    console.log(hex);       // 354d413043b4b440e1510b00
    
    var not_hex = (Buffer.from(hex, "hex").toString("binary"))
    console.log(not_hex);   // 5MA0C´´@áQ♂
    
    var hex_again = Buffer.from(not_hex, 'binary').toString("hex");
    console.log(hex_again); // 354d413043b4b440e1510b00
    console.log(hex === hex_again); // true
    Ответ написан
    3 комментария
  • Почему метод "хочет стать" функцией?

    Lynn
    @Lynn
    nginx, js, css
    Потому что точки с запятой нужно ставить.
    const greeting = {
    ...
    }; // <-- вот тут!!!
    
    (username) ? ...

    или убрать ненужные скобки
    const greeting = {
    ...
    }
    
    username ? ...
    Ответ написан
    1 комментарий
  • Чем лучше пользоваться docker-compose или docker compose?

    fox_12
    @fox_12
    Расставляю биты, управляю заряженными частицами
    The new Compose V2, which supports the compose command as part of the Docker CLI, is now available.

    Compose V2 integrates compose functions into the Docker platform, continuing to support most of the previous docker-compose features and flags. You can run Compose V2 by replacing the hyphen (-) with a space, using docker compose, instead of docker-compose.
    Ответ написан
    Комментировать
  • Как в маршруте laravel получить всё после параметра?

    Sanasol
    @Sanasol Куратор тега Laravel
    нельзя просто так взять и загуглить ошибку
    Route::get('/search/{search}', function ($search) {
        return $search;
    })->where('search', '.*');


    https://laravel.com/docs/9.x/routing#parameters-en...
    Ответ написан
    Комментировать
  • Как я могу ждать выполнения setInterval?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вот пример с setTimeout() — сначала зарядится таймер, отработает: отресолвит промис, и после этого уже сработает финальный console.log()
    async function monitor() {
      await new Promise(resolve => {
        setTimeout(() => {
          console.log("Прошла секунда");
          resolve();
        }, 1000);
      });
    
      console.log("После Вас!")
    }
    
    monitor();
    Ответ написан
    3 комментария