Issott_Common Design Patterns for Symbian OS-The Foundations of Smartphone Software_0470516356 (779879), страница 70
Текст из файла (страница 70)
The reasons for thisrange from pragmatic ones of engineering cost or risk, to business reasons(for example, licensing terms), to quality reasons (avoiding tight couplingbetween logically independent components).Each of the following kinds of problem demonstrates the same commonfactor: the need, for whatever reason, to make incompatible interfaceswork together, without changing existing components:• Preserving compatibilityWhen the legacy functionality provided by one component is madeobsolete by changes that, as your system evolves, introduce new,alternative functionality which meet at least the same requirements,clients relying on the legacy behavior must still be supported, if onlyfor a transitional period. For reasons of maintainability and code size,it may not be feasible to leave the old component in place alongsidethe newer version.• Wrapping components to ease portingFor existing components created for a different environment fromthe one you would like to use it in, it may be impossible or undesirable to make changes to the component.
This commonly ariseswhen integrating an industry-standard implementation of a specifictechnology.The interfaces presented to a component in the Symbian OS environment may be incompatible with what the component expects and,vice versa, the interfaces it presents may be incompatible with whatpotential Symbian OS clients of the component expect.For Symbian OS, the problem is complicated by the fact that nativeC++ interfaces are often not directly usable by ported componentswritten in standard C or C++; and standard C or C++ client interfacesof ported components are typically not directly usable by nativeSymbian OS clients.• Run-time adaptationDifferent components that all store state may present very differentsettings interfaces, but updating their settings may be the responsibilityof a single agent or service.
Hardwiring knowledge of each differentsettings interface into the updating service may be a poor designchoice, because it breaks modularity and flexibility by forcing atight coupling between many different components, possibly in quitedifferent parts of the system.ExampleHere we give an example for each of the three main uses of this patternidentified in the Description above.374MAPPING WELL-KNOWN PATTERNS ONTO SYMBIAN OSPreserving CompatibilitySymbian OS provides a communications database which is a persistentstore of the data required to configure communications components orto make connections with remote servers. Until Symbian OS v9.1, theinterface to this communications database was via the CCommsDatabaseprovided by the CommDB component that used the existing OS databaseservice DBMS.However, in Symbian OS v9.1, Symbian introduced a new componentcalled CommsDat that provides the same interface as the old CommDB,CCommsDatabase, but uses the Symbian OS Central Repository instead.This move makes use of the extra functionality provided by the CentralRepository compared to DBMS, such as standard tools to set up and configure the Central Repository during development as well as performanceenhancements such as caching repositories used by multiple clients.Since the underlying data is stored in a different place, the oldCommDB component cannot simply be maintained alongside the newCommsDat component.
Hence an alternative solution is needed whichmaintains compatibility to allow the legacy clients of CommDB to continue to work but which uses the new storage location.Wrapping Components to Ease PortingBefore Symbian OS v9.2, a native database component known as DBMSprovided all clients with a database service supporting the SQL specification. However, for v9.2, Symbian decided to port the open source SQLitecomponent25 to Symbian OS. One of the main reasons for this was thatthere was a requirement to provide more SQL features, such as triggers,that aren’t provided by DBMS.One decision taken early on was not to attempt to attempt to preservecompatibility with the old DBMS interface but instead to provide aninterface to SQLite alongside it.
This was because, whilst SQLite providedmore SQL functionality than DBMS, it didn’t, at the time, provide asuperset, i.e. there is some SQL functionality that DBMS supported thatSQLite didn’t.This left the following remaining challenges to be overcome to integrateSQLite into Symbian OS:• SQLite exposes a C-based API to clients but most Symbian OS programmers would expect a Symbian OS C++ API.• The databases accessed through SQLite need to comply with featuresof the operating system such as platform security as well as backupand restore.• SQLite expects a POSIX API to support it from underneath.25 www.sqlite.org .ADAPTER375Run-time AdaptationConsider the example of the remote management of a device, for example,a network operator configuring an email account on a subscriber’s device‘over the air’.
In this case, the provisioning agent or service needs toprovide a service to the network that is logically identical to a serviceprovided locally on the device. However, it’s often the case that thestandards-driven network interface is different to the interface providedlocally. Hence a means is needed to join the two interfaces together.That’s not the end of the problem though because clearly it wouldbe beneficial to deploy the same device management system on asmany devices as possible and they will vary in their support for featuressuch as email. This means that the central device management systemneeds to provide an extension point which discovers and loads plug-insrepresenting the components being remotely managed.
This extensionpoint defines a target interface into which we need to adapt existingcomponents.SolutionThis pattern decouples interfaces by creating an intermediary class, calledthe adapter, whose purpose is to adapt the interface presented by oneclass, the adaptee, and present the interface, known as the target, expectedby another class, the client, that wants to use the adaptee. This patterncan therefore be used to solve the problem of incompatibility betweentwo existing interfaces, without requiring changes to either interface.StructureFrom the client’s point of view, only the adapter need be visible or known;the implementation of the adapter and any details of the conversion ortranslation it performs using the adaptee can remain hidden from theclient.
In short, the client never doesn’t directly depend on the adaptee.This is achieved by the structure shown in Figure 9.8.DynamicsAt its simplest, an adapter is a wrapper. For example, methods areprovided that convert the API of a ported application and make it appearto be a native API to clients. Wrappers can also be used to convertoutbound system calls from the ported component to match nativeSymbian OS calls. The adapter simply redirects a call made through thetarget’s interface to a matching adaptee function (see Figure 9.9).In more complex cases, rather than simply wrapping each method, anadapter may be a complete component that intercepts and converts callsmade to one API into calls to a quite different API where there doesn’t376MAPPING WELL-KNOWN PATTERNS ONTO SYMBIAN OSFigure 9.8 Structure of the Adapter patternFigure 9.9 Dynamics of the Adapter pattern (simple)exist a close match for the target method called.
The adapter may evenneed to use multiple adaptees to satisfy the client’s request on the targetinterface (see Figure 9.10).In the most complex case, at run time the adapter may need to selectand load the adaptee that satisfies the client’s request on the targetinterface. In these more complex cases, it is common to implement theFigure 9.10 Structure of the Adapter pattern (complex)ADAPTER377adapter in its own DLL separately from the adaptees so that clients haveeven fewer dependencies on the adaptees.
This allows the adapter to usethe ECom service to dynamically load adapters as plug-ins at run time ifneeded.ImplementationThere’s little to say about the implementation of this pattern over andabove what’s already been said in the Structure and Dynamics sections.The one exception to this is if you wish to load adaptees at run time. Ifso, you should consider using Buckle (see page 252) to do this securelybased upon the ECom plug-in service provided by Symbian OS.ConsequencesPositives• This pattern is simple to implement and understand.• Development time is reduced by enabling the re-use of existingcomponents.• By preserving any pre-existing interfaces, you reduce your testingcosts because any existing tests written to use the target interface alsowork for the adaptees if the tests use the adapter.• It preserves decoupling between the target and adaptee interfaces.