Очень часто в программировании для провайдера - ie. myFunctionA()
, чтобы ничего не знать о его потребителе (ах) myFunctionB()
. только правильный способ справиться с этим - определить API заранее и никогда не изменить его;)
Я не вижу цели создания версий потребитель - эта причина должна быть "ниже по течению" myFunctionB()
- ie. потребитель из myFunctionB()
, что автор myFunctionB()
не контролирует ... в этом случае myFunctionB()
сам становится провайдером , и автор будет иметь справиться с этим (возможно, используя тот же шаблон, что и вы) ... Но это не ваша проблема для решения.
Что касается вашего провайдера myFunctionA()
: Если вы не можете заранее определить интерфейс / API для самих данных - ie. вы знаете, что структура данных должна будет измениться (обратно-совместимым образом), но вы не знаете, как ... тогда вам понадобится версия что-то так или иначе .
Вы намного опережаете большинство, так как вы видите это грядущее и планируете его с самого начала.
Единственный способ избежать внести изменения в потребителя myFunctionB()
в какой-то момент, значит сделать все изменения в поставщике myFunctionA()
обратно совместимым способом. Изменения, которые вы описываете, не являются обратно совместимыми, потому что myFunctionB()
не может знать, что делать с новым выводом из myFunctionA()
без изменения.
Предлагаемое вами решение звучит так, как будто оно должно работать. Однако есть как минимум пара недостатков:
- Это требует от вас постоянно растущего списка устаревших функций на случай, если когда-нибудь кто-нибудь запросит их данные. Это станет очень сложным в обслуживании и, вероятно, будет невозможно в долгосрочной перспективе.
- В зависимости от того, какие изменения необходимо внести в будущем, больше не будет возможности вообще выводить данные для
myFunctionA__v1_0()
- in В вашем примере вы добавляете возможность нескольких page_types
в вашей системе - в этом случае вы, вероятно, можете просто переписать v1_0
, чтобы использовать первый, и унаследованные потребители будут счастливы. Но если вы решите полностью удалить концепцию page_types
из вашей системы, вам придется планировать полное удаление v1_0
так или иначе. Таким образом, вам нужно установить sh способ сообщить об этом потребителям.
Единственный правильный способ справиться с этим - определить API заранее и никогда изменить это.
Поскольку мы установили, что:
- вам придется вносить обратно несовместимые изменения
- вы ничего не знаете о потребители и вы не можете изменять их при необходимости
Я предлагаю вместо определения неизменяемого API для ваших данных вы определяете неизменный API, который позволяет вам общаться с потребителями, когда они должны или должны обновить.
Это может показаться сложным, но это не обязательно должно быть:
Примите параметр версии в provider :
Идея состоит в том, чтобы позволить потребителю явно сообщить поставщику, какую версию возвращать.
Поставщик может выглядеть следующим образом:
function myFunctionA(string $version) {
$page_types = ['TypeA', 'TypeB'];
$page = new stdClass();
$page->title = 'Page title';
switch ($version) {
case '1.0':
$page->error = 'Version 1.0 no longer available. Please upgrade!';
break;
case '1.1':
$page->page_type = $page_types[0];
$page->warning = 'Deprecated version. Please upgrade!';
break;
case '2.0':
$page->page_types = $page_types;
break;
default:
$page->error = 'Unknown version: ' . $version;
break;
}
return $page;
}
Таким образом, поставщик принимает параметр, который будет содержит версию, понятную потребителю - обычно ту, которая была самой новой, когда потребитель последний раз обновлялся.
Поставщик делает все возможное для доставки запрошенной версии
- если это невозможно, существует «договор» для информирования потребителя (
$page->error
будет существовать для возвращаемого значения) - , если возможно , но есть доступна более новая версия, имеется другой «контракт» для информирования потребителя об этом (
$page->warning
будет существовать в возвращаемом значении).
И обрабатывать несколько случаев у потребителя )
Потребитель должен отправить версию, которую он ожидает, в качестве параметра.
function myFunctionB() {
//The consumer tells the provider which version it wants:
$page = myFunctionA('2.0');
if ($page->error) {
//Notify developers and throw an error
pseudo_notify_devs($page->error);
throw new Exception($page->error);
} else if ($page->warning) {
//Notify developers
pseudo_notify_devs($page->warning);
}
do_stuff_with($page);
}
Вторая строка старой версии myFunctionB()
- или совсем другого потребителя myFunctionC()
может вместо этого запросить старая версия:
$page = myFunctionA('1.1');
Это позволяет вам вносить обратно совместимые изменения в любое время, когда вам не нужно ничего делать. Вы можете сделать все возможное, чтобы по-прежнему поддерживать старые версии, когда это возможно, обеспечивая «постепенное» ухудшение в старых потребителях .
Когда вам действительно нужно сделать критические изменения Вы можете продолжить поддерживать старую версию, прежде чем окончательно полностью ее удалить.
Мета-информация
Я не уверен, что это будет полезно ... но вы могли бы добавить некоторую метаинформацию для потребителей, используя устаревшую версию:
function myFunctionA(string $version) {
# [...]
if ($page->error || $page->warning) {
$page->meta = [
'current_version' => '3.0',
'API_docs' => 'http://some-url.fake'
]
}
return $page;
}
Затем ее можно использовать для потребителя:
pseudo_notify_devs(
$page->error .
' - Newest version: ' . $page->meta['current_version'] .
' - Docs: ' . $page->meta['API_docs']
);
... на вашем месте я был бы осторожен не переусердствуйте, хотя ... Всегда KISS