CSC/ECE 517 Fall 2012/ch1 1w7 am

From Expertiza_Wiki
Revision as of 22:07, 9 September 2012 by Arvaidya (talk | contribs) (→‎Techniques)
Jump to navigation Jump to search

Definition

Code reuse is the way in which an existing code can be used to perform a specific service regardless of the application in which it is used. Software Reuse involves the use of some previously constructed software artifact source code, library, component requirements and design documents e.g. design patterns in a new context or development project

Overview

Code reuse is the idea that a partial computer program written at one time can be, should be, or is being used in another program written at a later time. The reuse of programming code is a common technique which attempts to save time and energy by reducing redundant work. The software library is a good example of code reuse. Programmers may decide to create internal abstractions so that certain parts of their program can be reused, or may create custom libraries for their own use. The general practice of using a prior version of an extant program as a starting point for the next version, is also a form of code reuse. Some so-called code "reuse" involves simply copying some or all of the code from an existing program into a new one. While organizations can realize time to market benefits for a new product with this approach, they can subsequently be saddled with many of the same code duplication problems caused by cut and paste programming. Many researchers have worked to make reuse faster, easier, more systematic, and an integral part of the normal process of programming. These are some of the main goals behind the invention of object-oriented programming, which became one of the most common forms of formalized reuse. A somewhat later invention is generic programming. Another, newer means is to use software "generators", programs which can create new programs of a certain type, based on a set of parameters that users choose. Fields of study about such systems are generative programming and metaprogramming.

History

Ad hoc code reuse has been practiced from the earliest days of programming. Programmers have always reused sections of code, templates, functions, and procedures. Software reuse as a recognized area of study in software engineering, however, dates only from 1968 when Douglas McIlroy of Bell Laboratories proposed basing the software industry on reusable components.

There are many dimensions along which we can trace the history of reuse: Software Development Life Cycle (SDLC) Model Prototyping, Iterative, ESP, etc. Requirements/Specification Method Business Model Implementation technology dimension - concentrating on source code and later life cycle objects

e.g. Mid 1980’s Mature Third Generation Programming Languages Late 1980’s Early Object Oriented Languages and SQL DB Early 1990’s Mature OO Languages, Source Code Libraries Mid 1990’s Early DIAE Component Packaging Late 1990’s Mature DIAE Components, Cross-Protocol Bridges 2000-2005 Early Service Oriented Architecture Products

Types of Code reuse

Reuse over fungible systems

portability commonality ex: numeric types of fixed range and/or precision

Reuse over different domains

inheritance and binding generality and instantiation ex: object oriented programming, generics, templates, unconstrained types

Reuse over time

maintenance evolution versions ex:product lines to be updated over time (such as the 360 family), updating programs for the year 2000

Examples

Best practices

It is not difficult to write reusable code. It is really a matter of how you approach the problem. If you understand how to create and use class modules, then you already know a great deal about how to approach writing reusable code.

The first consideration when you are writing reusable code is writing code that uses a consistent naming convention, that is formatted properly, and that contains useful comments.

Examine your existing code to make sure that your procedures have a single, specific purpose. Can you describe your procedures in a short, plain sentence? For example, "This procedure accepts an SQL string as an argument and returns a Recordset object containing the records described by the string." If you are unable to describe a procedure simply and clearly, it probably does too many things. Break down complicated procedures into smaller ones that do one thing each. Procedures should contain only code that clearly belongs together. Avoid making specific reference to named application objects. For example, the following code makes a specific reference to a combo box control and a text box control on a Microsoft® Access form:

strEmployeeName = Forms!frmEmployees!cboEmployeeName
strSQL = "SELECT * FROM Employees WHERE LastName = '" & Mid(strEmployeeName, InStr(strEmployeeName, " ") + 1) & "'"
Set rstAddresses = dbs.OpenRecordset(strSQL)
Forms!frmEmployees!txtHireDate = rstAddresses!HireDate
Function GetDataFromField(strTableName As String, strFieldName As String, strCriteria As String) As Variant
   ' Returns a value from the field specified by strFieldName
   ' in the table specified by strTableName according to the
   ' criteria specified by strCriteria.
   Dim rstFieldData    As New ADODB.Recordset
   Dim strSQL          As String
   On Error Resume Next
   strSQL = "SELECT " & strFieldName & " FROM " & strTableName & " WHERE " & strCriteria
   rstFieldData.Open strSQL, DATA_CONNECTSTRING & DATA_PATH
   If Err = 0 Then
      GetDataFromField = rstFieldData(strFieldName)
   Else
      GetDataFromField = ""
   End If
