2. Who I am
● Senior Software Engineer @ Upwork
● 10+ years of PHP (Pear -> ZF 1 -> Symfony 1 -> Yii 1 -> ....)
● 4+ years of Symfony 2
● Also experience in Java (Spring, GWT, ...), C# (.Net), Ruby (Rails), JS (...)
● KNU, Faculty of Cybernetics, Theory of Programming
3.
4. How to perceive this speech
This speech ...
● … is not a manual
⇒ use Google please!
● … covers some problems of modularity
⇒ it doesn’t cover a lot of stuff.
● … displays some Symfony problems
⇒ but we love Symfony anyway =)
9. Symfony modules
Component is Symfony library.
You need Composer to use Component.
Bundle is Symfony module.
You also need Composer to use Bundle.
But you must enable Bundle in your AppKernel
10. How does Bundle extend our framework?
● Commands
● Controllers
● Public services
○ also tagged services (event listeners, annotation processors etc.)
● Service Container processing
○ add support of custom service tags
○ preconfigure other modules (prepend)
● Other common code and assets (careful!)
11. Symfony 2.x ⇒ 4.x
● Flex
○ Flex is a tool to simplify bundle installation.
● Bundle-less
○ Application is not a bundle
○ Symfony 4.x application directory structure is self-sufficient
13. Specifics of big product companies
● A lot of developer teams
● A lot of code
● A lot of different applications may fit in one project
● “Core” team
14. Example structure of corporate applications
Symfony
Team 1
Application 1
Team 1 library
Team 2
Application 2Common library 1
Common library 2
15. Example problems
● Create a bundle to process some common incoming
HTTP headers
● Make an update of some widely used bundle and make
everyone to upgrade
● Create a bundle with common layouts/assets (careful!)
16. Corporate is not opensource
● We don’t try to create an universal solution
● Bundles can depend on corporate architecture
● Some corporate bundles can go opensource
20. Dependencies
What if one bundle depends on another?
APP Bundle-1 Bundle-3
Team 1 Team 2
Bundle-2
Please add Bundle-3
to your AppKernel
21. Migration
APP Bundle-1 Bundle-3
Team 1 Team 2
Bundle-2
OK! Will try to
add that to the
next sprint
We released
major version of
Bundle-3. Please
update!
22. Coupling and cohesion
High cohesion
= modules must have exact purpose and clear functionality
Low coupling
= modules have to be independent from others
23.
24. SOLID on bundle level
S: Bundle should have single purpose
O: Bundle should provide an API and be protected from external changes
L: Bundle should be a bundle
I: Bundle should not make us use unnecessary features
D: Bundle should depend on APIs (interfaces) instead of other bundles
25. Solution:
create libraries for common interfaces
Depend on libraries in your bundle instead of other bundles
Interfaces rarely break
Example: PSR-3 (logging interface)
26. Service as a dependency
BundleX BundleY
Service-Y2
LibraryZ
InterfaceZ
Service-X1 Service-Y1
27. Service as a dependency - Symfony way
my_chat:
dependencies:
http_client: "my_http.client"
formatter: "html.formatter"
Pass service name to bundle configuration
Note: use “alias” feature to reference a service by a
name
28. Framework-agnostic code
● Your code should be independent from framework
(controllers too)
● But bundles still depend on Symfony (bundles extend
your framework)
30. Dependency hell
● Great amount of dependencies
● Great amount of consumers of your dependency
○ Hard to ask all consumers to update ASAP
● Lack of proper versioning
○ Legacy code
● Requirement of a different major versions of the same
dependency
● Dependencies created by different teams using
different approaches
31. Dependency hell - Best practices
● KISS
● Work hard if you want to create a shared library
● Implement versioning ASAP
● Provide style guidelines
32. Listeners
● Listener priority
○ Example: what is the priority of a security listener?
○ How to ensure that your listener will be the first one?
○ Conflict of listeners order at the same priority
● Standard “kernel” events vs own dispatchers
● How to disable a listener?
○ master/slave requests
○ by condition from another listeners
● How to be sure that listener processed an event?
33. Listeners - Best practices
● Avoid listeners (if you can)
○ lazy initialization
○ explicit pipelines
○ before/after
● Final listeners
● Provide exact API
○ define priority value
34. Assets & Twig
● Assetic
○ Removed for Symfony 4
○ Webpack Encore doesn’t do the same stuff
● Twig
○ Static HTML code(templates) depends on your JS/CSS framework
○ Hard to manage SSR and CSR
○ You still need another templating engine for JS
● Asset management
○ npm vs composer
○ Is Encore useful?
35. Assets & Twig - Best practices
● Don’t provide assets by bundles
● Avoid using of templates by bundles
● Move common static web stuff to separate project
(under npm)
37. Bundle testing - Best practices
public function testMyBundle()
{
$container = $this->createContainer();
$container->registerExtension(new MyExtension());
$container->loadFromExtension('my', []);
$container->compile();
$this->assertTrue(is_a(
$container->getDefinition('my.service')->getClass(),
MyInterface::class,
true
));
}
38. Other funny complications with bundles
● Register a route from a bundle
● A/B testing and graceful feature delivery
● Advanced bundle configuration processing
○ Type check
○ What about compile time validation?
● Optional dependencies
● What is “bundle API”? Can we define it well?
● Common application configuration
● ...
40. So where are we now?
● Modules (bundles) is a good way to extend a framework
- Now we know how to use them well
- Now we know the difference between modules and libraries
● Complications
- We know the complications that may appear when project grows
- We will try to avoid complications on early stage
41. What about Symfony
● Symfony is not an ideal framework
- But still the best one (for PHP)
- It’s made by people (not gods)
- It can be improved
- Now we can see parts that can be improved