Универсальный веб-объект?

Sender

Новичок
Универсальный веб-объект?

Приветствую. Попробую описать доступно что я хочу сделать, может сразу посоветуете что я неправ в корне и наведете критику, или подскажете кто уже изобрел этот велосипед...

По опыту заметил что все объекты в ВЕБ-е достаточно идентичны, будь то новость, пользователь или еще какой-нибудь объект, соответственно чтобы не копировать постоянно код я сейчас пробую разработать универсальный объект.
У каждого объекта есть БД составляющая, какие-то прикрепленные файлы и т.п., но это все повторяется от объекта к объекту.
То есть чтобы сделать Удаление, Редактирование, Добавление, Вывод какого-либо объекта достаточно разработать всего лишь один класс, а все объекты будут от него наследоваться и возможно добавляться уникальными какими-то свойствами/методами.

Для чего хочется сделать такой объект? чтобы ускорить разработку какого-либо сайта, и в последствии попробовать на основе этого объекта разработать CMS или еще что-нибудь.

что вы об этом думаете?
пока что реализовал такой объект и его функционирование с БД. Встраиваю потихоньку в предыдущие сайты, выходит достаточно мило и быстро
 

Фанат

oncle terrible
Команда форума
достаточно идентичны, будь то новость, пользователь
фигасе обобщения.
Для чего хочется сделать такой объект? чтобы ускорить разработку какого-либо сайта
ты её усложнишь. в разы.

но поскольку остановить таких абстракторов все равно невозможно, то пиши, болезный.
все лучше, чем наркотой ширяться.
 

dacuan

Новичок
Sender
Уже более двух лет работаю с системой, построенной подобным образом. Все устраивает, админская собирается моментально, оверхед небольшой.

а все объекты будут от него наследоваться и возможно добавляться уникальными какими-то свойствами/методами.
За время, которое используется данный подход ни разу не потребовалось создавать объект-наследник на уровне системы. А вот классы-интерфейсы используются довольно часто.

Поясню подробнее. Например, есть объект "Заказ" в идеале у него, кроме базовой функциональности должны быть методы "Добавить товар", "Удалить товар" и т.п., Но на самом деле на уровне системы для этого достаточно метода "Вложить объект" и "удалить объект". И только на уровне API сайта абстрактные методы можно "обернуть" в более удобне интерфейсы.
 

Scud

Новичок
Вообще похоже на "сфирического коня в вакууме", можно как-то поподробнее раскрыть архитектуру?
 

Gorynych

Посетитель PHP-Клуба
2 Фанат хи-хи! вообще-то двух таких абстрактеров ты и сам знаешь
ты её усложнишь. в разы
ох, не хочу пересказывать идеи Макса, но абстрактно ты не прав. А вот чисто конкретно я доверяю твоему чутью :)
 

master_x

Pitavale XXI wieku
Фанат
ты её усложнишь. в разы.
ничего не усложняется. если подумать, то выйдет что большая часть web-приложений ничто иное как фронтенд к базе данных.
то, о чем говорит топикстартер, уже давно реализованно в самых распространенных фреймворках (CRUD-контроллеры).
естественно, надо понимать что универсальную модель данных никто делать не собирается. есть всего лишь набор одинаковых операций, выполняемых над моделью.
 

bubblegum

Новичок
Dacuan, master_x
+1
у объектов БД есть общая составляющая сущность - таблица ) и соответственно одинаковый интерфейс для запросов insert, update, delete
Различается только дополнительная функциональность - к примеру поля админки "файл" или "фото" соответсвуют допустим полю таблицы varchar (100) - при инсерте/апдейте требуется еще произвести аплод и сохранить имя созданного файла..
 

svetasmirnova

маленький монстрик
У каждого объекта есть БД составляющая, какие-то прикрепленные файлы и т.п., но это все повторяется от объекта к объекту.
То есть чтобы сделать Удаление, Редактирование, Добавление, Вывод какого-либо объекта достаточно разработать всего лишь один класс, а все объекты будут от него наследоваться и возможно добавляться уникальными какими-то свойствами/методами.
А реализация всего вышеперечисленного тоже в базовом классе?
 

Sender

Новичок
Автор оригинала: Фанат
ты её усложнишь. в разы.
пока что наоборот, все упрощается, создание любого объекта который хранится в БД минутное дело, если получится прикрутить файлы то по крайней мере большинство объектов будут создаваться и использовать один базовый код
хотя не буду пока что утверждать обратное :)

Автор оригинала: Фанат
фигасе обобщения.
а чем отличается новость от пользователя для программного движка? суть одна: запись в БД. Если описать как эта запись берется какие поля экранировать, а какие не надо, но все пройдет на ура


dacuan
Мысль. Делал задатки для форума. Там был объект Thread. У него есть объекты Message. Это как раз вложенность одного объекта в другое, обдумаю насколько это удачное решение.
Я пока что думал разделять эти объекты как самостоятельные.


Scud
см. ниже листинг, про архитектуру говорить не имеет смысла, нету у меня опыта и знаний пока что таких :)


