software re engineering for re usability

Upload: hina-singh

Post on 08-Apr-2018

225 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/7/2019 Software Re Engineering for Re Usability

    1/7

    Software reengineering for reusability

    Stan Jarzabek

    Department of Information Systems and Computer ScienceNational University of Singapore

    e-mail: [email protected]

    Abstract

    Programs are o fe n reengineered fo r bettermainta inability or in order to migrate programs intonewer computerlsofhuareplatforms. However, manyof

    the aging business systems must be also upgraded inorder to meet strategic goals of an organization .To meetsuch ambitious objectives, we must fundamentally re-design progra ms, rather than merely restructure them orimproved maintainability. When much progra m re-designis involved , reengineering option becomes challenging attechnical level, expensive and risky. To increase thevalue of a reengineering solutio n, we propose to addressreusability issues in the context of reengineering. In th ispap er, we discuss lifecycle phases and outline a possibletechnical scenario or reengineering or reusability.

    1. Introduction

    Many of the aging business programs show a coupleof seriousdeficiencies:

    High cost of maintenance. After years of ad hoc

    maintenance, programs have become complex andprogram modifications cannot be implemented in atimely and reliable way.Inadequate functionality. Many of the old programsdo not provide functions that companies need inorder to remain competitive and to meet companies'strategic goals. Such programs should besubstantially extended and re-designed to meet newrequirements. But because of low quality, programevolution is difficult.Not using new computer and software platforms.New technology can reduce the overall computingcosts, facilitate better use of stored data and simplifyuser-system interface. M a n y old programs do nottake advantage of new technology and still run onoutdated and inefficient platforms.

    To cope with these problems, increasing number ofcompanies embark on some kind of a software

    improvement program. Usually, programs arerestructured for better maintainability and converted intoa new computer, database, operating system, language,etc. But software restructuring and conversions do notsolve all the problems with existing programs. In fact,they can only help a company to achieve a short-termgoal which is to extend the life time of a system that has

    become technically obsolete. In long-term, however,programs must be reengineered (or re-written) to fullyexploit advantages of new technology and to be in tunewith company's strategic plans [15,22,12]. Softwarereengineering is defined in [4] as "examination andalteration of a subject system to reconstitute it in a newform and subsequent implementation of the new form".There is a wide range of possible reengineering scenariosand the right scenario depends on the objectives of areengineering project. In this paper, we shall be tallcingabout reengineering that aims at upgrading programs ina fundamental way and, therefore, requires much ofprogram re-design.

    Why to address reusability in the context of software

    reengineeringReengineering that involves much re-design of

    programs is expensive and risky. In order to improvecost-effectiveness of the reengineering approach, wepropose to conduct reengineering in a way that enablesextracting reusable features from programs. Manyresearchers and practitioners express opinion thatsoftware reuse has a potential to bring productivitybreakthroughs and can fundamentally change the way wedevelop programs [2,15]. One of the important potentialsources of reusable software assets are existing programs.We observe a growing number of aging programs thathave become technically obsolete but still have muchbusiness value. Some of those programs will bereengineered. During reengineering, we must extractdesign information (and sometimes requirements) fromprograms, break programs into components and thenrefine and synthesize programs in a new form that meets

    0730-3167/93 3.00 0 1993 EE E100

    Authorized licensed use limited to: Universidade Estadual Do Sudoeste da Bahia. Downloaded on May 14,2010 at 12:44:53 UTC from IEEE Xplore. Restrictions apply.

  • 8/7/2019 Software Re Engineering for Re Usability

    2/7

    new software requirements. All this requires intimateunderstanding of global and local programcharacteristics. "herefore, reengineering is an opportunemoment to capture viable assets from existing programsand make them available for future reuse. Reengineeringand reusability are the two emerging technologies that

    have a potential to ease a so-called software crisis, but atthe same time are still expensive and difficult toimplement in organizations. We think these twotechnologies can reinforce each other in the way that willincrease cost-effectiveness of the solutions they offer.

    In this paper, we explore means for integratingreengineering efforts with software reuse. We start byoutlining main phases of the "reengineering forreusability" lifecycle (section 2), then comment oncost-benefit analysis issues (section 3) and outline areengineering for reusability scenario (sections 4 and 5).In section 6, we discuss the pposed approach in thecontext of current technology and other research projects.

    2. Reengineering for reusability: lifecycleP h W

    Fig. 1 shows main phases in the reengineering forreusability lifecycle. Before reengineering of softwaresystems, a fair amount of planning must be done in orderto select and prioritize candidate systems fornxngineering. Planning is based on analysis of thequality and business value of soaware systems andincludes cost-benefit-risk analysis [12,2021].

    Ca-M-liItU&j#i#

    iy~Sar.kUL4foro.@uliq

    Fig. 1 Reengineering or reusability lifecycle phases

    After planning, selected systems are incrementallyreengineered. During reengineering of a system S,designs and code accumulated within the reusabilityframework are used in reconsauction of the targetsystem S'. The repository of rezlsable f e a m s grows asreengineering process progresses: newly recovered

    features from S may be included into the repository forfuture reuse.

    Colap~LYu:

    Fig. 2 Logical structure of the reengineering process

    During reengineering, we transform an existingsystem S into a new system, S', that meets some newobjectives. Rectangles represent p g r a m views at variouslevels of abstraction. The physical layer is created usingreverse engineering techniques. The physical layerincludes abstract syntax trees and design abstractionssuch as control flow and data flow graphs, procedure

    calling trees, data structure charts, etc. The logical layercontains ER data models and logical processes. Theconceptual layer provides the description of a program interms of user-oriented, domain concepts. Mappingsbetween layers facilitate traceability of information fromthe conceptual layer down to program d e . Recovery ofthe physical layer is fully automatic, while higher layersrequire human involvement.

    At each layer indicated in fig. 2, we identify programviews that help programmers during various stages ofreengineering and maintenance. We model these viewsand, for each layer, we define methack for exploring andquerying program information. Finally, we defineautomatic and semi-automatic techniques for obtaininghigher level program abstractions from lower level ones.The description of specific reengineering techniques isnot covered in this paper. In sections 5 and 6, a readerwill find an overview of research related to extractingreusable features from code.

    101

    Authorized licensed use limited to: Universidade Estadual Do Sudoeste da Bahia. Downloaded on May 14,2010 at 12:44:53 UTC from IEEE Xplore. Restrictions apply.

  • 8/7/2019 Software Re Engineering for Re Usability

    3/7

    3. Reengineering planning

    In selecting candidate systems for reengineering, onetakes into account the technical quality of a system andweighs it against the business value a system still

    represents [10,15]. Systems of low technical quality butcontaining much business value are candidates forreengineering. During further evaluation, we try toestimate cost-effectiveness of a reengineering solution.To evaluate merits of a reengineering solution, we takeinto account estimated cost of reengineering, expectedbenefits (both tangible and intangible) and risks.

    Addressing reusability in the context of reengineeringhas direct impact on incurred costs and expected benefitsof reengineering. On cost side, a reusability framework(as described in section 4) must be built prior toreengineering. The reengineering p e s s tself will alsobe more time consuming for two reasons: fmt, programarchitecture will have to be fundamentally changed andsecond, extracted features will have to be Eviewed fromthe perspective of various contexts of potential users,cleaned from implementation dependencies andgeneralized (e.g., through parameterization). On benefitside, once understood and properly refined, a reusablefeature (such as design fragment, data model, procedure,etc.) can be reused within the same system (hencesimplifying the structure of the target program) andacross systems in a given application domain (hencesimplifying reengineering of other systems, developmentof new systems and future maintenance of systems). Areengineering solution should be chosen if, in areasonable time-frame, expected benefits outgrow costsand if risks of failure are low. Practitioners in thereengineering field have published cost figures andproposed cost models that can be used to evaluate themerits of various renovation options [20,21]. In [12], weshowed how these cost models can be adapted forevaluating the cost of reengineering for reusability.

    4. A reusability framework forreengineering

    classifies and describes potentially reusable feat"across systems in a given application domain. Featuresmay nefer to objects (e.g.. EMPLOYEE andSALARY-RECORD in payroll systems), procedures("how is an EMPLOYEE salary computed?") andbusiness rules ("part-time EMPLOYEES are not entitled

    to a bonus" or "a bonus should be paid at the end of ayear"). Within a domain model, concepts are representedby structures that help programmers understand how agiven concept has been implemented. Two parallelactivities contribute to building the domain model:reverse engineering of existing programs andindependent domain analysis [1,11].

    Reusable features can be modeled using Object-Oriented approach (00). bjects represent meaningfulconcepts from the application domain (e.g. an employeein a payroll system). In business programs, many of theinteresting candidates for objects are naturally derivedfrom a conceptual data model [19]. Objects comprisedata models and procedures related to specific datagroups. Modeling reusable features starts by reverseengineering of a conceptual data model based onanalysis of data s trucms and database schema fromexisting programs. Reverse engineered data model isreconciled with new requirements for target systems andfurther refined in the process of data analysis. Next,object models are built by identifying procedures relatedto data model entities. Relationships between objects arederived from entity relationships. More objectrelationships may be derived from analysis of objectinteractions. In addition to objects and relationships, wemodel rules ("employee cannot earn more than hisboss"), events (firing an employee), control (what shouldbe done when an employee is fired) and timing ("paybonus at the end of the year").

    We have to stress that building an 00 omain modelto handle reusable features is helpful even if we do notintend to reengineer procedural programs into 00programs. If obtaining 00 rogram architechm happensto be our objective, certainly an 00 domain model willimmensely help in such a transformation. But essentially,the main purpose of the object model is to organizeprogram information for ease of understanding and reuseand to help in navigation through design/code duringprogram reengineering and maintenance.

    docmentation template for objects

    a list of attributes

    We described a reusability framework for

    establishes a mechanism for reuse of designs and codeacross all the systems in a given application domain. Assuch, it must provide usual facilities for classifying,describing, storing and retrieving reusable feat" . The other classes to this onereusability framework contains two components, namely

    management facilities. The domain model identifies,

    reengineering [13i.The framework Reusable fames are documented by templates. Athe

    information:parent classes (in an inheritance hierarchy)

    the domain framework . oreachattributeitmaybespecified:attribute value domain and value constraints102

    Authorized licensed use limited to: Universidade Estadual Do Sudoeste da Bahia. Downloaded on May 14,2010 at 12:44:53 UTC from IEEE Xplore. Restrictions apply.

  • 8/7/2019 Software Re Engineering for Re Usability

    4/7

    0 whether attribute value can be changed or notwhether attribute is a key or notwhether attribute is computedornot

    0 invariants: characterize valid object states

    .nitiakmustbetrueforanobjecttobecreated

    0 final:mustbetmeforanobjecttobedestmyeda list of methods (methods are specified bymethod templates)

    0 alistofrules(rulesarespecitiedbyseparateruletemp-)

    objectconstratn t s ( B o O 1 e a n d m )

    Here is an example of a doclrmenula on templatedescribing areusable feature BOOK m alibrary system:

    domah object class BOOK {wormal description:

    //rationale, design constraints, etc. are described here

    &rivedfronr:LIBRARY-ITEM

    tlt@ibU&?S:

    AuthorTitle#copies // numbex ofcopiesStatus //borrowed or available

    ...metho&:

    RegisterNewBook(BOOK)checkout(BOOK)checkln(BOOK)ISResened@OOK)...

    object constnzhts:

    a library

    rides:

    remirsdertoaborrower

    remove a book Erom a library

    other overdue books he/she ma y haveother descriptions:I

    Methods, global procedures, constraints and b u s hrules are documented in a similar way [11,13].Conceptual program descriptions (such as above object

    BOOK and its descriptors) are linked o design templatesthat show multiple implementations of various conceptsin the original program, n the target program (i.e., one

    Thm should be no more han 10 Oopies of any title in

    I f a bock is ovedue more than one week, send a

    If a book is not borrowed for consecutive 5 years,

    When a user returns a book, inform him/her about any

    obtained after reengineering) and genericimplementation in the library of reusable components.Multiple hheaitance is used to show similarities anddifferences between properties of a generic andsystem-specific mplemMons of a given concept.

    5. Extracting reusable features h mcode

    In this section, for completeness, we outline asemi-automatic technique for extracting reusable codethat we investigate. A reader should refer to 111,121 formore d e d .

    Let's say we reengineer programs computing taxesand we are intmsted in a procedure P that computestaxes for non-residents. First, we identify domain objectsthat may be involved in P. We may suspect that thisprocedure involves objects such as PERSON,TAX-FORM, INCOME-RECORD. (It may be that wealready have NON-RESIDENT s a special type of

    PERSON. If not, we may consider including it into theinheritance network of domain objects.) From theidentified objects we obtain a set of data definitions,D(PJ, which are potentially involved in computation ofP. We use set D(P) to zoom into code segments relatedto procedure P. First, we may want to find out whichprogram modules are related to TAX-FORMS andNON-RESIDENTS:

    Module M,find M

    such that Ref(M,TAX-FORM) &Ref(M,NON-RESIDENT)

    The result of this query is a l l the modules thatreference data related to objects TAX-FORM andNON-RESIDENT. We can further d u c e the number of

    modules by specifying that we are interested only inmodules that write information to a file connected toobject TAX-FORM. Program modules identified in thatway may st i l lcontain lots of code that is irrelevant to thecomputation in question. To find a better approximationof the computation, we use techniques of patternmatching and program slicing. First, we try to findprogram points that play important role in thecomputation. Continuing our example with taxes,important points may involve the statements that assignthe amount of tax to be paid by a non-resident to acertain field in a tax form record. We can express this interms of a domain model pa":Statement sl, s2;find s l

    such that AssignTo(s1, TAX-FORM.TotalTax)& exists s2 such that Write(s2,

    TAX-FORM.TO~~T~X) Affets(~1, Z)

    103

    Authorized licensed use limited to: Universidade Estadual Do Sudoeste da Bahia. Downloaded on May 14,2010 at 12:44:53 UTC from IEEE Xplore. Restrictions apply.

  • 8/7/2019 Software Re Engineering for Re Usability

    5/7

    The above pattem specifies that we want to fmd allstatements sl that assign value to data related toTAX-FORM.TotalTax, such that the value computed insl is subsequently written (i.e., printed to a file or

    Having identified program points of interest, we can

    try to fmd other statements in a program which deal withcomputing tax. The next step is then to extract from aprogram only these statements that really affect the valueof attribute TAX-FORh4.TotalTax for non-residents.This is done by computing program slices [23] in respectto statements that match our pattem. The amount of codeextracted from a program can be further reduced byspecifying that we are really interested in slices thatinvolve non-residents (i.e., which involve data structureslinked to NON-RESIDENT objects).

    Pattem matching and program slicing techniques helpto identify procedures. Isolated code can beautomatically restructured to clean the program controlflow and to enhance readability by providing a uniformprogramming style. Now the task of a programmer is toanalyze and re-specify code. If the objective ofreengineering is to produce logical-level specificationsfrom which code can be generated into multipleplatforms, a programmer must isolate code related tophysical implementation and other platformdependencies. In particular, physical database accesssequences should be replaced by logical operationsexpressed in terms of a conceptual data model.Conversion tools and reverse engineering tools can helpa programmer in this task.

    displayed).

    6. Related work

    In this section we evaluate the proposed approach inthe view of both commercial tools and tools developed inresearch labs. We also evaluate certain techniques thatare required in order to identify and extract reusable codefrom existing programs.

    6.1. Commercial tools for reengineering

    Many of todays CASE tools provide reverseengineering front-ends that can read code, xtract designabstractions from code and store them in a CASErepository. Using CASE editors, design abstractions canbe displayed and further refmed. Advanced reverseengineering tools can help to analyze and re-builddatabase definitions, procedural code and user interfaces.Tools for data reverse engineering use expert rules andelicit additional information from analysts to transformphysical data defintions into a logical data model.

    During reengineering for reusability, programmerstask often is to isolate code that implements a givenconcept, to raise code to the logical level by removingimplementationdepdent details and, eventually, toconvert code into a reusable module. As it often happensin old programs, code that implements related concepts is

    not found in one program module, but is delocalized (i.e.,spans a range of program modules). The process offmding and isolating that code can be greatly simplifiedwith use of static program analysis tools. Those tools cancompress huge amount of code nto a compact abstractview that is directly related to a certain aspect aprogrammer wants to study. Irrelevant details are filteredout of this view. Many useful program views areproduced based on control and data flow relations.particularly, program slicing views can automate theprocess of searching code that implements specificconcepts. There are tools that compute program slices,extract them from programs and convert extracted codeinto a module, including necessary data declarations.Program slicing is an example of a technique that wasfirst developed and experimented with in academicenvironments [6,23] and then successfully transferredinto production use.

    Domain analysis [ l] is, perhaps, the onlyreengineering activity that today is hardly supported bycommercial tools. None of the CASE tools known to theauthor provides for domain analysis. This is a rathersurprising observation, if we recall that one of bigpromises of CASE is to promote and support reusability.Many of the useful reusable components aredomain-specific. (This is, perhaps, why domain-specificprogram generators have been so successful, whilegeneral-purpose automatic programming systems still arenot around.) During domain analysis, we identifypotentially reusable components and then, during domainmodeling, we build organizational structures to capturesoftware components for future reuse. Adding a domainanalysis level would help CASE tools to address moredirectly problems of reusability.

    6.2. Relevant research projects

    The program slicing technique, though very useful,provides only i n k t means for recovering conceptsbehind programs. To address the problem more directly,we must explicitly model programming and applicationdomain concepts and link them to relevant designabstractions and code. A number of research projectsinclude a domain model as an essential component of an

    environment for program understanding. The objective ofLaSSIE 5] system is to explain the design of a complexapplication and to identify code which has a potential for

    104

    Authorized licensed use limited to: Universidade Estadual Do Sudoeste da Bahia. Downloaded on May 14,2010 at 12:44:53 UTC from IEEE Xplore. Restrictions apply.

  • 8/7/2019 Software Re Engineering for Re Usability

    6/7

    reuse. LaSSE uses a he - b a s e d expert system to storedomain models, design abstractions and code views. InLaSSIE, domain models are built manually while thedesign abstractions are computed by parsers. Interestingresearch has been recently done on automated programrecognition [8,9,16]. These system attempt to definelibraries of program plans that connect abstract conceptsand their implementations. In the process of automatedprogram recognition, a program is searched or instancesof plans. As plans can be organized in a hierarchicalway, the recognition process can progress from lower tohigher abstract levels of program description. Many ofthe techniques for recovering reusable features that wedescribe in this paper are semi-automatic. If the resultsof research on automated program recognition scale upto real world programs, it may be possible that futuretools will be able to control a bigger portion of thereengineering process.

    Research on recovering object-oriented views f "programs is also relevant to the reengineering for

    reusability. A method for identifying objects in Cprograms is described in [14]. Candidate objects areselected based on the analysis of type definitions; next,procedms which have arguments of a given type, orreturn a value of a given type, re identified as candidatemethods. In [lo] , procedural programs are incrementallyreengineered into an object-oriented architecture.

    7. Conclusions

    Many researchers and practitioners express opinionthat software reuse has a potential to bring productivitybreakthroughs and can fundamentally change the way wedevelop programs [2,15]. An important source ofpotentially reusable software assets are existingprograms. Some of those programs, though they stillcontain much business value, will have to bereenginwed, as they have become technically obsolete.To reengineer programs, we must understand them.Therefore, reengineering is an opportune moment tocapture viable assets from existing programs and makethem available for future reuse. Reengineering andreusability have a potential to reinforce each other, butwe need technical means to realize this potential. Theintention behind the work described in this paper was toexplore a mechanism for integrating reengineeringefforts with work on software reuse. In particular, weidentified lifecycle phases and described a reusabilityframework that addresses specific needs of reengineering.

    The benefit of the "reengineering for reusability"scenario is threefold first, better quality systems can beobtained through reengineering (by eiimitingredundant designs and code): second, designs and code

    can be unified across systems within a given applicationdomain (by sharing common functionalities), easingfuture maintenance effort: third, the framework reducesthe effort of both reengineering and new development ofother systems in a given application domain.

    Further work should concentrate on evaluating thismethod in the context of real reengineering projects andon providing higher level of automation forreengineering pmesses. Technical solutions are neededto bridge domain models and design abstractions used byCASE tools and to automate the p e s s of conceptrecognition in programs. Representation structures forreusable features described in section 4 may be improvedby introducing elements of formal specifications. Cost-effectiveness of a reengineering scenario described in thispaper depends on advancements in many research areassuch as domain modeling, reusability and automatic codegeneration from software specifications.

    Acknowledgments

    This work was supported by National University ofSingapore Research Grant Rp920613. Thanks are due toDr. Tan Chew Lim and Kelly Tham for comments andmany interesting discussions.

    References

    Arango, G. "Domain Analysis - From Art Form toEngineering Discipline," Proc. Fifth InternationalWorkshop on Sofhvare SpecifKation and Design, May

    Biggenrstaff, T. and Perlis, A. (Editors) SofhvareReusability,vol. I and 11, ACM Press, 1989

    Chen, P. "The Entity-Relationship Model -- Toward aUnified View of Data," ACM Tramactions on DatabaseSystem,vol. 1, no. 1, 1976, pp. 9-36Chikofsky, E. and Cross II, J. "Reverse Engineering andDesign Recovery: A Taxonomy," IEEE Software, January

    Devanbu, P. Brachman, R.J., Selfridge, P.G. and Ballard,B.W. "LaSSE A Knowledge-Based Software InformationSystem," CACM,vol. 34, No. 5 , May 1991, pp. 34 49Gallagher, K. "Using Program Slicing in SoftwareMaintenance," TR CS-90-05, Ph.D. Thesis, University ofMaryland, 1990Hart, C. and Shiling, J. "An Environment forDocumenting Software Features," Proc. 4 t h ACMSIGSOFT Symp.on Sofhvare Development Environments,Irvine, USA, Dec. 1990, pp. 120-132

    Hartman, J. "Technical Introduction to the First Workshopon Artificial Intelligence and Automated programUnderstanding," Workshop Notes AAAI-92 AI &

    1989, Pittsburgh, pp. 152-159

    1990, pp. 13-18

    Authorized licensed use limited to: Universidade Estadual Do Sudoeste da Bahia. Downloaded on May 14,2010 at 12:44:53 UTC from IEEE Xplore. Restrictions apply.

  • 8/7/2019 Software Re Engineering for Re Usability

    7/7

    Automated Program Understanding,July 1992, San Jose,

    [9] Hartman, I. "Understanding Natural Programs UsingProper Decomposition," 13th International Conference onSofh are Engineering, May 1991

    [lo] Jackobson, I. and Lindstrom, F. "Reengineering of oldsystems to an objectaiented architecture," Proc.OOPSL.4'91,pp. 340-350

    [111 Jarzabek, S. "Domain Model-Driven SoftwareReengineering and IMaintenance," Journal of Systems andSofcware,Jan. 1993, pp. 37-51

    [12] Jarzabek, S. "Strategic Reengineering of Software:Lifecycle Approach," accepted for the 6th Int. Workshopon CASE, CASE93, Singapore, July 1993

    [13] Jarzabek. S. "A Reusability Framework forReengineering," accepted for Joint Conference onSoftware Engineering, JCSE93, Nov. 1993, Fukuoka,Japan

    [14] Liu, S. and Wilde. N. "Identifying Objects in aConventional Procedural Language: An Example of DataDesign Recovery," Proc. Conference on SofhvareM a i n t e m e , 1990, pp. 266-271

    [15] McClure, C. The Three Rs of Sofha re Automation: Re-

    engineering, Repos itory, Reusability,Prentice Hall, 1992

    pp. 8-31[16] Rich, C. and Wills, L. "Recognizing Porgram's Design: A

    Graph-Parsing Approach," IEEE Sofcware, January 1990,

    [17] Rochfeld, A. and Tardieu, H. "MEIUSE: An InformationSystem Design and Development Methodology,"Information and Management, vol. 6, no. 1, 1983, NortHolland

    and Hales, K. "Reverse Engineering:Markets, Methods and Tools," Ovwn Report vol. 1,published by Ovum Ltd. England, 1990

    1191 Rumbaugh, J., Blaha, M.. Premerlani, W., Eddy, F. andLorensen, W. Object-Oriented Modeling and Design,Prentice-Hall, 1991

    [20] Sneed, H. "Bank Application Reengineering Conversionat the Union bank of Switzerland," Proc . Conference onSofhvare Maintenanc e,1991.60-71

    [21] Sneed, H. "Economics of Software Reengineering,"Sofhare Maintenance: Research and Practice, vol. 3, no.3, September 1991, pp. 163-182

    [22] Ulrich, W. "Redevelopment Engineering: Formulating anInformation Blueprint for the lWOs," CASE Outlook,No.

    [23] Weiser M. " h g r a m slicing." IEEE TSE, vol. 10. no. 4,

    pp. 82-89

    [18] Rock-Evans, R.

    2,1990, pp. 15-21

    July 1984, pp. 352-357

    106