Wednesday, November 4, 2009

4.4 Formalizing Use Cases




I l@ve RuBoard









4.4 Formalizing Use Cases


The initial description of a use case is text. We can formalize the definition of a use case in terms of preconditions and postconditions. Preconditions state what must be true for the use case to execute. Postconditions state what must be true when the use case has completed.


The formulation of a use case in terms of pre- and postconditions is both precise and concise, in no way presupposes a particular design, and avoids the pitfall of specifying the use case in an overly procedural form.


4.4.1 Preconditions


Each use case may have zero or more preconditions.


Definition:
A use case precondition denotes a relevant, verifiable property of the system that is required to be true before the use case is performed.


To help identify preconditions, examine the use case's parameters. For example, Add Item to Order has the parameters Order Number, Book Number, and Quantity. This raises questions about each of these items. What must be so? In the case of Add Item to Order, then, we expect the following to be true:



  • There is an unexpired Order not yet checked out.


  • The item selected is a book carried by the store.


  • The quantity selected is a number greater than zero and less than stock on hand.




4.4.2 Postconditions


Each use case has at least one postcondition.


Definition:
A use case postcondition represents what must be true when the use case has completed.


After Add Item to Order completes successfully, we expect the following to be true:



  • The order is no longer empty.


  • The order is not checked out.


  • The book is included in the order with the given quantity.


  • The total value of the order is increased by the unit price of the book times the quantity selected.



We can write a use case in terms of preconditions and postconditions, as seen in Figure 4.9.


Figure 4.9. Preconditions and Postconditions for Add Item to Order




4.4.3 Linked Use Cases


One use case's postcondition is often another's precondition. This is especially true when we have sequences of use cases characterized as activities, as you can see in Figure 4.10.


