Страница 1 из 1

CPubliher/CSubscriber

Добавлено: 23 май 2004, 16:53
vg
Парни, нужен совет по такому вопросу. Я всё правлю своё резюме. Попросил, чтобы посмотрел один, хороший канадский программер (таких немного). Он посмотрел, сказал, что малова-то у меня в резюме всего путного. В общем, я расписал. Написал там про такую фичу, как CPubliher/CSubscriber паттерн проектирования, и как я её имплементировал для проектов c гуями WinAPI или MFC. Похожих имплементаций для проектов WinAPI и MFC я просто не видел. Ну, и сгоряча преподал это в резюме в качестве «гордости» за собственную драгоценную персону. Парень тот написал мне, мол, а чё тут такого, заслуживающего быть помещённым в резюме.
Вот я и в раздумьях, а мож выкинуть вовсе неактуальный для канадских С++ программистов-гуистов вопрос об имплементации CPubliher/CSubscriber. Там, конечно, всё просто имплементровано. Ну, не видел, чтобы кто-то реально это делал для построения объектно-ориентированной модели ГУИ(себя драгоценного я не учитываю :lol: ).

Классы там приблизительно такие (это одна из первых имплементаций):

Код: Выделить всё

#define IDO_ALL	0			// send message to all objects
#define afxtempl			// use MFC templated collection classes

#ifdef afxtempl
	#include <afxtempl.h>
#endif


/////////////////////////////////////////////////////////////////////////////
//	forward declarations
class CCustomSubscriber;
class CSubscriber;		
class CCustomPublisher;	
class CPublisher;		

/////////////////////////////////////////////////////////////////////////////
//	CCustomCommand class 
class CCustomCommand {
public:
	CCustomSubscriber*	Sender;		// Source
	UINT				SenderID;
	CCustomSubscriber*	Rcpt;		// Destination
	UINT				RcptID;
	CCustomCommand (UINT _RcptID = IDO_ALL) 
	{
		memset(this, 0 ,sizeof(CCustomCommand));
		RcptID		= _RcptID;
	}
};

/////////////////////////////////////////////////////////////////////////////
//
//		CCustomSubscriber class
//
/////////////////////////////////////////////////////////////////////////////
class CCustomSubscriber { 
public:
	// Publisher event handling
	virtual void		OnKillPublisher	(void);
	virtual bool		OnRegistering	(CCustomPublisher * pPublisher);
	virtual bool		OnRegistered	(CCustomPublisher * pPublisher);
	virtual bool		OnUnRegistering	(void);
	virtual bool		OnUnRegistered	(void);
	virtual void*		OnGetInterface	(LPCTSTR InterfaceName);
	virtual void		OnPush			(const CCustomCommand* pCommand) = 0;
	UINT				get_ID			(void)	{return m_ID;}

private:
	UINT				m_ID;			// user symb.const. for the registered object
	CCustomPublisher*	m_pPublisher;	// own publisher

	// CCustomSubscriber interface
protected:	
	CCustomSubscriber(): m_pPublisher(NULL), m_ID(0L), rcRegistration(false){}
	~CCustomSubscriber () {	_SelfUnRegister();	}
	bool				rcRegistration;

	// Properties 
	void				set_ID			(UINT ID_OBJ) { m_ID = ID_OBJ; }
	CCustomPublisher*	get_Publisher	(void)	{ return m_pPublisher; }
	void				set_Publisher	(CCustomPublisher* pPublisher) { m_pPublisher = pPublisher; }
	CCustomSubscriber*	get_Self		(void)	{ return this; }

	// Methods
	virtual bool		_SelfRegister	(CCustomPublisher* pPublisher, UINT ID_OBJ);
	virtual bool		_SelfUnRegister	(void);
	virtual void		Push			(CCustomCommand* pCommand);
};

/////////////////////////////////////////////////////////////////////////////
//
//		CCustomPublisher class
//
/////////////////////////////////////////////////////////////////////////////
class CCustomPublisher 
{
private:
	CArray <CCustomSubscriber*, CCustomSubscriber*> m_aObject;
protected:
	inline bool	IsSubscriberRegistered	(CCustomSubscriber* pSubscriber);
	inline		CCustomSubscriber*		GetSubscriber(UINT	ID_OBJ);
	inline bool	IsIDRegistered			(CCustomSubscriber* pSubscriber);
public:
	CCustomPublisher() {}
	~CCustomPublisher()
	{
			for (int i = 0; i < m_aObject.GetSize(); i++)
			m_aObject.GetAt(i)->OnKillPublisher();
	}
	virtual bool GetSubscriberInterface	(UINT ID_OBJ, LPCTSTR InterfaceName, void ** ppvInterface);
	virtual bool RegisterSubscriber		(CCustomSubscriber* pSubscriber);
	virtual bool UnRegisterSubscriber	(CCustomSubscriber*	pSubscriber);
	virtual void Publish				(CCustomCommand*	pCommand);
};
/////////////////////////////////////////////////////////////////////////////
//
//		CPubliher/CSubscriber classes
//
/////////////////////////////////////////////////////////////////////////////
class CPublisher : protected CCustomPublisher
{
protected:
	CPublisher() {}
	CCustomPublisher::GetSubscriberInterface;
public:
	CCustomPublisher::Publish;
};
//----------------------------------------------------------------------------
class CSubscriber: protected CCustomSubscriber { 
protected:
	virtual bool OnRegistering(CCustomPublisher * pPublisher)
	{// Permit single registration only
		return rcRegistration = ( get_Publisher () )? false : true;
	}
	// OR Permit unregistration and re-registration only
	//virtual bool OnRegistered(CCustomPublisher* pPublisher)
	//{	 
	//	CCustomPublisher* m_pPublisher = get_Publisher();
	//	if (m_pPublisher && (m_pPublisher != pPublisher)) m_pPublisher->UnRegisterSubscriber(this);
	//	set_Publisher( pPublisher ); // than apply registration
	//	return rcRegistration = true;
	//}

