Найти - Пользователи
Полная версия: Правильный CRUD репозиторий.
Начало » Python для новичков » Правильный CRUD репозиторий.
1 2 3 4 5
bootcd
Rodegast
  class Crud_Singleton:
  orm = ....
 
class BaseData:
    def __init__(self):
        self._orm = Crud_Singleton()
 
class Server(BaseData):
    def __init__(self, _id, form_data):
        super().__init__()
        self._id = _id
        self.form_data = form_data
     
    def create(self):
        self._orm.save(self.form_data)
   
    def get_by_id(self):
        self._orm.get(self._id)
   
    def delete(self):
        self._orm.delete(self._id)

Вот практическая такая штука была на самом начале проектирования. И я от нее отказался по следующей причине: объект класса Server обязан создаваться с _id и form_data. Но для CRUD методов, которые будут вызываться от инстанса, не всегда будут иметь место как form_data так и _id.
В случае R будет только _id, в случае C - только form_data и так далее. Значит в инициализатор надо передавать в какой-то позиции None. Я понял такой подход как неверный. Именно это у меня и вызвало все вопросы. Мы имеем в виду телевизор, который умеет включаться и показывать изображение. Но производим то телевизор без экрана, то без кнопки включения.
Я подозревал, что я неправильно понимаю ООП, но копаясь в гугле, нашел статью ровно о том же. Там предлагалось делать в классе методы порождения объекта через разные наборы как раз. То есть что-то типа:

 @classmethod
create_instance_by_form_data(cls, form_data):
    return cls(form_data=form_data)
  
create_instance_by_id(cls, id):
    return cls(id=id)

Обосновывалось тем, что так честнее для клиента и это не запутывает использование инициализатора.
bootcd
py.user.next
Это не абстракция. Абстракция - это такая сущность, которая нужна, чтобы выделить основные черты и спрятать детали

“Работа с моделями ОРМ по определенной теме” - это и есть абстракция.

Основные черты - механизмы работы с ОРМ
Детали - определенная тема данных в БД. Например записи о пользователях.

Мы прячем детали работы с конкретными данными ОРМ за общий механизм - набор CRUD методов.
Конкретная тема данных (раздел в программе, информация о пользователях, например) несет свой конкретный набор механизмов работы.

Абстракция может описывать вещь (абстрактный стул - конкретный стул), процесс/явление (стройка здания - конкретная стройка здания, подключение к БД - конкретное подключение к БД).

Или я не прав?
py.user.next
bootcd
“Работа с моделями ОРМ по определенной теме” - это и есть абстракция.

Основные черты - механизмы работы с ОРМ
Детали - определенная тема данных в БД. Например записи о пользователях.
Вот смотри, есть абстрактная собака, которую я описывал здесь. У этой абстрактной собаки есть уши. Они какие? Они стоят или висят, они целые или порванные в боях? Вот уши - это абстракция. Собака - это абстракция. У абстрактной собаки есть абстрактные уши. Каким образом эти уши прикреплены к этой собаке? Ну они прикручены или прилеплены, пришиты или растут из неё? Эта прикрепленность - это абстракция. Итак, мы имеет абстрактную собаку, к которой абстрактно прикреплены абстрактные уши. И мы можем описать реализацию этой связки из абстракций через набор конкретных объектов. Из живого добермана растут стоячие уши. К плюшевому щенку неопределённой породы пришиты висячие уши. К железной собаке приварены треугольные уши. В снежную собаку вставлены длинные морковные уши. Вот эти все объекты разные, а описаны все они одной вот этой связкой из трёх абстракций. Каждый объект своей абстракцией описан. Он реализует абстракцию, которая его описывает, выражает её.

А у тебя так, каша-малаша какая-то. У тебя, например, фигурирует ОРМ, но вопрос возникает “а почему ОРМ?”, это конкретное что-то.

Вот у тебя два человека общаются стоят. Ты что будешь описывать? Абстракцию Человек и ещё одну абстракцию Человек? Вообще-то там нужна только одна абстракция Человек. А потом её можно реализовать в двух объектах - человек один и человек второй. Эти человеки одинаковые, для них не нужно делать две одинаковые абстракции. Два человека одинаковых образуют класс человеков по их одинаковости в струкуре, поведении и семантике. Класс - это множество объектов.

Как видишь, нет ни кода, ни чего-то такого. Просто на одних идеях строится эта система. Она потом будет в виде кода записываться, когда она построится вся. А у тебя как-то наоборот всё происходит. Ну как у новичка. “Я сейчас выучу язык и начну на нём писать программу, и таким образом у меня начнут получаться строчки и она начнёт работать сама по себе и станет правильной ещё там сама собой”. Не, ничего не будет. Если ты не придумал программу, то тебе и писать нечего. А никакой код не поможет тебе её придумать. Это так же как карандаш не поможет тебе придумать рисунок и нарисовать его. Это так же как флейта не поможет тебе придумать мелодию и сыграть её. То есть это другие вообще процессы.
bootcd
py.user.next
Вот у тебя два человека общаются стоят. Ты что будешь описывать? Абстракцию Человек и ещё одну абстракцию Человек?

Скорее я опишу абстракцию “Разговор людей”, где свойством “участники” будет список, состоящий, например из объектов людей, а методами, например “фиксация разговора”, в виде “запись разговора на диктофон”, если абстракцию “Разговор людей” я через наследование, например, могу выделить в абстракцию “Интервью” или метод “запись разговора на видео”, если это будет наследник - “Видеоподкаст”.
Что-то типа:


 class Human:
    pass
  
class TalkingPerson(Human):
    def __init__(self, name, role):
        self.role: str = role
        self.name: str = name
    
  