svetasmirnova
да, чтобы не писать их реализацию для каждого объекта


Bermuda
пока что не дорос я до этого... значит велосипед?



Приведу код, может так понятнее будет что я хочу сделать и насколько это имеет смысл и серьезно...

PHP:
<?php
	/**
	 * Универсальный класс для любого объекта, представленного в Web %)
	 *
	 * @todo Обработка possible флага
	 */
	class Object
	{
		/**
		 * ObjectDB
		 *
		 * @var ObjectDB
		 */
		var $DB;
		
		/**
		 * Пример, для мета-данных объекта
		 *
		 * @var array
		 */
		var $MetaData = array(
			'DB' => array(								#мета-данные для базы данных 
				'Object' => array(							#Мета-данные самого объекта
					'Table' => 'TNews',							#таблица базы данных для объекта
					'Fields' => array(							#поля таблицы базы данных
						'id' => 'id',
						'date' => array( 'select' => 'NOW()', 'quoting' => false, 'escaping' => false ),
						'name' => 'name'
					),
					'WhereUpdate' => array( 'id' )
				)
			)
		);


		/**
		 * конструктор
		 *
		 * @return Object
		 */
		function Object()
		{
			$this->DB = new ObjectDB( $this->MetaData['DB'] );
		}
	}
	
	/**
	 * БД исполнение объекта
	 *
	 */
	class ObjectDB
	{
		/**
		 * Мета-данные для работы с БД
		 *
		 * @var array
		 */
		var $MetaData = array();
		
		/**
		 * Данные из полей
		 *
		 * @var array
		 */
		var $Data = array();
		
		/**
		 * конструктор
		 *
		 * @return ObjectDB
		 */
		function ObjectDB( $MetaData )
		{
			$this->MetaData = $MetaData;

			#Устанавливаем Quoting, Escaping для всех БД полей, обнуляем Possible
			$this->SetFieldParam( 'Quoting', array_keys( $MetaData['Object']['Fields'] ) );
			$this->SetFieldParam( 'Escaping', array_keys( $MetaData['Object']['Fields'] ) );
			$MetaData['Object']['Possible'] = array();
			

			#Устанавливаем Quoting, Escaping явно заданные в мета-данных, приводим мета-данные в единый вид
			foreach ( $this->MetaData['Object']['Fields'] as $FieldName => $Field )
			{
				if( is_array( $Field ))
				{
					$Field['quoting'] === false ? $this->UnSetFieldParam( 'Quoting', array( $FieldName ) ) : null;
					$Field['escaping'] === false ? $this->UnSetFieldParam( 'Escaping', array( $FieldName ) ) : null;
					$this->MetaData['Object']['Fields'][$FieldName] = $Field['select'];
				}
			}
		}
		
		/**
		 * Записать объект в БД
		 *
		 * @return int
		 */
		function Insert()
		{
			global $DB;
			$QueryPart = array();
			foreach ( $this->Data as $Field => $Value )
			{
				$QueryPart[] = "`{$Field}` = " . $this->ProcessFieldValue( $Field, $Value );
			}
			
			$dbq = "INSERT INTO `" . $this->MetaData['Object']['Table'] . "` SET " . join( ',', $QueryPart );
			$DB->Query( $dbq );
			return $DB->InsertID();
		}
		
		/**
		 * Провести необходимые операции со значением поля, например escape, quoting
		 *
		 */
		function ProcessFieldValue( $Field, $Value )
		{
			global $DB;
			if( in_array( $Field, $this->MetaData['Object']['Escaping'] ) )
			{
				$Value = $DB->Escape( $Value );
			}
			if( in_array( $Field, $this->MetaData['Object']['Quoting'] ) )
			{
				$Value = "'" . $Value . "'";
			}
			return $Value;
		}
		
		/**
		 * Установить значение поля
		 *
		 * @param string $FieldName
		 * @param string $FieldValue
		 */
		function SetFieldValue( $FieldName, $FieldValue )
		{
			$this->Data[$FieldName] = $FieldValue;
		}

		
		/**
		 * Взять значение поля
		 *
		 * @param string $FieldName
		 */
		function GetFieldValue( $FieldName )
		{
			return $this->Data[$FieldName];
		}
		
				
		/**
		 * Загрузить из БД
		 *
		 */
		function Get()
		{
			global $DB;
			$QueryPart = array( 1 );
			foreach ( $this->Data as $Field => $Value )
			{
				$QueryPart[] = "`{$Field}` = " . $this->ProcessFieldValue( $Field, $Value );
			}
			
			$this->ObjectDB( $this->MetaData );			
			$dbq = "SELECT * FROM `" . $this->MetaData['Object']['Table'] . "` WHERE " . join( ' AND ', $QueryPart );
			$rs = $DB->Query( $dbq );
			if( $DB->RecordCount( $rs ) )
			{
				$row = $DB->FetchArray( $rs );
				foreach ( $row as $k => $v )
				{
					$this->SetFieldValue( $k, $v );
				}
				return true;
			}
			return false;
		}
		
		/**
		 * Поля в массив взять
		 *
		 * @return array
		 */
		function GetFields()
		{
			return $this->Data;
		}
		
		/**
		 * Установить флаг, e.g. 'Quoting', 'Escaping'
		 *
		 * @param array $Fields
		 */
		function SetFieldParam( $Param, $Fields = array() )
		{
			if ( !isset( $this->MetaData['Object'][$Param] ) || !is_array( $this->MetaData['Object'][$Param] ) ) $this->MetaData['Object'][$Param] = array();
			$this->MetaData['Object'][$Param] = array_unique( array_merge( $this->MetaData['Object'][$Param], $Fields ) );
		}
		
		/**
		 * Убрать флаг, e.g. 'Quoting', 'Escaping'
		 *
		 * @param array $Fields
		 */
		function UnSetFieldParam( $Param, $Fields = array() )
		{
			$this->MetaData['Object'][$Param] = array_diff( $this->MetaData['Object'][$Param], $Fields );
		}

		/**
		 * Установить поля из массива
		 *
		 * @param unknown_type $Data
		 */
		function SetFieldsFromData( $Data = array() )
		{
			$this->ObjectDB( $this->MetaData );			
			$this->Data = $Data;
		}
	}
