Code Reuse

When new projects are started in an organization, it makes sense to identify parts specific to the application and other parts that can be reused from earlier projects. Code reuse is a practice that reduces development time and effort since we're reusing existing code rather than writing from scratch.

Code reuse is not limited to within an organization. Languages often ship with built-in functions and standard libraries. Third-party libraries add functionalities to these. When developers write applications, they make use of these libraries.

There are two approaches to code reuse: design and implement code with the expectation of future reuse; identify and refactor when we see opportunities for immediate reuse. The industry is divided over which of these two approaches is the better one. Some experienced developers have shared useful tips about how best to adopt each approach.

Discussion

• Could you explain code reuse with an example?

Suppose we're building an accounting application. Obviously it has a lot of business logic related to the domain of accounting. But it also does user authentication, interfaces to a database and logs errors: these are features that are not specific to accounting. In fact, other applications (such as shopping cart or content management) may have similar requirements.

It therefore makes sense to build these components once and reuse them across applications. Thus, we could have a shared library that connects to a database. This library is then reused across applications that need such a connection. Likewise, separate libraries can be created for authentication or logging, and reused across applications.

By reusing code this way developers can focus on the core business logic of their apps instead of "reinventing the wheel". If reusable code is well tested, it improves overall product quality.

• What are some types of software reuse?

Reuse can be vertical (within an application domain) or horizontal (across application domains). Reuse is not just about code. We can reuse other software artefacts including requirements, architecture, design models, test reports, etc.

An application can be decomposed into components, each fulfilling a specific purpose. A component hides its complexity behind an interface. Reuse happens via such an interface. Such components could be views, models, controllers, data access objects, or plugins.

When a component is deployed independently, it's called a service. Other applications or services can call it. Thus, reuse happens at the service level.

When components are shared across multiple applications and systems, they can be packaged and distributed as APIs or libraries. Platforms and frameworks extend this philosophy by bringing together many useful APIs or libraries.

Another form of reuse is at the level of source code. Code is forked or copied and then adapted to new requirements. A coarser form of this is cut-and-paste programming. This is also code reuse but it's not favoured because duplicating code this way makes it less maintainable.

• Isn't code reuse a myth?

During the late 1980s, ad hoc or unplanned reuse was not favoured. It was thought that "reuse should be considered at design time, not after the implementation has been completed". Software architects cared about interface design, low coupling and high cohesion.

By the late 1990s, it was realized the code reuse is hard and needs practice. It's more of an art than a science. It combines both technical and non-technical challenges. Reusing software across business units in a large organization needs coordination. It's also not clear which cost centre will fund it. Developers also don't like management forcing them to use components and frameworks developed by another team.

Striving for a high degree of reuse can lead to complex dependencies and high coupling, not to mention the higher development cost. Changes to shared libraries take longer. Complex abstractions reduce code readability. Developers therefore start implementing their own code rather than reuse code they don't understand. Sometimes, "reusable code" is too application or domain specific to be reused. It's been said that,

There is no such thing as reusable code, only code that is reused.
• Could you share some tips towards writing reusable code?

Apply the Don't Repeat Yourself (DRY) principle. If you find yourself repeating the same code, it's time to extract that code into a separate function or class method.

Think about unit testing your code. Code that's easier to unit test implies less coupling, higher modularity and better reuse.

Encapsulation reduces external dependencies and makes code more self-contained. When writing code, imagine you're creating tools for others to reuse.

Chances of reuse are better if a class or method does only one thing. You'll end up with more classes or methods but there's less coupling in your codebase. Better still, use interfaces and abstract classes. These can be easily extended in future. Don't include business logic as they lead to higher coupling and less reuse.

If you're struggling to name your class or method, it's an indication that the abstraction is probably wrong. If the abstraction requires many inputs, it's likely to introduce high coupling.

In conclusion, if you write modular, loosely coupled, maintainable and unit testable code, that code is also likely to be reusable.

• What should I avoid when attempting to write or use reusable code?

Don't develop applications from a framework perspective. Application development should not start focusing on building a framework of reusable components. Framework development should be a separate activity. Otherwise, too much of what goes into the framework will become application specific and never reused. Don't try to reuse code from another application or context. It may require far more effort than coding it afresh.

Don't let reuse become your primary goal at the expense solving real problems. You'll end up with unnecessary interfaces, confusing abstractions and heavily partitioned codebases. Such code will not get reused.

Don't try to solve generic problems and create your own reusable libraries. Most likely, there are already frameworks and libraries that solve them for you.

Don't force developers to use reusable frameworks. Frameworks should speak for themselves in terms of clean interfaces, readability, usability, reliability, performance and security. They should act as "reuse magnets" for developers.

Don't reuse something old and outdated. Take benefit from newer languages, technologies and frameworks. For example, where possible, code in Swift instead of trying to reusing old Objective-C code.

• Is code reuse a good thing from a security standpoint?

Within enterprises, code reuse promotes higher security if code is well tested. If not, it becomes a single point of failure, making many applications vulnerable.

