Transformation Priority Premise

Last updated

Transformation Priority Premise (TPP) is a programming approach developed by Robert C. Martin (Uncle Bob) as a refinement to make the process of test-driven development (TDD) easier and more effective for a computer programmer.

Contents

Transformation Priority Premise states that simpler transformations should be preferred:

[...]Refactorings have counterparts called Transformations. Refactorings are simple operations that change the structure of code without changing its behavior. Transformations are simple operations that change the behavior of code. Transformations can be used as the sole means for passing the currently failing test in the red/green/refactor cycle. Transformations have a priority, or a preferred ordering, which if maintained, by the ordering of the tests, will prevent impasses, or long outages in the red/green/refactor cycle.

"Uncle Bob" Martin, "The Transformation Priority Premise", [1] Uncle Bob's Blog

This approach facilitates the programmer doing the simplest possible thing for the purposes of test-driven development as they can explicitly refer to the list of transformations and favor the simpler transformations (from the top of the list) over those further down in the list in the first instance.

The Transformation Priority Premise is a name given to the mental structure TDD’ers build up over time as to balance your code from being too specific, rather than generic. The idea is that with each example you add to the tests you move up the Transformation Priority list, making your code more generic, so able to handle more of the cases. In contrast, your tests, with more examples, become ever more specific and focused on the problem. So you start with a constant for your first test, for your next test you might change that constant to an “if” for the next step you might introduce a loop. Each time you’re moving up the priority premise. The aim of following this structure is to avoid Accidental Complication, and to add only to Essential Complication. Each step is the smallest possible change you can make to implement only the code required to implement the examples given in the test..

Billie Thompson, Transform Priority Premise - Software Engineering Topic of the Day #21 [2]

The Transformations [3]

  1. ({} → nil) no code at all → code that employs nil
  2. (nil → constant)
  3. (constant → constant+) a simple constant to a more complex constant
  4. (constant → scalar) replacing a constant with a variable or an argument
  5. (statement → statements) adding more unconditional statements.
  6. (unconditional → if) splitting the execution path
  7. (scalar → array)
  8. (array → container)
  9. (statement → tail-recursion)
  10. (if → while)
  11. (statement → non-tail-recursion)
  12. (expression → function) replacing an expression with a function or algorithm
  13. (variable → assignment) replacing the value of a variable.
  14. (case) adding a case (or else) to an existing switch or if

Uncle Bob also explicitly stated: "There are likely others", [1] and

[I] think that the priority list is language specific... In Java, for example, we might move (if→while) and (variable→assignment)above(statement→tail-recursion) so that iteration is always preferred above recursion, and assignment is preferred above parameter passing ... because Java is not a functional language.

Robert Martin, blog post "Fib. The T-P Premise" [3]

How to use the Transformations in Practice

Ridlehoover clarifies that the Transformations help you pick which tests to write and in what order.

[The Transformations] can actually help us pick which tests we should write in what order. For example, if we decide to write a test that requires us to add an if statement to our code, that test requires the “unconditional –> if” transformation. Knowing that, we can try to think of other tests that rely solely on transformations higher up the list. The ultimate reward is that by writing our tests using transformation priority order, we should not ever get to a point where one test causes us to rewrite an entire method.

Alan Ridlehoover, The Transformation Priority Premise [4]

Corey Haines provides a live coding demo (Roman Numerals Kata) where he solves a coding challenge utilising the Transformations.

Related Research Articles

<span class="mw-page-title-main">Recursion</span> Process of repeating items in a self-similar way

Recursion occurs when the definition of a concept or process depends on a simpler or previous version of itself. Recursion is used in a variety of disciplines ranging from linguistics to logic. The most common application of recursion is in mathematics and computer science, where a function being defined is applied within its own definition. While this apparently defines an infinite number of instances, it is often done in such a way that no infinite loop or infinite chain of references can occur.

In computer programming and software design, code refactoring is the process of restructuring existing computer code—changing the factoring—without changing its external behavior. Refactoring is intended to improve the design, structure, and/or implementation of the software, while preserving its functionality. Potential advantages of refactoring may include improved code readability and reduced complexity; these can improve the source code's maintainability and create a simpler, cleaner, or more expressive internal architecture or object model to improve extensibility. Another potential goal for refactoring is improved performance; software engineers face an ongoing challenge to write programs that perform faster or use less memory.

In computing, an optimizing compiler is a compiler that tries to minimize or maximize some attributes of an executable computer program. Common requirements are to minimize a program's execution time, memory footprint, storage size, and power consumption.

In computer science, control flow is the order in which individual statements, instructions or function calls of an imperative program are executed or evaluated. The emphasis on explicit control flow distinguishes an imperative programming language from a declarative programming language.

<span class="mw-page-title-main">L-system</span> Rewriting system and type of formal grammar

