Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!pt.cs.cmu.edu!sei!ajpo!eberard From: eberard@ajpo.sei.cmu.edu (Edward Berard) Newsgroups: comp.lang.smalltalk Subject: Re: Teaching object oriented programming Summary: OODIL Has Some Unique Problems Message-ID: <536@ajpo.sei.cmu.edu> Date: 5 Aug 89 15:37:40 GMT References: <1318@massormetrix.ida.liu.se> <80500066@p.cs.uiuc.edu> Lines: 272 In article <80500066@p.cs.uiuc.edu>, johnson@p.cs.uiuc.edu writes: > > >If you find any object-oriented examples of any size, you will find > >that they often address such issues as "object-oriented domain > >analysis," "object-oriented requirements analysis," and > >"object-oriented design." Unfortunately you will find precious few > >references to "object-oriented development in the large" (OODIL) -- > >but there are a few. > > As far as I can tell, there aren't any problems in OODIL that are > unique to OO, they are all caused by the DIL. Consider the following: Object-oriented approaches offer some surprising benefits in the area of configuration management. The introduction of the concept of subroutines in the 1950s allowed people to group lines of code, give them a name, and, thus, manage large amounts of code more easily. For example, it is easier to manage 10 subroutines, each with 100 lines of code, than it is to manage 1000 lines of unpartitioned code. You might say that a class is to a subroutine, as a subroutine is to a line of code. Specifically, classes can be viewed as encapsulating several subroutines, as well as some other material. Classes allow you to more effectively manage large amounts of code, than do simple subroutines. The object-oriented paradigm, it appears, is a very useful way of managing complexity in large systems. It offers significant benefits over approaches which partition software along functional lines. (If you are not using a language which directly supports something like a class, your benefits are not all that they could be.) If this is so good, then where is the problem? There is an axiom of system design that says: the larger the overall system, the larger the size of the largest objects ("objects" here is being used in the generic, non-software sense) in the system. What this means for the object-oriented paradigm is that for very large systems, even classes are not enough, we need something bigger. Two concepts that become very useful in large, object-oriented systems, and are _unique_ to object-oriented systems are: subsystems and systems of objects. Let me define each concept. Subsystems are collections of items which support large, object-oriented concepts. For example, consider windows. To support the concept of windows, many classes are required, e.g., several different types of window classes, scroll bar classes, text classes, graphics classes, and more. To offer as much flexibility as possible, it is desirable to keep each of these classes as independent of each other as possible. Subsystems are highly logically cohesive. That is, all the components of the subsystem are there to support a single, large, object-oriented concept. Subsystems, however, are not very physically cohesive, i.e., there is no requirement that there be a direct or indirect physical connection between any two arbitrary components of the subsystem. Subsystems can be viewed as having three parts: - An export (or visible) part which contains those items which the subsystem wishes to make available to the outside world. These items include objects, classes, other subsystems, systems of objects, and other items (usually dependent on the programming language being used). - A body (or hidden) part which contains those items necessary to support the items in the export part. The items contained in the body part are not available (or are not _supposed_ to be available) to the outside world. - An import (or requirements) part which details the items necessary to use the subsystem, i.e., these are the items which users of the subsystem must supply to use the subsystem. You might say these are the parameters for the subsystem. Subsystems, as you might have guessed, tend to be large, e.g., 20,000 lines of code and more. There are several methods for designing subsystems, but I don't have time to go into them here. However, speaking as both a designer and user of subsystems, they are worth the effort, and, if designed well, are highly reusable. Let's now discuss "systems of objects." We generally think of objects as having a single, cohesive interface. We might be initially tempted to say that a big object might still have a single interface. However, two things may make our interface overly complex: - the overall size and complexity of the object itself, and - a requirement that our object interface with a number of different classes of object, and provide different sets of services to each of these classes. Consider an automobile engine. Most object-oriented people would be willing to stipulate that an automobile engine is a single cohesive object. However, consider the interfaces to the engine object. There is the interface to the transmission, the interface to the fuel system, and the interface to the cooling system, for example. Each of these interfaces is totally disjoint, e.g., when the transmission interfaces with the engine, it doesn't care about such things as the fuel system or the cooling system. If we attempted to combine all of these separate interfaces into a single, large interface, the resulting interface would not be very logically cohesive. For a large object, with several (two, or more) distinct and disjoint interfaces we should consider a "system of objects." There is the trivial case of a large system of objects which has a single interface. This is little different from a small object with its single cohesive interface. The more interesting cases involve large objects with two, or more, distinct interfaces. (Consider a post office. There is the interface seen by the postal patrons in the front, and the interface seen by mail trucks and letter carriers in the back.) Note that "systems of objects" are highly logically cohesive, _and_ highly physically cohesive. They differ from smaller simple objects in that they allow for multiple, disjoint interfaces. There is a requirement that each of these disjoint interfaces be logically cohesive. As with subsystems, there are several methods for designing systems of objects. I do not have the time to go into them here. You might also want to give some thought as to how object-oriented configuration management might be different from traditional configuration management. > > One feature of object-oriented technology is that it squashes together > the various phases of the design cycle. OOP is great for prototyping, > so usually systems are built during the requirements analysis phase to > help figure out what the user needs. Not surprisingly, a certain amount > of design information is discovered here as well, and sometimes a few > components are developed that are reused later. Here, you have observed what other have observed: that the object-oriented life-cycle is different from the traditional, waterfall life-cycle. Note that I am talking about something different from the use of object-oriented techniques for rapid prototyping, and something different from the use of object-oriented techniques in a spiral life-cycle. The object-oriented life-cycle has been described as a "recursive/parallel" life-cycle. While I would prefer not to go into detail on this approach, I will tell you that its description has often been oversimplified to: "Analyze a little, Design a little, Implement a little, Test a little." This yields some interesting results, especially when people attempt their first large, in-house object-oriented project. Many existing software development standards (government, in-house, and those described in software management texts) assume a functional decomposition approach, and thus present problems when someone attempts to use them with an object-oriented approach. [If you are doing small, one-person projects, you seldom notice this problem, unless, for example, someone asks you to show "input-processing-output" for your objects, or asks to see a "structure chart."] > At the other end of > the life-cycle, I find that code is not reusable until it has been > reused, and this implies that you have to redesign software after it > has been used in a couple of projects. If you study software reusability technology, you find that you do not have to approach software reusability in a "trial and error" manner. You really can design software so that it is reusable _without_ _modifications_ later. There are techniques, rule, methods, and guidelines which can be used at all levels of abstraction to ensure and enhance software reusability. (I incorporate many of these items into the courses on object-oriented technologies that I teach.) > On the other hand, OOP provides a consistent world-view that can carry > you through the whole life-cycle. Requirements analysis is determining > the objects from the users point of view and figuring out what operations > will take place on them. Design is decomposing these objects into smaller > objects, delegating responsibility for operations to various objects, > determining the class hierarchy, and discovering new classes that are > part of the solution domain, not the problem domain. Implementation > is writing code for all the operations and defining data structures > for the classes. Invariably new classes are discovered and the design > is revised during implementation, but that's just because top-down > development is impossible to carry off perfectly. In attempting to define, document, and apply Object-Oriented Requirements Analysis (OORA), Object-Oriented Design (OOD), Object-Oriented Domain Analysis (OODA) over the past 8 years, I have to agree with you in principle. However, there are some points that I would clarify, e.g.: - It is not the purpose of OORA to identify _all_ of the code software objects and classes in the system. It is perfectly normal, healthy, and _expected_ to uncover additional objects and classes during an OOD process. In fact, the larger the overall project, the greater the percentage of objects and classes which will be uncovered during OOD. - Some objects and classes, will be described in OORA to provide some context for the problem. However, these items may never become code software. (One of the nice things about an object-oriented approach is that people, hardware, and code can all be viewed as objects, and treated in a similar manner. Can you say polymorphism? ;-)) > >Most of the work which has been done in the area of object-oriented > >life-cycle issues, outside of object-oriented programming, has been > >accomplished within the Ada community. > > In general, I don't like this work. Speaking from the point of view > of a Smalltalk programmer, I think that they are really talking about > data abstraction and NOT object-oriented programming. Important > issues that they miss are the importance of building families of > components with the same interface, using abstract classes for > templates for new components, and polymorphism. > > On the other hand, I haven't read all these papers, so perhaps I am > missing something. I'll read them. You are partially correct. Much, but not all, of the early (starting in 1980) work in attempting an object-oriented approach for Ada software development did center on data abstraction. However, much work has been done to incorporate many of the principles of object-oriented thinking found in the traditional object-oriented programming (OOP) community. Regarding the building of families of components with consistent interfaces: I would strongly recommend that you look at Grady Booch's second book (Software Components With Ada), or that you contact my former company, EVB Software Engineering, Inc. (800-877-1815), and ask about GRACE (Generic Reusable Ada Components for Engineering), or that you get a copy of my course notes from "Creating Reusable Ada Software." One of the things that all of these items directly, and explicitly, address is that reusability is enhanced through uniformity, and there is explicit mention of families of components with consistent interfaces. Regarding the use of abstract classes as templates for building new components: Let me assure you that the construction of the over 512K lines of source code which comprise GRACE would have been virtually impossible without this concept. The developers achieved productivity rates of over 8,000 lines of code/person/month. That is fully documented, warranted code. Booch's book talks about this issue as well. Regarding polymorphism: The construction of many of the resuable software components described in Booch's book, or which comprise GRACE, or the Common Ada Missile Packages (CAMP), would have been fairly difficult without some degree of polymorphism. There is other work being done to enhance the incorporation of polymorphism into object-oriented Ada software, especially in the area of communication systems. [I am not one of those who will try to tell you that Ada is an object-oriented language. Ada clearly does not follow the Smalltalk paradigm very closely. However, many in the Ada community have recognized the value of object-oriented approaches to software development. Like any good engineer, they have "stolen" a good deal of the useful technology that the OOP community has to offer.] (I better stop talking about Ada before some "C Fundamentalists" come after me. You know the joke about what is difference between C programmers and the Iranian Revolutionary Guard? The Iranian Revolutionary Guard is less fanatical. ;-)) -- Ed Berard (301) 353-9652 P.S.: If you think this message is long, look at the one I posted to comp.lang.c++ on "object coupling," or the one I posted to comp.lang.ada on "objectification."