We use cookies to distinguish you from other users and to provide you with a better experience on our websites. Close this message to accept cookies or find out how to manage your cookie settings.
To save content items to your account,
please confirm that you agree to abide by our usage policies.
If this is the first time you use this feature, you will be asked to authorise Cambridge Core to connect with your account.
Find out more about saving content to .
To save content items to your Kindle, first ensure [email protected]
is added to your Approved Personal Document E-mail List under your Personal Document Settings
on the Manage Your Content and Devices page of your Amazon account. Then enter the ‘name’ part
of your Kindle email address below.
Find out more about saving to your Kindle.
Note you can select to save to either the @free.kindle.com or @kindle.com variations.
‘@free.kindle.com’ emails are free but can only be saved to your device when it is connected to wi-fi.
‘@kindle.com’ emails can be delivered even when you are not connected to wi-fi, but note that service fees apply.
Sockets are an abstraction for interprocess communication (IPC) that were introduced as part of the Berkeley version of Unix in 1982. They have become a de facto standard for network communication and are supported by most major operating systems (including PC systems). The SML Basis Library provides an optional collection of modules for programming with sockets. The interface provided by the Basis follows the C interface for the most part; the major difference is that the SML interface is more strongly typed. In particular, the type system distinguishes between passive and active sockets, between sockets in different domains, and between sockets of different protocols.
The Berkeley Socket API supports two styles of communication: stream sockets provide virtual circuits between pairs of processes, and datagram sockets provide connectionless packet-based communication. In stream-based interactions, the server allocates a master socket that is used to accept connections from clients. The server then listens on the master socket for connection requests from clients; each request is allocated a new socket that the server uses to communicate with that particular client. As the name suggests, stream-based communication is done as a stream of bytes, not as discrete packets. Connectionless communication is more symmetric: messages are sent to a specific port at a specific address. While datagram sockets provide better performance, messages may be lost or received out of order, which requires additional programming by the client. For this reason, stream sockets are more commonly used than datagram sockets.
You build a wide variety of artifacts, including models, documents, and source code.
Software development is a complex endeavor. You create a variety of artifacts throughout a project, some of which you keep and some you do not. Regardless of whether you keep the artifact, the reason why you create it (I hope) is because it adds some sort of value. Perhaps you create a model in order to explore a business rule, a model that may then be used to drive your coding efforts. If the model is wrong then your code will be wrong too. If it is a complex business rule, one that requires a significant amount of time to implement, you might be motivated to validate your model before you act on it. If it's a simple business rule you might instead trust that your code-testing efforts will be sufficient. You will also find that many artifacts, such as user manuals and operations manuals, never become code yet still need to be validated. The point is that you will need testing techniques that enable you to validate the wide range of artifacts that you create during software development.
In this chapter I explore the following:
The cost of change;
Testing philosophies;
The FLOOT methodology;
Regression testing;
Quality assurance;
Techniques for validating models;
Techniques for testing code;
Techniques for system testing;
Techniques for user-based testing; and
Test-driven development (TDD).
THE COST OF CHANGE
A critical concept that motivates full-lifecycle testing is the cost of change.
Data does not have to be a four-letter word anymore.
The predominant development technologies are object technology for implementing business logic and relational database (RDB) technology for storing information. You have other options—procedural technologies such as COBOL for implementing business logic and XML-based or object-oriented databases for storage, for instance. COBOL is beyond the scope of this book and XML databases and object databases are at best niche technologies (albeit very interesting ones). My focus is on mainstream, modern development, and that means objects on the front end and RDBs on the back end.
The fit between object technology and RDB technology is not perfect. In the early 1990s, the difference between the two approaches was labeled the object/relational impedance mismatch, also referred to as the O/R impedance mismatch or simply the impedance mismatch, terms still in common use today. Why does a technological impedance mismatch exist? The object-oriented paradigm is based on proven software engineering principles. The relational paradigm, however, is based on proven mathematical principles. Because the underlying paradigms are different, the two technologies do not work together seamlessly. The impedance mismatch becomes apparent when you look at the preferred approach to access: With the object paradigm you traverse objects via their relationships, whereas with the relational paradigm you join rows of tables. This fundamental difference results in a nonideal combination of the two technologies, although when have you ever used two different things together without a few hitches?
Agile software development has moved from the fringes of the software development community to the mainstream. This movement is driven by the need to produce better software faster, which is integral to developing competitive advantage in the global software community. From North America to Asia and everywhere in between, the ability to deliver software that delights the customer has become a critical success factor. The agile community particularly focuses on that customer and ensures that he or she receives maximum value.
Much of the way that we traditionally built software was based on the constraints posed by the systems of old. The amount of time needed to compile these systems was large and software development processes were built around this activity. Getting the code right the first time was important to maximize productivity in this environment. However, many of today's integrated development environments (IDEs) no longer require us to compile the whole system to add some new functionality. In fact, newer compilers often help us get the syntax of our programs correct as we are writing it.
The agile software development movement is taking advantage of the lifting of these constraints. All agile software development processes focus on creating small increments of functionality using an iterative approach. This new approach is in contrast to the “big bang” or waterfall approach where the software is delivered all at one time. Again, today's technology and software development processes allow us to lift another constraint.
The purpose of structural design modeling is exactly what the name implies—to model the design of the structural aspects of your system. Structural design focuses on the identification of entities, classes or data structures, and the relationships among those entities. For modern systems there are two basic styles of structure that you need to be concerned about at the detailed design level. The first is the design of your object schema, something that is typically modeled with a class diagram. The second is the design of your database, something that is done with a physical data model (PDM).
This chapter addresses the following topics:
UML class diagrams;
Applying design patterns effectively; and
Physical data modeling with the UML.
UML CLASS DIAGRAMS
The purpose of design is to model how the software will be built; as you would expect, the purpose of design class modeling is to model the static structure of how your software will be built. The techniques of analysis class modeling that you learned in Chapter 8 still apply. The only difference is your focus is on the solution domain instead of on the problem domain. In fact your analysis class model often evolves into your design class model—you simply introduce changes to your class model based on implementation technologies. Although modeling purists may insist that you keep your analysis and design models separate, the reality is that you will often work through requirements to analysis to design in a matter of minutes, sometimes even seconds.
If you always think what you have thought you will always get what you have got.
Architecture provides the foundation from which systems are built, and models are one way to define the vision on which your architecture is based. The scope of architecture can be that of a single application, of a family of applications, for an entire organization, or for an international infrastructure such as the Internet. The focus of this chapter is on architectural modeling for a single system, although much of the advice is pertinent to larger efforts. Regardless of the scope, my experience is that you can take an agile approach to the modeling, development, and evolution of architectures. Table 10.1 overviews the artifacts described in this chapter for architectural modeling.
For our purposes the architecture for a system is simply its high-level design. Good architectures are based on requirements—developers taking on the role of architect will often analyze the pertinent requirements as part of the architectural modeling process. One way to look at architecture is that it, along with analysis, is the bridge between requirements and design. Architects will also consider high-level design decisions such as “What will we build this system from?”, “How will the parts of this system fit together?”, and “How can we ensure this system will work under less-than-perfect (or real-world) conditions?”
Modern software development requires modern ways of working.
The only constant in the information technology (IT) industry is change. To remain employable, let alone effective, software developers must continually take the time to identify and then understand the latest development approaches. The goal of this chapter is to introduce you to leading-edge technologies and techniques that enable you to succeed at developing modern business systems. I will try to steer you through the marketing hype surrounding these approaches, and in one case try to dissuade you from adopting it—just because something is new and well hyped does not mean that it has much of a future. In short, this chapter provides you with a foundation for reading the rest of this book.
This chapter discusses
Modern development technologies;
Modern development techniques;
How this book is organized; and
The case studies.
MODERN DEVELOPMENT TECHNOLOGIES
Effective developers understand the fundamentals of the technologies that they have available to them. The good news is that we have many technologies available to us; the bad news is that we have many technologies available to us.
Figure 1.1, which depicts a high-level architecture detailing how these technologies are used together, shows how some applications may be n-tiered—an approach where application logic is implemented on several (n) categories of computing devices (tiers)—whereas others fall into the “fat client” approach where most business logic is implemented on the client. Object technology is used to implement all types of logic, including both business and system logic.