Создать правильное отношение объекта - PullRequest
0 голосов
/ 16 мая 2018

Я начинаю изучать ООП, и я знаю, что трудно создать хороший, качественный, тестируемый код, и я боюсь сделать какую-то архитектурную ошибку и начать, потому что потом труднее провести рефакторинг.

В настоящее время я работаю над Laravel, и мне нужен компонент (небольшая часть программы) для вычисления статистики онлайн-рекламы (CPM, EPC и т. Д.) В cronjob.Для этого мне нужно собрать данные из базы данных, рассчитать статистику (и) и сохранить их в связанной таблице.Это нужно запустить через CLI с помощью cronjob.Расчет статистики должен выполняться, если это возможно, с помощью SQL, но это не всегда может быть сделано с текущей архитектурой.Поэтому мне нужно создать какой-то повторно используемый компонент, который можно легко расширить с помощью новой логики расчета статистики, либо просто извлекая уже рассчитанную логику из БД и сохраняя ее, либо извлекайте, вычисляйте и сохраняйте в БД.И чтобы у futuhre была возможность легко использовать его в любой части приложения, а не только в CLI.

Для запуска из CLI я использую команду Laravel с расписанием:

class StatsComamnd extends Command
{
    protected $signature = 'project:calculatestats {statName}';
    public function __construct(StatsService $statsService){
        parent::__construct();
        $this->statsService = $statsService;
    }
    public function handle() {
        $method = $this->argument('statName');
        if(!method_exists($this, $method)) {
            $this->error('Invalid stat name provided!');
       }

       $this->{$method}();
    }
    public function networkOffers():void {
         $this->stastService->setStatsHandler(app(OffersNetworkStatsHandler::class))->handle();
    }
    public function networkOffersCpm():void{
         app(OffersNetworkCpmHandler::class)->handle(); 
    }
    public function networkOffersEpc:void{
         app(OffersNetworkEpcHandler::class)->handle(); 
    }
    public function networkSurveys():void{
         app(SurveysNetworkHandler::class)->handle(); 
    }
    public function networkSurveysCpm():void{    
         app(SurveysNetrworkCpmHandler::class)->handle(); 
    }
    public function networkSurveysEpc:void{
         app(SurveysNetworkEpcHandler::class)->handle(); 
    }
    //...other handlers, like countryOffersCpm, toolSpecificOffersCpm and so on
}

SurveysNetrworkCpmStatsHandler:

/** This handle responsible of collectiong, calculating and storing network wide survey CPMs. We can't calculate CPM inside DB, so here we are going to use CpmCalculator */
class SurveysNetrworkCpmStatsHandler implements StatsHandlerInterface {
    private $surveyImpressionsRepo;
    private $statsRepo;
    private $vcPointRepo;
    private $calculator;
    public function __construct(
        SurveyImpressionRepositoryInterface $surveyImpressionRepository,
        SurveyStatsRepositoryInterface $statsRepository,
        VcPointRepositoryInterface $vcPointRepository,
        CpmCalculator $calculator
    ){
        $this->surveyImpressionsRepo = $surveyImpressionRepository;
        $this->calculator = $calculator;
        $this->vcPointRepo = $vcPointRepository;
        $this->statsRepo = $statsRepository;
    }
    public function handle() {
        $stats = [];
        list($impressions, $conversions) = $this->fetchStatisticData();
        foreach ($impressions as $impression) {
            $sid = $impression->survey_id;
            $conversion = $conversions->first(function($conversion) use ($sid) {
                return $conversion->survey_id === $sid;
            });
            if(!isset($conversion)) {
                continue;
            }
            $stat = new \SurveyNetworkCpmStat();
            $stat->offer_id = $impression->offer_id;
            $stat->survey_id = $sid;
            $stat->mobile_cpm = $this->calculator->setConversionCount($conversion->conversions_count_mobile)->setImpressionsCount($impression->unique_impressions_count_mobile)->setPayoutSum($conversion->payout_sum_mobile)->calculate();
            $stat->desktop_cpm  = $this->calculator->setConversionCount($conversion->conversions_count_desktop)->setImpressionsCount($impression->unique_impressions_count_desktop)->setPayoutSum($conversion->payout_sum_desktop)->calculate();
            $stat[] = $stat->toArray();
        }
        $this->store($stats)
   }

   private function fetchStatisticData(){
       $impressions = $this->surveyImpressionsRepo->getImpressionsForNetworkCpm();
       $conversions = $this->vcPointRepo->getConversionsForSurveyNetworkCpm();

       return [$impressions, $conversions];
   }

   private function store($stst): bool{
       $this->statsRepo->insert()
   }
}

SurveysNetrworkStatsHandler:

/** This handle responsible of collectiong, calculating and storing all network wide survey stats.*/
class SurveysNetrworkStatsHandler implements StatsHandlerInterface {
    private $cpmHandler;
    private $epcHandler;
    private $statsRepo;
    public function __construct(
        SurveysNetrworkCpmStatsHandler $cpmHandler,
        SurveysNetrworkEpcStatsHandler $epcHandler,
        SurveyStatsRepositoryInterface $statsRepository
    ){
        $this->cpmHandler = $cpmHandler;
        $this->epcHandler = $epcHandler;
        $this->statsRepo = $statsRepository;
    }
    public function handle() {
        $this->cpmHandler->handle();
        $this->epcHandler->handle();
    }
}

ПредложенияNetrworkCpmStatsHandler:

etrworkCpmStatsHandler:

/** This handle responsible of collectiong, calculating and storing network wide offers CPMs. We can calculate CPM inside DB, so here do not need any Calculator */
class OffersNetrworkCpmStatsHandler implements StatsHandlerInterface {
    private $surveyImpressionsRepo;
    private $statsRepo;
    public function __construct(
        SurveyImpressionRepositoryInterface $surveyImpressionRepository,
        SurveyStatsRepositoryInterface $statsRepository
    ){
        $this->surveyImpressionsRepo = $surveyImpressionRepository;
        $this->statsRepo = $statsRepository;
    }
    public function handle() {
        $stats = [];
        $stats =  $this->fetchStatisticData();
        $this->store($stats)
   }

   private function fetchStatisticData(){
       return $this->surveyImpressionsRepo->getCpm();
   }

   private function store($stst): bool{
       $this->statsRepo->insert()
   }
}

CpmCalculator:

1020 ** Я удаляю всю логику проверки здесь и интерфейсы, чтобы уменьшить количество кода.

Может кто-нибудь предложить какие-либо улучшения, может быть, я могу использовать некоторые шаблоны здесь?Спасибо за любые предложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...