An L-system or Lindenmayer system is a parallel rewriting system and a type of formal grammar. An L-system consists of an alphabet of symbols that can be used to make strings, a collection of production rules that expand each symbol into some larger string of symbols, an initial "axiom" string from which to begin construction, and a mechanism for translating the generated strings into geometric structures. L-systems were introduced and developed in 1968 by Aristid Lindenmayer, a Hungarian theoretical biologist and botanist at the University of Utrecht. Lindenmayer used L-systems to describe the behaviour of plant cells and to model the growth processes of plant development. L-systems have also been used to model the morphology of a variety of organisms and can be used to generate self-similar fractals.

<span class="mw-page-title-main">Dynamic programming</span> Problem optimization method

Dynamic programming is both a mathematical optimization method and an algorithmic paradigm. The method was developed by Richard Bellman in the 1950s and has found applications in numerous fields, from aerospace engineering to economics.

Programming style, also known as code style, is a set of rules or guidelines used when writing the source code for a computer program. It is often claimed that following a particular programming style will help programmers read and understand source code conforming to the style, and help to avoid introducing errors.

Test-driven development (TDD) is a software development process relying on software requirements being converted to test cases before software is fully developed, and tracking all software development by repeatedly testing the software against all test cases. This is as opposed to software being developed first and test cases created later.

In computer programming, a statement is a syntactic unit of an imperative programming language that expresses some action to be carried out. A program written in such a language is formed by a sequence of one or more statements. A statement may have internal components.

TPP may refer to:

Loop unrolling, also known as loop unwinding, is a loop transformation technique that attempts to optimize a program's execution speed at the expense of its binary size, which is an approach known as space–time tradeoff. The transformation can be undertaken manually by the programmer or by an optimizing compiler. On modern processors, loop unrolling is often counterproductive, as the increased code size can cause more cache misses; cf. Duff's device.

In computer science, a tail call is a subroutine call performed as the final action of a procedure. If the target of a tail is the same subroutine, the subroutine is said to be tail recursive, which is a special case of direct recursion. Tail recursion is particularly useful, and is often easy to optimize in implementations.

<span class="mw-page-title-main">Dependency injection</span> Software programming technique

In software engineering, dependency injection is a programming technique in which an object or function receives other objects or functions that it requires, as opposed to creating them internally. Dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs. The pattern ensures that an object or function which wants to use a given service should not have to know how to construct those services. Instead, the receiving 'client' is provided with its dependencies by external code, which it is not aware of. Dependency injection makes implicit dependencies explicit and helps solve the following problems:

<span class="mw-page-title-main">Scala (programming language)</span> General-purpose programming language

Scala is a strong statically typed high-level general-purpose programming language that supports both object-oriented programming and functional programming. Designed to be concise, many of Scala's design decisions are intended to address criticisms of Java.

Extreme programming (XP) is an agile software development methodology used to implement software systems. This article details the practices used in this methodology. Extreme programming has 12 practices, grouped into four areas, derived from the best practices of software engineering.

<span class="mw-page-title-main">Recursion (computer science)</span> Use of functions that call themselves

In computer science, recursion is a method of solving a computational problem where the solution depends on solutions to smaller instances of the same problem. Recursion solves such recursive problems by using functions that call themselves from within their own code. The approach can be applied to many types of problems, and recursion is one of the central ideas of computer science.

The power of recursion evidently lies in the possibility of defining an infinite set of objects by a finite statement. In the same manner, an infinite number of computations can be described by a finite recursive program, even if this program contains no explicit repetitions.

A database refactoring is a simple change to a database schema that improves its design while retaining both its behavioral and informational semantics. Database refactoring does not change the way data is interpreted or used and does not fix bugs or add new functionality. Every refactoring to a database leaves the system in a working state, thus not causing maintenance lags, provided the meaningful data exists in the production environment.

In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral (null) behavior. The null object design pattern, which describes the uses of such objects and their behavior, was first published as "Void Value" and later in the Pattern Languages of Program Design book series as "Null Object".

The DMS Software Reengineering Toolkit is a proprietary set of program transformation tools available for automating custom source program analysis, modification, translation or generation of software systems for arbitrary mixtures of source languages for large scale software systems. DMS was originally motivated by a theory for maintaining designs of software called Design Maintenance Systems. DMS and "Design Maintenance System" are registered trademarks of Semantic Designs.

In computer programming, a function, subprogram, procedure, method, routine or subroutine is a callable unit that has a well-defined behavior and can be invoked by other software units to exhibit that behavior.

References

  1. 1 2 Martin, Robert (2010). "The Transformation Priority Premise".
  2. Thompson, Billie (2021). "The Transformation Priority Premise".
  3. 1 2 Martin, Robert (2010). "Fib. The T-P Premise".
  4. Ridlehoover, Alan (2011). "The Transformation Priority Premise".