CS636 Thinking about Layers
Examining the Pizza and Music systems that will be the basis of
future projects. You should read this before the
Here are some coding rules to set up serious client-server applications
(and later, web applications) using layering, applicable to pizza1, and
music1, pizza2, and (in the future) the webapps pizza3 and music3. Note
that “business logic layer” is just another name for “service layer”. Let
us know if you disagree with any of my interpretations in the following.
- System.in and System.out are only for talking to the user, only in
the presentation layer. This means no System.out.println's in
the lower layers, except temporarily for debugging.
- Don't ever call System.exit() from anywhere but main().
Instead, generate an exception to tell the top-level app what's
- The business layer service APIs should be able to handle all the
needed actions for the apps in the presentation layer, i.e., the apps
should not call the DAO APIs directly.
- The DAO should provide all the DB actions needed by the
business/service layer, in a way natural to the business layer
requirements. No SQL knowledge should be needed by the business
- No service or DAO object should construct another service or DAO
object (to follow IOC, inversion of control pattern), and the service
and DAO objects should all be set up by special code.
- Errors in the DAO layer should throw SQLException (or, for JPA
implementations, JPA’s subclass of RuntimeException), caught in the
business logic layer and usually rethrown as ServiceException.
- Errors in the business logic layer should throw ServiceException,
caught in the presentation layer.
- Don't call up to a higher layer (i.e., use an upcall): we are using
pure call-down layers.
- Consistent with the earlier rules, as much code as possible should
be pushed down from the presentation layer to the logic layer.
The presentation layer has the minimal code needed to interface
to the user.
- Consistent with the earlier rules, all database handling code should
be pushed down to the DAO layer from the logic layer. However,
the DAO code should make no business decisions. The facts from the
data should presented by the DAO to the BL, and the BL should be
completely in charge of specifying changes to the database.
- We are using a “stateless service layer”, in the sense that the
service layer code (and DAO code) has no fields holding domain data
across multiple service layer calls. The presentation layer is
allowed to hold domain data across multiple service calls (it's
- Many domain objects represent (as "scratch copies") entity instances
in the database, or data on the way to the database, and should have a
unique id "id" that corresponds to its PK in the database.
- However, not all data from the database needs to be represented by
domain objects. The ones that are needed are the ones that are
natural to the business layer coding needs. Domain data can be
held in simple ints, Strings, etc., as for example the current day
number in Pizza.
- Domain objects may have related information from the database in
addition to what is in the entity table row. In particular, Sets
can hold multi-valued attributes or other N-1 related data for the
entity instance. They can be Sets of other domain objects or just Sets
of Strings, say.
- Domain objects may be created in the service or DAO layer (from
database data). They should not be created or modified in the
- Domain objects can move across layers, carrying data around.
They do not themselves constitute a layer in the sense of the three
layers discussed above, but since the heart of the webapp is the
service layer, the domain objects are most closely tied to the service
- Some domain objects such as Cart in the music project, help
represent data for one user not yet committed to the database.
- If a domain object (one directly related to database data) has
business-method mutators (used after its original creation), it is a
good idea to provide another invariant object (a “transfer object”) to
carry the database-related data to the presentation layer, as
PizzaOrderData does for PizzaOrder. This is especially true if there
are multiple presentation layers using the system, with different
subsets of needed data. Note that this is a best practice, not always
heeded in the rush of development (i.e., you can send Invoices to
presentation in music1, for example, without losing credit.)
For pizza2 and music2 (and for future):
1. All database statements are inside of some
2. Transactions are started and committed or
rolled back in the service layer, because it's in charge of the business
logic and transaction boundaries are important to the semantics of
. 3. A transaction must never include user input or
output. Thus the service layer needs to finish a transaction before
returning from its service-API call.
4. It is particularly important to mark local helper
methods as private in the service layer. They don't need to start
a transaction because (usually) one should already be in progress when
they are called.