Avoiding “side effects” in recursive functions

I am writing a function to find the intersection between two sets.

The non-functional requirements of the assignment include avoiding “side effects”.

function intersection(a, b) {   return helper(a, b, []); }  function helper(a, b, c) {   if (a = []) {     return c;   }    if (b.contains(a[0])) {     c.append(a[0]);     return helper(a.slice(1, a.length), b, c);   }    return helper(a.slice(1, a.length), b, c); } 

Would mutating the argument c in the above code be considered a side effect?

The specific assignment is written in OCaml, so, though the above example is in an imperative language, I want to stay true to the spirit of functional programming.

Please don’t provide any alternate solutions to the problem.

Avoiding code repeating in RESTful APIS PHP

Since my last question related to this I have managed to create a working base and to understand how MVC works.

I’m writing RESTful APIS in PHP, they serve the purpose but I see that my code is repeating.

For example, for each action, I have a controller, a service… etc and a lot of that code can be reused not that I write a ton of code for one simple route.

I have tried a few of my ideas but I end up having spaghetti code and it does not look clean.


Here is folder the structure in one of my APIS.

. ├── README.md ├── apache_default ├── composer.json ├── composer.lock ├── config │   ├── config-development.yml │   ├── config-production.yml │   ├── dependencies │   │   ├── common │   │   │   ├── cashing.yml │   │   │   ├── components.yml │   │   │   ├── controllers.yml │   │   │   ├── domains.yml │   │   │   ├── middleware.yml │   │   │   ├── objmap.yml │   │   │   ├── repositories.yml │   │   │   └── services.yml │   │   ├── development │   │   │   └── db.yml │   │   ├── general-production.yml │   │   ├── general.yml │   │   └── main.yml │   ├── parameters │   │   └── development │   │       └── tables.yml │   └── routing.yml ├── phpunit.xml ├── public │   ├── Bootstrap.php │   ├── Kernel.php │   ├── index.php │   └── monolog.log ├── resources │   ├── git │   │   ├── diagram.png │   │   ├── schema.png │   │   └── schema_1.png │   └── loggs │       └── monolog.txt ├── src │   └── Spartan │       ├── Core │       │   ├── Component │       │   │   ├── Collection.php │       │   │   ├── Controller.php │       │   │   ├── DataMapper.php │       │   │   ├── Exception.php │       │   │   ├── MapperFactory.php │       │   │   └── Service.php │       │   ├── Database │       │   │   ├── ES.php │       │   │   └── PDOCompat.php │       │   ├── Entities │       │   │   ├── CanPersistMapper.php │       │   │   ├── HasId.php │       │   │   └── ResponseBootstrap.php │       │   ├── Logger │       │   │   └── Logger.php │       │   └── Mapper │       │       └── CanCreateMapper.php │       ├── Models │       │   ├── Adapters │       │   ├── Cashing │       │   │   └── WorkoutCashing.php │       │   ├── Collections │       │   │   ├── DescriptionCollection.php │       │   │   ├── ExerciseCollection.php │       │   │   ├── NameCollection.php │       │   │   ├── RoundCollection.php │       │   │   ├── TagCollection.php │       │   │   ├── WorkoutCollection.php │       │   │   └── WorkoutListCollection.php │       │   ├── Domains │       │   │   ├── AddWorkoutDomain │       │   │   │   └── AddWorkoutDomain.php │       │   │   ├── DeleteWorkoutDomain │       │   │   │   └── DeleteWorkoutDomain.php │       │   │   ├── EditWorkoutDomain │       │   │   │   └── EditWorkoutDomain.php │       │   │   ├── GetWorkoutDomain │       │   │   │   └── GetWorkoutDomain.php │       │   │   ├── GetWorkoutIdsDomain │       │   │   │   └── GetWorkoutIdsDomain.php │       │   │   ├── GetWorkoutListDomain │       │   │   │   └── GetWorkoutListDomain.php │       │   │   ├── ReleaseWorkoutDomain │       │   │   │   └── ReleaseWorkoutDomain.php │       │   │   └── WorkoutExsistsDomain │       │   │       └── WorkoutExsistsDomain.php │       │   ├── Entities │       │   │   ├── Description.php │       │   │   ├── Exercise.php │       │   │   ├── Name.php │       │   │   ├── Round.php │       │   │   ├── Tag.php │       │   │   ├── Version.php │       │   │   ├── Workout.php │       │   │   └── WorkoutList.php │       │   ├── Exceptions │       │   │   ├── BaseError.php │       │   │   ├── DescriptionConfliect.php │       │   │   ├── ESError.php │       │   │   ├── NameConflict.php │       │   │   ├── RoundError.php │       │   │   └── TagError.php │       │   ├── Facades │       │   ├── Helpers │       │   ├── Interfaces │       │   │   └── CanPersistWorkout.php │       │   ├── Mappers │       │   │   ├── VersionMapper.php │       │   │   ├── WorkoutBase.php │       │   │   ├── WorkoutDescription.php │       │   │   ├── WorkoutListMapper.php │       │   │   ├── WorkoutName.php │       │   │   ├── WorkoutRound.php │       │   │   └── WorkoutTag.php │       │   ├── Middlewares │       │   │   ├── CreateWorkoutMiddleware.php │       │   │   ├── DeleteWorkoutMiddleware.php │       │   │   ├── EditWorkoutMiddleware.php │       │   │   ├── GetWorkoutByIdsMiddleware.php │       │   │   ├── GetWorkoutListMiddleware.php │       │   │   ├── GetWorkoutMiddleware.php │       │   │   └── ReleaseWorkoutMiddleware.php │       │   ├── Repositories │       │   │   └── WorkoutRepository.php │       │   └── Services │       │       └── WorkoutService.php │       └── Presentation │           ├── Controller │           │   ├── LogController.php │           │   └── WorkoutController.php │           └── Mappers │               └── WorkoutMapp.php └── tests     ├── bootstrap.php     ├── fixture     ├── integration     ├── mock     │   ├── Entity.php     │   ├── Factory.php     │   ├── Mapper.php     │   ├── RepoEntity.php     │   └── RepoMapper.php     ├── report     └── unit         └── Spartan             ├── Cashing             │   └── WorkoutCashingTest.php             ├── Component             │   ├── CollectionTest.php             │   ├── DataMapperTest.php             │   └── MapperFactoryTest.php             ├── Controller             │   └── MappTest.php             ├── Domains             ├── Entities             │   ├── DescriptionTest.php             │   ├── ExerciseTest.php             │   ├── NameTest.php             │   ├── RoundTest.php             │   ├── TagTest.php             │   ├── VersionTest.php             │   ├── WorkoutListTest.php             │   └── WorkoutTest.php             ├── Mappers             │   ├── VersionTest.php             │   ├── WorkoutBaseTest.php             │   ├── WorkoutDescriptionTest.php             │   ├── WorkoutListTest.php             │   ├── WorkoutNameTest.php             │   ├── WorkoutRoundTest.php             │   └── WorkoutTagTest.php             ├── Repositories             │   └── WorkoutTest.php             └── Services                 └── WorkoutTest.php 