End Function

Try to minimize the number of arguments in a procedure and pass in only what is actually required by the procedure. In addition, make sure your procedures use all the arguments passed to them.

Group related procedures and the constants they use together in the same module, and where appropriate, consider grouping related procedures together in a class module with a clearly defined interface.

Keep procedures in standard modules and not in modules behind forms or documents. The code in form modules should be only that code that is tied directly to the form itself and the code required for calling general procedures stored in standard modules.

Communicate between procedures by passing data as arguments to the procedures. Persist data by writing it to disk or to the Windows registry. Avoid using a procedure to write to a global variable so another procedure can read data from that global variable. Avoid communicating with another procedure by passing data out of the application, for example, using one procedure to write data to a disk file, .ini file, or the registry so another procedure can read that data.


Techniques

DRY

=== procedures, macros

=== High level languages Functions, subroutines, libraries

=== Object Oriented Languages Mixin, Object orientation, inheritance

=== generators, Reusable code is code that can be used, without modification, to perform a spectific service regardless of what application uses the code.

There are everyday objects that perform a specific service in different circumstances all around you. Think of a calendar. It gives you the ability to look up days and dates. You can use it to determine that this year your birthday falls on a Tuesday, or that Thanksgiving is on the 25th, or that there are two extra days to file tax returns because April 15 is on a Saturday. When you are building software, objects are created in code, and reusable objects that perform specific services in different circumstances are called components. Some characteristics that make software more easily reusable are modularity, loose coupling, high cohesion, information hiding and separation of concerns. For newly written code to use a piece of existing code, some kind of interface, or means of communication, must be defined. These commonly include a "call" or use of a subroutine, object, class, or prototype. In organizations, such practices are formalized and standardized by domain engineering aka software product line engineering.

Nowadays, no one would seriously argue that software reuse has failed to become a standard software engineering practice. Let have a quick look at each of the technique mentioned in the paper, in the light of the tools we have today. Note that I've tried to be consistent with the paper, in terms of the software abstractions behind each reuse technique. Some of the terms used in the paper may have a slightly different meaning today. Also note that the different techniques may overlap, as already pointed implicitly by Krueger himself. I must add that the presentation order I've chosen is related to my own understanding of the concepts ;-) Therefore, all subtitles and some other links below can be used easily to launch a google search! High Level Languages

Java, Clojure, Ruby, Haskell, and so on. High level languages are numerous and various. Each one comes with its set of tools to raise the abstraction level (sometimes in certain respects only, like providing good abstractions for concurrency, or low-level tasks). Source code components

High level languages also come with effective abstractions to build and share "abstract data types" and other "reusable libraries". Source code components are generally intended to be used as black-boxes: a public interface of usage is announced, formally or not (ruby has not equivalent of java interfaces, for example), while the realization of this interface is kept hidden (or at least intended to be). Think to C libraries, java's .jars, python's modules, ruby's gems, and so on. In many languages, "find a component, download it, and go" has become a reality! Software architectures

Software architectures are large-grain software frameworks. In contrast with source code components which are often black-boxes, software architecture are designed as grey-boxes: they are intended to be extended and provide specific extension points for this. We have a lot of reusable frameworks nowadays. Probably the most common are web frameworks (Ruby on Rails, django, ASP.net, ...), integrated development environment (IDE, Eclipse is worth mentioning due to its architecture), service oriented architectures (SOA), and so on. Design and code scavenging

Design and code scavenging is simply a form of "find, copy-paste, adapt". The well-known design patterns[3] provide an organized form of design scavenging, by providing catalogues for applying such kind of reuse. Even if invented in the context of the object-oriented programming, design patterns had a great impact far beyond that programming paradigm.

Code scavenging is less organized as few such catalogues exists. Every day however, the web gives use better ways to apply such a reuse technique: google code search, github's gist, pastie, and so on. I also remember having read an book about Eclipse[4] whose authors encouraged applying the monkey see, monkey do rule, that is, copy pasting code from other Eclipse plugins whose source code is available. Application generators

The paper compares application generators with software compilers. According to it, generators differ from compilers in that the input specifications are typically very high level, special-purpose abstractions from a very narrow application domain. I would add that compilers traditionnaly transform source code from a high-level language to something which is intended to be executable by a (virtual) machine, while application generators transform (very) high level descriptions into code that generally need to be compiled in turn.

