Ответы пользователя по тегу ООП
  • Как упростить метод, выполняющий операции для всех других методов класса, если он получается слишком раздутым?

    @rPman
    Вам зачем нужна прослойка? Что бы заменить некрасивый синтаксис curl_xxx на свой некрасивый?

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

    Обычно не доходят до того, чтобы создать под каждый тип запроса свой метод, но как минимум нужно создать метод request, который под капотом будет:
    * обрабатывать авторизацию
    * обрабатывать ошибки сети и отслеживать лимиты сервиса и отправлять повторные запросы
    * выжидать необходимые таймауты
    * обрабатывать пакетные запросы, к примеру если сервис требует постранично работать с данными
    * регистрировать и обрабатывать обратные вызовы callback, если такие есть (само собой это уже другой метод)

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

    @rPman
    DIP из SOLID
    не уверен, на сколько глубоко ты готов залезать в проблему, так как в зависимости от этого будет и подход к разработке. Выбор - поддержка или нет практически любого из этих пунктов будут менять структуру и алгоритм чуть ли не полностью.

    1. имена файлов и пути, а кодировки?
    в разных ос разные правила, разные символы разделители, значимость больших/маленьких букв в именах
    2. symbolic и hardlink свихнуться можно
    это огромная головная боль для любых кто занимается копированием данных, поведение разнится к примеру, попадает ли путь в пределах каталогов, входящих в копию или нет
    3. фичи типа sparce files или reflink (этакий hardlink но не для файла а на его сектора)
    существуют задачи, в которых не сохранение и учет этих вещей могут невероятно усложнить восстановление данных (например если данные хранятся в дырявых файлах, логически петабайтового размера, в реальности же занимающие на порядки меньше, восстановить да и скопировать без учета этого будет практически нереально)
    4. extended attributes
    этим мало кто пользуется (но если пользуются то на столько глубоко, что не сделать резервную копию будет фатально), но помнить об этом надо, особенно когда нужно абстрагироваться от их реализации в ОС
    5. права доступа
    очень мало кто заморачивается с резервированием этой информации, а она зачастую не менее важна чем сами данные, так как иначе, при восстановлении данных со сложной структурой прав и большим количеством пользователей может превратиться в ад, и даже нести опасность утечки важных данных
    6. инкрементальное хранение бакапов
    это конечно не обязательно, но системы хранения резервных копий без этой фичи неудобны либо слишком дороги
    7. работа с сетевыми nas, инструменты выборочного восстановления, поиск данных
    Хранить бакапы локально - это фатальная ошибка, значит доступ к хранилищу должен быть удаленный
    А еще, вероятность что понадобится восстановить весь бакап на столько низкая, по сравнению с другими сценариями, и заставлять человека извлекать петабайтовые архивы ради мегабайтового файлика, который удалили по ошибки и решили восстановить из бакапа...

    p.s. не придумывай сам, спроси своего руководителя, на сколько глубока кроличья нора, так как к примеру все правильно сделать может тянуть на диплом или еще круче.

    p.p.s. совет, не изобретай форматы хранения данных, храни все в файлах, пусть контейнером будет сама файловая система (не вздумай файлы хранить к примеру в БД), но вот за имена файлов придется чтобы отвечал кто то другой (вот тут БД), причем не рекомендуется полностью исключать имена файлов и каталогов из архива, достаточно составить список разрешенных символов (общих для большинства ос и основной кодировки) но это может наложить лимит на структуру данных (например в разных ос разный лимит глубины вложенности или длины символов в пути к файлу), тут же храни extended attributes (так же в виде файлов со своими именами)
    Все остальное (настройки, структуру инкрементальных бакапов, права доступа, наличие дыр, symlink/hardlik, reflink и т.п.) так же храни в базе данных, может не так удобно как кажется с первого взгляда, но будет легче восстанавливать.
    Ответ написан
  • Как контролировать двух телеграм ботов одним Python процессом?

    @rPman
    Покопался в исходниках
    в них все что нужно подготовлено для нормальной асинхронщины, но собственно главный метод обработки не вывернут на изнанку, чтобы можно было сделать что то типа:
    bot1 = telebot.AsyncTeleBot(API_TOKEN1, threaded=False)
    bot2 = telebot.AsyncTeleBot(API_TOKEN2, threaded=False)
    ...
    loop = asyncio.get_event_loop()
    loop.create_task(bot1.pooling_step())
    loop.create_task(bot2.pooling_step())
    loop.run_forever()

    смотри код метода _process_polling, и создай свой pooling_step только в нем должно быть только что что в оригинальном внутри цикла while, что то типа
    if updates:
                        self.offset = updates[-1].update_id + 1
                        self._loop_create_task(self.process_new_updates(updates)) # Seperate task for processing updates
                    if interval: await asyncio.sleep(interval)

    непонятно почему создатели библиотеки это не сделали сами, возможно еще не успели или я не правильно понял их код?
    Ответ написан
    Комментировать
  • Рефакторинг кода. Как оптимизировать количество if?

    @rPman
    Вместо if в таких случаях используют switch case.

    Альтернатива - определи map с ключом твои сравниваемые значения и значением делегат Func или экземпляр класса с виртуальным методом. Но что бы ты не делал, синтаксически это не добавит тебе простоты, а просто переместит в другое место определение кода и сравниваемое значение.

    Есть еще препроцессор #if или даже собственный кодогенератор, иногда оно оправдано.

    Городить что то сложнее switch нужно, когда логика, стоящая внутри кода около каждого из вариантов значения, может быть свернута в общий единый код или наоборот, он весь сводится к коротким инструкциям,красиво смотрящимся в виде анонимных функций, которые неплохо смотрятся в виде констант иннициализатора map
    Ответ написан
    Комментировать
  • Плохая практика менять объект ненапрямую?

    @rPman
    Согласен с ответом DollyPapper, но формально возможна ситуация когда так можно делать

    К примеру, если научить объект Position сообщать о действиях над собой своим овнерам, создав абстрактный класс CanHavePosition с виртуальным методом doMoving который должен быть имплементирован в классе Character (который наследуешь от CanHavePosition) и вызываться на каждое движение Position::to (способы оформления могут другими быть, например наоборот, в конструкторе Character будет вызываться метод init у Position с колбеком, который будет вызываться внутри Position::to) то такое оформление как у вас будет оправдано.

    Само собой, нет необходимости так делать всегда, и нет нужды следовать строго прямо гайдлайнам, хотя они и 'написаны кровью и ошметками говнокода', всегда можно найти ситуацию, когда не нужны over engineering.

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

    @rPman
    2 основных подхода к реализации отката:
    1. вместо вычислений, на каждом шаге просто добавляете или удаляете описание операций (иногда подойдут обычные замыкания) в специальный массив, реальные вычисления проводите в момент когда запрашивается результат
    2. каждый шаг вычислений сохраняет предыдущее значение в специальном массиве, соответственно откат - это получение этого значения и удаление последнего элемента в масссиве (если не нужен redo)

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

    Так же возможно сочетание обоих подходов, для оптимизации ресурсов.
    Ответ написан
    Комментировать