19.1. Simulation ServiceCanned, Double, Dummy, Fake, Masquerade, Mock, Service, Shunt, Sim, Simulation, Stub Figure 19-1. Simulation Service19.1.1. Developer StoryDave is beginning to work on a new email application. Eventually, the server will need to expose a mail API, so the browser can query for recent messages and upload new ones. However, that will require email expertise, and Dave wants to focus on the user interface in the browser for now. Thus, he hardcodes the responses he'd like in a "fake" server-side service. This allows him to proceed with user-interface development while his colleague takes care of the real server implementation. 19.1.2. ProblemHow can you develop the browser script in parallel with the services it uses? 19.1.3. SolutionDevelop the browser application against "fake" web services that simulate the actual services used in production. A Simulation Service is typically a hardcoded response that ignores any input parameters. So instead of: $taxRate = calculateTaxRate($userId, $year); print $taxRate; a Simulation Service would just say: print "0.1235"; It's also possible to do all this in a browser. If you use a library to perform Web Remoting (Chapter 6), you could make the implementation produce a hardcoded response, and ignore the server altogether. In some cases, you might make the service more flexible; e.g., it can expose an operation to let the browser tell it what to output later on. Simulation Service decouples the server and browser components of the application. Once the interface is defined, each can be developed in parallel. Moreover, this pattern paves the way for an agile process for building the application, based loosely on concepts such as Test-Driven Design (TDD) and lean manufacturing.
Conventional web development is usually a bottom-up approach: first comes the database, then the data layer to access it, then the business components on top of that, and finally the user interface. This sequence might seem like the most logical thing to do, given the dependency relationships involved. But the problem is that the user interface is really the whole point of the application, so there's a good argument for starting there instead. For a given feature, flesh out the user interface and use that work to drive the service interface. So instead of designing the server side first and forcing the browser script to work with whatever interface arises, let the needs of the browser script drive the interface design. Consequently, the service will not only contain the precise functionality required by the browser, but also expose it with the most suitable interface. Starting development in the browser sounds like a good idea until you realize the browser depends on the service, which doesn't yet exist! That's where a Simulation Service comes in: it lets you define what the service offers, not how the service achieves it. As you develop the browser script, you'll continue to come across refinements to the servicean extra operation here, a different response format there. In each case, changing the Simulation Service is usually as simple as editing the hardcoded response. Once you're confident with the requirements for the Service, youor someone elsecan go build the real thing. Another application is in Browser-Side Tests (see later in this chapter). When testing a browser component, it's important to test only the component itself, and not the services it depends on. Imagine you're testing a browser component that renders news arriving from an RSS web service. An automated test could then interrogate the DOM and run a bunch of assertions to ensure it was formatted correctly. But if the component uses the real service, the resulting DOM will reflect the news of the hour. A human could manually verify it, but automation wouldn't be possible. A hardcoded response would eliminate that problem, allowing the assertions to be consistent with the simulated RSS. Furthermore, there's no dependence on the real implementationno matter how complex the actual search algorithm, the rendering component will always be tested on its own merit. 19.1.4. Decisions19.1.4.1. How will you switch between different services?It's easy enough to create a Simulation Service, but how do you switch between the simulation and the real thing? And, how do you switch between different simulation services, since you might prefer one or the other for different tasks. Right now, there's no easy answer to that because there's no real support in the way of tools and libraries. Where the practice of Simulation Service is followed, most developers probably switch over to a real service in the most brute-force way possible: they edit the code. But doing so means there's a manual step involved in order to test or deploy. Here are a few ways to make the process more manageable:
19.1.5. Code Example: Simulation ServiceThe Ajax Pattern Reader (http://ajaxify.com/run/reader/) runs against a couple of Cross-Domain Proxy (Chapter 10) services. They fetch information from the AjaxPatterns.org web site and return them in a format easily parsed by the browser. For development purposes, the Basic version (http://ajaxify.com/run/reader/) uses Simulation Service. The first service produces a Plain-Text Message (Chapter 9) containing the patterns in a pipe-separated list. A hand-created simulation (http://ajaxify.com/run/reader/patternList.phtml) is used instead of fetching the page from AjaxPatterns.org, parsing the HTML, and reformatting it. Periodic Refresh|||One-Second Spotlight|||Slider For comparison, the real service outputs a list that looks similar, but is much longer, and, of course, not hardcoded (http://ajaxify.com/run/reader/logging/realService/patternList.phtml). Ajax Stub|||Browser-Side Cache|||Browser-Side Templating||| ... |||XML Message|||XMLHttpRequest Call Similarly, there's a simulation of the summary service (http://ajaxify.com/run/reader/patternSummary.phtml?patternName=Slider), whose job is to produce an HTML Message summarizing a given pattern. The simulation includes some rudimentary logic to make the response vary according to the input: <? $patternName = urlDecode($_GET["patternName"]); ?> <h1><?= $patternName ?></h1> <? if ($patternName=="Periodic Refresh") { ?> With periodic refresh, it's all about the timer. <? } else if ($patternName=="Slider") { ?> <p>The slider slides from left to right.</p> ... <? } else { print ("Text goes here."); } ?> The output from the real service is in the same format (http://ajaxify.com/run/reader/logging/realService/patternSummary.phtml?patternName=Slider), but as with the list service, it's fetched from AjaxPatterns.org in real-time. 19.1.6. Related Patterns19.1.6.1. Service TestA Simulation Service is a good starting point for a real service. You might begin developing a Service Test (see later) against a Simulation Service, then evolve both into a real service and test. 19.1.7. Want to Know More?
|