When reusing code from external sources, document the software supply chain. Reuse frameworks and libraries only from trusted sources. Install updates and patches at the earliest. This is critical if a vulnerability in an open source codebase becomes public.

Use Software Composition Analysis (SCA) tools. These can identify vulnerabilities in third-party source code and libraries. Examples include Black Duck, Sonatype and OWASP Dependency-Check. Use them together with other security testing tools.

A checklist can also be useful when selecting software for reuse. Such a checklist would assess feature capabilities, limitations and interfaces. Apart from security considerations, such an assessment would consider initializations, memory usage, throughput, accuracy, synchronization, re-entrancy, etc.

• What support do languages offer towards code reuse?

Generics in Ada and classes in object-oriented languages promote code reuse. However, these features alone don't guarantee code reuse. Proper domain analysis, modularity, abstractions and parameterization are important to get reuse right.

In C++, functions, macros, encapsulation, composition, parameterized types, overloading and polymorphism are seen as useful techniques for code reuse.

In OOP, complex class hierarchies and huge classes with lots of methods and arguments can make reuse difficult to achieve. In functional programming, the approach is to reuse tiny bits of code. Lambda functions enable this. We can implement complex behaviour by composing code from many tiny parts.

In JavaScript, use immutables and functional programming for higher reuse. For example, prefer map/reduce/filter over forEach/push/splice. Pure functions and Higher-Order Functions (HUFs) are useful constructs. They enable reuse across JavaScript frameworks.

Milestones

1949

While working on the stored-program computer EDSAC, researchers at the University of Cambridge propose the creation and use of a subroutine library. This is probably one of the earliest instances of code reuse.

Oct
1968

At the NATO Software Engineering Conference, McIlroy proposes a components factory dedicated to producing parameterized families of components arranged by precision, robustness, generality and time-space performance. Rather than reuse entire compilers, it's easier to start with numerical approximation routines, I/O conversions, 2D-3D geometries, storage management and text processing. As time will tell, only the Japanese pay attention to his suggestions.

1990

Hewlett-Packard creates a corporate software reuse program. This brings together many divisional programs that have been active since the early 1980s. About the same time (early 1990s), many other companies have similar reuse programs: AT&T, IBM, GTE, NEC, Toshiba, etc. HP engineers learn that a large software library doesn't necessarily lead to higher reuse. The library may have many useful low-level, generic parts but created without consideration of quality, documentation, testing or interoperability. They also note that effective software reuse will require changes to processes. The returns will also come only in the long term.

Feb
1992

Krueger notes that though software reuse has been discussed since the late 1960s, it's not yet a standard industry practice. He also looks at reuse from four perspectives: (a) abstraction: essential for reuse; (b) selection: identify and select what to reuse, classify and organize reusable code; (c) specialization: reuse a generalized artefact but specialize it during reuse via parameters, transformations or constraints; (d) integration: ways to export and import reusable code.

1995

Gamma et al. publish the book titled Design Patterns: Elements Of Reusable Object-Oriented Software. This marks a shift from reusing just code to reusing design. These patterns describe proven solutions to common problems.

2004

Reuse in Software Engineering (RiSE) project is initiated to provide a framework for effective code reuse. RiSE includes a number of best practices, describes the reuse process and addresses both technical and non-technical aspects.

2008

Haefliger et al. investigate code reuse in six open source software projects. They find that developers reuse code to reduce costs, integrate functionality quickly, and overcome resource constraints. Developers select components based on their popularity.

Sample Code

• // Source: https://medium.com/@erfangc/the-reusability-myth-59a370f60da
// Accessed 2021-10-05

// Example Kotlin code illustrating bad code reuse that
// introduces a complex abstraction and reduces readability

// ---- Orginial code ----
fun areaOfTriangle(h: Double, b: Double): Double {
return (h * b) / 2.0
}

fun areaOfSquare(s: Double): Double {
return s * s
}

fun areaOfRectangle(l: Double, w: Double): Double {
return l * w
}

fun areaOfTrapezoid(a: Double, b: Double, h: Double): Double {
return (a + b) / 2 .0 * h
}

// ---- Code refactored for reuse ----
fun areaOfTriangle(h: Double, b: Double): Double {
return area(a = 0, b = b, h = h)
}

fun areaOfSquare(s: Double): Double {
return area(a = s, b = s, h = s)
}

fun areaOfRectangle(l: Double, w: Double): Double {
return area(a = w, b = w, h = l)
}

fun areaOfTrapezoid(a: Double, b: Double, h: Double): Double {
return area(a = a, b = b, h = h)
}

fun area(a: Double, b: Double, h: Double): Double {
return (a + b) / 2 .0 * h
}

Author
No. of Edits
No. of Chats
DevCoins
2
0
1177
1
1
15
1757
Words
2
Likes
5262
Hits

Cite As

Devopedia. 2022. "Code Reuse." Version 3, February 15. Accessed 2022-09-22. https://devopedia.org/code-reuse
Contributed by
2 authors

Last updated on
2022-02-15 11:56:58
• Site Map