?>
-~{}~ 22.11.06 15:44:

Gorynych
как насчет идей Макса? :)
 

Bermuda

Новичок
Sender
Велосипед, не первый и не последний.
Qcodo = PHP on rails + MVC + ORM + Code generator
Правда пока бета, но подход очень вдохновляет. Код написанный с использованием Qcodo читается как художественная литература, доки по реализованному проекту становятся не нужны.

-~{}~ 22.11.06 12:05:

Автор оригинала: Sender
а чем отличается новость от пользователя для программного движка? суть одна: запись в БД.
Ничем. Суть одна -- объект (экземпляр класса, сущности).

Именно поэтому для начала
- строят UML модель
- потом модель данных
- потом сам дизайн базы данных согласно модели
и уж в конце реализацию в коде.

Вот например Qcodo применяет концепцию "один класс (сущность) == одна таблица, один объект (экземпляр) == одна запись".
Ты пытаешься сделать ORM.
ORM это проекция UML модели пропущенная через призму модели базы данных и спроецированная в конечный код.
 

Sender

Новичок
Bermuda
среди всех моих знакомых программистов UML пока что никто не применяет. Кто применяет среди твоих знакомых? применяешь ли ты сам UML?
 

Bermuda

Новичок
Sender
Сам применяю, потому и агитирую. Помогает привести голову в порядок :)
 

Sender

Новичок
Bermuda
рискну предположить что ты используешь UML как разновидность документации
я пытаюсь совсем другое сделать, я же не описываю классы, я делаю универсальный класс


StUV
ну пока что не дорос я до этого
 

Bermuda

Новичок
Автор оригинала: Sender
Bermuda
рискну предположить что ты используешь UML как разновидность документации
Как иструмент для построения модели. Имеет мало чего общего с конкретным языком программирования, но позволяет "объять необъятное" и четко видеть обязанности и поведение каждого класса.

я же не описываю классы, я делаю универсальный класс
Все же посмотри как сделан codegenerator в Qcodo.
 

whirlwind

TDD infected, paranoid
> Qcodo = PHP on rails + MVC + ORM + Code generator
очень вдохновляет. Код написанный с использованием Qcodo читается как художественная литература,

Bermuda это очень субъективное мнение.

2Sender по ORM тебе имхо верно говорят. Лучше сразу с него, потому что это по сути то что ты хочешь, но с меньшими ограничениями на схему. Сэкономишь массу времени и сил.

-~{}~ 22.11.06 15:40:

> четко видеть обязанности и поведение каждого класса
а я например считаю что все это позволяет только TDD а никакой ни UML.
 

StUV

Rotaredom
whirlwind
а tdd не предполагает предварительного проектирования базовой модели сложной системы? ;)
 

whirlwind

TDD infected, paranoid
тдд для того и придуман, что бы не топтаться на месте рисуя на доске абстракции мелком, а двигаться вперед, проверяя модель на практике.

Что такое сложная система? Это некоторое множество более простых объектов, между которыми могут быть связи. Любое рисование, если это не А+Б, позволяет пропустить слишком мелких деталей, от которых много чего зависит. Именно по этому некоторые товарищи (такие как PM, заказчик) считают что программисты нифига не делают, потому что они видят проект поверхностно и для них он видится простым. Ну вот прошли мы

- строят UML модель
- потом модель данных
- потом сам дизайн базы данных согласно модели
и на последнем этапе выяснили что шиш - не срастаются у нас объекты А и Б так как изложено на схеме. И что, все заново? Тест - это первая объективная оценка интерфейса, который по сути определяет взаимодействие объектов. Все взгляды с "высоты птичьего полета" часто теряют свою актуальность до того, как этап кодинга будет завершен.

Я не говорю что прикидывать на бумажке это плохо. У самого стол завален. Но рисовать UML до выхода больмень стабильной версии, это ИМХО просто трата времени.
 
Сверху