Practices of Good Component Design
Microsoft Research Asia Advanced Technology
2
Introduction
Barn-Wan Li
Born in Toronto, Canada
B.A., University of California, Berkeley
Microsoft Silicon Valley Campus
Microsoft Research Asia, Beijing
3
Software Components
Conceptualized in the 60s
Improve encapsulation and reuse
4
Software Components
Conceptualized in the 60s
Improve encapsulation and reuse
5
Software Components
Conceptualized in the 60s
Improve encapsulation and reuse
PowerPoint Word Excel
OfficeArt Drawing
6
How is a Component different than an Object?
Object-oriented Programming History– created in the 60s
• real-world modeling and metaphors• microcosm of objects with messages
7
How is a Component different than an Object?
Object-oriented Programming History– created in the 60s
• real-world modeling and metaphors• microcosm of objects with messages
– the promise of the 80s• combining the concept of components for
abstraction and reuse
8
How is a Component different than an Object?
Object-oriented Programming History– created in the 60s
• real-world modeling and metaphors• microcosm of objects with messages
– the promise of the 80s• combining the concept of components for
abstraction and reuse
– fear in the 90s• fragile software reuse with objects
9
Inheritance for Reuse
class Car
{
};
10
Inheritance for Reuse
class Car
{
};
11
Inheritance for Reuse
class Car
{
};
class Racecar : public Car
{
};
class Truck : public Car
{
};
class Taxi : public Car
{
};
12
Inheritance for Reuseclass Truck
{
};
13
Inheritance for Reuseclass Truck
{
};
class FireHydrant
{
};
class FireTruck :
public Truck,
public FireHydrant
{
};
14
Inheritance for Reuseclass Truck
{
};
class FireHydrant
{
};
class FireTruck :
public Truck,
public FireHydrant
{
};
15
Inheritance for Reuse
• polymorphism• incremental behavior changes• self-recursive down-calls
16
Inheritance for Reuse
• polymorphism• incremental behavior changes• self-recursive down-calls
class Car {
void Stop() { SayMessage(); }
virtual void SayMessage()
{ cout << “Bye!” << endl; }
};
class Taxi : public Car {
virtual void SayMessage()
{ cout << “50 RMB please” <<
endl; }
};
17
Inheritance for Reuse
18
Inheritance for Reuse
19
Inheritance for Reuse
breaks encapsulation
breaks data hiding
breaks implementation hiding
compile-time and run-time dependencies
syntactic and semantic fragility
20
Reuse and Sharing - Templates
class LinkList
{
…
};
class MyObjList : public LinkList
{
…
};
21
Reuse and Sharing - Templates
template <class T>
class LinkList
{
…
T *operator -> () { return &m_t; }
T m_t;
};
class MyObj
{
…
};
typedef LinkList<MyObj> MyObjList;
class LinkList
{
…
};
class MyObjList : public LinkList
{
…
};
22
Reuse and Sharing - Templates
class LinkList
{
…
};
class MyObjList : public LinkList
{
…
};
class MyObjTree : public BinTree
{
…
};
template <class T>
class LinkList
{
…
T *operator -> () { return &m_t; }
T m_t;
};
class MyObj
{
…
};
typedef LinkList<MyObj> MyObjList;
typedef BinTree<MyObj> MyObjTree;
23
Reuse and Sharing - Templates
class LinkList
{
};
class MyObjList : public LinkList
{
};
class MyObjTree : public BinTree
{
};
class MyObjList : public MyObj, public LinkList
{
};
template <class T>
class LinkList
{
…
T *operator -> () { return &m_t; }
T m_t;
};
class MyObj
{
…
};
typedef LinkList<MyObj> MyObjList;
typedef BinTree<MyObj> MyObjTree;
24
class LinkList
{
};
class MyObjList : public LinkList
{
};
class MyObjTree : public BinTree
{
};
class MyObjList : public MyObj, public LinkList
{
};
template <class T>
class LinkList
{
…
T *operator -> () { return &m_t; }
T m_t;
};
class MyObj
{
…
};
typedef LinkList<MyObj> MyObjList;
typedef BinTree<MyObj> MyObjTree;
Reuse and Sharing - Templates
25
Reuse and Sharing - Containment
class LinkList
{
…
void Set(Object *pobj) { m_pObject = pobj; }
Object *Get() { return m_pObject; }
Object *m_pObject;
};
class Object
{
…
Object() { m_linklist.Set(pobj); }
Object *Next() { return m_linklist.Next().Get(); }
…
LinkList m_listlist;
};
26
What is a Component
different layers– within a single system– sharable library– crossing application boundaries– crossing system boundaries
encapsulation and abstraction
27
How is a Component Design “Good”?
• the component’s interface upholds a clear “contract”.
• changes to the implementation of the component do not require changes in the code that uses it.
• the component has reuse value when the time required to understand and integrate for a new user is faster and easier than to rewrite it.
28
Life-time of a Component
• conception of an abstract layer, a sharable service, or a piece of code that has reuse value
• understanding the requirements and limitations
• designing the interfaces• implementation• creating the user of the component that
wraps and tests the implementation
29
Example – Face DetectionBOOL DetectFace(HBITMAP image,
CArray<RECT> &faces, CArray<long> &angles);
30
Example – Face DetectionBOOL DetectFace(HBITMAP image,
CArray<RECT> &faces, CArray<long> &angles);
BOOL DetectFace(HBITMAP image, int &facenum, RECT *faces[], long *angles[]);
31
Example – Face DetectionBOOL DetectFace(HBITMAP image,
CArray<RECT> &faces, CArray<long> &angles);
BOOL DetectFace(HBITMAP image, int &facenum, RECT *faces[], long *angles[]);
ULONG DetectFaceNumber(HBITMAP image);
BOOL DetectFace(HBITMAP image, int index, RECT *face, long *angle);
32
Example – Face DetectionBOOL DetectFace(HBITMAP image,
CArray<RECT> &faces, CArray<long> &angles);
BOOL DetectFace(HBITMAP image, int &facenum, RECT *faces[], long *angles[]);
ULONG DetectFaceNumber(HBITMAP image);
BOOL DetectFace(HBITMAP image, int index, RECT *face, long *angle);
BOOL DetectFace(HDC image, int width, int height, int index, RECT *face, long *angle);
BOOL DetectFace(void pvBits, int width, int height, int bitsperpixel, int index, RECT *face, long *angle);
33
Introducing COM
• Component Object Model• interface == pure virtual class• may be more than one object• language independent
interface IUnknown
{
ULONG AddRef(); // reference counting
ULONG Release();
HRESULT QueryInterface(); // dynamic casting
}
34
Face Detection Interfaceinterface IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
35
Face Detection Interfaceinterface IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
interface IFDImage
{
HRESULT SetHBitmap(HBITMAP bitmap);
HRESULT SetHDC(HDC image, int width, int height);
HRESULT SetBits(void pvBits, int width, int height, int bitsperpixel);
};
36
Face Detection Interfaceinterface IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
interface IFDImage
{
HRESULT SetHBitmap(HBITMAP bitmap);
HRESULT SetHDC(HDC image, int width, int height);
HRESULT SetBits(void pvBits, int width, int height, int bitsperpixel);
};
interface IFDFaceEnum
{
HRESULT GetNum(ULONG *pNum);
HRESULT GetFace(int index, IFDFace **pFace);
};
37
Face Detection Interfaceinterface IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
interface IFDImage
{
HRESULT SetHBitmap(HBITMAP bitmap);
HRESULT SetHDC(HDC image, int width, int height);
HRESULT SetBits(void pvBits, int width, int height, int bitsperpixel);
};
interface IFDFaceEnum
{
HRESULT GetNum(ULONG *pNum);
HRESULT GetFace(int index, IFDFace **pFace);
};
interface IFDFace
{
HRESULT GetRect(RECT *pRect);
HRESULT GetAngle(long *pAngle);
};
38
Face Detection Interfaceinterface IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
interface IFDImage
{
HRESULT SetHBitmap(HBITMAP bitmap);
HRESULT SetHDC(HDC image, int width, int height);
HRESULT SetBits(void pvBits, int width, int height, int bitsperpixel);
};
interface IFDFaceEnum
{
HRESULT GetNum(ULONG *pNum);
HRESULT GetFace(int index, IFDFace **pFace);
};
interface IFDFace
{
HRESULT GetRect(RECT *pRect);
HRESULT GetAngle(long *pAngle);
HRESULT GetLeftEye(RECT *pRect);
HRESULT GetRightEye(RECT *pRect);
HRESULT GetAccuracy(long *pPercent);
};
39
Face Detection Interface
Face Detection Component
Application
40
Face Detection Interface
IFaceDetectorIFDImage
Face Detection Component
IFDFaceEnum IFDFace
Application
41
Face Detection Implementation
interface IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
42
Face Detection Implementation
interface IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
class CFaceDetector : public IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
43
Face Detection Implementation
HRESULT CFaceDetector::Detect(IFDImage *pImage, IFDFaceEnum **ppFaces)
{
if (pImage == NULL ||
ppResult == NULL)
return E_INVALIDARG;
:
* ppFaces = new CFDFaceEnum;
return E_SUCCESS;
}
interface IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
class CFaceDetector : public IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
44
Face Detection Usage
void main()
{
CComPtr<IFaceDetector> pDetector;
pDetector.CreateInstance(
CLSID_FaceDetector);
:
CComPtr<IFDFaceEnum> pResult;
pDetector->Detect(pImage, pResult);
:
}
interface IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
class CFaceDetector : public IFaceDetector
{
HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces);
};
45
Face Detection Interface
IFaceDetector
CFaceDetector
IFDImage
Face Detection Component
IFDFaceEnum
CFDFaceEnum
IFDFace
CFDFace
Application
46
Tips for Authoring a Component
• know your callers• check for parameter errors at external APIs , assert for
internal• avoid allocating memory that the caller must free• use existing types-- or create your own abstract
interfaces• aggregate types for reuse or to hide complexity
47