In that sense, parser generators (lex & yacc, antlr, rats!, treetop, pyPEG, and so on.) are probably the best-known examples of application generators. Other examples include wizards that one can find in Integrated Development Environments (to design and generate code of user interfaces, for example), tools that generate classes from UML class diagrams, generators of database schemas, report generators, etc. In note in passing that the Noe library I was talking about recently is of course a kind of application generator. Transformational systems

Transformational systems are the holy grail of computer science, nothing less! In that paradigm, software developers actually describe the behavior of the software using a high-level specification language (related to VHLL described before). In a second phase, the specifications are transformed in order to produce an executable system. The transformations are meant to enhance efficiency without changing the semantics.

Transformational systems emphasizes the what instead of the how. They actually bet on the concision of declarative statements over procedural ones to achieve effective reuse. While general purpose transformation systems remain mostly research topics, notable results have been achieved in some specific domains: relational systems come with effective query optimizers, some rapid prototyping approaches uses transformations from high-level descriptions down to code, etc. Very High Level Languages (VHLL)

Very High Level Languages, also known as executable specification languages, are languages with very high level of abstraction. They are somewhat difficult to capture precisely and may lead to software reuse that is very specific to specialized domains. However, I would say that the recent advent of Domain Specific Languages (DSLs) and good support for them in dynamic languages (ruby, python, clojure, ...) can be seen as promoting and helping building VHLLs. Software schemas

I must confess not being familiar with software schemas. The paper states that software schemas are a formal extension to reusable software components . From what I understand, it seems that we are talking about some kind of formal pseudo code, intended to be instantiated in a particular language. Unfortunately, a google search does not return relevant results, at the time of writing. I would like to know if they had an impact on current software engineering practices. So if someone knows something about software schemas, just let me know (see the comment form at bottom of this page), and I'll be happy to update this section!

Advantages

  • Efficiency
  • Reduces time spent designing or coding
  • Standardization
  • Reuse of UI widgets in MacOS and Win32 leads to common “look-and-feel” between applications
  • Debugging
  • Reused design/code is often tested design/code
  • Profit!
  • Reuse can lead to a market for component software

real-world examples: ActiveX components, Hypercard stacks, Java packages, even software tools, such as xerces and xalan from xml.apache.org (they are often included in other software systems)

Software reuse increases the software productivity and decreases the time required for the development of a software. By using the technique of software reuse, a company can improve software system interoperability and needs less people for software development. This provides a competitive advantage for the company and helps to produce better quality software and standardized software. Software reuse technique helps the company to reduce the costs involved in software development and maintenance. By using it the software developers can be moved from one project to the other project easily. Systems that incorporate a high level of reusable components are more reliable and more easily constructed. Software reuse also reduces the risk involved in software development process.

Practical problems

Although software reuse provides many benefits for the developers, there are some disadvantages, like it increases the maintenance cost and occasionally there may be lack of tool support.


Mismatch 􀀁 Reused Reqs. and/or Design may not completely match your situation 􀀁 Requires time/effort to convert 􀀁 Non-functional characteristics of code may not match your situation 􀀁 Consider a database that can scale to 10,000s of items, but you need it to scale to 100,000s of items 􀀁 Expense 􀀁 Some components may be too expensive for your project’s budget. For instance, SGML (a precursor to HTML and XML) tools sell for 5000 dollars a license!

Building reusable objects requires extensive analysis and design. "You really need to understand what the generalities are," says Kerth. Then, you will need to invest extra time in testing and quality assurance, optimization, and documentation. All this takes time and labor, which increases the cost of the code. IT departments must also add to the payback equation the cost of tools to support reuse, such as version control and repositories. Finally, the cost of administering an ongoing reuse program must be considered. With all these elements, it becomes apparent that reuse doesn't come cheap. Reusable Components

Different types of application code require varying levels of investment to achieve successful reuse

Reusable GUI objects reduce development time and improve quality and consistency but provide only modest payback in terms of overall application development costs. Server-side components that constitute reusable business logic can provide significant payback but require extensive up-front analysis and design. They also require an architectural foundation but may experience a short shelf life. Infrastructure components and services frameworks are generic services for transactions, messaging, security, and database connectivity. They eliminate the need to repeatedly build infrastructure that all applications use, but require extensive analysis and design, and complex programming. These standards-based components can often be purchased off-the-shelf. High-level patterns allow organizations to achieve design reuse and identify components with high reuse potential, but developers must build or acquire the components. Packaged applications provide the only guaranteed form of reuse, letting user companies acquire functionality for significantly less than the cost of building it themselves. However, these applications may not offer the exact functionality an organization needs; the subsequent customization that's required will add to the cost.