Figure 4.10. Connecting Preconditions and Postconditions










    I l@ve RuBoard



    8.1 Unique Instance Constraints




    I l@ve RuBoard









    8.1 Unique Instance Constraints


    Objects may have sets of attributes that are required to be unique.



    • a customer's login ID


    • a publisher's ISBN code


    • an order's order number





    Object orientation endows each object with its own unique identity, the object handle. This handle uniquely identifies an object, but it is implicit and carries no semantic significance. An object's identifier carries semantics�it's a rule about the domain�and is made explicit.



    These attributes constitute ways to identify an individual instance. We call each required-to-be-unique set of attributes an identifier.


    Definition:
    An identifier is a set of one or more attributes that uniquely distinguishes each instance of a class.


    8.1.1 Single Attribute Identifiers


    To capture this notion of uniqueness in the model, we establish uniqueness constraints. Examples of unique-instance constraints are:



    • No two customers can have the same e-mail address.


    • Each publisher has a unique ISBN prefix code.


    • Each new order is assigned a unique number.




    Uniqueness constraints formalize rules in the domain�both rules about the world (e.g., publishers are assigned unique ISBN prefix codes by the publishing industry) as well as rules that we make up (the customer's e-mail address is his login ID and therefore must be unique).


    Any kind of attribute can be used to make up an identifier.




    The notion of a naming attribute is different from that of an identifier, although naming attributes are frequently used in identifiers. For example, nothing prohibits two publishers from having the same company name if they were established in different jurisdictions, but the ISBN code is required, by policy, to be unique.



    Constraints in OCL.

    To define a unique-instance constraint formally, we may use the Object Constraint Language (OCL). Figure 8.1 depicts the constraint for the Customer.


    Figure 8.1. Unique Instance Constraint in OCL



    The first line defines the context of the constraint, namely the class for which the constraint applies, and the fact that the constraint is a definition of an invariant (inv).


    The second line iterates over all instances of the class using two free variables, p1 and p2. allInstances is a predefined operator that finds all the instances of the associated class, and the dagger symbol (->) indicates that the following operation acts on a collection, in this case, all the instances of the customer.


    The third line introduces an implication. For two arbitrary instances of the class, p1 and p2, that are not equal, this fact implies something (on the following line).


    The last line states the invariant, namely that the identifying attribute of the two instances must not be the same.



    Unique instance constraint idiom.

    The example in Figure 8.2 forms an idiom.


    Figure 8.2. Unique Instance Constraint Idiom



    This idiom is the unique instance constraint. The unique instance constraint for the Publisher and the Order follow the same idiom.



    OCL�The Object Constraint Language


    The Object Constraint Language (OCL) is a fundamental part of the UML, described in Section 6 of the UML 1.4 Specification [1]. It is designated as the official way to express constraints on UML models. The semantics of UML themselves are defined using OCL.


    The constraints shown in this chapter are written in OCL and in action language. These constraint expressions are written as boolean functions that return true if the constraint is satisfied and false if the constraint is violated.


    We hope for and encourage a convergence between OCL and action languages, such that a developer can write a constraint using the same language used for actions and that model compilers will be able to check and to enforce these constraints.



    Definition:
    A constraint idiom is a general pattern for a commonly occurring type of constraint that can be represented by a predefined tag.



    Constraints in action language.

    The constraints in Figure 8.1 can also be written in action language, as shown in Figure 8.3.


    Figure 8.3. Unique Instance Constraint in Action Language



    Specifically, this is written as an instance function on the Customer class.



    Graphical notation.

    UML allows the definition of tags. A tag is a string that can be added to any model element, enclosed in braces {}. Figure 8.4 shows how we use the tag {I} on each identifying attribute to denote an identifier.


    Figure 8.4. Identifiers on the Class Diagram



    The presence of the tags is a shorthand for writing the unique instance constraint, so there is no need to explicitly write the OCL or action language.



    Contrived identifiers unnecessary.

    Shlaer-Mellor ([2] and [3]), a precursor to Executable UML, required that every class contain at least one identifier, even if that identifier was an attribute placed in the object solely for the purpose of being its identifier. This practice is not required in Executable UML.




    8.1.2 Multiple Attribute Identifiers


    An identifier may consist of multiple attributes. For example, publishers have code numbers assigned by "ISBN agencies." The code number is not unique among all publishers, but is unique among publishers in the same ISBN agency group.


    Definition:
    An identifying attribute is an attribute that forms part of at least one identifier.


    The Publisher's identifier comprises two identifying attributes: Publisher.groupCode and Publisher.publisherCode.


    The constraint is depicted in Figure 8.5. Or, see Figure 8.6 for the constraint in action language. This action language snippet asserts that the combination of the two attributes must be distinct.


    Figure 8.5. Multiple-Attribute Identifier Constraint in OCL



    Figure 8.6. Multiple-Attribute Identifier Constraint in Action Language



    This idiom is another unique instance constraint, this time with multiple identifying attributes. Constraints involving any number of attributes are possible. But since the unique instance constraint is a common idiom, we do not need to write OCL or action language for it; we simply tag the attributes as shown in Figure 8.7.


    Figure 8.7. Multiple-Attribute Identifier on Class Diagram




    8.1.3 Multiple Identifiers


    A class may have several identifiers, each of which consists of one or more identifying attributes. In this case, we write several unique instance constraints for the same class.


    When there is more than one identifier, use the tags {I}, {I2}, {I3}, and so on. Select a new tag for each new identifier, and tag every identifying attribute in a given identifier with that tag. Hence, each identifying tag ({I}, {I2}, {I3}, etc.) applies to all attributes of a single identifier that defines one of the unique instance constraints.


    Furthermore, an identifying attribute may be a part of more than one identifier. For example, a car can be identified by:



    • manufacturer + serialNumber


    • state + titleNumber


    • state + tagNumber



    In this example, the state attribute is a part of two identifiers.


    A single attribute may be a part of several identifiers, so it may be tagged several times. In our example depicted in Figure 8.8, the tags {I2, I3} are shown for the state attribute of Car.


    Figure 8.8. Multiple Identifiers on Class Diagram



    Search for identifiers.

    When abstracting attributes of classes, pay special attention to finding identifying attributes. Look for situations in which no two instances may have the same value for an attribute or set of attributes. In some cases, the business may have unique numbering or identifying schemes for many of the things being modeled. These are the identifying attributes, and they constitute a rule in the domain.










      I l@ve RuBoard



      Chapter 3. Domains and Bridges




      I l@ve RuBoard









      Chapter 3. Domains and Bridges



      Building a system involves understanding many different subject matters and gluing them together to make a coherent whole. In an online bookstore, for example, we need to understand the application itself, the look and feel of a user interface, the details of user-interface screen layout using, say, HTML, messaging between computers, networking, and so on. In addition to these subject matters, we must also state how they relate to one another, so we can put them together into a complete system.


      Each subject matter is a domain, capable of being understood and modeled using executable UML. We build one or more executable UML models for each domain.


      Domains are semantically autonomous. For example, we can understand an online bookstore application without having to understand networking, and vice versa. But domains also depend on one another: The online bookstore makes assumptions about the existence of a networking domain and so places requirements on it. This assumption�requirement pair is a bridge.


      At implementation time, the models of each domain are woven together by specifying a set of join points between the models. The joining together of two domains is an implementation of a bridge. We take up this topic in Chapter 18: Model Compilers.


      This chapter describes the concepts of domains and bridges, introduces a domain chart to visualize the relationships between them, and discusses how requirements relate to both systems and domains.









        I l@ve RuBoard



        Getting Started


















































        Getting Started



        This chapter extends the Utils class so that it also includes an implementation of SecureRandom,
        which will produce predictable output. Although this sounds insane from
        a cryptographic point of view, it will make it a lot easier for me to
        talk about the examples that use it, as you will be able to reproduce
        the output exactly.


        Here is the class:



        package chapter4;

        import java.security.MessageDigest;
        import java.security.SecureRandom;

        /**
        * Utility class for chapter 4 examples
        */
        public class Utils
        extends chapter3.Utils
        {
        private static class FixedRand extends SecureRandom
        {
        MessageDigest sha;
        byte[] state;

        FixedRand()
        {
        try
        {
        this.sha = MessageDigest.getInstance("SHA-1", "BC");
        this.state = sha.digest();
        }
        catch (Exception e)
        {
        throw new RuntimeException("can't find SHA-1!");
        }
        }

        public void nextBytes(
        byte[] bytes)
        {
        int off = 0;

        sha.update(state);

        while (off < bytes.length)
        {
        state = sha.digest();

        if (bytes.length - off > state.length)
        {
        System.arraycopy(state, 0, bytes, off, state.length);
        }
        else
        {

        System.arraycopy(state, 0, bytes, off, bytes.length - off);
        }

        off += state.length;

        sha.update(state);
        }
        }
        }

        /**
        * Return a SecureRandom which produces the same value.
        * <b>This is for testing only!</b>
        * @return a fixed random
        */
        public static SecureRandom createFixedRandom()
        {
        return new FixedRand();
        }
        }


        As you can see, it just builds on the idea of using a message digest to generate a pseudorandom stream of bytes. Type the new Utils class in to start off the chapter4 package and you are ready to begin.








































        15.6 Checking and Repairing InnoDB Tables











         < Day Day Up > 





        15.6 Checking and Repairing InnoDB Tables



        To check InnoDB tables for problems, use the CHECK TABLE statement:










        mysql> CHECK TABLE table_name;




        Another way to check InnoDB tables is to use the mysqlcheck client program, which acts as a command-line interface to the CHECK TABLE statement:










        shell> mysqlcheck db_name table_name




        More detailed instructions for using mysqlcheck can be found in the "Core Study Guide."



        If a table check indicates that an InnoDB table has problems, you should be able to restore the table to a consistent state by dumping it with mysqldump, dropping it, and re-creating it from the dump file.



        In the event of a crash of the MySQL server or the host on which it runs, some InnoDB tables might need repairs. Normally, it suffices simply to restart the server because the InnoDB storage engine performs auto-recovery as part of its startup sequence. In rare cases, the server might not start up due to failure of InnoDB auto-recovery. If that happens, use the following procedure:



        • Restart the server with the --innodb_force_recovery option set to a value in the range from 1 to 6. These values indicate increasing levels of caution in avoiding a crash, and increasing levels of tolerance for possible inconsistency in the recovered tables. A good value to start with is 4.

        • When you start the server with --innodb_force_recovery set to a nonzero value, InnoDB treats the tablespace as read-only. Consequently, you should dump the InnoDB tables and then drop them while the option is in effect. Then restart the server without the --innodb_force_recovery option. When the server comes up, recover the InnoDB tables from the dump files.

        • If the preceding steps fail, it's necessary to restore the InnoDB tables from a previous backup.













           < Day Day Up > 



          Chapter 3. HTML Optimization




          [ Team LiB ]









          Chapter 3. HTML Optimization



          HTML is still the lingua franca for publishing hypertext documents on the web. With simple markup tags like <h1> and </h1> used to denote structure, HTML has become the universal language of the web. As designers and browser manufacturers morphed HTML into the web equivalent of PageMaker, however, HTML code became too verbose with presentational tags, scripts, and objects intermixed with structural markup. This chapter and the ones that follow show you how to optimize and simplify your code for maximum speed, while still maintaining the functionality and visual appeal of your site.


          Ask any group of users today what makes the web so slow, and you'll hear about large video, Flash, and image files. You might hear about overused and unoptimized Java and JavaScript. What is seldom mentioned is bloated HTML. Yet HTML size is the one web page component that users cannot control. They can turn off JavaScript, images, plug-ins, and Java, but they can't turn off HTML bloat�only designers can.


          Because it has looser rules, HTML offers more opportunities for optimization than its newer cousin, XHTML. In HTML, you can omit some end tags and abbreviate attributes and still have a valid document. In XHTML, every tag must be closed, every attribute fully qualified and quoted. Because HTML offers more opportunities for savings and it isn't going away anytime soon, it is the focus of this chapter. Chapter 5, "Extreme XHTML," focuses on optimizing XHTML, which can use a subset of the techniques discussed here.









            [ Team LiB ]



            12.4 Bitmap Color




            < BACK  NEXT >

            [oR]

            12.4
            BITMAP COLOR TRANSFORMATION


            There are numerous algorithms that need to transform color for each pixel in the bitmap in a certain way. A color transformation is applied to each pixel independently and without a global context. Sample usage for this group of algorithms includes converting color bitmaps to grayscale, gamma correction, color space conversion, adjusting bitmap hue, lightness, or saturation, etc.



            Such bitmap color transformation algorithms have the same pattern. If the bitmap has a color table, each entry in the color table needs to be transformed. Otherwise, we have to scan through each pixel in the pixel array and apply a transformation to each of them. An easy way to implement them would be to use a generic algorithm and a function pointer parameter. Each color transformation is a simple static function. To transform a bitmap with a given color transformation, just call the generic algorithm with the specific color transformation routine a parameter. A similar way is to define an abstract color transformation class, which has a virtual member function that does the color transformation.



            Performance is normally considered critical for bitmap-handling algorithms, so calling a function or a virtual function for every pixel in a huge bitmap is normally unacceptable. We certainly do not want to repeat the same code over and over again, nor would we like to use macro-based programming. So the only alternative is a template function.



            We would like to define these algorithms on the KDIB class. But the trouble with a template function is that our available C++ compiler does not support a template member function. So we have to use a static template function that accepts a pointer to a KDIB instance. To make things worse, our C++ compiler does not support a friend template function, which forces us to change some private members to be public members.



            Listing 12-4 shows a template-based DIB color transformation algorithm.





            Listing 12-4 Template for Bitmap Color Transformation Algorithms


            template <class Dummy>
            bool ColorTransform(KDIB * dib, Dummy map)
            {
            // OS/2 DIB color table: 1,4,8-bpp, include RLE compression
            if ( dib->m_pRGBTRIPLE )
            {
            for (int i=0; i<dib->m_nClrUsed; i++)
            map(dib->m_pRGBTRIPLE[i].rgbtRed,
            dib->m_pRGBTRIPLE[i].rgbtGreen,
            dib->m_pRGBTRIPLE[i].rgbtBlue);

            return true;
            }

            // Windows DIB color table: 1,2,4,8-bpp, include RLE compression
            if ( dib->m_pRGBQUAD )
            {
            for (int i=0; i<dib->m_nClrUsed; i++)
            map(dib->m_pRGBQUAD[i].rgbRed,
            dib->m_pRGBQUAD[i].rgbGreen,
            dib->m_pRGBQUAD[i].rgbBlue);

            return true;
            }

            for (int y=0; y<dib->m_nHeight; y++)
            {
            int width = dib->m_nWidth;
            unsigned char * pBuffer = (unsigned char *) dib->m_pBits +
            dib->m_nBPS * y;

            switch ( dib->m_nImageFormat )
            {
            case DIB_16RGB555: // 15-bit RGB color image, 5-5-5
            for (; width>0; width�)
            {
            BYTE red = ( (* (WORD *) pBuffer) & 0x7C00 ) >> 7;
            BYTE green = ( (* (WORD *) pBuffer) & 0x03E0 ) >> 2;
            BYTE blue = ( (* (WORD *) pBuffer) & 0x001F ) << 3;

            map( red, green, blue );
            * ( WORD *) pBuffer = ( ( red >> 3 ) << 10 ) |
            ( ( green >> 3 ) << 5 ) |
            ( blue >> 3 );

            pBuffer += 2;
            }
            break;

            case DIB_16RGB565: // 16-bit RGB color image, 5-6-5
            for (; width>0; width�)
            {
            BYTE red = ( (* (WORD *) pBuffer) & 0xF800 ) >> 8;
            BYTE green = ( (* (WORD *) pBuffer) & 0x07E0 ) >> 3;
            BYTE blue = ( (* (WORD *) pBuffer) & 0x001F ) << 3;

            map( red, green, blue );

            * ( WORD *) pBuffer = ( ( red >> 3 ) << 11 ) |
            ( ( green >> 2 ) << 5 ) |
            ( blue >> 3 );

            pBuffer += 2;
            }
            break;

            case DIB_24RGB888: // 24-bpp RGB
            for (; width>0; width�)
            {
            map( pBuffer[2], pBuffer[1], pBuffer[0] );
            pBuffer += 3;
            }
            break;

            case DIB_32RGBA8888: // 32-bpp RGBA
            case DIB_32RGB888: // 32-bpp RGB
            for (; width>0; width�)
            {
            map( pBuffer[2], pBuffer[1], pBuffer[0] );
            pBuffer += 4;
            }
            break;
            default:
            return false;
            }
            }

            return true;
            }

            The ColorTransform function accepts two parameters: a pointer to a KDIB instance and a function pointer. It's strange to pass a function pointer a template function without specifying the function prototype. But apparently, this method is supported and used by STL. The first part of the function handles the color table in the OS/2 BMP file format; each of the RGBTRIPLE structures is handled by calling the color transformation function through the map parameters. The color transformation routine accepts three reference parameters for the red, green, and blue channels, and returns the transformed color using the same variable. The code handling Windows color table is very similar, except now the RGBQUAD structure needs to be mapped. This part of the code handles all palette-based DIB formats, including RLE compressed and uncompressed formats.



            The remaining code handles 16-bit high color bitmaps, 24-bit true color bitmaps, and 32-bit true color with alpha bitmaps. The logical order of the pixel array is not important here, so the code just goes through each pixel in the order they appear. For 16-bit bitmaps, two common formats are supported. The code needs to extract the RGB channels, convert them to 8 bits each, call the color transformation routine, and pack the results back into a 16-bit WORD. A 24-bit bitmap is very easy to handle. For a 32-bit bitmap, its alpha channel is untouched.



            Any other rare DIB formats, like JPEG or PNG compressed bitmaps, or bitmaps with unusual bit fields, are not supported by the currently implemented ColorTransform routine.



            Converting Bitmaps to Grayscale


            The commonly used formula for converting color in RGB space to grayscale is





            For computer implementation, we would like to implement the conversion without any floating-point computation. Based on the ColorTransform template, here is our RGB-bitmap to grayscale-bitmap conversion method.





            // 0.299 * red + 0.587 * green + 0.114 * blue
            inline void MaptoGray(BYTE & red, BYTE & green, BYTE & blue)
            {
            red = ( red * 77 + green * 150 + blue * 29 + 128 ) / 256;
            green = red;
            blue = red;
            }

            class KImage : public KDIB
            {
            public:
            bool ToGreyScale(void);
            ...
            };

            bool KImage::ToGreyScale(void)
            {
            return ColorTransform(this, MaptoGray);
            }


            A new class KImage is derived from the KDIB class to encapsulate image-processing algorithms developed in this chapter. The KImage class has no extra member variables. Its only method shown here is ToGreyScale. More methods will be added later in this chapter.



            The KImage::ToGreyScale method transforms the current color DIB to a grayscale DIB. It simply calls the ColorTransform template function with the MaptoGray routine as the color transformation routine. MaptoGray uses integer operation to calculate the lightness of a color and assign it to all three RGB channels.



            In a debug build, MaptoGray is compiled as a subroutine and its pointer is passed to ColorTransform. In a release build, all calls to MaptoGray are in-lined to get the best performance.




            Gamma Correction


            Image displaying suffers from photometric distortions caused by the nonlinear response of display devices to lightness. The photometric response of a displaying device is known as the gamma response characteristic. Display monitors for different operating systems use different gammas. When an image prepared on a Macintosh screen is displayed on a PC screen, it normally looks too dark. On the other hand, an image downloaded from a PC server to a Macintosh machine may look too bright. To compensate for these differences, the gamma of the image needs to be corrected.



            Gamma correction is normally done in the three RGB channels independently. Three arrays of 256 bytes each are precalculated and passed to either the software gamma transformer or the hardware display card. Each of the three arrays is applied to one of the channels.



            Gamma correction can be easily implemented using the ColorTransform template function.





            BYTE redGammaRamp[256];
            BYTE greenGammaRamp[256];
            BYTE blueGammaRamp[256];

            inline void MapGamma(BYTE & red, BYTE & green, BYTE & blue)
            {
            red = redGammaRamp[red];
            green = greenGammaRamp[green];
            blue = blueGammaRamp[blue];
            }

            BYTE gamma(double g, int index)
            {
            return min(255, (int) ( (255.0 * pow(index/255.0, 1.0/g)) + 0.5 ) );
            }

            bool KImage::GammaCorrect(double redgamma, double greengamma,
            double bluegamma)
            {
            for (int i=0; i<256; i++)
            {
            redGammaRamp[i] = gamma( redgamma, i);
            greenGammaRamp[i] = gamma(greengamma, i);
            blueGammaRamp[i] = gamma( bluegamma, i);
            }

            return ColorTransform(this, MapGamma);
            }


            The user level routine provided here is KDIB::GammaCorrect. It accepts three independent gamma values, which normally range between 0.2 and 5.0. The routine pre-calculates three gamma ramps for each of the RGB channels, according to the definition of gamma. It then calls ColorTransform with the MapGamma routine as the color transformer. MapGamma does a simple table lookup for each pixel.



            A gamma correction with gamma equal to 1.0 is an identity color transformation. Gamma less than one makes a picture look �darker,� and gamma larger than one makes a picture look �lighter.�



            If you apply a gamma correction of 2.2 to images prepared on a Macintosh, they will look exactly as they originally appeared on their creator's screen. Figure 12-2 shows a tiger picture with the wrong gamma and its gamma-corrected version.




            Figure 12-2. Gamma correction.


            The table lookup mechanism implemented by MapGamma can also be used to adjust color according to other criteria. Actually, the only condition is that the RGB channels are independent of each other. For example, you can define a red Gamma Ramp to reduce the red channel by 10%, while leaving the other two as identity transformations.



            Win32 GDI supports setting a graphics device's gamma ramp if the hardware and device driver supports downloadable gamma ramps. The related function is SetDeviceGammaRamp, which is part of ICM 2.0. DirectDraw also supports gamma ramps through the IDirectDrawGammaControl interface. Newer PC hardware should all support downloadable gamma ramps.







            < BACK  NEXT >