For each activity I have a controller, that controller has a service injected into it via DI over yml.

When the service loads I have a domain folder where I keep my logic and over a factory, I create mappers there which I need(if I need them).

Each domain does one action, for example version workout(I need this for auditing of my data in MySQL).

Than I have a middleware in my service which does cashing(I’m working to change)

And thats basically how each of my routes works a lot of repeated code.

It looks very boring to write code now and I need a push into another direction.


Here is a part of my code:

index.php

<?php  //Display errors ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL);  use Symfony\Component\HttpFoundation\Request; // load vendor require __DIR__.'/../vendor/autoload.php'; require_once __DIR__.'/../public/Kernel.php'; require_once __DIR__.'/../public/Bootstrap.php';  // new kernel $  kernel = new Kernel('dev'); $  bootstrap = new Bootstrap;  // new request $  request = Request::createFromGlobals(); // loader interface $  config = $  kernel->registerContainerConfiguration(); // response from $  response = $  bootstrap->handle($  request,$  config,null); 

bootstrap.php

<?php class Bootstrap {      public function handle($  request,$  config,$  ipRange)     {                   // Configuration          $  locator = new FileLocator(__DIR__ . '/../config');         $  data = new ResponseBootstrap();           // Create a log channel         $  log = new Logger('spartan_workouts_ms');         $  log->pushHandler(new StreamHandler('monolog.log'));         $  log->pushHandler(new LogglyHandler('55920048-11f0-4b7e-a203-e90083d6962d/tag/monolog', Logger::INFO));           // Dependency Injection Container         $  container = new DependencyInjection\ContainerBuilder;         $  loader = new DependencyInjection\Loader\YamlFileLoader($  container, $  locator);         $  loader->load($  config);         $  container->compile();           // Routing         $  loader = new Routing\Loader\YamlFileLoader($  locator);         $  context = new Routing\RequestContext();         $  context->fromRequest($  request);         $  matcher = new Routing\Matcher\UrlMatcher(             $  loader->load('routing.yml'),             $  context         );           try{             $  parameters = $  matcher->match($  request->getPathInfo());             foreach ($  parameters as $  key => $  value) {                 $  request->attributes->set($  key, $  value);             }             $  command = $  request->getMethod() . $  request->get('action');             $  resource = "controller.{$  request->get('controller')}";             $  controller = $  container->get($  resource);             $  data = $  controller->{$  command}($  request);              }         // log custom thrown exceptions         catch (\Exception $  e) {              /**              * This is to slow it takes to much time to log              */ //             // log errors //             $  log->addWarning( //                     json_encode([ //                         "date"=> date("Y-m-d h:i:s"), //                         "code"=> $  e->getCode(), //                         "message"=> $  e->getMessage(), //                         "file"=> $  e->getFile(), //                         "line"=> $  e->getLine() //                     ]) //                 );              $  data->setData([                 "date"=> date("Y-m-d h:i:s"),                 "code"=> $  e->getCode(),                 "message"=> $  e->getMessage(),                 "file"=> $  e->getFile(),                 "line"=> $  e->getLine()             ]);              if($  e->getCode() == 0){                 // TODO log data                 $  data->setStatus(404);             }else{                 // TODO log data                 $  data->setStatus($  e->getCode());             }             $  data->setMessage($  e->getMessage());               //echo "log to monolog";         } catch (\TypeError $  error) {             // TODO log data             $  data->setStatus(404);             $  data->setMessage(new Response("Invalid dependency: {$  error->getMessage()}"));             die(print_r(new Response("Invalid dependency: {$  error->getMessage()}")));         }           // Check if json in array from         if(!empty($  data->getData())){             $  response = new JsonResponse($  data->getData());         }else{             // Not json             $  response = new Response;         }           //Set custom headers         $  response->setStatusCode(             (int)$  data->getStatus(),             empty($  data->getMessage()) ? $  data->getMessage() : null             );           // preflighted request handle         if($  request->getMethod() === 'OPTIONS'){             // set status             $  response->setStatusCode((int)200);         }           // headers         $  response->headers->set('Access-Control-Allow-Origin', '*');         $  response->headers->set('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS,POST,PUT,DELETE');         $  response->headers->set('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');         $  response->headers->set('Access-Control-Allow-Credentials', 'true');         $  response->headers->set("Access-Control-Max-Age", "1728000");           // return response         $  response->send();           return $  response;     }  } 

Kernel.php

<?php class Kernel {      protected $  env;      public function __construct($  env = null)     {         if (is_null($  env)) {             $  this->env = is_null($  env) ? 'prod' : 'dev';         }else{             $  this->env = $  env;         }     }      /**      * Loads the container configuration.      */     public function registerContainerConfiguration()     {         if((string)$  this->env === (string)'dev'){             $  configuration = 'config-development.yml';         }else{             $  configuration = 'config-production.yml';         }         return $  configuration;     }  } 

WorkoutController.php

<?php class WorkoutController extends Controller {       private $  workoutService;     private $  workoutMapp;       public function __construct(WorkoutService $  workoutService, WorkoutMapp $  workoutMapp){          $  this->workoutService = $  workoutService;         $  this->workoutMapp = $  workoutMapp;          // construct the parent         parent::__construct();     }       /**      * Get workout      * Get workouts by id      * Get workout list      *       * @param Request $  request      * @return ResponseBootstrap      */     public function get(Request $  request):ResponseBootstrap     {         $  workout = $  this->workoutMapp->getWorkoutUniversal($  request);          // list         if(!is_null($  workout->getOffset()) && !is_null($  workout->getLimit()) && !is_null($  workout->getState())){             return $  this->workoutService->getWorkoutList($  workout);         }         // get workout by id         if($  workout->getId() && $  workout->getState()){             return $  this->workoutService->getWorkout($  workout);         }         // get workout ids         if($  workout->getIds()){             return $  this->workoutService->getWorkoutIds($  workout);         }           return $  this->badRequest();     }       /**      * Create workout      *       * @param Request $  request      * @return ResponseBootstrap      */     public function post(Request $  request)     {         // raw data         $  data = json_decode($  request->getContent(), true);         // map raw data to workout object         $  workout = $  this->workoutMapp->addWorkout($  data);           // check if the name, description, tags and rounds are not empty         if(!empty($  workout->getNames()->toArray()) && !empty($  workout->getDescriptions()->toArray()) && !empty($  workout->getTags()->toArray()) && !empty($  workout->getRounds()->toArray())){             return $  this->workoutService->addWorkout($  workout);         }          // when empty return a response from the base controller         return $  this->badRequest();     } .... 

WorkoutService.php

<?php class WorkoutService extends Service {      ......      /**      * Add Workout      *       * @param Workout $  workout      * @return ResponseBootstrap      */     public function addWorkout(Workout $  workout):ResponseBootstrap     {                                // middleware for handling cashing         $  this->createWorkoutMiddleware->handle(             $  this->addWorkoutDomain,              $  workout,              $  this->getWorkoutDomain);          return $  this->formResponse($  workout, true);     }       /**      * Delete Workout      *       * @param Workout $  workout      * @return ResponseBootstrap      */     public function deleteWorkout(Workout $  workout):ResponseBootstrap     {                 // middleware for handling cashing         $  this->deleteWorkoutMiddleware->handle(             $  this->deleteWorkoutDomain,             $  workout);          return $  this->formResponse($  workout, false);     }       /**      * Edit Workout      *       * @param Workout $  workout      * @return ResponseBootstrap      */     public function editWorkout(Workout $  workout):ResponseBootstrap     {                 // middleware for handling cashing         $  this->editWorkoutMiddleware->handle(             $  this->editWorkoutDomain,             $  workout,             $  this->getWorkoutDomain);          return $  this->formResponse($  workout, false);     } 

WorkoutRepository.php

<?php     class WorkoutRepository implements CanPersistWorkout {      private $  mapperFactory;     private $  list = [         Workout::class => WorkoutBase::class,         Round::class => WorkoutRound::class,         Name::class => WorkoutName::class,         Version::class => VersionMapper::class,         Description::class => WorkoutDescription::class,         Tag::class => WorkoutTag::class,         RoundCollection::class => WorkoutRound::class,         NameCollection::class => WorkoutName::class,         DescriptionCollection::class => WorkoutDescription::class,         TagCollection::class => WorkoutTag::class,         WorkoutListCollection::class => WorkoutListMapper::class     ];       public function __construct(CanCreateMapper $  mapperFactory)     {         $  this->mapperFactory = $  mapperFactory;     }       /*********************************************************************************************/     /************************************     Store         **************************************/     /*********************************************************************************************/       public function storeDescription(Description $  description, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  description), $  override);         $  mapper->store($  description);     }       public function storeBase(Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  workout), $  override);         $  mapper->store($  workout);     }       public function storeRound(Round $  round, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  round), $  override);         $  mapper->store($  round);     }       public function storeName(Name $  name, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  name), $  override);         $  mapper->store($  name);     }       public function versionUp(Version $  version, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  version), $  override);         $  mapper->versionUp($  version);     }      public function storeTag(Tag $  tag, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  tag), $  override);         $  mapper->store($  tag);     }       /*********************************************************************************************/     /************************************     Delete        **************************************/     /*********************************************************************************************/       public function deleteWorkout(Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  workout), $  override);         $  mapper->delete($  workout);     }       public function deleteRounds(Round $  round, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  round), $  override);         $  mapper->delete($  round,$  workout);     }       public function deleteDescriptions(Description $  description, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  description), $  override);         $  mapper->delete($  description,$  workout);     }       public function deleteNames(Name $  name, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  name), $  override);         $  mapper->delete($  name,$  workout);     }       public function deleteTags(Tag $  tag, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  tag), $  override);         $  mapper->delete($  tag,$  workout);     }       /*********************************************************************************************/     /************************************     Fetch         **************************************/     /*********************************************************************************************/       public function getDescriptions(DescriptionCollection $  description, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  description), $  override);         $  mapper->fetch($  description, $  workout);     }       public function getRounds(RoundCollection $  round, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  round), $  override);         $  mapper->fetch($  round, $  workout);     }       public function getNames(NameCollection $  name, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  name), $  override);         $  mapper->fetch($  name,$  workout);     }       public function getWorkout(Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  workout), $  override);         $  mapper->fetch($  workout);     }       public function getTags(TagCollection $  tag, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  tag), $  override);         $  mapper->fetch($  tag, $  workout);     }       public function getWorkoutList(WorkoutListCollection $  list, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  list), $  override);         $  mapper->fetch($  list, $  workout);     }       public function getTotalWorkotus(Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  workout), $  override);         $  mapper->total($  workout);     }        /*********************************************************************************************/     /***********************************     Update   ********************************************/     /*********************************************************************************************/       public function updateNameState(NameCollection $  name, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  name), $  override);         $  mapper->update($  name, $  workout);     }       public function updateRoundState(RoundCollection $  round, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  round), $  override);         $  mapper->update($  round,$  workout);     }       public function updateBaseState(Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  workout), $  override);         $  mapper->update($  workout);     }       public function updateDescriptionState(DescriptionCollection $  description, Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  description), $  override);         $  mapper->update($  description,$  workout);     }       /*********************************************************************************************/     /***********************************     Audit    ********************************************/     /*********************************************************************************************/       public function auditRound(Round $  round,Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  round), $  override);         $  mapper->storeToAudit($  round, $  workout);     }       public function auditDescription(Description $  description,Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  description), $  override);         $  mapper->storeToAudit($  description, $  workout);     }       public function auditBase(Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  workout), $  override);         $  mapper->storeToAudit($  workout);     }       public function auditName(Name $  name,Workout $  workout, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  name), $  override);         $  mapper->storeToAudit($  name,$  workout);     }       /*********************************************************************************************/     /***********************************    Helpers   ********************************************/     /*********************************************************************************************/       public function begginTransaction()     {         $  mapper = $  this->mapperFactory->create(WorkoutBase::class);         $  mapper->begginTransaction();     }       public function commitTransaction()     {         $  mapper = $  this->mapperFactory->create(WorkoutBase::class);         $  mapper->commit();     }       private function computeKey(string $  key, string $  override = null): string     {         if ($  override !== null) {             $  key = $  override;         }         if (array_key_exists($  key, $  this->list) === false) {             throw new \RuntimeException("No mapper for class '{$  key}' has been defined!");         }         return $  key;     }       private function retrieveMapper(string $  name, string $  override = null)     {         $  key = $  this->computeKey($  name, $  override);         $  entry = $  this->list[$  key];         return $  this->mapperFactory->create($  entry);     }        public function define(string $  entity, string $  mapper)     {         if (class_exists($  entity) === false) {             throw new \RuntimeException("Entity class '{$  entity}' was not found!");         }         if (class_exists($  mapper) === false) {             throw new \RuntimeException("Mapper class '{$  mapper}' was not found!");         }         $  this->list[$  entity] = $  mapper;     }       public function load($  identity, string $  override = null)     {         $  mapper = $  this->retrieveMapper(get_class($  identity), $  override);         $  mapper->fetch($  identity);     }   } 

