Using Code ExamplesThis book is here to help you get your job done. In general, you may We appreciate, but do not require, attribution. An attribution If you feel your use of code examples falls outside fair use or the |
Wednesday, October 21, 2009
Using Code Examples
Removing Hypersonic
Removing HypersonicHypersonic is a great database for testing an application, but it isn't production ready. In Chapter 4, you saw how to switch to another database. If you aren't using Hypersonic, you can remove the entire service. Hypersonic doesn't listen for connections from the outside world unless you ask it to, so you don't need to worry about securing it. However, you might not want an extra relational database hanging around in memory. It's fairly lightweight, but you'll probably be better off just getting rid of it. How do I do that?The hsqldb-ds.xml file not only configures the Hypersonic datasources, but also it has the MBeans that control the entire embedded database service. Removing this file will remove all traces of Hypersonic. It sounds trivial, and it would be except that several other services depend on Hypersonic. We'll go through the changes now, assuming you have created a MySQL database as shown in Chapter 4, and that the ToDo application is already switched over to using that. The first service is the EJB timer service, in ejb-deployer.xml. You should replace the reference to DefaultDS with a reference to the correct datasource. In Chapter 4, we chose the name MySqlDS. The change is simple:
JMS also requires persistence changes to be made. If you aren't using JMS and you chose to remove it from your configuration, you can stop here. Otherwise, go to the deploy/jms directory and look for hsqldb-jdbc2-service.xml and hsqldb-jdbc-state-service.xml. hsqldb-jdbc2-service.xml controls message persistence. You can remove it completely and replace it with a database-specific file from docs/examples/jms. For MySQL, copy mysql-jdbc2-service.xml into the jms directory. hsqldb-jdbc-state-service.xml isn't quite so simple. There are no database-specific templates for this. You'll need to update the datasource dependency manually:
This datasource reference needs to be the same as the datasource you saw earlier, in the jbossmq security domain in login-config.xml. You'll want to update that now too:
The final dependency on DefaultDS is uuid-key-generator.sar. If you aren't using the JBoss UUID key generator, remove this service from the deploy directory. If you are, you'll need to update the META-INF/jboss-service.xml file to reference the preferred datasource:
Unfortunately, this service is not provided in exploded form, so you'll have you unpack the archive to get to it. What just happened?You removed Hypersonic and updated, or removed, the services that depend on it. All of the persistent services will write their tables into the new database. If you've kept them around and restarted JBoss, you should find several new database tables in your external database:
You could have saved yourself some trouble by creating a replacement DefaultDS. Then it wouldn't have been necessary to change all the datasource references. However, it's important to be explicit about your configuration in a production machine. The extra effort is worth the peace of mind of knowing that all your persistent services are configured correctly. |
Section 2.8. Lists and Tuples
2.8. Lists and TuplesLists and tuples can be thought of as generic "arrays" with which to hold an arbitrary number of arbitrary Python objects. The items are ordered and accessed via index offsets, similar to arrays, except that lists and tuples can store different types of objects. There are a few main differences between lists and tuples. Lists are enclosed in brackets ( [ ] ) and their elements and size can be changed. Tuples are enclosed in parentheses ( ( ) ) and cannot be updated (although their contents may be). Tuples can be thought of for now as "read-only" lists. Subsets can be taken with the slice operator ( [] and [ : ] ) in the same manner as strings. >>> aList = [1, 2, 3, 4] Slice access to a tuple is similar, except it cannot be modified: >>> aTuple = ('robots', 77, 93, 'try')You can find out a lot more about lists and tuples along with strings in Chapter 6. |
7.3. Good Routine Names
< Free Open Study > |
7.3. Good Routine NamesA good name for a routine clearly describes everything the routine does. Here are guidelines for creating effective routine names: Cross-Reference For details on naming variables, see Chapter 11, "The Power of Variable Names." Describe everything the routine does In the routine's name, describe all the outputs and side effects. If a routine computes report totals and opens an output file, ComputeReportTotals() is not an adequate name for the routine. ComputeReportTotalsAndOpen-OutputFile() is an adequate name but is too long and silly. If you have routines with side effects, you'll have many long, silly names. The cure is not to use less-descriptive routine names; the cure is to program so that you cause things to happen directly rather than with side effects. Avoid meaningless, vague, or wishy-washy verbs Some verbs are elastic, stretched to cover just about any meaning. Routine names like HandleCalculation(), PerformServices(), OutputUser(), ProcessInput(), and DealWithOutput() don't tell you what the routines do. At the most, these names tell you that the routines have something to do with calculations, services, users, input, and output. The exception would be when the verb "handle" was used in the specific technical sense of handling an event.
In other cases, the verb is vague because the operations performed by the routine are vague. The routine suffers from a weakness of purpose, and the weak name is a symptom. If that's the case, the best solution is to restructure the routine and any related routines so that they all have stronger purposes and stronger names that accurately describe them. Don't differentiate routine names solely by number One developer wrote all his code in one big function. Then he took every 15 lines and created functions named Part1, Part2, and so on. After that, he created one high-level function that called each part. This method of creating and naming routines is especially egregious (and rare, I hope). But programmers sometimes use numbers to differentiate routines with names like OutputUser, OutputUser1, and OutputUser2. The numerals at the ends of these names provide no indication of the different abstractions the routines represent, and the routines are thus poorly named. Make names of routines as long as necessary Research shows that the optimum average length for a variable name is 9 to 15 characters. Routines tend to be more complicated than variables, and good names for them tend to be longer. On the other hand, routine names are often attached to object names, which essentially provides part of the name for free. Overall, the emphasis when creating a routine name should be to make the name as clear as possible, which means you should make its name as long or short as needed to make it understandable. To name a function, use a description of the return value A function returns a value, and the function should be named for the value it returns. For example, cos(), customerId.Next(), printer.IsReady(), and pen.CurrentColor() are all good function names that indicate precisely what the functions return. Cross-Reference For the distinction between procedures and functions, see Section 7.6, "Special Considerations in the Use of Functions," later in this chapter. To name a procedure, use a strong verb followed by an object A procedure with functional cohesion usually performs an operation on an object. The name should reflect what the procedure does, and an operation on an object implies a verb-plus-object name. PrintDocument(), CalcMonthlyRevenues(), CheckOrderlnfo(), and RepaginateDocument() are samples of good procedure names. In object-oriented languages, you don't need to include the name of the object in the procedure name because the object itself is included in the call. You invoke routines with statements like document.Print(), orderInfo.Check(), and monthlyRevenues.Calc(). Names like document.PrintDocument() are redundant and can become inaccurate when they're carried through to derived classes. If Check is a class derived from Document, check.Print() seems clearly to be printing a check, whereas check.PrintDocument() sounds like it might be printing a checkbook register or monthly statement, but it doesn't sound like it's printing a check. Use opposites precisely Using naming conventions for opposites helps consistency, which helps readability. Opposite-pairs like first/last are commonly understood. Opposite-pairs like FileOpen() and _lclose() are not symmetrical and are confusing. Here are some common opposites: Cross-Reference For a similar list of opposites in variable names, see "Common Opposites in Variable Names" in Section 11.1.
Establish conventions for common operations In some systems, it's important to distinguish among different kinds of operations. A naming convention is often the easiest and most reliable way of indicating these distinctions. The code on one of my projects assigned each object a unique identifier. We neglected to establish a convention for naming the routines that would return the object identifier, so we had routine names like these:
The Employee class exposed its id object, which in turn exposed its Get() routine. The Dependent class exposed a GetId() routine. The Supervisor class made the id its default return value. The Candidate class made use of the fact that the id object's default return value was the id, and exposed the id object. By the middle of the project, no one could remember which of these routines was supposed to be used on which object, but by that time too much code had been written to go back and make everything consistent. Consequently, every person on the team had to devote an unnecessary amount of gray matter to remembering the inconsequential detail of which syntax was used on which class to retrieve the id. A naming convention for retrieving ids would have eliminated this annoyance. |
< Free Open Study > |
Section 26.6. Singletons
26.6. SingletonsIn general, Eclipse is able to concurrently run multiple versions of the same plug-in. That is, org.eclipsercp.hyperbola version 1.0 and 2.0 can both be installed and running at the same time. This is part of the power of the Runtime's component model. Dependent plug-ins are bound to particular versions of their prerequisites and see only the classes supplied by them. There are cases, however, where there really should be only one version of a given plug-in in the system. For example, SWT makes certain assumptions about its control over the display and main thread. SWT cannot cohabitate with other SWTs. More generally, this occurs wherever one plug-in expects to have exclusive access to a global resource, whether it be a thread, an OS resource, a network port, or the extension registry namespace. To address this, OSGi allows a bundle to be declared as a singleton. The bundle in the example below is marked as a singleton. This tells OSGi to resolve at most one version of the bundle. All other version constraints in the system are then matched against the chosen singleton version. org.eclipse.core.runtime/MANIFEST.MF The most common reason to mark a plug-in as a singleton is that it declares extensions or extension points. The extension registry namespace is a shared resource that is populated by bundle ids. If we allowed multiple versions of the same bundle to contribute to the registry, interconnections would be ambiguous. By default, bundles that declare extensions or extension points but do not have a MANIFEST.MF are marked as singletons. If you have a MANIFEST.MF, you should annotate it accordingly. |
Walking Through Scenarios
| [ Team LiB ] |
Walking Through ScenariosTo cross-check all these decisions, we have to constantly step through scenarios to confirm that we can solve application problems effectively. Sample Application Feature: Changing the Destination of a CargoOccasionally a Customer calls up and says, "Oh no! We said to send our cargo to Hackensack, but we really need it in Hoboken." We are here to serve, so the system is required to provide for this change. Delivery Specification is a VALUE OBJECT, so it would be simplest to just to throw it away and get a new one, then use a setter method on Cargo to replace the old one with the new one. Sample Application Feature: Repeat BusinessThe users say that repeated bookings from the same Customers tend to be similar, so they want to use old Cargoes as prototypes for new ones. The application will allow them to find a Cargo in the REPOSITORY and then select a command to create a new Cargo based on the selected one. We'll design this using the PROTOTYPE pattern (Gamma et al. 1995). Cargo is an ENTITY and is the root of an AGGREGATE. Therefore, it must be copied carefully; we need to consider what should happen to each object or attribute enclosed by its AGGREGATE boundary. Let's go over each one:
Notice that we have copied everything inside the Cargo AGGREGATE boundary, we have made some modifications to the copy, but we have affected nothing outside the AGGREGATE boundary at all. |
| [ Team LiB ] |
Section 13.6. Summary
13.6. SummaryIn this chapter, we covered some of the history of Ruby on Rails, including the fact that Ruby on Rails is separated into Ruby and Rails. From there, we covered the process of installing Ruby and then installing Rails and viewing the default page. Then we covered how to create an empty project and fire up the included WEBrick web server and access a MySQL database, albeit with a little difficulty. In essence, the purpose of this chapter is to point the reader in the right direction when in search of an environment that supports Ajax. |