Tuesday, November 3, 2009

5.2 Attributes




I l@ve RuBoard









5.2 Attributes


Definition:
An attribute is the abstraction of a single characteristic possessed by all the entities that were, themselves, abstracted as a class.


The goal is to obtain a set of attributes for a class that is:



  • Complete� They capture all information about the class.



  • Fully factored� Each attribute captures a separate aspect of the class abstraction.



  • Mutually independent� The attributes take on values independently of one another.




5.2.1 Finding Attributes


For each class, start out by asking yourself, "What characteristics do all the things in the domain possess (that we care about)?" Another approach is to go back to the abstraction and ask, "What information is inherent to this abstraction that makes the abstraction what it is?"


Attributes fall into three informal categories: descriptive, naming, and referential. These categories are offered only as a way to ease finding attributes for classes.


A descriptive attribute is an attribute that describes an intrinsic characteristic of the thing, such as the amount of the order, or the customer's address. These attributes can be found by considering what describes each thing.


A naming attribute is an arbitrary name or label used to refer to a thing. You can change the names or labels of each thing without changing what it is: That is, if we re-number an airplane, it is still the same airplane. Naming attributes help identify things from outside the domain. (Inside the domain, we have object references.)


A referential attribute provides facts about links. For example, an Order may have a customer attribute that refers to the Customer who made the order. Referential attributes formalize associations (e.g., "the Order's Customer"), a topic we address in Chapter 6: Relationships and Associations.









    I l@ve RuBoard



    CRITICAL SKILL 8.6 Create a Relational View from XML


    Team Fly 


    Page 294



    Project Summary


    This project illustrated the use of existsnode(), extract(), and extractvalue() when identifying an XML document stored in the Oracle Database 10g.



    In the future, Oracle is looking at adding several new capabilities to this list, including additional database and XML functionalities, such as XQuery, which will be a language specifically designed to query XML data from a document perspective rather than the rows-and-tables perspective of SQL. We have had fun finding and returning XML documents. Let's proceed and look at how we can take XML documents and represent them relationally.



    Progress Check



    1. Is the Oracle XML DB repository separate from the Oracle Database 10g?



    2. Why must we ''register" the URL of XML Schemas into the Oracle XML DB repository?



    3. How do we load an XML document into the Oracle XML DB repository?



    4. What is the difference between the existsnode() function and the extract() function?



    CRITICAL SKILL 8.6
    Create a Relational View from XML



    Oracle XML DB makes it possible to expose XML content, stored in the database through conventional relational views. This means that tools, applications, and programmers who have no understanding of XML, but understand the Oracle Database 10g, can now work with XML content. To accomplish this, the view










    Progress Check Answers


    1. No, the Oracle XML DB is integrated with Oracle Database 10g.


    2. The XML Schema defines the legal structure for an XML document. To confirm that the XML stored within the XMLType is "valid," the URL for the XML Schema it is associated with must be registered.


    3. XML documents can be loaded into the Oracle XML DB via programs using SQL, PL/SQL, and Java or by going through the protocols FTP, HTTP, and WebDAV.


    4. The existsnode() function identifies the existence of a node returning a Boolean value, while the extract() function extracts the node or set of nodes identified, returning a single text node.



    Team Fly 

    Using Regular Expressions









    Using Regular Expressions


    How you use regular expression depends on the specific application you're using. In most languages, such as Perl or PHP, you use a function in the language that compares the regular expression to a string, returning a value meaning the string matched or didn't match. In many applications with a GUI, such as OpenOffice, you type the regular expression into a field. Each application has its own method for regular expression input.


    In many cases, you use characters to indicate the beginning and end of the regular expression. The characters that specify the beginning and end are called delimiters. In some applications, you can specify what delimiter you want to use. Forward slashes (/) and quotation marks are often used as delimiters.









      Summary




















      Summary


      Virtual Private Database (VPD) helps resolve some of the challenges associated with views. An RLS policy is defined as a mapping from a PL/SQL implemented security function to a table, view, or synonym. The actual PL/SQL implementation that enforces the VPD can be based on whatever is relevant—IP address, time of day, application context values. The policies also are transparent to queries on the protected objects.


      New to Oracle Database 10g is the ability to support column-sensitive policies, which allows a more selective invocation of the RLS mechanisms. This is very practical and allows you to more easily store data with different sensitivities within the same table. One of the challenges to implementing VPD is debugging faulty implementations. You saw various best practice techniques for helping to mitigate the debug challenge.


      To ensure high performance, the RLS mechanism has been written to modify the SQL before it is parsed and executed. This allows the database to use indexes and optimization plans to ensure fast access to data. Using bind variables and application contexts and enabling policy caching can significantly improve RLS performance.


      In Chapter 12, you will explore an implementation (or perhaps an augmentation) of VPD called Oracle Label Security.



















      File Permissions









      File Permissions


      Because Linux is a multi-user system, directories and files need to be protected from unauthorized use. Each directory and file has associated permissions, settings that determine who can access the file and what they can do with it.


      Permissions to the file are given to three types of user accounts:



      • Owner:
        The account that owns the file


      • Group:
        Members of a group that owns the file


      • All users:
        All accounts on the system


      Users can be given permission to do one or more of three things to the file:



      • Read:
        Look at the contents of the file


      • Write:
        Save the file to the hard disk


      • Execute:
        Run the file or enter the directory


      The permissions can be given in any combination. For instance, file1 might have permission as follows:



      • Owner:
        Read, write, execute


      • Group:
        Read, execute


      • All users:
        Read


      The owner can look at, edit, save, and run the file. Members of the group can only look at and run the file, but they can't change it. Everyone on the system can look at the contents of the file. Remember that a directory is simply a file, so directories can be given the same type of permissions as a file.


      File permissions are often displayed in a shorthand format as follows:



      rwxr--r--


      The r, w, and x stand for read, write, and execute, as described earlier in this section. The 9 characters shown represent three groups of three: rwx and r-- and r--. The first group displays the permissions for the owner, the second is the permissions for the group, and the third is the permissions for everyone. Thus, in this case, the owner can read, write, and execute the file, but the group and all users can only read the file, not write/execute it. Only the owner or the root account can change file permissions.









        TestSuite











         < Day Day Up > 





        TestSuite



        Description



        TestSuite (see Figure B-10) is a class representing a collection of

        Tests. Since it implements

        Test, it can be run just like a

        TestCase. When run, a TestSuite

        runs all the Tests it contains. It may contain

        both TestCases and other

        TestSuites.





        A TestSuite can be constructed by giving it the

        class name of a TestCase. The

        TestSuite constructor uses reflection to find all

        methods in the TestCase having names starting with

        test. The code below adds all of

        BookTest's test methods to a

        TestSuite and runs it:



        TestSuite test = new TestSuite( BookTest.class );

        test.run( new TestResult( ) );







        Tests also can be added to a TestSuite using the

        addTest( ) method.



        Figure B-10. The class TestSuite









        Declaration





        public class TestSuite



        extends Object



        implements Test









        Constructors






        TestSuite( )





        A constructor that creates an empty TestSuite.






        TestSuite(String name)





        A constructor that creates an empty TestSuite with

        the given name.






        TestSuite(Class class)





        A constructor that takes a Class, uses reflection

        to find all methods with names starting with test,

        and adds them to the TestSuite as test methods.






        TestSuite(Class class, String name)





        A constructor that creates a TestSuite with the

        given name and all test methods found in the

        Class, as described for the previous constructor.











        Public Methods






        void addTest(Test test)





        Adds a Test to the TestSuite.






        void addTestSuite(Class testClass)





        Adds the test methods from the Class to the

        TestSuite. Test methods are found using

        reflection.






        int countTestCases( )





        Returns the total number of test cases that will be run by this

        TestSuite. Test cases are counted by recursively

        calling countTestCases( ) for every

        Test in this TestSuite.






        static Test createTest(Class theClass, String name)





        Creates an instance of Class as a

        Test with the given name.






        String getName( )





        Returns the name of the TestSuite.






        static java.lang.reflect.Constructor getTestConstructor(Class theClass)





        Gets a constructor for the given Class that takes

        a single String as its argument, or gets a

        constructor that takes no arguments.






        void run(TestResult result)





        Runs the Tests in this

        TestSuite and collects the results in

        TestResult.






        void runTest(Test test, TestResult result)





        Runs Test and collects the results in

        TestResult.






        void setName(String name)





        Sets the name of the TestSuite.






        Test testAt(int index)





        Returns the Test at the given index.






        int testCount( )





        Returns the number of Tests in this

        TestSuite.






        java.util.Enumeration tests( )





        Returns the Tests as an

        Enumeration.






        String toString( )





        Returns a string representation of this TestSuite.











        Protected/Private Methods






        private void addTestMethod(java.lang.reflect.Method m, Vector names, Class class)





        A private method to add a test method to this

        TestSuite.






        private static String exceptionToString(Throwable t)





        Returns the Throwable's stack

        trace as a string.






        private boolean isPublicTestMethod(java.lang.reflect.Method m)





        Returns TRUE if Method has

        public access.






        private boolean isTestMethod(java.lang.reflect.Method m)





        A private method that returns TRUE if

        Method has no arguments, returns

        void, and has public access.






        private static Test warning(String message)





        Returns a Test that will fail and logs a warning

        message.











        Attributes






        private String fName





        The name of this TestSuite.






        private Vector fTests





        The Tests contained by this

        TestSuite.

























           < Day Day Up > 



          11.1 Comments



          [ Team LiB ]





          11.1 Comments


          The double hyphen (--) is used to comment a single line. A slash followed by an asterisk (/*) begins a block comment. An asterisk followed by a slash (*/) ends a block comment.


          The C-style comments (/*, */) can be used to block out a section of code. The following procedure illustrates both forms.





          -- Filename hello.sql
          CREATE OR REPLACE PROCEDURE hello IS
          str CONSTANT VARCHAR2(15) := 'Hello World!';
          len INTEGER; /* length of the constant */
          BEGIN
          --
          -- Set len to length of character string.
          --
          len := LENGTH(str);

          /*
          * write the string length
          */
          dbms_output.put_line(str||'-string length:'||len);
          END hello;

          Place comments after the CREATE statement, not before. This only applies if you are using a text editor with a tool like SQL*Plus�a tool such as JDeveloper will not permit you to place comments prior to a CREATE statement. The situation to avoid is the following:





          -- This procedure prints hello.
          CREATE OR REPLACE PROCEDURE hello IS
          str CONSTANT VARCHAR2(10) := 'Hello World!';
          . . . etc

          Comments that precede the CREATE statement are not included with the source code saved in the data dictionary. Comments after the CREATE clause are stored in the data dictionary.


          Packages require extensive comments, mostly because they typically have many procedures and functions that provide a wealth of functionality. A package should have overview comments that describe the package. This overview should document any Oracle privileges required to use the package. It should also document the need for any database parameter settings.


          Sometimes there is an ordered dependency among the subprograms in the package. For example, to use a package properly, you may have to call one subprogram first, prior to calling other procedures. You want to document this dependency.


          An overview that includes examples that demonstrate how to use the package is very useful. These overview comments immediately follow the CREATE PACKAGE statement. Following the general comments are the procedure and function definitions, which have individual comments.





          PACKAGE students_pkg is
          --
          -- general comments about how to use the package
          --
          --
          -- comments on print_name
          PROCEDURE print_name (v_student_id IN VARCHAR2);
          --
          -- comments on print_major
          PROCEDURE print_major (v_student_id IN VARCHAR2);
          END students_pkg;

          The Oracle built-in packages are well documented with an overview section, frequently including examples, plus detailed comments on each procedure and function.


          Packages you can use are available through the ALL_SOURCE view. This view contains the source you have written, as well as code in other schemas to which you have access. This includes the Oracle built-in packages. The interface and comments that describe the DBMS_OUTPUT package can be extracted from the ALL_SOURCE view with a SQL statement similar to that used to extract the HELLO source and comments.





          SQL> SELECT text FROM all_source
          2 WHERE name='DBMS_OUTPUT'
          3 AND type='PACKAGE';




            [ Team LiB ]



            Section 2.7. Dealing with Errors










            2.7. Dealing with Errors






            When an error occurs in a stored program, the default behavior of MySQL is to terminate execution of the program and pass the error out to the calling program. If you need a different kind of response to an error, you create an error handler that defines the way in which the stored program should respond to one or more error conditions.


            The following are two relatively common scenarios that call for the definition of error handlers:


            • If you think that an embedded SQL statement might return no rows, or you need to fetch all the rows from a SELECT statement using a cursor, a NOT FOUND error handler will prevent the stored program from terminating prematurely.

            • If you think that a SQL statement might return an error (a constraint violation, for instance), you may need to create a handler to prevent program termination. The handler will, instead, allow you to process the error and continue program execution.


            Chapter 6 describes in detail how to use error handlers. An example of using a NOT FOUND error handler with a cursor is shown in the next section.












            15.2 Ways to Authenticate Users












            for Ru-Brd & DownSky

            size=+0>

            15.2 Ways to Authenticate Users


            As we said in the previous section, keys are
            actually parameters you reference when you run your program (algorithm) to
            either encrypt or decrypt a message or a piece of data. Keys were first
            used with algorithms to enable people to communicate electronically in a
            more private manner. Originally, the same algorithm was used to both
            encrypt and decrypt a message. But that approach often proved vulnerable
            to the sophisticated computer programs hackers wrote to break the
            encrypted messages. By necessity, keys have had to become more complex,
            and their use and protection more secure. Different approaches have been
            used to try to ensure that encrypted material cannot be decrypted by
            anyone other than the intended receiver. This section describes some of
            these approaches.


            15.2.1 Private Keys


            One way for two people who want to communicate
            privately with each other to do so is for them to ensure that they each
            have a copy of the same key, referred to as a private key, which
            they use for both encryption and decryption of their message. But to use
            this approach, they need to find a way to exchange the key information so
            no one else can get the key.


            If Mary and Ralph want to communicate, they will each need a copy of a
            key to encrypt and decrypt their messages. Let's say that Ralph and Ed
            also want to communicate privately. They will need a different key so that
            Mary cannot read their messages. Now Ralph needs to maintain, protect, and
            track two different keys — one for communication with Mary and one for
            communication with Ed. If Ralph wants to communicate with a third or
            fourth person, his key maintenance will quickly compound.


            A number of commonly used cryptography approaches are based on the
            notion of the sharing of private keys. Two of the best known private key
            algorithms are the Data Encryption Standard (DES), published in 1975 by
            the National Institute of Standards and Technology (NIST) and the
            International Data Encryption Algorithm (IDEA), published in 1990.


            15.2.1.1 The problem with private keys

            On a company-wide basis, the need for users to get and maintain
            multiple private keys becomes a managerial nightmare. As the number of
            users grows, the number of possible keys required grows proportionally.
            Some companies have implemented various forms of central key servers to
            provide users with a place to obtain a key each time they want to
            communicate with another user in a private manner. The problems with this
            approach are that the centralized key server:




            • Becomes a single point of failure



            • May become a bottleneck point on the system


            Both of these problems are really time-based. If everyone is relying on
            obtaining their private keys from a centralized key server and that key
            server crashes, no one will be able to obtain a key until the server is
            back online and available. Without a backup server, secure communication
            might have to be halted until the key server can be repaired or recovered.
            Likewise, if a substantial number of users are obtaining private keys
            frequently, the key server could become overwhelmed. Response times for
            obtaining private keys could impact your system and user performance.


            15.2.2 Public Keys


            Another approach to encrypting secret
            communications is to use a public key system. With public key systems,
            each user has a set of two keys — a public key to which everyone can have
            access, and a private key which is available to only the owner of that
            key. The public key is made available to anyone who wants to communicate
            in a secure manner with you. The public key is truly public — it can be
            placed anywhere on a system, including a web page.


            The public key is used to encrypt the plaintext message, while the
            private key is used to decrypt the message. Anyone can use the public key
            to encrypt a message, while only someone who has the corresponding private
            key can decrypt it. The keys are generally complex enough that the private
            key cannot be easily derived from the public key. Public key algorithms
            are usually much larger than private key algorithms and, therefore, are
            generally much slower to use.


            The beauty of the public key/private key approach is that it provides
            much greater security and privacy. Going back to our example earlier, if
            Mary wants to communicate with Ralph, she will encrypt her message using
            Ralph's public key. Since Ralph is the only one who has his private key
            (we hope) Ralph will use his private key and easily decrypt Mary's
            message. Likewise, if Ralph wants to communicate with Ed, Ralph will use
            Ed's public key to encrypt the message.


            15.2.2.1 Private keys, public keys, and authentication

            In a reverse manner, with public key systems, private keys can be used
            to authenticate a user — just as you proved you were who you said you were
            by showing your birth certificate and driver's license to an official to
            obtain a passport. Let's say that Mary encrypts a message using her
            private key. Anyone who has Mary's public key can decrypt her message
            since the keys can work in either order — public to private or private to
            public. However, unless someone else has access to Mary's private key,
            duplicating Mary's encryption would be very difficult.


            15.2.2.2 Advantages of a public key system

            Since each person maintains his or her own private key, there is no
            single point of failure in a public key system. People have the ability to
            authenticate themselves by using their own private key to encrypt
            something that can be decrypted with their own public key. Key
            distribution is simplified since private keys do not need to be shared
            between two people to be useful.


            Figure
            15.2 shows an example of public key encryption and decryption.



            Figure 15.2. Public key encryption and
            decryption

            15.2.3 Digital Signatures


            In earlier times, when a military leader wanted to
            communicate with his troops who were some distance away from him, the
            leader would write his message, fold the paper, and affix a special wax
            seal. The seal was recognized to be his alone. The seal was affixed to the
            open edge of the message, thus both sealing the message closed so that no
            one could read it without disturbing the seal, and authenticating the
            message as having been sent by the leader personally. The seal was
            recognized by the troops, and the directives within the message were
            followed as if the military leader were present and issuing the orders
            himself.


            In a similar way, digital signatures have become a way to
            authenticate that a message was sent by a specific user. The digital
            signature is generated using a two-step process. First, the sender uses a
            one-way hash function to generate a
            specific-length number known as a message digest . The hash function can take a message of any length and
            generate a fixed-length number. Next, the sender uses his or her private
            key to encrypt the message digest. The digital signature — the encrypted
            message digest — can be attached to any message.


            When someone receives a message with a digital signature, the receiver
            goes through a two-step process to decrypt the signature and verify that
            the message was actually sent by the person who claimed to send the
            message. The receiver would apply the same one-way hash function the
            sender used to generate the message digest and then apply the sender's
            public key to decrypt the received message digest. The result should be a
            match of the sender's transmitted message digest. If it is a match, the
            receiver can feel pretty comfortable that the message has not been
            tampered with.


            Figure
            15.3 shows an example of using a digital signature.



            Figure 15.3. Digital signature

            15.2.4 Certificates of Authority


            With a digital signature, the
            person who receives a message takes responsibility for authenticating the
            message. Another approach to security is to have a trusted entity,
            referred to as a certificate authority (CA), validate that someone
            is who he says he is. At the beginning of the chapter, we talked about a
            government agency you go to when you need a passport issued. The CA, like
            the government agency, validates that you are who you claim to be and
            issues an appropriate credential, the certificate of authority, to
            you.


            A certificate of authority is an electronic message digitally
            signed by the CA. It states that a public key belongs to a specific user
            or process. The CA signs a certificate by using its private key to encrypt
            the signature and place it on the certificate. Anyone or anything
            receiving a certificate can decrypt the signature using the public key and
            thereby verify the authenticity of the CA. Based on the trust in the CA,
            the receiver can trust whoever presents a certificate from the CA.


            Think back to our initial example of an agency issuing a passport and
            the traveler then showing his passport to move from place to place in a
            trusted manner. In similar fashion, the certificate that is electronically
            signed by a CA can enable a user or process to be trusted and allowed to
            move from system to system or to transact business in a trusted
            manner.


            The OSS provides the ability for a user or process to obtain a
            certificate of authority to enable the process or person to perform one or
            many transactions, with one or several databases, without having to use a
            username and password for each interaction. The OSS supports a form of
            certificates known as X.509 version 1 (a standard protocol). The OSS
            places the certificate of authority, otherwise referred to as an X.509
            certificate
            , along with a public and private key pair, into a
            structure called a wallet .


            15.2.4.1 Certificate format

            An X.509 certificate has a standard format; here we
            show the values generally used by the OSS:



            Version

            Currently, this value for an OSS is always "0," which refers to the
            X.509 version 1 certificates. In future releases, the OSS will support
            X.509 version 3 certificates. These future certificates will use a
            version value of "1."


            Serial number

            A unique identifier for the certificate.


            Algorithm identifier

            The algorithm the CA used and any necessary parameters for
            validation.


            Issuer

            The name of the CA.


            Period of validity

            The range of dates over which the certificate is valid. Usually, it
            is the range of dates requested by the certificate requester, which
            would typically span the period from the date of creation to a specified
            end time.


            Subject

            Identifies to whom the certificate belongs.


            Subject's public key

            This area includes the certificate owner's public key, identifies
            which algorithm the CA used, and includes any necessary parameters.


            Signature

            The digital signature of the CA.


            As you can see, the information contained in a certificate is enough
            for a receiver to validate the CA and the owner of the certificate.


            15.2.4.2 Period of validity and revocation

            The period of validity for a certificate (see the list of certificate
            elements above) is the amount of time requested by the certificate owner
            during which the certificate will be able to be accepted. At the end of
            that period of time, the certificate becomes invalid. A certificate can
            also be revoked (so it is no longer valid) before its period of validity
            expires. Even though a certificate may still have a valid time period,
            something might have happened to cause the CA to revoke the use of a
            specific certificate.


            There are a number of events that might cause the revocation of a
            certificate. For example, the certificate owner's key or the CA's key
            might have been compromised, or an event might have occurred that makes
            the certificate owner no longer worthy of trust. Leaving the company would
            generally be a reason for the CA to revoke a user's certificate before it
            had automatically expired.


            Periodically, the CA will issue, sign, and timestamp a list of
            certificates which have been revoked. Referred to as a certificate revocation list (CRL), the list can be
            checked by any receiver to verify the status of a certificate. However,
            since checking the CRL can be a very slow process, verification against
            the CRL is generally reserved for really important or critical documents
            or might be used only infrequently to perform complete verification
            checks.


            15.2.4.3 Distinguished names

            The concept of a distinguished name (DN) is used not only by Oracle Corporation for its OSS
            product, but by other companies and products as well. For example,
            Verisign Corporation, when issuing a digital identification for a server,
            requires the server's distinguished name as part of the certification
            process. In Verisign's case, the requirement is to present the server name
            as the fully qualified domain name used for standard Internet DNS (Domain
            Name System) lookups for a server location — like a web server address
            (e.g., www.my_web_address.com).


            In Oracle's case, the DN has a very specific structure:

            DN=([Country,][Organization,][OrganizationUnit,][State,][Locality,] CommonName)

            The one mandatory value in the distinguished name definition is the
            common name. The other values are optional, but the order in which the
            values are entered is very important. The rules associated with a
            distinguished name are the following:




            • A distinguished name must have at least the common name



            • All of the other elements, if used, must be in the specific listed
              order: "C=,O=,OU=,S=,L=,CN="



            • All element labels used for a distinguished name must be uppercase,
              though the elements can be upper/lower



            • The actual definition values must match exactly the values used in
              the OSS identity



            • Elements in the distinguished name definition cannot have any spaces
              between the elements



            • The elements in the distinguished name definition can only be
              separated by a comma (,)


            The order in which the values are entered when defining a distinguished
            name becomes important when a "global user" definition is entered. (The
            OSS global definitions are discussed in a later section.)


            An example of a valid DN structure would be:

            DN='C=US,O=MyCompany,OU=MyDept,ST=VA,L=Vienna,CN=mary'


            The only mandatory value in this example is the "CN=mary" at the end of
            the string; this is the common name. The Country is "US"; the Organization
            is "MyCompany"; the OrganizationUnit is "MyDept"; the State is "VA"; the
            Locality is "Vienna"; and the CommonName is "mary."



            border=0>



            border=0>




            The OSS toolset is case-sensitive and, if you actually
            enter the values as shown here (i.e., "C=US, CN=mary"), you
            will have to ensure that you carry the upper/lowercase entries
            throughout the steps exactly as you have entered them
            initially. A much better approach would be to always
            use
            uppercase.












            for Ru-Brd & DownSky


            9.11. (Optional) Software Engineering Case Study: Starting to Program the Classes of the ATM System


            9.11. (Optional) Software Engineering Case
            Study: Starting to Program the Classes of the ATM System


            In the Software Engineering Case Study sections in Chapters
            1–7, we introduced the fundamentals of object
            orientation and developed an object-oriented design for our ATM system. Earlier
            in this chapter, we discussed many of the details of programming with C++
            classes. We now begin implementing our object-oriented design in C++. At the end
            of this section, we show how to convert class diagrams to C++ header files. In
            the final Software Engineering Case Study section (Section
            13.10), we modify the header files to incorporate
            the object-oriented concept of inheritance. We present the full C++ code
            implementation in Appendix
            E, ATM Case Study Code.


            Visibility


            We now apply access specifiers
            to the members of our classes. In Chapter
            3, we introduced access specifiers public and private.
            Access specifiers determine the visibility or accessibility
            of an object's attributes and operations to other objects. Before we can begin
            implementing our design, we must consider which attributes and operations of our
            classes should be public and which should be private.


            In Chapter
            3, we observed that data members normally should be
            private and that member functions invoked by
            clients of a given class should be public. Member
            functions that are called only by other member functions of the class as
            "utility functions," however, normally should be private. The UML employs visibility
            markers
            for modeling the visibility of
            attributes and operations. Public visibility is indicated by placing a plus sign
            (+) before an operation or an attribute; a minus sign (–) indicates private
            visibility. Figure
            9.20 shows our updated class diagram with
            visibility markers included. [Note: We do not include any operation parameters in Fig. 9.20. This is perfectly normal. Adding visibility
            markers does not affect the parameters already modeled in the class diagrams of
            Figs.
            6.34–6.37.]




            Fig. 9.20. Class diagram with visibility markers.




            Navigability


            Before we begin implementing our
            design in C++, we introduce an additional UML notation. The class diagram in Fig. 9.21 further refines the relationships among classes in the ATM
            system by adding navigability arrows to the association lines. Navigability arrows
            (represented as arrows with stick arrowheads in the class diagram) indicate in
            which direction an association can be traversed and are based on the
            collaborations modeled in communication and sequence diagrams (see Section
            7.12). When implementing a system designed using the
            UML, programmers use navigability arrows to help determine which objects need
            references or pointers to other objects. For example, the navigability arrow
            pointing from class ATM to class
            BankDatabase indicates that we can navigate
            from the former to the latter, thereby enabling the ATM to invoke the
            BankDatabase's operations. However, since Fig. 9.21 does not contain a navigability arrow pointing from
            class BankDatabase to class ATM, the BankDatabase cannot access the ATM's operations.
            Note that associations in a class diagram that have navigability arrows at both
            ends or do not have navigability arrows at all indicate bidirectional navigability—navigation can proceed
            in either direction across the association.




            Fig. 9.21. Class diagram with navigability arrows.






            Like the class diagram of Fig.
            3.23, the class diagram of Fig. 9.21 omits classes
            BalanceInquiry and Deposit to keep
            the diagram simple. The navigability of the associations in which these classes
            participate closely parallels the navigability of class Withdrawal's associations.
            Recall from Section
            3.11 that BalanceInquiry has an association with class
            Screen. We can navigate from class BalanceInquiry to class
            Screen along this association, but we cannot navigate
            from class Screen to class BalanceInquiry. Thus, if we were to model class BalanceInquiry
            in Fig. 9.21, we
            would place a navigability arrow at class Screen's end of this
            association. Also recall that class Deposit associates with classes
            Screen, Keypad and DepositSlot. We can navigate from class
            Deposit to each of these classes, but
            not vice versa. We therefore would place navigability arrows at the Screen,
            Keypad
            and DepositSlot ends of these associations.
            [Note: We model
            these additional classes and associations in our final class diagram in Section
            13.10, after we have simplified the structure
            of our system by incorporating the object-oriented concept of
            inheritance.]


            Implementing the ATM System from
            Its UML Design


            We are now ready to begin implementing
            the ATM system. We first convert the classes in the diagrams of Fig. 9.20 and Fig. 9.21
            into C++ header files. This code will represent the "skeleton" of the system. In
            Chapter
            13, we modify the header files to incorporate the object-oriented concept of inheritance. In Appendix
            E, we present the complete working C++ code for our model.


            As an example, we begin to develop the header
            file for class Withdrawal from our design of class Withdrawal
            in Fig. 9.20. We use this figure to determine the attributes and
            operations of the class. We use the UML model in Fig. 9.21
            to determine the associations among classes. We follow the following five
            guidelines for each class:






            1. Use the name located in the first
              compartment of a class in a class diagram to define the class in a header file
              (Fig. 9.22). Use #ifndef, #define and #endif preprocessor directives to prevent the header file from
              being included more than once in a program.











              Fig. 9.22. Definition of class Withdrawal
              enclosed in preprocessor wrappers.


               

               1   // Fig. 9.22: Withdrawal.h
              2 // Definition of class Withdrawal that represents a withdrawal transaction
              3 #ifndef WITHDRAWAL_H
              4 #define WITHDRAWAL_H
              5
              6 class Withdrawal
              7 {
              8 }; // end class Withdrawal
              9
              10 #endif // WITHDRAWAL_H





            2. Use the attributes located in the class's second
              compartment to declare the data members. For example, the private
              attributes accountNumber and amount of class
              Withdrawal yield the code in Fig. 9.23.











              Fig. 9.23. Adding attributes to the
              Withdrawal class header file.


               

               1   // Fig. 9.23: Withdrawal.h
              2 // Definition of class Withdrawal that represents a withdrawal transaction
              3 #ifndef WITHDRAWAL_H
              4 #define WITHDRAWAL_H
              5
              6 class Withdrawal
              7 {
              8 private:
              9 // attributes
              10 int accountNumber; // account to withdraw funds from
              11 double amount; // amount to withdraw
              12 }; // end class Withdrawal
              13
              14 #endif // WITHDRAWAL_H





            3. Use the associations described in the
              class diagram to declare references (or pointers, where appropriate) to other
              objects. For example, according to Fig. 9.21, Withdrawal can
              access one object of class Screen, one object of class Keypad,
              one object of class CashDispenser and one object of class
              BankDatabase. Class Withdrawal
              must maintain handles on these objects to send messages to them, so lines 19–22
              of Fig. 9.24 declare
              four references as private data members. In the
              implementation of class Withdrawal in Appendix
              E, a constructor initializes these data members with
              references to actual objects. Note that lines 6–9 #include the header files containing the definitions of classes
              Screen, Keypad, CashDispenser and BankDatabase so that we can declare references to objects of these
              classes in lines 19–22.











              Fig. 9.24. Declaring
              references to objects associated with class Withdrawal.


               

               1   // Fig. 9.24: Withdrawal.h
              2 // Definition of class Withdrawal that represents a withdrawal transaction
              3 #ifndef WITHDRAWAL_H
              4 #define WITHDRAWAL_H
              5
              6 #include "Screen.h" // include definition of class Screen
              7 #include "Keypad.h" // include definition of class Keypad
              8 #include "CashDispenser.h" // include definition of class CashDispenser
              9 #include "BankDatabase.h" // include definition of class BankDatabase
              10
              11 class Withdrawal
              12 {
              13 private:
              14 // attributes
              15 int accountNumber; // account to withdraw funds from

              16 double amount; // amount to withdraw
              17
              18 // references to associated objects
              19 Screen &screen; // reference to ATM's screen
              20 Keypad &keypad; // reference to ATM's keypad
              21 CashDispenser &cashDispenser; // reference to ATM's cash dispenser
              22 BankDatabase &bankDatabase; // reference to the account info database
              23 }; // end class Withdrawal
              24
              25 #endif // WITHDRAWAL_H





            4. It turns out that including the header files for classes
              Screen, Keypad, CashDispenser and BankDatabase in Fig. 9.24 does more than is necessary. Class Withdrawal
              contains references
              to objects of these classes—it does not contain actual objects—and the amount of
              information required by the compiler to create a reference differs from that
              which is required to create an object. Recall that creating an object requires
              that you provide the compiler with a definition of the class that introduces the
              name of the class as a new user-defined type and indicates the data members that
              determine how much memory is required to store the object. Declaring a reference (or pointer) to an
              object, however, requires only that the compiler knows that the object's class
              exists—it does not need to know the size of the object. Any reference (or
              pointer), regardless of the class of the object to which it refers, contains
              only the memory address of the actual object. The amount of memory required to
              store an address is a physical characteristic of the computer's hardware. The
              compiler thus knows the size of any reference (or pointer). As a result,
              including a class's full header file when declaring only a reference to an
              object of that class is unnecessary—we need to introduce the name of the class,
              but we do not need to provide the data layout of the object, because the
              compiler already knows the size of all references. C++ provides a statement
              called a forward declaration that signifies that a header file contains references or
              pointers to a class, but that the class definition lies outside the header file.
              We can replace the #includes in the Withdrawal class
              definition of Fig.
              9.24 with forward declarations of classes Screen, Keypad,
              CashDispenser
              and BankDatabase (lines 6–9 in Fig. 9.25). Rather than
              #include the entire header file for each of these
              classes, we place only a forward declaration of each class in the header file
              for class Withdrawal. Note that if class
              Withdrawal contained actual objects instead of
              references (i.e., if the ampersands in lines 19–22 were omitted), then we would
              indeed need to #include the full header files.











              Fig. 9.25. Using forward
              declarations in place of #include directives.


               

               1   // Fig. 9.25: Withdrawal.h
              2 // Definition of class Withdrawal that represents a withdrawal transaction
              3 #ifndef WITHDRAWAL_H
              4 #define WITHDRAWAL_H
              5
              6 class Screen; // forward declaration of class Screen
              7 class Keypad; // forward declaration of class Keypad
              8 class CashDispenser; // forward declaration of class CashDispenser
              9 class BankDatabase; // forward declaration of class BankDatabase
              10
              11 #class Withdrawal
              12 {
              13 private:
              14 // attributes
              15 int accountNumber; // account to withdraw funds from
              16 double amount; // amount to withdraw
              17
              18 // references to associated objects
              19 Screen &screen; // reference to ATM's screen
              20 Keypad &keypad; // reference to ATM's keypad
              21 CashDispenser &cashDispenser; // reference to ATM's cash dispenser
              22 BankDatabase &bankDatabase; // reference to the account info database
              23 }; // end class Withdrawal
              24
              25 #endif // WITHDRAWAL_H



              Note that using a forward declaration
              (where possible) instead of including a full header file helps avoid a
              preprocessor problem called a circular
              include
              . This problem occurs when the header file
              for a class A #includes the header file for a class B and vice versa. Some preprocessors are not be able to resolve
              such # include directives, causing a compilation error. If class
              A, for example, uses only a reference to an
              object of class B, then the #include in class A's header file can be replaced by a forward declaration
              of class B to prevent the circular include.




            5. Use the operations located in the third compartment of Fig. 9.20 to write the function prototypes of the class's member
              functions. If we have not yet specified a return type for an operation, we
              declare the member function with return type void. Refer to the class diagrams of Figs.
              6.21–6.24 to declare any necessary parameters. For
              example, adding the public operation execute in class
              Withdrawal, which has an empty parameter
              list, yields the prototype in line 15 of Fig. 9.26. [Note: We code the
              definitions of member functions in .cpp
              files when we implement the complete ATM system in Appendix
              E.]











            Fig. 9.26. Adding operations to the Withdrawal
            class header file.


             

             1   // Fig. 9.26: Withdrawal.h
            2 // Definition of class Withdrawal that represents a withdrawal transaction
            3 #ifndef WITHDRAWAL_H
            4 #define WITHDRAWAL_H
            5
            6 class Screen; // forward declaration of class Screen
            7 class Keypad; // forward declaration of class Keypad
            8 class CashDispenser; // forward declaration of class CashDispenser
            9 class BankDatabase; // forward declaration of class BankDatabase
            10
            11 class Withdrawal
            12 {
            13 public:
            14 // operations
            15 void execute(); // perform the transaction
            16 private:
            17 // attributes
            18 int accountNumber; // account to withdraw funds from
            19 double amount; // amount to withdraw
            20
            21 // references to associated objects
            22 Screen &screen; // reference to ATM's screen
            23 Keypad &keypad; // reference to ATM's keypad
            24 CashDispenser &cashDispenser; // reference to ATM's cash dispenser
            25 BankDatabase &bankDatabase; // reference to the account info database
            26 }; // end class Withdrawal
            27
            28 #endif // WITHDRAWAL_H





            Software Engineering Observation 9.11








            Several UML modeling tools can convert UML-based
            designs into C++ code, considerably speeding the implementation process. For
            more information on these "automatic" code generators, refer to the Internet and
            web resources listed at the end of Section
            2.7
            .



            This concludes our discussion of
            the basics of generating class header files from UML diagrams. In Section
            13.10, we demonstrate how to modify the header
            files to incorporate the object-oriented concept of inheritance.


            Software Engineering Case Study
            Self-Review Exercises













            9.1State whether the following statement is true or false, and if
            false, explain why: If an
            attribute of a class is marked with a minus sign (-)
            in a class diagram, the attribute is not directly accessible outside of the
            class.
            9.2In Fig. 9.21, the
            association between the ATM and the Screen indicates that:




            1. we can navigate from the Screen
              to the ATM




            2. we can navigate from the
              ATM to the Screen




            3. Both a and b; the association is
              bidirectional




            4. None of the above

            9.3Write C++ code to begin implementing the design for class
            Account.


            Answers to Software Engineering
            Case Study Self-Review Exercises













            9.1True. The minus sign ()
            indicates private visibility. We've mentioned "friendship" as an exception to
            private visibility. Friendship is discussed in Chapter
            10.
            9.2b.
            9.3The design for class Account yields the header file
            in Fig. 9.27.










            Fig. 9.27. Account class header file based on
            Fig. 9.20 and Fig.
            9.21.

             1   // Fig. 9.27: Account.h
            2 // Account class definition. Represents a bank account.
            3 #ifndef ACCOUNT_H
            4 #define ACCOUNT_H
            5
            6 class Account
            7 {
            8 public:
            9 bool validatePIN( int ); // is user-specified PIN correct?
            10 double getAvailableBalance(); // returns available balance
            11 double getTotalBalance(); // returns total balance
            12 void credit( double ); // adds an amount to the Account
            13 void debit( double ); // subtracts an amount from the Account
            14 private:
            15 int accountNumber; // account number
            16 int pin; // PIN for authentication
            17 double availableBalance; // funds available for withdrawal
            18 double totalBalance; // funds available + funds waiting to clear
            19 }; // end class Account
            20
            21 #endif // ACCOUNT_H



             


            Visual C#



            Visual C#


            Microsoft Visual C#® 2008 Express Edition: Build a Program Now!
            Patrice Pelland
            978-0-7356-2542-6


            Microsoft XNA™ Game Studio 2.0 Express: Learn Programming Now!
            Rob S. Miles
            978-0-7356-2522-8


            Microsoft Visual C# 2008 Step by
            Step

            John Sharp
            978-0-7356-2430-6


            Microsoft Visual C# 2005 Step by
            Step

            John Sharp
            978-0-7356-2129-9


            Programming Microsoft Visual C# 2008: The Language
            Donis Marshall
            978-0-7356-2540-2


            Programming Microsoft Visual C# 2005: The Language
            Donis Marshall
            978-0-7356-2181-7


            Programming Microsoft Visual C# 2005: The Base Class Library
            Francesco Balena
            978-0-7356-2308-8


            CLR via C#, Second Edition
            Jeffrey Richter
            978-0-7356-2163-3


             


            CRITICAL SKILL 2.2 Use Basic insert and select Statements


            Team Fly 


            Page 36



            All DML commands require reference to an object that will be manipulated. More often than not, the object being referenced is a table.



            A conditional statement can be added to any select, update, or delete command. Absence of a conditional statement means that the command will be performed against every record in the object. A conditional statement is used when the DML command is intended to only act upon a group of records that meet a specific condition. The where clause will be discussed a little later in this chapter.



            More optional DML statements will be described later in this chapter. For now, let's concentrate on understanding the fundamental structure of each DML statement starting with the insert and select statements.



            CRITICAL SKILL 2.2
            Use Basic insert and select Statements



            Getting data into and out of a database are two of the most important features of a database. Oracle provides two basic features that help you do just that. To get data into the database, use the insert command; to get it back out, use the select command. You must master these commands, as they form the basic of most data access to your Oracle database. This section talks first about how to get data into your database, and then how to get data out.



            insert



            Using the state table created in the DDL example, the following is an illustration of using the insert statement in its simplest form:




            SQL> insert into state values ('AZ','Arizona');
            1 row created.


            Each time you execute an insert command, you receive the message ''1 row created." Thus, you get immediate feedback that you are populating the given table with data. When you load data into a table, you may also specify the column to load it into. This ensures that there is no mistaking where you want the data to be placed. In the next example, the columns are specified after the insert command:




            SQL> insert into state (state_cd, state_name) values ('NJ','New Jersey');
            1 row created.
            SQL> insert into state (state_cd, state_name) values ('CA','California');
            1 row created.
            SQL> insert into state (state_cd, state_name) values ('TX','Texas');


            Team Fly 

            Objectives of This Book









            Objectives of This Book




            What, specifically, will this book help you do?



            Take full advantage of PL/SQL


            Oracle's reference manuals may describe all the features of the PL/SQL language, but they don't tell you how to apply the technology. In fact, in some cases, you'll be lucky to even understand how to use a given feature after you've made your way through the railroad diagrams. Books and training courses tend to cover the same standard topics in the same limited way. In this book, we'll venture beyond the basics to the far reaches of the language, finding the nonstandard ways that a particular feature can be tweaked to achieve a desired result.


            Use PL/SQL to solve your problems


            You don't spend your days and nights writing PL/SQL modules so that you can rise to a higher plane of existence. You use PL/ SQL to solve problems for your company or your customers. In this book, we try hard to help you tackle real-world problems, the kinds of issues developers face on a daily basis (at least those problems that can be solved with mere software). To do this, we've packed the book with examplesnot just small code fragments, but substantial application components that you can apply immediately to your own situations. There is a good deal of code in the book itself, and much more on the accompanying web site. In a number of cases, we use the code examples to guide you through the analytical process needed to come up with a solution. In this way you'll see, in the most concrete terms, how to apply PL/SQL features and undocumented applications of those features to a particular situation.



            Write efficient, maintainable code


            PL/SQL and the rest of the Oracle products offer the potential for incredible development productivity. If you aren't careful, however, this capability will simply let you dig yourself into a deeper, darker hole than you've ever found yourself in before. We would consider this book a failure if it only helped programmers write more code in less time; we want to help you develop the skills and techniques to build applications that readily adapt to change and that are easily understood and maintained. We want to teach you to use comprehensive strategies and code architectures that allow you to apply PL/SQL in powerful, general ways to the problems you face.