VersionMapper.php

<?php     class VersionMapper extends DataMapper {       /**      * Version Up      *       * @param Version $  version      */     public function versionUp(Version $  version) // TODO handle exceptions     {         $  sql = "INSERT INTO version VALUES(null)";         $  statement = $  this->connection->prepare($  sql);         $  statement->execute();          $  version->setVersion($  this->connection->lastInsertId());     }   } 

AddWorkoutDomain.php

<?php     class AddWorkoutDomain {       private $  repository;       public function __construct(Repository $  repository)     {         $  this->repository = $  repository;     }       /*********************************************************************************************/     /*****************************    Visible functions to children ******************************/     /*********************************************************************************************/       /**      * Handle       *       * @param Workout $  workout      * @return array      */     public function handle(Workout $  workout):array     {         // beggin transaction         $  this->repository->begginTransaction();          $  messages = [];          $  messages = array_merge($  messages, $  this->storeBase($  workout));         $  messages = array_merge($  messages, $  this->storeNames($  workout));         $  messages = array_merge($  messages, $  this->storeDescriptions($  workout));         $  messages = array_merge($  messages, $  this->storeRounds($  workout));         $  messages = array_merge($  messages, $  this->storeTags($  workout));          // commit transaction         $  this->repository->commitTransaction();          return $  messages;     }       /**      * Get Total      *       * @param Workout $  workout      */     public function getTotal(Workout $  workout):void     {         $  this->repository->getTotalWorkotus($  workout);     }       /*********************************************************************************************/     /*************************************  Executors   ******************************************/     /*********************************************************************************************/       /**      * Store Base      *       * @param Workout $  workout      * @return array      */     private function storeBase(Workout $  workout):array     {                 // version up         $  workout->setVersion($  this->versionUp()->getVersion());         $  workout->setState('P');          $  this->repository->storeBase($  workout);          return ['success'=>'Base'];     }       /**      * Store Names      *       * @param Workout $  workout      * @return array      */     private function storeNames(Workout $  workout):array     {         foreach($  workout->getNames()->toArray() as $  name){             // set workout parent             $  name->setParent($  workout->getId());             $  name->setState('P');              $  this->repository->storeName($  name);         }          return ['success'=>'Names'];     }       /**      * Store Descriptions      *       * @param Workout $  workout      * @return array      */     private function storeDescriptions(Workout $  workout):array     {         foreach($  workout->getDescriptions()->toArray() as $  description){             // set workout parent             $  description->setParent($  workout->getId());             $  description->setState('P');              $  this->repository->storeDescription($  description);         }          return ['success'=>'Descriptions'];     }       /**      * Store Rounds      *       * @param Workout $  workout      * @return array      */     private function storeRounds(Workout $  workout):array     {         foreach($  workout->getRounds()->toArray() as $  round){             // set workout parent             $  round->setParent($  workout->getId());             $  round->setState('P');              $  this->repository->storeRound($  round);         }          return ['success'=>'Rounds'];     }       /**      * Store Tags      *       * @param Workout $  workout      * @return array      */     private function storeTags(Workout $  workout):array     {         foreach($  workout->getTags()->toArray() as $  tag){             // set workout parent             $  tag->setParent($  workout->getId());              $  this->repository->storeTag($  tag);         }          return ['success'=>'Rounds'];     }       /**      * Version Up      *       * @return Version      */     private function versionUp():Version     {         $  version = new Version();         $  this->repository->versionUp($  version);          return $  version;     }   } 

Any comment and advice are welcome, I’m seeking to expand my knowledge.

Is it possbile to avoiding writing router codes twice when developing web SPA app?

When developing web SPA I always need to write router codes twice, one in server side, be it nodejs/express or php/laravel, one in client side, e.g vue router.

Of course these 2 router codes are not same, but the router logic is largely duplicated. So is there anyway to avoid that ?

Microservices communication: Avoiding single point of failure

As far as I know, there are two commonly used patterns when dealing with services communication in a microservices architecture:

  1. Direct-calling other services. For example: Service A handles some data, then it needs to tell Service B to do something with that data. A knows B‘s endpoint URL and calls it directly.
  2. Using a bus (commonly a Message Queue) to dispatch messages which will be picked up by the single microservices. For example: A will send a message on a common queue, B will receive it and will know what to do.

Both have downsides:

  • Direct-calling other services leads to tight coupling services to other services. If you change service B, you’ll likely need to adapt and re-deploy also all other services that interact with B.
  • Using a bus is cool because you don’t need to know which service will be able to handle the request, but if the MQ fails for whatever reason it will become the single point of failure of the entire system.

So, what is the preferred way of managing service communications?

Do we have alternatives which can reduce failures and avoid tight-coupling between microservices?

puppet code design: how to collect arguments into a string (avoiding possible duplicate declaration errros)

I’m having trouble with puppet (version 5.5) code design. I’ve written a component module to deal with ucarp. It make use of the module eyp-systemd to register an ucarp service within systemd. Now I would like to consume the ucarp module from two independant profile modules that manage different services (in my case actually haproxy and bind9). Essentially this looks like this:

class ucarp {   systemd::service { 'ucarp':     /* list of parameters */   } }  define ucarp::vip {   /* defines a virtual IP to be shared among several nodes */ }  /* ==================== */  class profile_haproxy {   include ::ucarp   ::ucarp::vip { 'haproxy': }   /* setup haproxy */ }  /* ===================== */  class profile_bind9 {   include ::ucarp   ::ucarp::vip { 'bind9': }   /* setup bind9 */ } 

This is straight forward and works well.

Now the actual issue: it is best practice to order the ucarp service after the services that are run over ucarp. This is possible using the after parameter:

class ucarp(   Array[String] $  after, ) {   systemd::service { 'ucarp':     after => $  after.join(' '),     /* list of other parameters */   } } 

This requires replacement of include ::ucarp by

class { ::ucarp:   after => ['haproxy'], } 

or

class { ::ucarp:   after => ['bind9'], } 

respectively. Of course this would immediately lead to a “duplicate declaration” error.

What I actually would like to have is a single instantiation of the class ucarp that collects all after parameters into one single string that can be passed to systemd::service. How would I do this?

Currently two possible solutions come to my mind:

  1. Fork eyp-systemd, remove the after parameter and replace it by a defined type, e.g. systemd::service::after. Internally the module then collects all instantes of systemd::service::after and all other information it needs into the resulting service declaration using richardc-datacat. This is something I really don’t want to do. Generally I shy away from modifying forge modules as I this forces me to maintain it on my own. In this case the introduction of datacat also seems like a major rewrite of the module.
  2. Introduce my own defined type in the ucarp module ucarp::order_after which does not do anyhing. The profile modules would define virtual instances of this type. The ucarp class could then use a puppetdb query to collect all instances of ucarp::order_after. The big drawback here is that I’m only dealing with virtual resources not with exported resources. So actually there is no need at all to involve puppetdb. So this would be an ugly work-around that forces me to always operate a puppetdb.

I hope there are other possibilities I can’t think of right now.

Role of weak entities in avoiding inconsistencies

My material on database claims that:

Weak entities help to avoid data duplication and inconsistencies arising due to duplicating the key of the strong entity.

My question is how can a strong entity key even be duplicated? This would make the key lose its uniqueness property.

Can anyone please help? How is the statement provided in the material justified?

Thanks in advance!

Avoiding the race condition between time of release and time of update

There is a kind of race condition between the time when a developer releases a security update and the time when the security update is actually applied by the user. In the meantime, an attacker will be able to learn about the vulnerability and attack a system that hasn’t been patched yet. Can this problem be avoided completely? If not, what are the best practices for mitigating it at much as possible?

This might not sound like a huge problem in some cases, for example when the patch is for a complex issue that is difficult to exploit, especially when the software is closed-source. In that case, an attacker will need several days to develop an exploit, and the user has enough time to update the system. But in other cases the effects of this race condition are actually disastrous. Imagine the following commit in an open-source project on GitHub:

- echo '<span>' . $  username . '</span>'; // line removed + echo '<span>' . htmlspecialchars($  username) . '</span>'; // line added 

That’s obviously a fix for a persistent XSS vulnerability. Even supposing that the security update is publicly released only an hour after that commit, and that the user is going to do the update only an hour after it’s been released (which is totally unrealistic), this would result in a two-hour window for a vulnerability that even an inexperienced attacker would be able to exploit in one minute. For very popular software, it’s not uncommon for automated attacks to start only a few hours after a security update has been released, or worse sometimes even shortly before the official release.

So what can be done to completely avoid or partially mitigate this race condition? What are the best practices used by vendors and customers who are serious about the security of their systems? Here are a few possible solutions that I thought of:

  • Don’t make the source code readily available, maybe by compiling or obfuscating it. This is what is often done for proprietary software. I suppose Microsoft relies on the fact that reverse-engineering their patches will take time, and in the meantime all users will be able to do the updates.
  • Don’t advertise security fixes. Just fix and release, without telling anybody that you have fixed anything, or leave any hints anywhere. This might delay the attacks, but might also delay the updates because the users might think “it doesn’t sound important, I’ll update it later”.
  • Force automatic patches for security bugs. Systems will be patched automatically as soon as possible and before making any public announcements or giving any security advisories, only fixing security issues and nothing else to avoid breaking any functionalities. This sounds like a good idea, provided that all systems are patched almost at once, in a short time frame. WordPress does something like this by default for its core, but I don’t know how long it takes to update all the installations (there are millions of them).
  • Rely on the services of a security company to stay ahead of the attackers. There are security companies that claim to monitor a variety of things just like an attacker would do (detect and investigate new attacks, check official advisories, even gather information from blackhat communities, etc.), and help you stay ahead of the attackers with special advisories, web firewalls, etc. This seems to be another popular solution, except it doesn’t really solve the race problem, it’s just trying to race faster. Also, this solution might help with popular software, but I guess it’s hard to find services that can help with less common applications.

I can’t think of anything else right now.

Avoiding copying and pasting text by using Microsoft Outlook or a third-party web app?

I was wondering if there was tool available that would automate copying and pasting form emails from a Word document into another program (Salesforce comments).

I envision something where a user could drag a button and it would copy text with it into a new field.

To explain, I am helping a low-tech savvy, resource-strapped team avoid copying and pasting form emails. They currently use a Microsoft Word document with over fifty messages that they copy and paste into a separate program. As you can imagine, there is a lot of scrolling and searching for the right message depending on circumstance, not to mention room for human error with the copying and pasting.

We are looking to automate this in some way and would love some suggestions.

How to install latest version of Okular on Ubuntu 14.04 (avoiding source install)?

Is there a way to install Okular in its latest version on Ubuntu 14.04? So far the default Ubuntu repository supports a really old version of Okular (offered by KDE Applications version 4.13.3), as one can confirm by running:

apt-cache show okular | grep Version 

The latest version now is 1.6 (offered by KDE Applications version 18.12.2).

I know that someone can install the latest version from source code (as described in Okular’s official webpage), but I want to avoid that and get an easier way to install.

I have also searched for Ubuntu 14.04 binary repositories on launchpad and I haven’t found Okular in its latest version.

Am I doomed to update to a newer Ubuntu release to get the latest version of Okular, or is there a way to stack with my beloved Ubuntu 14.04 for a little longer before they get deprecated?