Faux implementations can apply to small parts of an application, such as a class in an object-oriented environment, or to large environments, such as software that emulates hardware. In the first case, the Faux Implementation pattern can aid developers who are doing parallel development. In the latter case, you could create an environment for an application that the application never expected to encounter, such as running an old Atari 2600 game on a Pentium 4 computer.
A fully specified architecture and ambitious programmers can lead to an especially productive environment if the developers are willing to rely on a specification rather than a concrete component deliverable from another team. Consider a simple case that contains two major subsystems ”a viewer for musical scores and a component that gathers the musical score from an input stream. In this case, an architecture document specifies interfaces for the view and reader component. The architecture also specifies the format of an Extensible Markup Language (XML) document that the components use to communicate a musical score with, as shown in Figure 14-1.
With the hand-off document and interface to the music reader specified, the developer building the music-viewing component can develop the entire component without ever having to use a real implementation of the music reader. As long as both developers implement the interface and the document specification from the architecture, integration between the two real components can wait until late in the development cycle.
The developer of the music viewer can spend the first few days of their development creating a simple implementation of the interface that returns documents from a file system. They can create hundreds of test documents and route them through their faux implementation to fully test the music viewer without ever seeing a real implementation of the music reader. In this case, developers use the Faux Implementation pattern as the basis of TestMusicReader so that they can test the MusicViewer component without ever receiving ProductionMusicReader . TestMusicReader is a faux implementation of MusicReader because it adheres properly to the interface but is not what the architects had in mind when they specified the architecture.
Faux implementations do not only apply to classes and granular components. Consider the revival of old console games through emulation . Emulators implement the interface and communication techniques defined by a particular device. For example, the Atari 2600 implemented an interface and defined a protocol to facilitate the communication between a game on a cartridge and the game console for processing. Now, consider if you could implement the same interface in software and then take an image of the game on the game cartridge and plug them together through software. This is emulation.
The Atari 2600 example is a bit different from the type of emulation you use to emulate an environment for testing programs. Consider the scenario of building applications for a wireless phone. Rather than downloading your applications to the phone to test it, you run the application in a software environment that emulates the phone. Once you have the application working, you download it to the wireless phone and run the application, just in case there are flaws in the emulator. Figure 14-2 shows the emulation scenario in the form of a class diagram.
The developer of WirelessApplication builds their application based on DeviceSoftwareSpecification . Phones implement this specification, but the specification is detailed enough so as to allow developers to also use WirelessPhoneEmulator . This software phone emulator is built into Integrated Development Environments ( IDEs ), such as the Sun ONE Studio Enterprise Edition, so that you never have to load your application onto a real phone for testing.
In essence, the practice of emulation is an implementation of the Faux Implementation pattern. You are using software to pretend it is a piece of hardware so you can test applications or run games without even owning the hardware. In many cases, the creators of the original hardware, such as the Atari 2600, could never have imagined the widespread use of emulation. Fortunately, using clean, predictable interfaces allows people to reverse-engineer them and create alternate implementations of the interface.