Если следовать определению унаследованного кода, данному Майклом Фезерсом (каждый код, не покрытый тестами), то первое направление работы с некоторым унаследованным кодом, требующим обновления, — поместить его в тестовую обвязку (написать для него тест). Но это часто легче сказать, чем сделать. Просто создать экземпляр (устаревшего) класса в тесте может быть на удивление сложно из-за того, как он обрабатывает свои зависимости.
Давайте рассмотрим две наиболее часто встречающиеся проблемы и способы их решения.
Скажем, мы создаем приложение для интернет-магазина. Чтобы рассчитать цену продукта, нам нужно применить некоторую бизнес-логику (скидки, ваучеры…) и учесть НДС (налог), который предоставляется некоторым внешним сервисом:
class CalculatePrice
{
public function __construct(private VatDotComClient $vatProvider)
{
}
public function calculate(Product $product)
{
$taxRate = $this->vatProvider->getRate($product->countryCode());
// some business logic to calculate price
}
}
public function itAppliesTheTaxRate()
{
$calculateTax = new CalculatePrice(
new VatDotComClient('api-key', 'secret')
);
// ...
}
Не поймите меня неправильно, нет ничего плохого в том, чтобы провести (интеграционный) тест, чтобы подтвердить, что мы VatDotComClientможем общаться с провайдером, но нам не нужно тестировать эту интеграцию каждый раз, когда мы тестируем некоторую бизнес-логику в нашем домене.
Что, если мы создадим какой-нибудь фиктивный НДС-клиент, возвращающий некоторые данные, которые мы контролируем (вместо того, чтобы общаться с каким-то реальным провайдером по сети). Затем мы могли бы использовать этого фиктивного провайдера в нашем тесте и настоящего в производственном коде. Звучит неплохо, но наш сервис зависит от (реального) VatDotComClient. Раздражает, да?
Чтобы обойти это, мы можем применить рефакторинг Extract Interface . Во-первых, мы создаем интерфейс (на основе VatDotComClient):
interface VatProvider
{
public function getRate(string $countryCode): float;
}
class CalculatePrice
{
public function __construct(private VatProvider $vatProvider)
{
}
public function calculate(Product $product)
{
$taxRate = $this->vatProvider->getRate($product->countryCode());
// some business logic to calculate price
}
}
class TestProvider implements VatProvider
{
public function __construct(private float $rate)
{
}
public function getRate(string $countryCode)
{
return $this->rate;
}
}
public function itAppliesTheTaxRate()
{
$calculateTax = new CalculatePrice(
new TestProvider(0.25)
);
// ... Assert price what expected (with 0.25 tax rate)
}
Теперь, когда мы можем рассчитывать цены на наши продукты и люди их покупают, нам также необходимо обрабатывать их платежи. Скажем, у нас есть такой сервис:
class ProcessPayment
{
public function __construct()
{
// ...
}
public function process(Payment $payment)
{
// ...
}
}
public function itRecordsThePayment()
{
$payment = new Payment(340, 'EUR', 12);
$processPayment = new ProcessPayment();
$processpayments->process($payment);
// ... Assert stuff
}
Что ж, при ближайшем рассмотрении нашего ProcessPaymentсервиса мы видим, что он имеет зависимость от Mailerкласса, но скрыт в конструкторе (или в каком-то методе), и где-то между всей бизнес-логикой был вызов к нему для отправки электронного письма.
class ProcessPayment
{
public function __construct()
{
// some code
$this->mailer = new Mailer('api-key', 'secret');
// some code
}
public function process(Payment $payment)
{
// ...
$this->mailer->send($payment->receiver(), new PaymentNotificationMessage($payment)):
}
}
class ProcessPayment
{
public function __construct(Mailer $mailer)
{
$this->mailer = $mailer;
}
public function process(Payment $payment)
{
// ...
}
}
Если вы посмотрите на наш код после рефакторинга, он теперь использует хорошо известный принцип хорошего дизайна — Dependency Injection . Кроме того, наш сервис больше не зависит от конкретной реализации, а зависит от абстракции (еще один принцип хорошего дизайна). Это позволяет нам обмениваться этими конкретными реализациями ( шаблон разработки стратегии ). Таким образом, теперь не только наш код стал более тестируемым, но и наш дизайн также улучшился.
Существует своего рода синергия между тестируемостью и хорошим дизайном. Для кода с хорошим дизайном легко писать тесты, и наоборот.
Вот почему вы должны стремиться использовать разработку через тестирование при разработке нового кода. Что касается наследства, если вам нужны дополнительные советы по работе с ним, прочтите книгу Майкла Фезерса « Эффективная работа с устаревшим кодом », чтобы получить дополнительные советы и рекомендации.
Когда вы делаете запрос на facebook.com, ваш компьютер ищет доменное имя, чтобы преобразовать это доменное имя в IP-адрес, чтобы ваш компьютер мог установить это соединение.
Наш язык является мощным инструментом, который может формировать наши мысли, отношения и действия. Даже кажущиеся безобидными термины могут увековечить вредные предубеждения и стереотипы.
Вчера мы закрыли двери конкурса песни «Евровидение» в этом году блестящим, хаотичным грандиозным финалом, в котором шведская певица Лорин забрала домой трофей, став первой женщиной, выигравшей дважды, и вернув корону Швеции спустя 50 лет после того, как ABBA выиграла конкурс. с «Ватерлоо». Они стали одним из крупнейших исполнителей в каноне поп-музыки.
Сколько раз вы, не задумываясь, выбрасывали пластиковую бутылку, стеклянную банку, алюминиевую банку или пакет экологически чистой энергии? Сколько раз вы хотели получить что-то взамен за их переработку? Если вы похожи на большинство людей, ответ, вероятно, много раз. Переработка часто рассматривается как хлопотное дело, рутинная работа или обязанность, не приносящая немедленных или ощутимых выгод.
Когда вы вырастаете, вам, как правило, говорят, что мир такой, какой он есть, и ваша жизнь состоит в том, чтобы просто жить своей жизнью внутри мира, никогда не рискуя своей жизнью, просто следовать установленному пути и умереть в конце, и стараться не слишком сильно бить стены. Но это очень ограниченная жизнь.
В сегодняшнем быстро развивающемся бизнес-ландшафте концепция гибридной и удаленной работы приобрела беспрецедентный импульс. Поскольку компании продолжают приспосабливаться к меняющимся потребностям и ожиданиям своих сотрудников, эксперты из разных областей собрались вместе, чтобы обсудить преимущества, проблемы и будущее этого преобразующего способа работы.