|
|
  |
си, паттерны ооп, разбиение на объекты, parent's parent, детско-родительские отношения |
|
|
|
Aug 16 2012, 10:15
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
да, у меня есть текcтовое описание того, какие есть компоненты у системы и как они взаимодействуют; разбивать сиситему на объекты сам я не властен то есть у меня описано что вот мол есть палета, есть менеджер, есть холодильник, есть ещё что-то, описана начинка и взаимодействие этого добра друг с другом моё дело - реализация согласно описания Цитата принято или нет - это вопрос вкуса может быть, просто это всё поддерживать надо, вопрос у меня именно про best practices
Сообщение отредактировал Idle - Aug 16 2012, 10:16
|
|
|
|
|
Aug 16 2012, 10:49
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(Idle @ Aug 15 2012, 22:57)  не использую си++, использую си, абстрактные типы данных через incomplete structure pointer-ы собственно вопрос, как правильно организовывать взаимодействие объектов, когда "вложенный объект" должен вызывать родителя родителя? Нет ничего нового под солнцем  - практически все механизмы взаимодействия объектов уже открыты и где-то используются. Общение дочерних объектов с родительскими широко применяется в библиотеках классов GUI, например, таких как MFC или VCL. Для того, чтобы организовать такое взаимодействие, очень желательно породить (как производные классы) все объекты, участвующие в родственных отношениях, от одного (супер)базового класса, хотя бы и формального (т.е. не имеющего собственных функций), просто для того, чтобы указатель любого участника "большой семьи" приводился к указателю одного и того же типа типа автоматически. А для большего удобства в этом же супербазовом классе (superbase) лучше сразу создать переменную (указатель), в которой каждый объект будет помнить указатель на своего родителя (естественно, приведенного к типу superbase*). Например, классу superbase достаточно выглядеть так: class superbase { Piblic: superbase *myParent; superbase(superbase *parent) { myParent = parent; } }; В принципе родительские и дочерние объекты могут быть совершенно разными по своим структурам классами, их переписывать не надо, а достаточно ОБЪЕДИНИТЬ с классом superbase! Скажем были раньше у вас три класса Object1, Object2 и Object3, на основе которых вы порождали состоящие в родстве объекты: бабушку, мать и дочь. А теперь создайте для них новую тройку объектов: class Family1 : public superbase, public Object1 // это для бабушки { Family1(superbase *parent, ...) : superbase(parent), Object1(...) { ... } }; class Family2 : public superbase, public Object2 // это для матери { Family2(superbase *parent, ...) : superbase(parent), Object2(...) { ... } }; class Family3 : public superbase, public Object3 // это для дочери { Family3(superbase *parent, ...) : superbase(parent), Object3(...) { ... } }; Мы видим, что новые семейные классы (Family1, Family2, Family3) функционально тождественны старым индивидуальным классам (Object1, Object2 и Object3) соответственно. А троеточием я обозначила список тех параметров, которыми инициируются старые классы. Фактически, семейные классы отличаются от старых только одним - дополнительным параметром parent и способностью его запоминать в своей переменной myParent. Процесс рождения чада сопровождается тем, что родитель при вызове конструктора сообщает, помимо прочего, указатель на самого себя (this), чтобы ребенок мог его запомнить: new Family3 child1( this, ...); Теперь дитя child1 всегда будет помнить свою маму в child1.myParent. Ну а самый старый патриарх, которого порождает уже не семья, а само приложение, инициируется с парамером NULL вместо указателя на parent. В смысле, что родителя у него среди семьи нет. Весь смак в том, что теперь любой потомок будет способным не только узнать адрес своего родителя по myParent, но и обратиться к нему (вызвать по этому поинтеру какую-нибудь родительскую функцию). А если возникнут затруднения с доступом, то поинтер myParent всегда можно привести к полному указателю на родительский класс динамически. Точно так же можно достучаться до предка в любом поколении через цепочку myParent->myParent->...->myParent. И если на каком-то этапе очередной myParent окажется равным NULL, то это родоначальник династии, и глубже опускаться по генеалогическому древу не надо. Например, послание собственной бабушке будет выглядеть так: myParent->myParent->Message = "Здравствуй, бабуля!"; А послание прадедушке так: myParent->myParent->myParent->Message = "Привет, прадед!"; Если последнее поколение - помидор, а предок всего сущего - admin, то жалобу ему помидор может оправить, либо вызвав myParent от myParent столько раз, каким по счету поколением от него является помидор. А если он точно этого не знает, то легко может узнать, проследив эту цепочку до нуля: superbase *Admin = myParent; while(Admin->myParent != NULL) Admin = Admin->myParent; // спускаем админа вглубь, пока не достигнем сироты Admin->Message = "Караул! Загниваю!";
|
|
|
|
|
Aug 16 2012, 10:54
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(Idle @ Aug 16 2012, 13:15)  да, у меня есть текcтовое описание того, какие есть компоненты у системы и как они взаимодействуют; разбивать сиситему на объекты сам я не властен то есть у меня описано что вот мол есть палета, есть менеджер, есть холодильник, есть ещё что-то, описана начинка и взаимодействие этого добра друг с другом моё дело - реализация согласно описания
может быть, просто это всё поддерживать надо, вопрос у меня именно про best practices При создании структур первые их члены идут максимально абстрактные и немодифицируемые. Применяют для этого и юнионы. Далее следуют более зависимые от контекста члены. Поэтому когда низший уровень не желающий знать о пертурбациях наверху и контекст хочет что-то туда передать он типизирует только первые наиболее абстрактные(или наиболее конкретные, кому-как  ) записи структур и что-то с ними передает. Далее сообщение получает промежуточный уровень который типизирует структуры еще глубже для передачи своей информации, и так до верха пока к менеджеру не придет полностью типизированная под него структура со всеми данными. Кстати, так оно физически (на бинарном уровне) в объектных языках и делается.
|
|
|
|
|
Aug 16 2012, 11:29
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Xenia @ Aug 16 2012, 13:49)  например, таких как MFC или VCL. не, лучше GTK. Там всё по косточкам можно разобрать при стойком желании. 2Idle: ну вот, исключения, теперь RTTI тянется за задачей... Цитата а внутри я удобно типизирую ввиду тестирования и tdd из-за оболваненности западной пропагандой У Вас же всё равно tdd подчинено требованиям более верхнего уровня?
|
|
|
|
|
Aug 16 2012, 11:41
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(_Pasha @ Aug 16 2012, 15:29)  У Вас же всё равно tdd подчинено требованиям более верхнего уровня? не подчинено, иногда в описании явно прописаны контейнеры различного добра, понятно что это отдельный модуль на сишные модули я выделяю сам, тесты тоже сам придумываю для них
|
|
|
|
|
Aug 16 2012, 14:33
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(Idle @ Aug 15 2012, 22:57)  ...как правильно организовывать взаимодействие объектов, когда "вложенный объект" должен вызывать родителя родителя?..палета .., ящик, ..и помидор. помидор ...вызывает владельца...что почитать на эту тему с учётом языка? 1) Тут господин ARV всё правильно сказал. +100500 Осталось только перечислить и выбрать способ реагирование на протухание(я специально не сказал натификации - потому что и это под вопрос можно поставить) 2) Если говорить об ОО подходе, то всё просто - он идёт от жизни и это принципиально в его юзанье . Почему - отдельная тема, если захотите могу разъяснить это. А теперь отталкиваемся от задачи. И в каком городе есть супер-пупер чудо помидоры которые орут хозяину что они протухли???? ну вот покажите мне, или подскажите где их глянуть можно? Посему глупости это. Потом придётся костыли крутить при таком подходе(предпологать что так лучше - орать помидору про протухание). Либо вы чего то утаили. А если так - то увы это круглый конь в вакууме. Возвращаясь к баранам... 1) Имеем овощехранилище 2) палетты, ящики, помидоры. 3) Того кто следит. Это либо человек либо автоматика (по температуре, хим состоянию и иже). Посему... Помидор выкидывает некий признак(по жизни) - запах, цвет, мягкость. Это и отслеживаем... НЕТ никакой натификации - это вздор. Если хотите - отсебятина, желание упростить или сделать как знается мне... Вот именно это и ведёт к костылям(отдельная тема). прелесть в Объектно Ориентированном Анализе и Проектировании - именно взятие от жизни. 4) книг в разрезе си - не найдёте. априори это не ОО язык. Книгу одну только рекомендую - одного из основоположников ООА и ООП - Гради Буча. Для тех кто просто листал или просто читал эту книгу ("Объектно Ориентированный Анализ и Программирование") - рекомендую хотя бы одну задачу сделать стэп-бай-стэп по методике описанной в этой книге. ЗЫ 5) Вы заметьте - люди которые слабо разбираются в ООА(анализе, а не коде) и ООП(проектировании а не программировании) - начинают свои рассуждения с технической стороны дела - коллекции, циклы, коллбэки, функции, векторы, листы и т.д... и путаются... потому как не понимают что ОО это методология, а не тот или иной язык...
Сообщение отредактировал kolobok0 - Aug 16 2012, 14:37
|
|
|
|
|
Aug 16 2012, 15:02
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(kolobok0 @ Aug 16 2012, 18:33)  И в каком городе есть супер-пупер чудо помидоры которые орут хозяину что они протухли? Либо вы чего то утаили. да, естественно я ничего не расскажу про задачу, помидоров конечно нет, есть сетевые потоки, пакеты, таймауты, записи в таблицах, хранилища пакетов одного вида, другого вида, третьего, перетасовка их туда-сюда и т.д. и т.п. не я разбиваю систему на функциональные блоки и не я определяю взаимодействие между ними, моё дело - реализация  Цитата(kolobok0 @ Aug 16 2012, 18:33)  4) книг в разрезе си - не найдёте. одна книжка точно есть "Object-oriented programming with ANSI C"
Сообщение отредактировал Idle - Aug 16 2012, 14:56
|
|
|
|
|
Aug 16 2012, 15:11
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(Idle @ Aug 16 2012, 18:56)  ...есть сетевые потоки, пакеты, таймауты, записи в таблицах, хранилища пакетов одного вида, другого вида, третьего, перетасовка их...не я разбиваю систему на функциональные блоки... это немного другой коленкор - согласитесь. и мне кажется, лучше спрашивать тут народ именно в разрезе реализации именно сетевых дел. в своё время при реализации протоколов преследовал задачу - меньше копировать данные. по поводу то, что Вы стеснены в выборе всех плюсов "у плюсов"  это плохо. тут как правило консерватория намудрила... возвращаясь к нотификации.. и к коду  тут уже прозвучало о супер классе (в плюсах это закос через статик методы). пойдём в эту сторону. одно из решений...(подчеркну слово одно из) мысль следующая... у вас есть типизация сущности. у вас есть типизация события(я так понимаю вы работаете в "событийных рамках" задачи). вам никто не запрещает создавать понятие коллекций по типам сущностей. При этом набор ивентов ограничен. Вам никто не мешает "подписаться" на конкретное событие конкретного типа сущности в любом месте логики... на плюсах это просто. на сях как лучше - тут немного подумать нуна.
|
|
|
|
|
Aug 16 2012, 18:26
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(Xenia @ Aug 16 2012, 14:49)  Для того, чтобы организовать такое взаимодействие, очень желательно породить (как производные классы) все объекты, участвующие в родственных отношениях, от одного (супер)базового класса, хотя бы и формального да, то что надо Цитата(AlexandrY @ Aug 16 2012, 14:54)  ага посмотрел на использование структуры kobject в ядре linux - оно структура вставляется внутрь "класса" и указатель на неё (а не на сам экземпляр родителя) передаётся при создании потомка и сохраняется в kobject потомка в поле parent и потом по цепочке parent->parent->...->parent можно добраться до самого верха не зная о реализации родителей указатель на саму структуру (там где её начинка известна) можно получить через container_of в моём случае нужен дополнительный клей для того чтобы отдать менеджеру указатель именно на палету, а не на встроенный kobject, но это не важно. CODE Kobjects are usually embedded in other structures and are generally not interesting on their own. Instead, a more important structure, such as struct cdev, defined in <linux/cdev.h>, has a kobj member: /* cdev structure - object representing a character device */ struct cdev { struct kobject kobj; struct module *owner; const struct file_operations *ops; struct list_head list; dev_t dev; unsigned int count; }; осталось, собственно, два момента - как оформить интерфейсы между модулями: если везде передавать kobject, то будет куча container_of даже там, где вызов метода идёт сверху, а если делать разделение вызов сверху/снизу - будет путаница - как юнит-тестить вызовы снизу вверх, т.е. нужно насоздавать цепочку родителей и только потом за_stub_ить метод
|
|
|
|
|
Aug 17 2012, 04:28
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Idle @ Aug 16 2012, 21:26)  посмотрел на использование структуры kobject в ядре linux - оно структура вставляется внутрь "класса" и указатель на неё (а не на сам экземпляр родителя) передаётся при создании потомка и сохраняется в kobject потомка в поле parent и потом по цепочке parent->parent->...->parent можно добраться Полиморфизм вынесен отдельно за пределы реализации класса. А по отношению к экземплярам класса parent->parent->... превращается в доступ по указателю на указатель. ЗЫ только что получил в рассылке виртуальные функции на СиЕще не читал, но осуждаю  ЗЗЫ ремарка понравилась Цитата C++ doesn't allow straightforward, dynamic changes to vtable entries (such changes inherently change the type of the object), but it does allow the implementation of a state machine just as you describe... По первой части - таки да, на Си таблица виртуальных функций получается экономнее и интереснее... а стейт-машины и того проще
Сообщение отредактировал _Pasha - Aug 17 2012, 05:06
|
|
|
|
|
Aug 17 2012, 06:39
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(_Pasha @ Aug 17 2012, 07:28)  ЗЫ только что получил в рассылке виртуальные функции на СиЕще не читал, но осуждаю  Ну где-то так у нас и писалась в конце 80-ых на ДВК поддержка печати на разные по набору команд матричные принтеры и в разных граф. режимах. Цитата(andrewlekar @ Aug 17 2012, 07:57)  Помидоры - тупо структуры и делать ничё не умеют. Если они помидоры. А если банки с помидорами, то очень даже ничего бахнуть могут. Поэтому надо таки идти от задачи, не всегда попытка объяснить через простые аналогии заводит куда надо.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Aug 17 2012, 09:04
|
Знающий
   
Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163

|
Цитата Если они помидоры. А если банки с помидорами, то очень даже ничего бахнуть могут. Поэтому надо таки идти от задачи, не всегда попытка объяснить через простые аналогии заводит куда надо. Активные объекты в природе куда реже встречаются, чем об этом думают апологеты ООП. Если уж сильно нужно использовать нотификацию от объектов, то вот 2 нормальных варианта (без нагромождений всяких пэрентов, визиторов и прочей лабуды): 1. pomidor.setManager(pomidorManager) 2. pomidor.onActionEvent = pomidorManager.actionEventHandler
|
|
|
|
|
Aug 17 2012, 09:48
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(andrewlekar @ Aug 17 2012, 13:04)  1. pomidor.setManager(pomidorManager) указатель на конкретного менеджера изначально знает только конкретная палета в которой находится коробка в которой находится помидор собственно вопрос был в том какой подход использовать, чтобы привязать помидор к палете в которой он находится, чтобы сообщить менеджеру о конкретной палете
Сообщение отредактировал Idle - Aug 17 2012, 09:49
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|