class Talking:
    def __init__(self, members):
        self.members: list[TalkingPerson] = members
  
    def get_fixation(self):
        pass
  
    def get_info(self):
        pass
  
    
class Interview(Talking):
  
    def __init__(self, members):
        super().__init__(members)
  
    def get_fixation(self, dictofon_recording_file=None):
        # record works
        return dictofon_recording_file
  
    def get_info(self):
        return f"{self.members[0].name} задает вопросы {self.members[1].name} и записывает на диктофон ответы."
  
  
class VideoPodcast(Talking):
    def __init__(self, members):
        super().__init__(members)
  
    def get_info(self):
        return f"{self.members[0].name} ведет подкаст с гостем {self.members[1].name} и записывает видео."
  
    def get_fixation(self, videostaff_recording_file=None):
        # record works
        return videostaff_recording_file
  
  
person1 = TalkingPerson('Васян', 'журналист')
person2 = TalkingPerson('Толян', 'интервьюируемый')
  
interview = Interview([person1, person2])
interview_file = interview.get_fixation()
interview_info = interview.get_info()
  
person3 = TalkingPerson('Иванов', 'подкастер')
person4 = TalkingPerson('Зубарев', 'гость')
  
videopodcast = VideoPodcast([person3, person4])
  
videopodcast_file = videopodcast.get_fixation()
videopodcast_info = videopodcast.get_info()
  
print(interview_info)
print(videopodcast_info)

Вот так на данный момент я понимаю самые простые конструкции ООП. Где я понимаю неверно? Я очень хочу разобраться.
Rodegast
> И я от нее отказался по следующей причине

Там объект с данными который может сохранять своё состояние в БД или восстанавливать его. Все норм.

> производим то телевизор без экрана, то без кнопки включения.

Если у объекта поле _id == None, то это означает что ты его в БД не сохранил. Когда вызовешь метод create, тогда _id и появится. Если захочешь то можно сделать статусы у объекта по типу: “удалён”, “сохранён”, “создан” и т.д.
bootcd
Rodegast
> И я от нее отказался по следующей причинеТам объект с данными который может сохранять своё состояние в БД или восстанавливать его. Все норм.> производим то телевизор без экрана, то без кнопки включения.Если у объекта поле _id == None, то это означает что ты его в БД не сохранил. Когда вызовешь метод create, тогда _id и появится. Если захочешь то можно сделать статусы у объекта по типу: “удалён”, “сохранён”, “создан” и т.д.

Вот у меня есть условный коллега, для которого я пишу этот класс. Написал - отдал.
Он пытается создать объект, но не знает на какой случай ему надо и каким образом вызывать инициализатор, с какими параметрами. В подсказке ему вылезет id, form_data, select_filter.

Насколько я понял теорию ООП, то как раз для конструктора надо создавать такие условия, когда объект инициализируется одинаково для всех случаев его работы. Мы же не создаем телевизор с кнопкой и экраном=None, чтобы только нажимать кнопку и слушать асмр щелчка? В этом вот вся суть моего вопроса.
Rodegast
> Вот у меня есть условный коллега…

Вот как раз для таких коллег придумали документацию

> Насколько я понял теорию ООП, то как раз для конструктора надо создавать такие условия, когда объект инициализируется одинаково для всех случаев его работы.

Ты удивишься, но у объекта может быть несколько конструкторов каждый под свои условия. Это распространено в java, c# и подобных языках в python-е это сделать сложнее, но всё рано можно. В моём примере _id из конструктора можно вообще удалить и сделать его частью реализации.
bootcd
Rodegast
> Вот как раз для таких коллег придумали документацию >

Тут как бы недостатки проектирования мы компенсируем хорошей инструкцией.

Rodegast
Ты удивишься, но у объекта может быть несколько конструкторов каждый под свои условия. Это распространено в java, c# и подобных языках в python-е это сделать сложнее, но всё рано можно. В моём примере _id из конструктора можно вообще удалить и сделать его частью реализации.

Да, я приводил пример, где вместо __init__ делают классметод, который отдает cls() с нужным набором.

Можно сделать __init__(form_data) и вызывать его или пустым или заполненным, а id и select_filter передавать в методы, которым они нужны. Но тогда часть методов станет static по сути. А у тех же джавистов написано, что если у вас в классе есть статические методы (по моему ,приводили - если больше одного), то ваш класс криво спроектирован.

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



sa
bootcd
В принципе мне ясны пути решения этого вопроса. Спасибо большое! Тут или расслабиться и кидать None в конструктор, или же городить какой-то огород, до которого я еще не дошел в плане изучения.
Сына несколько лет назад учил ООП на руби, на пайтоне чуть посложнее синтаксис. Через руби зашел в ООП очень легко. Руби для новичков самый простой язык, и он как брат близнец пайтон.
Посмотри:
https://rubyrush.ru/
https://stepik.org/course/87996/info
Rodegast
> Тут как бы недостатки проектирования мы компенсируем хорошей инструкцией.

Ну вот тебе более элегантный пример:
 class ServerData(BaseData):
    def __init__(self, form_data):
        super().__init__()
        self._id = None
        self.form_data = form_data
      
    def create(self):
        self._id = self._orm.save(self.form_data)
    
    def get_by_id(self):
        self._orm.get(self._id)
    
    def delete(self):
        self._orm.delete(self._id)
 
class ServerBase(ServerData):
    def __init__(self, _id, form_data):
        super().__init__(form_data)
        self._id = _id
 
def read_servers(select_filter):
   ...
   return ServerBase(_id, form_data)

> А у тех же джавистов написано, что если у вас в классе есть статические методы (по моему ,приводили - если больше одного), то ваш класс криво спроектирован.

Не надо на них внимание обращать, у них свой ООП со своими приколами.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB