1. Python / Говнокод #28524

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    def __get_column_names(table: str) -> tuple:
        try:
            with conn:
                cur.execute("SELECT name FROM PRAGMA_TABLE_INFO(?)", (table,))
                column_names = cur.fetchall()
        except Exception as excpt:
            print(excpt)
        column_names = tuple(i[0] for i in column_names)
        return column_names
    
    
    def db_register_user(user_data: types.User):
        """
        SQL запрос для внесения данных о пользователе
    
        Args:
            user_data: telebot User объект, содержащий словарь с параметрами пользователя
        """
        user_data = user_data.to_dict()
        column_names: tuple = __get_column_names('Users')
        user_values = tuple(user_data.get(key) for key in column_names if key in user_data)
        try:
            with conn:
                query = 'INSERT INTO Users cn'.replace('cn', str(column_names))+' VALUES (?,?,?,?,0,3)'
                parameters = (*user_values,)
                conn.execute(query, parameters)
        except Exception as excpt:
            print(excpt)
        conn.close()

    На сколько в такой ситуации .format не безопасен? Идея в том, чтобы не объебошится программисту в коде введя неверное значение колонки. Для этого имена колонок берутся из самой базы (есть мысль ещё и типы брать). Есть вариант реализации получше? Спасибо

    Запостил: rockkley94, 26 Декабря 2022

    Комментарии (22) RSS

    • то есть .replace, а не .format
      Ответить
    • Лучше так не делай а пиши названия колонок сам
      Ответить
      • Почему не делать-то? Таким образом я могу сделать универсальную функцию, которая каждый раз будет давать корректные имена из самой бд. Если бы я понимал, почему так лучше не делать (по твоим словам), я бы не постил это сюда)
        Ответить
        • Белые люди описывают модель на питоне, и автоматически получают по ней код для CRUD. Типы и имена колонок проверяются автоматически.

          Серьезно, не нужно делать кривое квадратное колесо
          https://docs.djangoproject.com/en/4.1/topics/db/models/
          Ответить
          • This. И да, белым людям после этого тайпчекер («mypy»/«pyright»/«pylance») проверяет типы колонок и удостоверяется, что белый человек не присвоил не то не тому, а IDE — подсказывает названия и подчёркивает опечатки.
            Ответить
        • а как ты ими будешь пользоваться, если ты их имён не знаешь?
          Ответить
        • Схема данных это самое важное что есть в твоем коде. Из нее ты строишь модели, из них проектируешь API. Общее правило - ты всегда подстраиваешь код приложения под бд, не наборот.

          Проблемы с твоим подходом:
          1) Ты делаешь два запроса в бд когда можно делать один. Это увеличивает время обработки запроса и больше потенциальных точек отказа.
          2) У тебя захардкожено 4 параметра в кверю если я правильно понимаю, то есть тебе все равно придется менять это место в коде когда захочешь поддерживать новую колонку.
          3) Если ты будешь добавлять новые колонки не строго в конец таблицы, то рано или поздно ты знапишешь что-то не так. С твоим подходом, ты в принципе сильно повышаешь вероятность что-то записать не так.
          4) Именнованные параметры намного лучше читаются в логах или инструментации твоей бд.
          Ответить
          • >Общее правило - ты всегда подстраиваешь код приложения под бд, не наборот.
            Есть и другой подход. Скажем, EF умеет генерировать схему по коду, но как правило схема получается не очень.

            А например в Django модель хоть и описываеца на питоне, но всё равно четко отражает СУБД
            Ответить
            • > умеет генерировать схему по коду,

              - graphql вроде так же делает
              Ответить
          • > Общее правило - ты всегда подстраиваешь код приложения под бд, не наборот.

            Опровергаю. Есть бизнес-контракты, требования к самому приложению, есть апи, которое оно должно предоставлять. Обычно оно выражается в каких-то структурах-объектах и сервисах. И вот уже от них пляшет вообще всё остальное.
            Ответить
            • Так речь же о слое доступа к СУБД

              Ты можешь сделать АПИ сервиса леера в бизнес-терминах, а слой доступа к базе в терминах базы, а потом их склеить, не?
              Ответить
            • >Есть бизнес-контракты, требования к самому приложению, есть апи, которое оно должно предоставлять

              В продуктовой разработке ничего этого нет. Именно потому я за продуктовую разработку.
              Ответить
    • Не нужно велосипедить, пожалуйста. Возьми SQL Alchemy или Django ORM, и не создавай динамическую хрень
      Ответить
    • А как выглядит types.User?
      Ответить

    Добавить комментарий