Задать вопрос
  • Что за код на 10000 строк?

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

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

    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
    15 лет пилю все эти штуки
    Вы ведь сами понимаете, что это ваш косяк, а не заказчика? А чего ему за него платить?

    Мне прям вспомнилась ситуация, когда я пришёл к стоматологу вылечить кариес (пусть будет 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 комментария
  • В каком формате рендерить видео разрешением 13440*2160?

    @ewgenc
    Так вам ТЗ должен был дать заказчик этого видео, в каком формате/контейнере что и как должно быть.
    Ответ написан
    Комментировать
  • При подключении жесткого диска HDD винда бесконечно грузится, как исправить?

    @Drno
    Отключите проверку смарт в биос
    И это не винда буксует, это БИОС ругается. До загрузки винды ПК еще не дошел
    Ответ написан
    4 комментария
  • Что лучше использовать в связке с Vue - Webpack или Vite?

    @deliro
    Бери vite. Вебпак- неуклюжее, лагающее, монструозное говно мамонта
    Ответ написан
    Комментировать
  • Как завести акк на AWS из России (по состоянию на 20 июня 2022) - появились какие-то годные решения?

    CityCat4
    @CityCat4
    //COPY01 EXEC PGM=IEBGENER
    Cейчас мир сошел с ума. Люди пачками принимают решения в ущерб себе по причине их политической мотивированности.
    Онлайн-игры не принимают платежи от игроков.
    Производители уходят с рынков, на которых торговали тридцать лет
    Потребители вынуждены ломать бизнес, чтобы заместить производителя, на которого ориентировались годами

    Эрик Блейн, которого больше знают под псевдонимом Джордж Оруэлл, нервно курит в сторонке.

    AWS может быть и рад был бы Вам что-то продать - но ему не дают :) И еще долго давать не будут. И не факт, что когда "там" разрешат - его не забанят "тут"

    "Я знал, что будет плохо, но не знал, что так скоро" (С) В. Цой "Фильмы"
    Ответ написан
  • Где используется Map и Set в JavaScript (примеры использования)?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Set удобен, например, когда нужно оставить из набора данных только уникальные.
    пример кода
    const data = [ 1, 2, 2, 3, 3, 3 ];
    const unique = [...new Set(data)];
    unique // [ 1, 2, 3 ]

    Map хорош тем, что ключами в нём могут быть и объекты. Например, HTML-элементы, для которых захочется хранить какие-то данные. И Map запоминает порядок добавления элементов, что может быть полезно при переборе.
    Ответ написан
    Комментировать
  • Что происходит при экспорте видео?

    1. у видео кодеков ещё масса параметров, влияющих на качество и объем файла. Но самый поверхностный – битрейт. Увеличился битрейт – файл стал тяжелее.

    2. качество при каждом перекодировании — падает. Поэтому лучше избегать перекодирования там, где оно необязательно. Например, когда только лишь вырезаете часть по времени, перекодировать не нужно, т.к. картинка остаётся та же самая. Поэтому п.3:

    3. просто обрезать видео лучше без перекодирования. Это можно сделать прямо из командной строки могучим инструментом ffmpeg. Примерная команда:
    ffmpeg \
      -ss 15 \         # пропустить 15 секунд от начала
      -i Source.mp4 \  # имя исходного файла
      -t 30 \          # продолжительность 30 сек.
      -c copy \        # кодек "копия" - не перекодировать
      Result.mp4       # что получится - в этот файл
    только удалите все комментарии – после слешей должен сразу быть перенос строки. Этот вариант, пожалуй, самый быстрый из возможных.
    Ответ написан
    4 комментария
  • Как правильно работать с Promise?

    Alexandroppolus
    @Alexandroppolus
    кодир
    можно грузить параллельно, если они не зависят друг от друга и последовательность загрузки не важна

    await Promise.all([
        'https://learn.javascript.ru/article/promise-chaining/one.js',
        'https://learn.javascript.ru/article/promise-chaining/two.js',
        'https://learn.javascript.ru/article/promise-chaining/three.js',
    ].map(loadScript));
    
    one();
    two();
    three();
    Ответ написан
    Комментировать
  • Как правильно работать с Promise?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вопрос если разница в таких записях?

    Только в передаваемом значении:
    • resolve(script) передаст дальше по цепочке этот script (который никому не нужен, похоже).
    • script.onload = resolve передаст по цепочке объект события (тоже всем по барабану)

    почему такой ее вызов дает ошибку script.onload = resolve(script);
    потому, что нужна функция, которую вызовут позже, а не мгновенный результат её выполнения.
    Ответ написан
    Комментировать