Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sebastianbergmann/de-legacy-fy
Tool for dealing with legacy PHP code
https://github.com/sebastianbergmann/de-legacy-fy
Last synced: about 2 months ago
JSON representation
Tool for dealing with legacy PHP code
- Host: GitHub
- URL: https://github.com/sebastianbergmann/de-legacy-fy
- Owner: sebastianbergmann
- License: other
- Archived: true
- Created: 2014-04-15T15:18:30.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2017-05-15T06:51:09.000Z (over 7 years ago)
- Last Synced: 2024-09-21T10:03:38.293Z (2 months ago)
- Language: PHP
- Homepage:
- Size: 58.6 KB
- Stars: 76
- Watchers: 7
- Forks: 4
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: ChangeLog.md
- License: LICENSE
Awesome Lists containing this project
README
# de-legacy-fy
[Legacy code is code without tests.](http://c2.com/cgi/wiki?WorkingEffectivelyWithLegacyCode)
Over the years I have helped many a team introduce (unit) testing into a legacy
code base, making it "less legacy" step by step.The `de-legacy-fy` command-line tool is an attempt to put concepts and ideas
that proved to be effective at dealing with legacy PHP applications into code
and make them as reusable as possible.## Installation
### PHP Archive (PHAR)
The easiest way to obtain de-legacy-fy is to download a [PHP Archive (PHAR)](https://secure.php.net/phar) that has all required dependencies of de-legacy-fy bundled in a single file:
```
$ wget https://phar.phpunit.de/de-legacy-fy.phar
$ chmod +x de-legacy-fy.phar
$ mv de-legacy-fy.phar /usr/local/bin/de-legacy-fy
```You can also immediately use the PHAR after you have downloaded it, of course:
```
$ wget https://phar.phpunit.de/de-legacy-fy.phar
$ php de-legacy-fy.phar
```### Composer
You can add this tool as a local, per-project, development-time dependency to your project using [Composer](https://getcomposer.org/):
```
$ composer require --dev sebastian/de-legacy-fy
```You can then invoke it using the `vendor/bin/de-legacy-fy` executable.
## Usage Examples
### Generating characterization tests using execution trace data
[Characterization Tests are an attempt to lock existing behavior into an untested or undocumented system.](http://c2.com/cgi/wiki?CharacterizationTest) They are described briefly in Michael Feathers' book ["Working Effectively With Legacy Code"](http://c2.com/cgi/wiki?WorkingEffectivelyWithLegacyCode), among other places.
We can automatically generate a [data provider](http://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers) for a PHPUnit-based characterization test using [execution trace](http://xdebug.org/docs/execution_trace) data that we can collect with [Xdebug](http://xdebug.org/).
Consider the following rather contrived and simple example:
```php
decode('aTozOw=='), $this->decode('aToxOw=='), $this->decode('aToyOw==')]
];
}/**
* @param string $serializedValue
*
* @return mixed
*/
private function decode($serializedValue)
{
return unserialize(base64_decode($serializedValue));
}
}
```All that is left for us to do in order to implement the characterization test can be seen below:
```php
assertEquals($expected, add($a, $b));
}/**
* @return array
*/
public function provider()
{
return [
[$this->decode('aTozOw=='), $this->decode('aToxOw=='), $this->decode('aToyOw==')]
];
}/**
* @param string $serializedValue
*
* @return mixed
*/
private function decode($serializedValue)
{
return unserialize(base64_decode($serializedValue));
}
}
```### Wrapping a static API class
[Static methods are death to testability.](http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/)
It is characteristic for a legacy code base to use global state and static
methods. Sometimes there are "library classes" that only contain static
methods:```php
library = $library;
}public function process()
{
// ...$this->library->doSomething('...', '...');
// ...
}
}
```The `Processor` class does not use the legacy `Library` class directly anymore
and can be tested in isolation from it (as we can now stub or mock the
`LibraryWrapper` class).Using the concept of [branch-by-abstraction](http://martinfowler.com/bliki/BranchByAbstraction.html)
we can now write new code that uses the `LibraryWrapper` class and migrate old
code from `Library` to `LibraryWrapper`. Eventually we can reimplement the
functionality of `Library` inside the `LibraryWrapper` class. Once no code
relies on `Library` anymore we can delete `Library` and rename `LibraryWrapper`
to `Library`.