	///////////////////////////////////////////////////////////////////////////
	// CSubscriber interface
	CSubscriber() {}
	CSubscriber(CPublisher* pPublisher, UINT ID_OBJ) { 	SelfRegister(pPublisher, ID_OBJ); }
	virtual bool SelfRegister(CPublisher* pPublisher, UINT ID_OBJ)
	{
		CCustomPublisher* pCustomPublisher = reinterpret_cast<CCustomPublisher*>(pPublisher);
		return (!pCustomPublisher)? false : (CCustomSubscriber::_SelfRegister(pCustomPublisher, ID_OBJ));
	}
};
Сейчас использую очень несколько другие классы, которые тоже позволяют выполнять PUSH-доставку широковещательно всем подписчикам, мультикастом, или direct. Кроме того, классы позволяют создавать как контейнеры (контейнер является подписчиком для вышележащего по иерархии паблишера, так и содержит список своих подписчиков. Т.е. одновременно он и подписчик и паблишер рангом пониже ), так и отдельные сабскрайберы. Короче, я про это в резюме версии 100.1 много написал.

Так вот, братцы, может, и правда это всё ламерство убрать из резюме :shock: ? Убрать ссылки на сей колоссальный труд? :lol: Неактуально?

Спасибо.

это зависит...

Добавлено: 24 май 2004, 10:48
Проф. Преображенский
Обычно работодатель любит, чтобы резюме точно соответствовало тому, что он вывесил (даже если там немыслимый компот и реальная работа потом совсем не то). Кроме того он не любит, когда в резюме что-то лишнее и непонятное. Поэтому такая частность, как эти твои классы могут повредить.
Но иногда ищут просто квалифицированного спеца и лишняя информация не помешает. Для широкой рассылки тем более. Для прицельной надо править аккуратно.

Добавлено: 24 май 2004, 16:24
vg
Да, спасибо, runner, за пояснения. Ясно, что такого рода "мелочёвка" мало может заинтересовать клерка. Только спеца.

Но я не случайно пропостил именно в "программизм", а не в "работу".
Мне интересно знать мнение "канадских" программеров С++, в какой мере их архитектура приложений с ГУИ соответствует парадигмам ООП, в части обработки сообщений о некоторых состояниях приложения в рантайм. То, что я пропостил даёт канву (реальная имплементация не на много сложнее) для создания таких архитектур. Кстати, это вообще ни коим боком не относится к приложениям, сделанным в Borland C++ Builder, или Delphi. :lol: Там это ни в коей мере не нужно. :lol: Там это излишне.

Вопрос мой был в том, действительно ли я на столько ламер в этой части, что не следует упоминать в резюме, что, мол, были разработаны такие-то классы, и теперь всё моё ГУИ строится исключительно на этой модели. Имеются в виду здесь достаточно сложные приложения ГУИ с большим числом окон, контролов. И когда сообщения об изменении состояния системы (приложения) могут (должны) получать не только оконные объекты (ака CWnd derived в MFC), но любые. Достаточно, чтобы класс наследовал от подписчика CSubscriber. Например, это может быть некий класс CDataBaseSrore : public CSubscriber, который умеет теперь получать и обрабатывать сообщения типа, ON_DATA_READ, ON_DATA_UPDATE, и т.п.

парадигмы ООП

Добавлено: 27 май 2004, 12:43
Проф. Преображенский
Имхо, знание парадигм ООП - не есть особое достоинство, это сейчас обязательно. Поэтому лучше кратко упомянуть в резюме, если очень хочется, что это имеет место и отложить подробности до интервью.
Для интермедиэйт и сеньора разработка такого рода классов - это норма, а для начинающего кодировщика ГУЕв может быть оверквалифаед :wink: .

Добавлено: 27 май 2004, 14:04
vg
Для интермедиэйт и сеньора разработка такого рода классов - это норма, а для начинающего кодировщика ГУЕв может быть оверквалифаед
Ок! Шоб не было оверквалифаед уберёмс. :lol: