470 likes | 609 Vues
This document outlines the practices essential for effective component design in software engineering. Written by Barn-Wan Li from Microsoft Research Asia, it explores the evolution of software components since their conceptualization in the 1960s, focusing on encapsulation, reuse, and clearer contracts. It distinguishes components from objects, delves into inheritance, polymorphism, and the impacts of these concepts on encapsulation. Best practices emphasize maintaining a clear interface, ensuring minimal changes to implementation, and facilitating easier integration for new users, ultimately leading to efficient software development.
E N D
Practices of Good Component Design Microsoft Research Asia Advanced Technology
Introduction • Barn-Wan Li • Born in Toronto, Canada • B.A., University of California, Berkeley • Microsoft Silicon Valley Campus • Microsoft Research Asia, Beijing
Software Components • Conceptualized in the 60s • Improve encapsulation and reuse
Software Components • Conceptualized in the 60s • Improve encapsulation and reuse
Software Components • Conceptualized in the 60s • Improve encapsulation and reuse PowerPoint Word Excel OfficeArt Drawing
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
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
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
Inheritance for Reuse • class Car • { • };
Inheritance for Reuse • class Car • { • };
Inheritance for Reuse • class Car • { • }; • class Racecar : public Car • { • }; • class Truck : public Car • { • }; • class Taxi : public Car • { • };
Inheritance for Reuse • class Truck • { • };
Inheritance for Reuse • class Truck • { • }; • class FireHydrant • { • }; • class FireTruck : • public Truck, • public FireHydrant • { • };
Inheritance for Reuse X • class Truck • { • }; • class FireHydrant • { • }; • class FireTruck : • public Truck, • public FireHydrant • { • };
Inheritance for Reuse • polymorphism • incremental behavior changes • self-recursive down-calls
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; } };
Inheritance for Reuse • breaks encapsulation • breaks data hiding • breaks implementation hiding • compile-time and run-time dependencies • syntactic and semantic fragility
class LinkList { … }; class MyObjList : public LinkList { … }; 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 { … }; 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; 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; 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; Reuse and Sharing - Templates X
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; • };
What is a Component • different layers • within a single system • sharable library • crossing application boundaries • crossing system boundaries • encapsulation and abstraction
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.
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
Example – Face Detection • BOOL DetectFace(HBITMAP image, CArray<RECT> &faces, CArray<long> &angles);
Example – Face Detection • BOOL DetectFace(HBITMAP image, CArray<RECT> &faces, CArray<long> &angles); • BOOL DetectFace(HBITMAP image, int &facenum, RECT *faces[], long *angles[]);
Example – Face Detection • BOOL 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);
Example – Face Detection • BOOL 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);
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 }
interface IFaceDetector { HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces); }; Face Detection Interface
interface 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); }; Face Detection Interface
interface 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); }; Face Detection Interface
interface 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); }; Face Detection Interface
interface 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); }; Face Detection Interface
Face Detection Interface Application Face Detection Component
Face Detection Interface Application IFDImage IFaceDetector IFDFaceEnum IFDFace Face Detection Component
interface IFaceDetector { HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces); }; Face Detection Implementation
interface IFaceDetector { HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces); }; class CFaceDetector : public IFaceDetector { HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces); }; Face Detection Implementation
interface IFaceDetector { HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces); }; class CFaceDetector : public IFaceDetector { HRESULT Detect(IFDImage *pImage, IFDFaceEnum **ppFaces); }; Face Detection Implementation HRESULT CFaceDetector::Detect(IFDImage *pImage, IFDFaceEnum **ppFaces) { if (pImage == NULL || ppResult == NULL) return E_INVALIDARG; : * ppFaces = new CFDFaceEnum; return E_SUCCESS; }
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); }; Face Detection Usage
Face Detection Interface Application IFDImage IFaceDetector IFDFaceEnum IFDFace CFaceDetector CFDFaceEnum CFDFace Face Detection Component
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