Dietro le quinte di Tom's Hardware
ECCENTRIC DEVELOPER
Oscar Fanelli
Engineering Manager
Zend Framework / Symfony
Doctrine
ReactJS
Docker
PhpStorm
Faccio cose
Conosco gente
Stringo mani
Pigio sulla tastiera
Infrastructure
(italian) Legal limitations
Provider
Cache
- Varnish
- Application is not touched
- No bottlenecks
- Efficient
- Plain
- Redis
- Customizable
- Scalable
- Scales third party services' requests
- Database relief
Cloudflare
- DDOS attacks
- Assets CDN
- Redirects
- HTTPS
Deploy
- VPN
- Zero downtime
- ... (the heaven) ...
- Rollback
- Flush cache
- One-line command
Actors
Actors
- CEO
- COO
- Director
- Provider
- SEO
- Designer
- Editors
- Sales
- Video-makers
- Purch
- Lawyer
- Google / Facebook
- Forum Manager
- Forum Moderators
- Blog authors
- Partner
- USERS
Third-party Services
Third-party services
$$$
ADV
$$$
AD placements
Back-office AD tools
AD placements
"The Coalition for Better Ads will leverage consumer insights and cross-industry expertise to develop and implement new global standards for online advertising that address consumer expectations."
Merchant
$$$
AdBlock
$$$
About AdBlock
- ~60% of users use AdBlock
- Let the user use AdBlock without any warning
Custom anti-AdBlock strategy
- Code injected on render (no JS async call)
- Dynamic CSS classes
- Unpredictable CSS classes
- CSS style injected on the same page
Back-office
Golden rules
- Things will change, very fast: be prepared
- Standardize UI (use fxxxxxg Bootstrap)
- MUST be easy to:
- Add/edit/remove fields on Entities
- Add/edit/remove fields on forms
- Add/remove CRUD Entities' panels
- Listen to who will use it
- Identify common flows and optimise the navigation
- Avoid internal stats (if you are not sure about them)
{The Code}
w(h)ell yes, sometimes we write some lines of code
SEO
TTFB and more
- Speed is SEO-friendly
- ~70% users use mobile connection
- Lazy loading
- If you can't optimise speed, at least optimise cache
Third-party JS
Third-party JS
- Server-side rendering
- Prefer GTM/Segment.io integration
- Time spent with the partner's tech team is well spent
Traits
- Dirty stuff
- Don't use traits
- BUT if you really need them, USE them
/**
* An Entity that implement VisitableTrait has a visit counter
* Needed an additional implementation of the job in the ControllerFactory and in the Controller
*/
trait VisitableTrait
{
/**
* @ORM\Column(type="integer")
* @var int
*/
protected $visits = 0;
public function visit()
{
$this->visits++;
}
/**
* @return int
*/
public function getVisits()
{
return $this->visits;
}
/**
* @param int $visits
*/
public function setVisits($visits)
{
$this->visits = $visits;
}
}
Interfaces
- Spread standards around your team
- Avoid common mistakes
- Do not replace docs
- If you can't init with them, at least implement them later
Golden rules
- Things will change, very fast: be prepared
- Standardize UI (use fxxxxxg Bootstrap)
-
MUST be easy to:
- Add/edit/remove fields on Entities
- Add/edit/remove fields on forms
- Add/remove CRUD Entities' panels
- Listen to who will use it
- Identify common flows and optimise the navigation
- Avoid internal stats (if you are not sure about them)
Back-office
DRY
- Help your team
- You are forced to create a well-structured codebase
- If you have to be quick, at least use traits
Dependency Injection
- More reusable code
- More readable code
- Easy unit-testing
class ContentControllerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $controllerManager)
{
$parentLocator = $controllerManager->getServiceLocator();
/** @var EntityManager $em */
$em = $parentLocator->get('Doctrine\ORM\EntityManager');
/** @var ContentService $contentService */
$contentService = $parentLocator->get('Toms\Service\ContentService');
/** @var ContentViewService $contentViewService */
$contentViewService = $parentLocator->get('Toms\Service\ContentViewService');
/** @var EmailService $emailService */
$emailService = $parentLocator->get('Toms\Service\EmailService');
return new Controller($em, $contentService, $contentViewService, $emailService);
}
}
/**
* @param EntityManager $em
* @param ContentService $contentService
* @param ContentViewService $contentViewService
* @param EmailService $emailService
*/
public function __construct(EntityManager $em, ContentService $contentService, ContentViewService $contentViewService, EmailService $emailService)
{
parent::__construct($em);
$this->contentService = $contentService;
$this->contentViewService = $contentViewService;
$this->emailService = $emailService;
}
Configuration files
- Readable
- Easy to understand by your team and the future-you
- Easy to find
- Feature toggling
Feature toggling
- PHP Entity
- Redis
- Configuration file
"Rilasciare funzionalità in modo progressivo"
by Fabio Mora
Assets
- Compile via PHP at runtime
- Use cache
- Do not version compiled assets
- Avoid watchers
- Hard to maintain
- Cross-OS troubles
RWOverdijk/AssetManager
'filters' => [
'css' => [
['filter' => 'ScssphpFilter'],
getenv('CACHE') && getenv('CACHE_ASSETS')
? ['service' => __NAMESPACE__ . '\Filter\UglifyCssFilter']
: null,
],
'js' => [
getenv('CACHE') && getenv('CACHE_ASSETS')
? ['service' => __NAMESPACE__ . '\Filter\UglifyJsFilter']
: null,
],
],
Queues
- You are lazy, find an easy-to-configure queues service
- Think about a different DB (maybe NoSQL?)
juriansluiman/SlmQueueDoctrine
'job_manager' => [
'factories' => [
'Toms\Job\VisitJob' => 'Toms\JobFactory\VisitJobFactory',
'Toms\Job\ShareOnSocialJob' => 'Toms\JobFactory\ShareOnSocialJobFactory',
'Toms\Job\UpdateEpriceProductJob' => 'Toms\JobFactory\UpdateEpriceProductJobFactory',
],
],
Debug
- Search for a live-debugging strategy
- Don't fxxxxxg edit via FTP
- But if you are in a hurry, at least think about a rollback strategy
Cronjobs
- Every job should be managed by your application
- Version-control
- When you add a cronjob, explicit it in the PR description
Deploy
- Every task should be managed by your application
- No extra actions before/after deploy
- Search for a one-line deploy strategy
- Keep your company updated
- Release notes on Slack
Release notes for lazy guys
- Automatic creation of a PR from develop --> master
- Automatic creation of releases notes based on your diff commits
php public/index.php github create-minor-release
Lesson learned
Learn to lie
can you do it?
For complaints
oscar.fanelli@gmail.com
@nesis
@pensiero
Dietro le quinte di Tom's Hardware
By Oscar Fanelli
Dietro le quinte di Tom's Hardware
- 1,762