Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Overview Last week we learned how to model dynamic system behavior in the design workflow when we looked at the sequence diagram, activity diagram, and the state diagram. This week we will continue our design efforts by looking at additional design activities. Specifically, software architecture, design patterns, and the data model. You will learn how to take a design class diagram and translate this into a relational database design for implementation. Outcomes After completing this week, you should be able to: Describe the various system architectures in use today, the types of businesses using them, and which architectures they use (e.g. three-tier, multi-tier, etc.). Define a design pattern and the purpose of a design pattern. Describe object persistence and how objects are stored in a database. Describe the process of transforming a class diagram into an entity relation diagram (ERD). 5.1 Designing the Software Architecture The term “software architecture” refers to the “big picture” structural aspects of an information system. The most important aspects of software architecture are the division of software into classes and the distribution of those classes across processing locations and specific computers. We covered design classes in Week 3. We will cover general software architectures this week and then expand to class distribution next week. Software architecture grows out of algorithms, data structures, and object-level designs. It is an abstraction of system implementation that describes the overall system structure, decomposition of functionality into components, the nature and properties of these components, interfaces, and communication protocols. A software system architecture diagram serves as the common ground for people of different backgrounds (developers, users, and project managers) to discuss and analyze jointly the high-level properties of the system with regard to its requirements. 1 Other architectural issues include relationships and constraints between components, external interfaces, overall access control and security, and strategies for scaling and performance. A good software system requires a sound and integrated architecture. Architectural integrity is like color coordination in paintings: it underpins the ultimate success of the system. In addition, architecture also determines a wide range of system characteristics, such as cost-effectiveness, interoperability, scalability, and so forth. The distinction between architecture and design is not absolute. In architecture we are more concerned with the coordination between components or nodes, overall system performance, and scaling properties. In design we focus on the details within a component, an interface and subsystem. However, you may see that problems arising design (such as a poorly designed interface) may force a revision of the architecture. Object-oriented architectures differ from traditional ones by emphasizing the allocation of distributed objects, components, and their interfaces, persistent objects, and objectbased communications. Different architectures are needed for different requirements and constraints. The following sections present common patterns in object-oriented software architectures. The study of such patterns allows us to: Communicate the high-level properties of a particular architecture to people of different backgrounds. Recognize the patterns that can be reused in other systems, either as variations or mixtures. Make informed decisions on architectural alternatives based on a thorough understanding of their properties. 5.1.1 Client/Server Systems To simplify development and maintenance of complex applications, we separate centralized, monolithic systems into more manageable components or nodes. In a simple client/server system, an application is partitioned into a client and a server. The client handles the presentation and the server handles low-level functions and database access. The server typically contains multiple server objects and may serve multiple clients as shown in the following figure: 2 Laptop Workstations Workstations Server The business logic may be handled by the client or by the server, depending on the implementation strategy. Clients communicate with the server via certain protocols, such as HTTP or CORBA/IIOP. The advantages of this architecture are: The clients can be detached from the server, allowing remote access and separate code development. One server may serve multiple clients. The limitations are: Client/server communication relies on a network, which may become the bottleneck of performance. Changes on the server side require changes on the client side if the interface definition is changed. When there are a large number of clients, keeping them upto-date becomes a difficult task. This is especially serious for enterprise applications that support thousands of users. The second limitation can be alleviated by introducing thin clients, which have a standardized interface definition. The best example of this is the Web browser. Web applications are free from the burden of client maintenance. Alternatively, the same objective can be achieved by using dynamic object distribution. This is where part or all of the objects are actually transported to the client when the client application starts up. This is the same principle as Java Applets, which in reality require a preinstalled set of libraries on the client side. The following figure shows the interaction between a thin client and a Web server for a Web-based application which is commonly in use today. 3 Web Applications using the MVC Framework The MVC (Model-View-Controller) framework is a particular type of the client/server architecture. It provides an effective approach for implementing Web-based applications. The MVC architecture decouples the user interface from the Web application functionality and information content. The model contains all application specific content and processing logic, including all content objects, access to external data sources, and processing functionality that are application specific. The view contains all interface specific functions and enables the presentation of content and processing logic, including all content objects, access to external data, and all processing functionality required by the end-user. The controller manages access to the model and the view and coordinates the flow of data between them. In a Web application, the view is updated by the controller with data from the model based on user input. A schematic representation of the MVC architecture is shown below. 4 5.1.2 Layered Systems Layers refer to logical groups of objects within a component or node. Layered systems typically appear in servers, in which each inner layer provides services to its immediate outer layer. For example, the interface functions call the core functions to perform tasks. The core functions in turn use the persistent services to make objects persistent. The figure below illustrates the layered approach. The advantages of this architecture are: 5 It promotes layers of design abstraction, allowing a complex problem to be decomposed into several layers of functions. It allows easy control of internal functions and services that should not be exposed to the external world. Only objects in the interface layer are visible as interface classes. New operations can be introduced in the interface layer. These are often combined operations from the core or persistent layers. For example, frequently used queries involving multiple calls to the server can be grouped into one function call that will result in improved system performance. The limitations are: Layering may degrade system performance because interface functions may need to go through several layers to invoke the operations of the inner layers. Standardizing layer interfaces may lead to cumbersome and inefficient function calls. Layered architectures are found mostly in application servers, database systems, layered communication protocols (such as CORBA/IIOP, J2EE), and operating systems. They are often used together with other types of architectures. 5.1.3 Three-Tier and Multi-Tier Systems Unlike layers which reside inside components or nodes, tiers are physically distributed components or nodes. In a three-tier system, there are two pairs of client/servers. The first tier is usually a Database Management node. The second or middle tier typically handles business logic or application-specific computation. It is a client to the first tier. It also serves as a server to the third tier, which include a number of clients. The third tier, or user-interface tier, handles user interaction. Its design focus is on efficient user interface and accessibility to the enterprise. The client software can either be a regular or thin client. Different user interfaces may also be provided to different types of users, who may access the same Business Logic node. See the figure below. 6 You can generalize the three-tier system to multi-tier systems or n-tiered systems. For example, we may add a Web server and thin clients to the three-tier system to obtain the four-tier system shown below. The Web server handles any Web browsers (thin clients) on the Internet. It translates HTTP requests into method invocations in the Business Logic node (second tier). The advantages of this architecture are: 7 The system is easy to maintain and extend because different groups of functions are distributed across several tiers of servers. It allows hierarchical control of functions from the lower tiers to the upper tiers and similarly different levels of service to clients of different tiers. It enables enterprise-level integration, typically by connecting the middle tiers with other enterprise systems. It is highly scalable to handle a large number of concurrent clients. This can be achieved by clustering with a pool of servers. The limitations of this architecture are: More than one communication protocol is involved between the client/server pairs. For example, in a four-tier system, these may include HTTP between thin clients and the Web server, CORBA/IIOP or J2EE between the Web server and the Business Logic node, and SQL between the Business Logic and the Database Management nodes. Hence, a wide range of expertise is needed when implementing such systems. Performance tuning of the system becomes more difficult because data may travel through multiple nodes (which may be in machine with different platforms and operating systems) before reaching the clients. Clustering and Serializing To scale up a multi-tier system to handle a large number of clients, we may use a set of server nodes, which cooperate with each other to provide services to clients. Two approached may be employed: 1. Each replicated server node provides the same functionality, and a client may use any one of them. We call this clustering. 2. Each server component provides a specialized function. A client request may start with one server, followed by other servers. This is called serializing. In clustering, client requests are processed in parallel, and is therefore most appropriate for a large number of clients who perform similar tasks. An example of clustering in a four-tier system is shown in the figure below. A large number of thin clients go through a Web server to use the components in the Business Logic nodes. Three identical nodes are shown in the figure. They all obtain data from the Database Management node in the first tier. The Web server determines how the work is distributed evenly across the Business Logic nodes to minimize users’ wait time. 8 Serializing is typically used together with clustering to provide specialized services. For example, in the figure below, two serialized nodes are used to handle security and load balancing. When a client request comes in, the security node checks its credentials. The dispatcher then determines which Business Logic node should be used and returns a reference for an object in that node to the client objects in the Web server. From this point on, the client object in the Web server talks directly with the chosen Business Logic node to complete the process. 9 5.2 Design Patterns Design patterns are part of the cutting edge of object-oriented technology. Have you ever designed or implemented a software solution and have gotten the feeling of deja’vu? It is understandable because different software systems may share similar aspects. With software design going the assembly line way, reusability has become an important criterion in software design. Design patterns are a key to this. In addition, learning design patterns early in the learning of object-oriented skills greatly helps improve understanding of object-oriented analysis and design. 5.2.1 What is a Design Pattern? A pattern is a commonly occurring reusable piece in a software system that provides a certain set of functionality. The formal definition of a design pattern posed by Christopher Alexander, one of the first proponents of design patterns, is: Each pattern describes a problem which occurs over and over again in our environment and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice. [Alexander, Christopher, A Pattern Language. Oxford University Press, New York, 1977.] Although Alexander was talking about patterns in buildings and towns, what he says is true about object-oriented design patterns. Our solutions are expressed in terms of objects and interfaces instead of walls and doors, but at the core, both kinds of patterns are a solution to a problem. In general, a pattern has four essential elements: The name of the pattern The purpose of the pattern, the problem it solves How we accomplish this The constraints and forces we have to consider in order to accomplish it. Alexander postulated that patterns can solve virtually every architectural problem that one will encounter. He further postulates that patterns can be used together to solve complex architectural problems. Design patterns became a widely accepted object-oriented design technique in 1995 with the publication of the book Design Patterns:Elements of Reusable Object-Oriented Software by Eric Gamma, Richard Helm, Ralph Johnson, and John Vlissides. The four authors of the book are now commonly referred to as the Gang of Four (GoF). 5.2.2 Why Study Design Patterns? Now that you have an idea about what a design patterns are, you may be wondering, “Why study them?” Design patterns benefit system developers by: 10 Helping to construct reliable software using proven architectures and accumulated industry expertise Promoting design reuse in future systems Helping to identify common mistakes and pitfalls that occur when building systems Helping to design systems independently of the language in which they will ultimately be implemented Establishing a common design vocabulary among developers Shortening the design phase in a software development project. To use design patterns effectively, designers must familiarize themselves with the most popular and effective patterns used in the software-engineering industry. Since a system is made up of static as well as dynamic elements, you will find patterns that can be used for either of these types. Based on how they are to be used, patterns are primarily categorized as: Creational Structural Behavioral The following sections describe several popular design patterns within the above categories. 5.2.3 Creational Design Patterns Creational patterns define mechanisms for instantiating objects. The implementation of the creational pattern is responsible for managing the lifecycle of the instantiated object. A few examples of Creational design patterns are listed below. Factory One of the easily recognized and frequently used design pattern is the Factory pattern. If you have designed any object that is responsible for creating and maintaining the lifecycle of another object, you have used the Factory pattern. Obtaining a database connection in your application using a connection manager or connection factory object is a good example of the Factory pattern. 11 Singleton A singleton is another example of a factory pattern. What makes the Singleton pattern unique is that one and only one instance of the object can exist irrespective of the number of times the object is instantiated. The most common use of a Singleton pattern is for server applications like a Java-based Remote Method Invocation (RMI) server application. 5.2.4 Behavioral Design Patterns Interaction between different objects is specifically covered by Behavioral patterns. An example is given below. Command The Command pattern is commonly used for gathering requests from client objects and packaging them into a single object for processing. The Command pattern allows for having well-defined command interfaces that are implemented by the object that provides the processing for the client requests packaged as commands. Structural Design Patterns The composition of objects and their organizations to obtain new and varied functionality is the underlying basis of Structural patterns. An example of a structural pattern is listed below. 12 Adapter In the Adapter pattern, an object provides an implementation of an interface used by other objects in a consistent way. The adapter object wraps different disparate implementations of the interface and presents a unified interface for other objects to access. A good example of this is a database driver like an ODBC (Open Database Connectivity) or JDBC (Java Database Connectivity) driver that wraps the custom database accessing implementation for different databases and yet, presents a consistent interface that is a published and standardized API for applications to use. 5.2.5 Designing for Change The key to maximizing reuse lies in anticipating new requirements and changes to existing requirements, and in designing your systems so that they can evolve accordingly. To design the system so that it’s robust to such changes, you must consider how the system might need to change over its lifetime. A design that does not take change into account risks major redesign in the future. Those changes might involve class redefinition and reimplementation, client modification, and retesting. Redesign affects many parts of the software system, and unanticipated changes are expensive! Design patterns help you avoid this by ensuring that a system can change in specific ways. Each design pattern lets some aspect of system structure vary independently of other aspects, thereby making a system more robust to a particular kind of change. Here are some common causes of redesignalong with the design pattern(s) that address them. Hopefully, these ideas will get you started in your investigation of design patterns. Creating an object by specifying a class explicitly. Specifying a class name when you create an object commits you to a particular implementation instead of a particular interface. This commitment can complicate future changes. To avoid it, create objects indirectly. Design patterns: Abstract Factory, Factory Method, Prototype. 13 Dependence on specific operations. When you specify a particular operation, you commit to one way of satisfying a request. By avoiding hard-coded requests, you make it easier to change the way a request gets satisfied both at compile-time and at run-time. Design patterns: Chain of Responsibility, Command Dependence on hardware and software platform. External operating system interfaces and APIs are different on different hardware and software platforms. Software that depends on a particular platform will be harder to port to other platforms. It may even be difficult to keep it up to date on its native platform. It’s important therefore to design your system to limit its platform dependencies. Design patterns: Abstract Factory, Bridge Dependence on object representations or implementations. Clients that know how an object is represented, stored, located, or implemented might need to be changed when the object changes. Hiding this information from clients keeps changes from cascading. Design patterns: Abstract Factory, Bridge, Memento, Proxy Algorithmic dependencies. Algorithms are often extended, optimized, and replaced during development and reuse. Objects that depend on an algorithm will have to change when the algorithm changes. Therefore, algorithms that are likely to change should be isolated. Design patterns: Builder, Iterator, Strategy, Template, Method, Visitor Tight coupling. Classes that are tightly coupled are hard to reuse in isolation, since they depend on each other. Tight coupling leads to monolithic systems, where you can’t change or remove a class without understanding and changing many other classes. The system becomes a dense mass that’s hard to learn, port, and maintain. Loose coupling increases the probability that a class can be reused by itself and that a system can be learned, ported, modified, and extended more easily. Design patterns use techniques such as abstract coupling and layering to promote loosely coupled systems. Design patterns: Abstract Factory, Bridge, Chain of Responsibility, Command, Façade, Mediator, Observer Extending functionality by subclassing. Customizing an object by subclassing often isn’t easy. Every new class has a fixed implementation overhead (initialization, finalization, etc.). Defining a subclass also requires an in-depth understanding of the parent class. For example, overriding one operation might require overriding another. An overridden operation might be required to call an inherited operation. And subclassing can lead to an explosion of classes, because you might have to introduce many new subclasses for even a simple extension. 14 Object composition in general and delegation in particular provide flexible alternatives to inheritance for combining behavior. New functionality can be added to an application by composing existing objects in new ways rather than by defining new subclasses of existing classes. On the other hand, heavy use of object composition can make designs harder to understand. Many design patterns produce designs in which you can introduce customized functionality just by defining one subclass and composing its instances with existing ones. Design patterns: Bridge, Chain of Responsibility, Composite, Decorator, Observer, Strategy Inability to alter classes conveniently. Sometimes you have to modify a class that can’t be modified conveniently. Perhaps you need the source code and don’t have it (as may be the case with commercial class libraries). Or maybe any change would require modifying lots of existing subclasses. Design patterns offer ways to modify classes in such circumstances. Design patterns: Adapter, Decorator, Visitor [Gamma, Helm, Johnson, Vlissides, Design Patterns: Elements of Reusable ObjectOriented Software, Addison-Wesley, 1995, pages 24-25. 5.2.6 Designing for Change The key to maximizing reuse lies in anticipating new requirements and changes to existing requirements, and in designing your systems so that they can evolve accordingly. To design the system so that it’s robust to such changes, you must consider how the system might need to change over its lifetime. A design that does not take change into account risks major redesign in the future. Those changes might involve class redefinition and reimplementation, client modification, and retesting. Redesign affects many parts of the software system, and unanticipated changes are expensive! Design patterns help you avoid this by ensuring that a system can change in specific ways. Each design pattern lets some aspect of system structure vary independently of other aspects, thereby making a system more robust to a particular kind of change. Here are some common causes of redesign along with the design pattern(s) that address them: Creating an object by specifying a class explicitly. Specifying a class name when you create an object commits you to a particular implementation instead of a particular interface. This commitment can complicate future changes. To avoid it, create objects indirectly. Design patterns: Abstract Factory, Factory Method, Prototype. 15 Dependence on specific operations. When you specify a particular operation, you commit to one way of satisfying a request. By avoiding hard-coded requests, you make it easier to change the way a request gets satisfied both at compile-time and at run-time. Design patterns: Chain of Responsibility, Command Dependence on hardware and software platform. External operating system interfaces and APIs are different on different hardware and software platforms. Software that depends on a particular platform will be harder to port to other platforms. It may even be difficult to keep it up to date on its native platform. It’s important therefore to design your system to limit its platform dependencies. Design patterns: Abstract Factory, Bridge Dependence on object representations or implementations. Clients that know how an object is represented, stored, located, or implemented might need to be changed when the object changes. Hiding this information from clients keeps changes from cascading. Design patterns: Abstract Factory, Bridge, Memento, Proxy Algorithmic dependencies. Algorithms are often extended, optimized, and replaced during development and reuse. Objects that depend on an algorithm will have to change when the algorithm changes. Therefore, algorithms that are likely to change should be isolated. Design patterns: Builder, Iterator, Strategy, Template, Method, Visitor Tight coupling. Classes that are tightly coupled are hard to reuse in isolation, since they depend on each other. Tight coupling leads to monolithic systems, where you can’t change or remove a class without understanding and changing many other classes. The system becomes a dense mass that’s hard to learn, port, and maintain. Loose coupling increases the probability that a class can be reused by itself and that a system can be learned, ported, modified, and extended more easily. Design patterns use techniques such as abstract coupling and layering to promote loosely coupled systems. Design patterns: Abstract Factory, Bridge, Chain of Responsibility, Command, Façade, Mediator, Observer Extending functionality by subclassing. Customizing an object by subclassing often isn’t easy. Every new class has a fixed implementation overhead (initialization, finalization, etc.). Defining a subclass also requires an in-depth understanding of the parent class. For example, overriding one operation might require overriding another. An overridden operation might be required to call an inherited operation. And subclassing can lead to an explosion of classes, because you might have to introduce many new subclasses for even a simple extension. 16 Object composition in general and delegation in particular provide flexible alternatives to inheritance for combining behavior. New functionality can be added to an application by composing existing objects in new ways rather than by defining new subclasses of existing classes. On the other hand, heavy use of object composition can make designs harder to understand. Many design patterns produce designs in which you can introduce customized functionality just by defining one subclass and composing its instances with existing ones. Design patterns: Bridge, Chain of Responsibility, Composite, Decorator, Observer, Strategy Inability to alter classes conveniently. Sometimes you have to modify a class that can’t be modified conveniently. Perhaps you need the source code and don’t have it (as may be the case with commercial class libraries). Or maybe any change would require modifying lots of existing subclasses. Design patterns offer ways to modify classes in such circumstances. Design patterns: Adapter, Decorator, Visitor [Gamma, Helm, Johnson, Vlissides, Design Patterns: Elements of Reusable ObjectOriented Software, Addison-Wesley, 1995, pages 24-25.] Hopefully, the ideas described above will get you started in your investigation of design patterns 5.3 Persistent Objects and Database Design In previous weeks, our discussion has focused on objects and their structural and behavioral relationships. Once we implement an object design with a specific programming language, the source code contains definitions of object classes along with their relationships. The code exists as a file in our current system. However, the object instances generated when we execute the code are transient. That is, they cease to exist at the end of the code execution, unless we some make them persistent. Thus, if we want to save the object instances as persistent data and be able to retrieve them later, we need to map them to a certain format and store it on a disk or other permanent medium (such as a database). This brings about persistent objects, which are representations of objects that exist independently of the processes that create them. Persistent objects (or persistent data in general) are managed by database management systems (DBMSs). There are, in general, four types of database models: relational, extended relational or object-relational, functional, and object-oriented. They are distinguished by their allowable kinds of data and schema. The relational model is based on the simple concept of the table. The extended relational model adds to the relational model certain object-related capabilities. Functional models use a declarative functional query language to define and access the function values. The object-oriented model is 17 built on the object paradigm. In this course, we do not go into the details of the database models or database management concepts. The course CS 445 and CS 442 are available for learning these topics. Ideally, we should be able to perform a persistent object design without worrying about the underlying persistent mechanism or database model. After that, if the database model is not object-oriented, we may follow a standard procedure or employ some semiautomatic tools to map the objects to the native database models. We can call this an object-relational approach to database design. The following discussion will show you how to map your classes from the class diagram to a relational database management system (RDBMS). This is the most common activity for object-oriented designers at this point in time. But first let’s review. 5.3.1 DBMS Component Review A database is an integrated collection of stored data that is centrally managed and controlled. A database typically stores information about dozens or hundreds of classes. The information stored includes class attributes as well as associations among the classes. A database also stores descriptive information about data such as attribute names, restrictions on allowed values, and access controls to data items. A database is managed and controlled by a database management system (DBMS). A DBMS is a system software component that is usually purchased and installed separately from other system software components. Popular DBMSs include Oracle, Sybase, Microsoft Access, MySQL, ObjectStore and GemStone. A database usually has the following components: Physical Data Store Schema Application Program Interface (API) Query Interface Administrative Interface Data access programs and methods The figure below shows these components and their relationships. 18 Databases and DBMSs provide several important data access and management capabilities: Simultaneous access by users and application programs Access to data without writing applications programs, e.g. SQL Application of uniform and consistent access and content controls. Relational Database Management System (RDBMS) A RDBMS is a DBMS that organizes data into structures called tables. These are twodimensional tables with columns and rows. Each table in a RDBMS must have a unique key which is called the primary key. In order to relate two or more tables, a foreign key is defined. A foreign key is an attribute value stored in one table that also exists as a primary key value in another table. Hence, the name “relational.” 5.3.2 Translating the Object Class Diagram Into a Relational Schema The figure below shows a class diagram for a portion of an ATM system. 19 Portion of ATM System Class Diagram CardAuthorization Bank -name +verifyPassword() +createSavingsAccount() +createCheckingAccount() +createCashCard() +verifyAmount() 1 0..1 -password -limit +addAccount() +removeAccount() +close() CashCard -serialNumber 1 * Account 0..1 1 -balance -creditLimit +close() +verifyAmount() +post() ** Customer * * 1 1 -name -tempAmount +getAmount() +getAccount() 1 CheckingAccount SavingsAccount 0..1 -protectFromOverdraft Address -address To create a relational database schema from a class diagram, follow these steps: 1. 2. 3. 4. 5. 6. 7. 8. Create a table for each class Choose a primary key for each table (invent one, if necessary) Add foreign keys to represent one-to-many associations Create new tables to represent many-to-many associations Represent classification hierarchies or generalizations Define referential integrity constraints Evaluate schema quality and make necessary improvements Choose appropriate data types and value restrictions (if necessary) for each field Now, let’s use the example above and walk through this process. Representing Classes Normally you should map each class to a table and each attribute to a column. You can add columns for an object identifier and associations (to be explained). The boldface indicates the primary key. Keywords are in UPPERCASE. Note that operations do not affect table structure. All these examples are using Oracle syntax. 20 Implementing Classes Make each one a table Customer Class Diagram -name -tempAmount +getAmount() +getAccount() Customer Table Tables customerID name tempAmount SQL code CREATE TABLE Customer ( customer_ID NUMBER(30) CONSTRAINT nn_customer1 NOT NULL, cust_name VARCHAR2(50) CONSTRAINT nn_customer1 NOT NULL, CONSTRAINT pk_customer PRIMARY KEY (customer_ID) ); Representing Associations The implementation rules for associations depend on the multiplicity. Many-to-many associations. Implement the association with a table and make the association’s primary key the combination of the classes’ primary keys. If the association has attributes, they become additional columns. 21 Implementing Many-to-Many Associations Make each one a table Class Diagram Tables Account -balance -creditLimit +close() +verifyAmount() +post() CardAuthorization * * -password -limit +addAccount() +removeAccount() +close() Account table CardAuthorization table accountID balance creditLimit cardAuthorizationID password limit Account_CardAuthorization table accountID(references Account) cardAuthorizationID (references CardAuthorization) SQL code CREATE TABLE Account ( account_ID NUMBER(30) CONSTRAINT nn_account1 NOT NULL, balance NUMBER(12,2) CONSTRAINT nn_account2 NOT NULL, credit_limit NUMBER(12,2), CONSTRAINT pk_account PRIMARY KEY (account_ID) ); CREATE TABLE Card_Authorization ( card_auth_ID NUMBER(30) CONSTRAINT nn_cardauth1 NOT NULL, password VARCHAR2(50), limit NUMBER(12,2), CONSTRAINT pk_cardauth PRIMARY KEY (card_auth_ID) ); CREATE TABLE Acct_CardAuth ( account_ID NUMBER(30) CONSTRAINT nn_acctca1 NOT NULL, card_auth_ID NUMBER(30) CONSTRAINT nn_acctca2 NOT NULL, CONSTRAINT pk_acctca PRIMARY KEY (account_ID, card_auth_ID) ); One-to-many associations. Each one becomes a foreign key buried in the table for the “many” class. If there had been a name on the “one” end of the association, we would have used it as the foreign key name. We presume that serialNumber is unique for CashCard. 22 Implementing One-to-Many Associations Bury each one as a foreign key in the “many” table CardAuthorization Class Diagram Tables -password -limit +addAccount() +removeAccount() +close() CashCard -serialNumber 1 * CashCard Table cashCardID serialNumber cardAuthorizationID (references CardAuthorization) SQL code Card_Authorization code from previous figure... CREATE TABLE Cash_Card ( card_auth_ID NUMBER(30) CONSTRAINT nn_carshcard1 NOT NULL, serial_num VARCHAR2(50), card_auth_ID NUMBER(30), CONSTRAINT pk_cashcard PRIMARY KEY (cash_card_ID), CONSTRAINT uq_cashcard1 UNIQUE (serial_num) ); One-to-one associations. These seldom occur. You can handle them by burying a foreign key in either class table. N-ary associations. They also seldom occur. You can treat them like many-tomany associations and create a table for the association. Typically, the primary key of the n-ary association combines the primary keys of the related tables. Association classes. An association class is an association that is also a class. It is easier to establish the proper dependencies if you make each association class into a table, regardless of the multiplicity. Aggregation, composition. Aggregation and composition follow the same implementation rules as association. 23