Php 时间测量探查器服务使用什么设计模式?
我有一个symfony2应用程序。它抽象了一组外部API,所有这些API都实现了Php 时间测量探查器服务使用什么设计模式?,php,symfony,design-patterns,Php,Symfony,Design Patterns,我有一个symfony2应用程序。它抽象了一组外部API,所有这些API都实现了externalapinterface 每个externalapinterface都有很多方法,例如fetchFoo和fetchBar 现在,我想编写一个服务来测量externalapinterface实例的每个方法调用的时间 我目前的想法是实现一个StopWatchExternalApiDecorator,它包装每个方法调用。然而,据我理解,这种方法会导致代码重复 我想我会使用时间测量,但这感觉很奇怪: class
externalapinterface
每个externalapinterface
都有很多方法,例如fetchFoo
和fetchBar
现在,我想编写一个服务来测量externalapinterface
实例的每个方法调用的时间
我目前的想法是实现一个StopWatchExternalApiDecorator
,它包装每个方法调用。然而,据我理解,这种方法会导致代码重复
我想我会使用时间测量,但这感觉很奇怪:
class StopWatchExternalApiDecorator implements ExternalApiInterface {
public function __construct(ExternalApiInterface $api, Stopwatch $stopWatch)
{
$this->api = $api;
$this->stopWatch = $stopWatch;
}
public function fetchBar() {
$this->stopWatch->start('fetchBar');
$this->api->fetchBar()
$this->stopWatch->stop('fetchBar');
}
public function fetchFoo() {
$this->stopWatch->start('fetchFoo');
$this->api->fetchFoo()
$this->stopWatch->stop('fetchFoo');
}
}
我似乎在伤害DNRY(不要重复你自己)的方法。我是在用正确的模式解决这类问题,还是有其他更合适的模式?更适合的含义是:一个地方进行所有测量,并且没有代码重复
我也不喜欢触摸装饰器,以防界面中出现新方法。在我看来,这应该是独立的。我正在考虑我开发的一些API,它们使用一个通用函数进行调用和一个方法参数 下面是一些非常基本的伪代码
public function call($method = 'fetchBar',$params=array()){
$this->stopWatch->start($method);
$this->{"$method"}($params);
$this->stopWatch->stop($method);
}
private function fetchBar(){
echo "yo";
}
也许这会有所帮助我正在考虑我开发的一些API,它们使用一个通用函数进行调用和一个方法参数 下面是一些非常基本的伪代码
public function call($method = 'fetchBar',$params=array()){
$this->stopWatch->start($method);
$this->{"$method"}($params);
$this->stopWatch->stop($method);
}
private function fetchBar(){
echo "yo";
}
也许这会有所帮助,我采用了装饰师的方法,只是在一个不同的层面上 在我的体系结构中,api服务使用的是
HttpClientInterface
,每个请求最后都通过调用doRequest
来处理。因此,在没有代码重复的情况下,decorator最有意义:
<?php
namespace Kopernikus\BookingService\Component\Http\Client;
use Kopernikus\BookingService\Component\Performance\PerformanceEntry;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Stopwatch\Stopwatch;
/**
* ProfileClientDecorator
**/
class ProfileClientDecorator implements HttpClientInterface
{
/**
* @var Stopwatch
*/
private $stopwatch;
/**
* @var HttpClientInterface
*/
private $client;
/**
* @var LoggerInterface
*/
private $logger;
/**
* ProfileClientDecorator constructor.
* @param HttpClientInterface $client
* @param Stopwatch $stopwatch
* @param LoggerInterface $logger
*/
public function __construct(HttpClientInterface $client, Stopwatch $stopwatch, LoggerInterface $logger)
{
$this->client = $client;
$this->stopwatch = $stopwatch;
$this->logger = $logger;
}
/**
* @param RequestInterface $request
*
* @return ResponseInterface
*/
public function doRequest(RequestInterface $request)
{
$method = $request->getMethod();
$response = $this->doMeasuredRequest($request, $method);
$performance = $this->getPerformance($method);
$this->logPerformance($performance);
return $response;
}
/**
* @param RequestInterface $request
* @param string $method
*
* @return ResponseInterface
*/
protected function doMeasuredRequest(RequestInterface $request, $method)
{
$this->stopwatch->start($method);
$response = $this->client->doRequest($request);
$this->stopwatch->stop($method);
return $response;
}
/**
* @param $method
* @return PerformanceEntry
*/
protected function getPerformance($method)
{
$event = $this->stopwatch->getEvent($method);
$duration = $event->getDuration();
return new PerformanceEntry($duration, $method);
}
/**
* @param PerformanceEntry $performance
*/
protected function logPerformance(PerformanceEntry $performance)
{
$context = [
'performance' => [
'duration_in_ms' => $performance->getDurationInMs(),
'request_name' => $performance->getRequestName(),
],
];
$this->logger->info(
"The request {$performance->getRequestName()} took {$performance->getDurationInMs()} ms",
$context
);
}
}
我采用了装饰师的方法,只是在一个不同的层面上 在我的体系结构中,api服务使用的是
HttpClientInterface
,每个请求最后都通过调用doRequest
来处理。因此,在没有代码重复的情况下,decorator最有意义:
<?php
namespace Kopernikus\BookingService\Component\Http\Client;
use Kopernikus\BookingService\Component\Performance\PerformanceEntry;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Stopwatch\Stopwatch;
/**
* ProfileClientDecorator
**/
class ProfileClientDecorator implements HttpClientInterface
{
/**
* @var Stopwatch
*/
private $stopwatch;
/**
* @var HttpClientInterface
*/
private $client;
/**
* @var LoggerInterface
*/
private $logger;
/**
* ProfileClientDecorator constructor.
* @param HttpClientInterface $client
* @param Stopwatch $stopwatch
* @param LoggerInterface $logger
*/
public function __construct(HttpClientInterface $client, Stopwatch $stopwatch, LoggerInterface $logger)
{
$this->client = $client;
$this->stopwatch = $stopwatch;
$this->logger = $logger;
}
/**
* @param RequestInterface $request
*
* @return ResponseInterface
*/
public function doRequest(RequestInterface $request)
{
$method = $request->getMethod();
$response = $this->doMeasuredRequest($request, $method);
$performance = $this->getPerformance($method);
$this->logPerformance($performance);
return $response;
}
/**
* @param RequestInterface $request
* @param string $method
*
* @return ResponseInterface
*/
protected function doMeasuredRequest(RequestInterface $request, $method)
{
$this->stopwatch->start($method);
$response = $this->client->doRequest($request);
$this->stopwatch->stop($method);
return $response;
}
/**
* @param $method
* @return PerformanceEntry
*/
protected function getPerformance($method)
{
$event = $this->stopwatch->getEvent($method);
$duration = $event->getDuration();
return new PerformanceEntry($duration, $method);
}
/**
* @param PerformanceEntry $performance
*/
protected function logPerformance(PerformanceEntry $performance)
{
$context = [
'performance' => [
'duration_in_ms' => $performance->getDurationInMs(),
'request_name' => $performance->getRequestName(),
],
];
$this->logger->info(
"The request {$performance->getRequestName()} took {$performance->getDurationInMs()} ms",
$context
);
}
}