The object-oriented thought process (3th edition) pdf download
However, as a programmer using this class, you do not need to know anything about these private methods and attributes. You simply need to know how to interact with the interfaces. What would the code for this public interface look like assume that we start with a Oracle database example? Now comes the fun stuff—what really makes interfaces so great!
Last night we translated all the data from an Oracle database to an SQLAnywhere database we endured the acute and chronic pain. It took us hours—but we did it. This is because even though the implementation changed, the interface did not! As far as the user is concerned, the calls are still the same.
The code change for the implementation might have required quite a bit of work and the module with the one-line code change would have to be rebuilt , but not one line of application code that uses this DataBaseReader class needed to change. Code Recompilation Dynamically loaded classes are loaded at runtime—not statically linked into an executable file. When using dynamically loaded classes, like Java and. NET do, no user classes would have to be recompiled.
By separating the user interface from the implementation, we can save a lot of headaches down the road. In Figure 2. In general, reusable classes tend to have interfaces that are more abstract than concrete. Concrete interfaces tend to be very specific, whereas abstract interfaces are more general. However, simply stating that a highly abstract interface is more useful than a highly concrete interface, although often true, is not always the case.
It is possible to write a very useful, concrete class that is not at all reusable. This happens all the time, and there is nothing wrong with it in some situations. However, we are now in the design business, and want to take advantage of what OO offers us. So our goal is to design abstract, highly reusable classes—and to do this we will design highly abstract user interfaces. How the cabbie implements the actual drive is of no concern to you, the passenger. Of course, the fare might become an issue at some point, if the cabbie cheats and takes you the long way to the airport.
Giving the User the Minimal Interface Possible Now, where does the connection between abstract and reuse come in? Ask yourself which of these two scenarios is more reusable, the abstract or the not-so-abstract? Obviously, the first phrase is more reusable. You can use it in any city, whenever you get into a taxi and want to go to the airport. The second phrase will only work in a specific case.
Giving the User the Minimal Interface Possible When designing a class, the rule of thumb is to always provide the user with as little knowledge of the inner workings of the class as possible. To accomplish this, follow these simple rules: n n n n Give the users only what they absolutely need.
In effect, this means the class has as few interfaces as possible. When you start designing a class, start with a minimal interface. The design of a class is iterative, so you will soon discover that the minimal set of interfaces might not suffice. This is fine.
It is better to have to add interfaces because users really need it than to give the users more interfaces than they need. There are times when it is problematic for the user to have certain interfaces.
Imagine handing a user a PC box without a monitor or a keyboard. Obviously, the PC would be of little use. You have just provided the user with the minimal set of interfaces to the PC. Of course, this minimal set is insufficient, and it immediately becomes necessary to add interfaces.
Public interfaces define what the users can access. If you initially hide the entire class from the user by making the interfaces private, when programmers start using the class, you will be forced to make certain methods public—these methods thus become the public interface.
Too often designers of classes not to mention any other kind of software design the class to make it fit into a specific technological model. Make sure when you are designing a class that you go over the requirements and the design with the people who will actually use it—not just developers.
The class will most likely evolve and need to be updated when a prototype of the system is built. We have already decided that the users are the ones who will actually use the system. This said, the obvious question is who are the users?
The first impulse is to say the customers. This is only about half right. Although the customers are certainly users, the cabbie must be able to successfully provide the service to the customers. Thus, in reality, to build a realistic and usable interface, both the customer and the cabbie must be considered users.
For a software analogy, consider that users might want a programmer to provide a certain function. In short, any object that sends a message to the taxi object is considered a user and yes, the users are objects, too. Providing services. Looking Ahead The cabbie is most likely an object as well. Object Behavior Identifying the users is only a part of the exercise. After the users are identified, you must determine the behaviors of the objects. From the viewpoint of all the users, begin identifying the purpose of each object and what it must do to perform properly.
Note that many of the initial choices will not survive the final cut of the public interface. Environmental Constraints In their book Object-Oriented Design in Java, Gilbert and McCarty point out that the environment often imposes limitations on what an object can do. In fact, environmental constraints are almost always a factor.
Computer hardware might limit software functionality. For example, a system might not be connected to a network, or a company might use a Giving the User the Minimal Interface Possible specific type of printer.
In the taxi example, the cab cannot drive on a road if a bridge is out, even if it provides a quicker way to the airport. Identifying the Public Interfaces With all the information gathered about the users, the object behaviors, and the environment, you need to determine the public interfaces for each user object.
So think about how you would use the taxi object: n n n n n Get into the taxi. Tell the cabbie where you want to go. Pay the cabbie. Give the cabbie a tip. Get out of the taxi. What do you need to do to use the taxi object? Hail a taxi. Pay the cabbie money. Initially, you think about how the object is used and not how it is built. As is always the case, nailing down the final interface is an iterative process. For each interface, you must determine whether the interface contributes to the operation of the object.
If it does not, perhaps it is not necessary. This returns us to the question of how abstract we want to get with the design. If we have an interface called enterTaxi , we certainly do not want enterTaxi to have logic in it to pay the cabbie.
If we do this, then not only is the design somewhat illogical, but there is virtually no way that a user of the class can tell what has to be done to simply pay the cabbie. Identifying the Implementation After the public interfaces are chosen, you need to identify the implementation. After the class is designed and all the methods required to operate the class properly are in place, the specifics of how to get the class to work are considered.
Technically, anything that is not a public interface can be considered the implementation. It is possible to have a private method that is used internally by the class.
Any private method is considered part of the implementation given that the user will never see it and thus will not have access to it. For example, a class may have a changePassword method; however, the same class may have a private method that actually encrypts the password. This method would be hidden from the user and called only from inside the changePassword method.
The implementation is totally hidden from the user. The code within public methods is actually a part of the implementation because the user cannot see it. The user should only see the calling structure of an interface—not the code inside it. This means that, theoretically, anything that is considered the implementation might change without affecting how the user interfaces with the class. This assumes, of course, that the implementation is providing the answers the user expects. Whereas the interface represents how the user sees the object, the implementation is really the nuts and bolts of the object.
The implementation contains the code that represents that state of an object. Conclusion In this chapter, we have explored three areas that can get you started on the path to thinking in an OO way. Remember that there is no firm list of issues pertaining to the OO thought process.
Doing things in an OO way is more of an art than a science. Try to think of your own ways to describe OO thinking. While it is alive, it might transition through many different states. For example, a DataBaseReader object is in one state if the database is open and another state if the database is closed. How this is represented depends on the design of the class. References References Meyers, Scott. Addison-Wesley Professional, Boston, MA.
Flower, Martin. UML Distilled, 3rd ed. Gilbert, Stephen, and Bill McCarty. Object-Oriented Design in Java. Berkeley, CA. Before we embark on our journey to learn some of the finer design issues relating to building an OO system, we need to cover several more advanced OO concepts such as constructors, operator overloading and multiple inheritance.
We also will consider error-handling techniques, the importance of understudying how scope applies to object-oriented design. Some of these concepts might not be vital to understanding an OO design at a higher level, but they are necessary to anyone actually involved in the design and implementation of an OO system.
Constructors Constructors are a new concept for people doing structured programming. In the first two chapters we alluded to special methods that are used to construct objects. In OO languages, constructors are methods that share the same name as the class and have no return type. Caution Note again that a constructor does not have a return value.
If you provide a return value, the compiler will not treat the method as a constructor. When Is a Constructor Called? When a new object is created, one of the first things that happens is that the constructor is called.
Then the constructor itself is called, passing the arguments in the parameter list. The constructor provides the developer the opportunity to attend to the appropriate initialization.
Thus, the code new Cabbie will instantiate a Cabbie object and call the Cabbie method, which is the constructor. Perhaps the most important function of a constructor is to initialize the memory allocated when the new keyword is encountered. In short, code included inside a constructor should set the newly created object to its initial, stable, safe state.
Initializing attributes is a common function performed within a constructor. The Default Constructor If you write a class and do not include a constructor, the class will still compile, and you can still use it.
If the class provides no explicit constructor, a default constructor will be provided. It is important to understand that at least one constructor always exists, regardless of whether you write a constructor yourself. If you do not provide a constructor, the system will provide a default constructor for you. Besides the creation of the object itself, the only action that a default constructor takes is to call the constructor of its superclass.
In many cases, the superclass will be part of the Constructors language framework, like the Object class in Java. The compiler actually inserts it. In this case, if Cabbie does not explicitly inherit from another class, the Object class will be the parent class.
Perhaps the default constructor might be sufficient in some cases; however, in most cases some sort of memory initialization should be performed. Regardless of the situation, it is good programming practice to always include at least one constructor in a class. If there are attributes in the class, it is always good practice to initialize them. Providing a Constructor The rule of thumb is that you should always provide a constructor, even if you do not plan on doing anything inside it.
You can provide a constructor with nothing in it and then add to it later. Although there is technically nothing wrong with using the default constructor provided by the compiler, it is always nice to know exactly what your code looks like. It is not surprising that maintenance becomes an issue here. If you depend on the default constructor and then maintenance is performed on the class that added another constructor, then the default constrictor is not created.
As soon as you include just one, the default constructor is not included. Using Multiple Constructors In many cases, an object can be constructed in more than one way. To accommodate this situation, you need to provide more than one constructor. Most OO languages provide functionality for overloading a method.
Overloading Methods Overloading allows a programmer to use the same method name over and over, as long as the signature of the method is different each time.
The signature consists of the method name and a parameter list see Figure 3. In Java and C , the return type is not part of the signature. For example, the following methods would conflict even though the return types are different: public void getCab String cabbieName ; public int getCab String cabbieName ; The best way to understand signatures is to write some code and run it through the compiler. Constructors By using different signatures, you can construct objects differently depending on the constructor used.
Consider that we have two ways we can construct a database reader: n n Pass the name of the database and position the cursor at the beginning of the database. Pass the name of the database and the position within the database where we want the cursor to position itself. Figure 3. Note that the diagram lists two constructors for the class.
Although the diagram shows the two constructors, without the parameter list, there is no way to know which constructor is which. To distinguish the constructors, you can look at the corresponding code listed below.
No Return Type Notice that in this class diagram the constructors do not have a return type. All other methods besides constructors must have return types. Here is a code segment of the class that shows its constructors and the attributes that the constructors initialize see Figure 3.
If the constructor is not passed the information via the parameter list, it is initialized to a default value, like 0. How the Superclass Is Constructed When using inheritance, you must know how the parent class is constructed. Remember that when you use inheritance, you are inheriting everything about the parent. The inheritance of an Constructors attribute is fairly obvious. However, how a constructor is inherited is not as obvious.
After the new keyword is encountered and the object is allocated, the following steps occur see Figure 3. If there is no explicit call to the superclass constructor, the default is called automatically; however, you can see the code in the bytecodes.
Then each class attribute of the object is initialized. These are the attributes that are part of the class definition instance variables , not the attributes inside the constructor or any other method local variables.
In the DataBaseReader code presented earlier, the integer startPosition is an instance variable of the class. Then the rest of the code in the constructor executes.
The Design of Constructors As we have already seen, when designing a class, it is good practice to initialize all the attributes. In some languages, the compiler provides some sort of initialization. In Java, you cannot use an attribute until it is initialized. If the attribute is first set in the code, make sure that you initialize the attribute to some valid condition—for example, set an integer to zero. For example, initializing an attribute to zero, when it is intended for use as a denominator in a division operation, might lead to an unstable application.
You must take 59 60 Chapter 3 Advanced Object-Oriented Concepts into consideration the fact that a division by zero is an illegal operation. Initializing to zero is not always the best policy. During the design, it is good practice to identify a stable state for all attributes and then initialize them to this stable state in the constructor. Error Handling It is rare for a class to be written perfectly the first time. In most, if not all, situations, things will go wrong.
Any developer who does not plan for problems is courting danger. Assuming that your code has the ability to detect and trap an error condition, you can handle the error in several different ways: On page of their book Java Primer Plus, Tyma,Torok, and Downing state that there are three basic solutions to handling problems that are detected in a program: fix it, ignore the problem by squelching it, or exit the runtime in some graceful manner.
On page of their book Object-Oriented Design in Java, Gilbert and McCarty expand on this theme by adding the choice of throwing an exception: n n n n Ignore the problem—not a good idea! Check for potential problems and abort the program when you find a problem. Check for potential problems, catch the mistake, and attempt to fix the problem. Throw an exception. Often this is the preferred way to handle the situation. These strategies are discussed in the following sections.
Ignoring the Problem Simply ignoring a potential problem is a recipe for disaster. And if you are going to ignore the problem, why bother detecting it in the first place? The bottom line is that you should not ignore the problem. The primary directive for all applications is that the application should never crash. If you do not handle your errors, the application will eventually terminate ungracefully or continue in a mode that can be considered an unstable state.
In the latter case, you might not even know you are getting incorrect results for some period of time. Checking for Problems and Aborting the Application If you choose to check for potential problems and abort the application when a problem is detected, the application can display a message indicating that there is a problem. In this case the application gracefully exits, and the user is left staring at the computer screen, shaking her head and wondering what just happened.
Although this is a far superior option to ignoring the problem, it is by no means optimal. However, this does allow the system to clean up things and put itself in a more stable state, such as closing files. Error Handling Checking for Problems and Attempting to Recover Checking for potential problems, catching the mistake, and attempting to recover is a far superior solution than simply checking for problems and aborting. In this case, the problem is detected by the code, and the application attempts to fix itself.
This works well in certain situations. By catching the exception and setting the variable a to 1, at least the system will not crash. However, setting a to 1 might not be a proper solution.
You might need to prompt the user for the proper input value. A Mix of Error Handling Techniques Despite the fact that this type of error handling is not necessarily object-oriented in nature, I believe that it has a valid place in OO design. Throwing an exception discussed in the next section can be expensive in terms of overhead.
Thus, although exceptions are a great design choice, you will still want to consider other error handling techniques, depending on your design and performance needs. Although this means of error checking is preferable to the previous solutions, it still has a few potentially limiting problems. It is not always easy to determine where a problem first appears. And it might take a while for the problem to be detected. In any event, it is beyond the scope of this book to explain error handling in great detail.
However, it is important to design error handling into the class right from the start. Throwing an Exception Most OO languages provide a feature called exceptions. In the most basic sense, exceptions are unexpected events that occur within a system. Exceptions provide a way to detect problems and then handle them. This might sound like a baseball game, but the key concept here is that a specific block of code is written to handle a specific exception.
This solves the problem of trying to figure out where the problem started and unwinding the code to the proper point. When an exception is thrown while the block is executing, the following occurs: 1. The execution of the try block is terminated.
The catch clauses are checked to determine whether an appropriate catch block for the offending exception was included. There might be more than one catch clause per try block.
If none of the catch clauses handle the offending exception, it is passed to the next higher-level try block. If the exception is not caught in the code, the system ultimately catches it, and the results are unpredictable, i.
If a catch clause is matched the first match encountered , the statements in the catch clause are executed. Execution then resumes with the statement following the try block. Suffice to say that exceptions are an important advantage for OO programming languages. You can catch all exceptions or just check for specific exceptions, such as arithmetic exceptions. In this example, the division by zero because count is equal to 0 within the try block will cause an arithmetic exception. If the exception was generated thrown outside a try block, the program would most likely have been terminated.
However, because the exception was thrown within a try block, the catch block is checked to see whether the spe- The Concept of Scope cific exception in this case, an arithmetic exception was planned for. Because the catch block contains a check for the arithmetic exception, the code within the catch block is executed, thus setting count to 1. If you had not put ArithmeticException in the catch block, the program would likely have crashed. The Concept of Scope Multiple objects can be instantiated from a single class.
Each of these objects has a unique identity and state. This is an important point. Each object is constructed separately and is allocated its own separate memory. However, some attributes and methods may, if properly declared, be shared by all the objects instantiated from the same class, thus sharing the memory allocated for these class attributes and methods. A Shared Method A constructor is a good example of a method that is shared by all instances of a class. There are three types of attributes: n Local attributes Object attributes n Class attributes n Local Attributes Local attributes are owned by a specific method.
This integer is accessible only inside method1. The method method2 has no idea that the integer count even exists. At this point, we introduce a very important concept: scope. Attributes and methods exist within a particular scope.
In this case, the integer count exists within the scope of method1. In the Number class, there are several possible scopes—just start matching the curly braces. The class itself has its own scope. Each instance of the class that is, each object has its own scope. Both method1 and method2 have their own scopes as well. When method1 terminates, the copy of count is removed. Remember that method1 and method2 each has its own scope.
Thus, the compiler can tell which copy of count to access simply by recognizing which method it is in. You can think of it in these terms: method1.
It is almost like two people having the same last name, but based on the context of their first names, you know that they are two separate individuals. Object Attributes There are many design situations in which an attribute must be shared by several methods within the same object.
In Figure 3. However, it is within the scope of the class. Thus, count is available to both method1 and method2. Basically, all methods in the class have access to this attribute.
Notice that the code for both methods is setting count to a specific value. There is only one copy of count for the entire object, so both assignments operate on the same copy in memory. However, this copy of count is not shared between different objects. There are actually three separate instances of the integer count. When number1 changes its attribute count, this in no way affects the copy of count in object number2 or object number3. In this case, integer count is an object attribute.
You can play some interesting games with scope. The object owns one copy, and method1 and method2 each have their own copy. However, we must live with it. The use of the this keyword directs the compiler to access the object variable count and not the local variables within the method bodies. Note The keyword this is a reference to the current object. Class Attributes As mentioned earlier, it is possible for two or more objects to share attributes.
Thus, all objects of the class use the same memory location for count. Essentially, each class has a single copy, which is shared by all objects of that class see Figure 3. This is about as close to global data as we get in OO design. There are many valid uses for class attributes; however, you must be aware of potential synchronization problems.
This is not a problem until the object Count2 decides to use attribute count to keep track of sheep. The instant that Count2 records its first sheep, the data that Count1 was saving is lost. Operator Overloading Some OO languages allow you to overload an operator.
Operator overloading allows you to change the meaning of an operator. For example, when most people see a plus sign, they assume it represents addition.
And in this case, you would be correct. However, there are times when a plus sign could represent something else. The plus sign here has been String Concatenation String concatenation is when two separate strings are combined to create a new, single string. Multiple Inheritance In the context of strings, the plus sign does not mean addition of integers or floats, but concatenation of strings.
What about matrix addition? Overloading is a powerful mechanism. However, it can be downright confusing for people who read and maintain code. In fact, developers can confuse themselves. To take this to an extreme, it would be possible to change the operation of addition to perform subtraction.
Why not? Thus, if the plus sign were changed to perform subtraction, the following code would result in an X value of —1. NET do not allow operator overloading. The designers of Java must have decided that operator overloading was more of a problem than it was worth. As the name implies, multiple inheritance allows a class to inherit from more than one class. In practice, this seems like a great idea. Objects are supposed to model the real world, are they not? And there are many real-world examples of multiple inheritance.
Parents are a good example of multiple inheritance. So it makes sense that you can design classes by using multiple inheritance. However, this situation falls into a category similar to operator overloading. Multiple inheritance is a very powerful technique, and in fact, some problems are quite difficult to solve without it. Multiple inheritance can even solve some problems quite elegantly. However, multiple inheritance can significantly increase the complexity of a system, both for the programmer and the compiler writers.
As with operator overloading, the designers of Java and. NET decided that the increased complexity of allowing multiple inheritance far outweighed its advantages, so they eliminated it from the language. In some ways, the Java and. NET language construct of 69 70 Chapter 3 Advanced Object-Oriented Concepts interfaces compensates for this; however, the bottom line is that Java and.
NET do not allow conventional multiple inheritance. Behavioral and Implementation Inheritance Java and. NET interfaces are a mechanism for behavioral inheritance, whereas abstract classes are used for implementation inheritance.
The bottom line is that Java and. NET interfaces provide interfaces, but no implementation, whereas abstract classes may provide both interfaces and implementation. For example, when you want to copy or compare primitive data types, the process is quite straightforward. However, copying and comparing objects is not quite as simple. Classes and References The problem with complex data structures and objects is that they might contain references.
Simply making a copy of the reference does not copy the data structures or the object that it references. In the same vein, when comparing objects, simply comparing a pointer to another pointer only compares the references—not what they point to. The problems arise when comparisons and copies are performed on objects. Specifically, the question boils down to whether you follow the pointers or not.
Regardless, there should be a way to copy an object. Again, this is not as simple as it might seem. Because objects can contain references, these reference trees must be followed to do a valid copy if you truly want to do a deep copy. Deep Versus Shallow Copies A deep copy is when all the references are followed and new copies are created for all referenced objects.
There might be many levels involved in a deep copy. For objects with references to many objects, which in turn might have references to even more objects, the copy itself can create significant overhead. A shallow copy would simply copy the reference and not follow the levels. Thus, both objects the original and the copy will point to the same objects. To perform a complete copy, in which all reference objects are copied, you have to write the code to create all the sub-objects.
This problem also manifests itself when comparing objects. As with the copy function, this is not as simple as it might seem. In most cases, languages provide a default mechanism to compare objects. As is usually the case, do not count on the default mechanism.
When designing a class, you should consider providing a comparison function in your class that you know will behave as you want it to. Conclusion This chapter covered a number of advanced OO concepts that, although perhaps not vital to a general understanding of OO concepts, are quite necessary in higher-level OO tasks, such as designing a class.
You could continuously see the link that we provide and all set to download and install The Object-Oriented Thought Process 4th Edition When many people are hectic to look for fro in the book store, you are quite simple to download the The Object-Oriented Thought Process 4th Edition here. So, what else you will choose? Take the motivation here! It is not only supplying the ideal book The Object-Oriented Thought Process 4th Edition however also the appropriate book collections.
Here we consistently offer you the best as well as easiest means. Posting Komentar. Minggu, 01 Maret [K Diposting oleh Unknown di Label: Ebooks. This item is printed on demand. AdvancED ActionScript 3. With each method broken down into different strategized explanations, you'll find the approach most suitable for you.
Whether it is an example you can utilize as-is, or one you can start with and develop further, you will have a glossary of definitions and organizational concepts at your fingertips. Object-oriented programming OOP and design patterns are not new to the field, but can often be overlooked in their value. They are, at times, not only overwhelming to learn, but difficult to put into practice.
However, they are useful because they create a structure that can be broken down, rebuilt, and reused. The amount of software used in safety-critical systems is increasing at a rapid rate. At the same time, software technology is changing, projects are pressed to develop software faster and more cheaply, and the software is being used in more critical ways. Developing Safety-Critical Software: A Practical Guide for Aviation Software and DOC Compliance equips you with the information you need to effectively and efficiently develop safety-critical, life-critical, and mission-critical software for aviation.
The principles also apply to software for automotive, medical, nuclear, and other safety-critical domains. An international authority on safety-critical software, the author helped write DOC and the U. In this book, she draws on more than 20 years of experience as a certification authority, an avionics manufacturer, an aircraft integrator, and a software developer to present best practices, real-world examples, and concrete recommendations. The book includes: An overview of how software fits into the systems and safety processes Detailed examination of DOC and how to effectively apply the guidance Insight into the DOC-related documents on tool qualification DO , model-based development DO , object-oriented technology DO , and formal methods DO Practical tips for the successful development of safety-critical software and certification Insightful coverage of some of the more challenging topics in safety-critical software development and verification, including real-time operating systems, partitioning, configuration data, software reuse, previously developed software, reverse engineering, and outsourcing and offshoring An invaluable reference for systems and software managers, developers, and quality assurance personnel, this book provides a wealth of information to help you develop, manage, and approve safety-critical software more confidently.
Now this classic book has been fully updated and revised with leading-edge practices—and hundreds of new code samples—illustrating the art and science of software construction. Capturing the body of knowledge available from research, academia, and everyday commercial practice, McConnell synthesizes the most effective techniques and must-know principles into clear, pragmatic guidance. No matter what your experience level, development environment, or project size, this book will inform and stimulate your thinking—and help you build the highest quality code.
Discover the timeless techniques and strategies that help you: Design for minimum complexity and maximum creativity Reap the benefits of collaborative development Apply defensive programming techniques to reduce and flush out errors Exploit opportunities to refactor—or evolve—code, and do it safely Use construction practices that are right-weight for your project Debug problems quickly and effectively Resolve critical construction issues early and correctly Build quality into the beginning, middle, and end of your project.
The 42 revised full papers presented together with 7 short papers were carefully reviewed and selected from submissions. The papers are organized in topical sections on: algorithm; applications; systems hardware and software ; biomedical informations; poster papers. Learn UML, the Unified Modeling Language, to create diagrams describing the various aspects and uses of your application before you start coding, to ensure that you have everything covered.
0コメント