2
votes

I started using and testing Symfony 4 for main project migration. I was used to getting told by Symfony on how files should be structured, but now when there are no more bundles, I wonder, how to structure huge monolith application.

Scale now: ~300 routes, ~70 controllers, ~90 entities, ~20 bundles

How services.yaml should look like? - should I stay on App namespace or maybe I could simulate bundles? Where to put service configuration for each component?

How services and controllers should be separated in directories? - Should I go for src/Service/{Something}/{Something}Manager.php or stay on src/{Something}/Service/{Something}Manager.php and just don't use Bundle keyword? Why?

Where would you put UserAuthenticationProvider and/or WebSocketServer?

2

2 Answers

4
votes

I've made a new set of REST APIs for a legacy monolith application and faced the same questions.

I will answer this question first: How services and controllers should be separated in directories?

I went down the src/Service/{Something}/{Something}Manager.php path as I thought that that was the way. As the project has grown, I regret that and will be moving to src/{Something}/Service/{Something}Manager.php

Why?

  1. I find the separation in namespacing much easier to read and much harder to accidentally use the wrong class.
  2. I now have files split out across the application and it's much harder to abstract it into a library that can be re-used by other applications.
  3. I can't refactor functionality as easily - everything is spread out an intertwined. If I were converting a monolith, I would prefer to have code to refactor that was bound by some function so I could work on that, before moving to the next.

There are other reasons but feel the need to separate this back out before the application gets any larger.

How services.yaml should look like? Well, the autowiring is amazing. I would keep your service yamls in the various functional splits (as above) and start refactoring them out. With the default autowiring config, you'll find that very little needs explicit definitions.

Where would you put UserAuthenticationProvider and/or WebSocketServer?

For the provider, probably something like, src/Security/Authentication/Provider/UserAuthenticationProvider.php.

For the WS server, I'm not really sure - it depends where it sits in the app and how it's used.

1
votes

To start with, S4 still supports bundles pretty much as before. The config section has been reorganized a bit but if you already have a huge app working under bundles then you might just consider keeping it more or less as is. It should still work just fine with minimal tweaking.

There are a couple of approaches for a bundle-less app. Typically you would group files by functions using feature sub-directories to keep things organized.

Assume you have three existing bundles called FooBundle, BarBundle, JarBundle

config
    services
        foo.yaml
        bar.yaml
        jar.yaml
    routes:
        foo.yaml
        bar.yaml
        jar.yaml
src
    Controller
        Foo
           Foo1Controller
           Foo2Controller
        Bar
           etc
    Entity
        Foo
            foo entities
        Bar
            bar entities
    Form
        etc
templates
    foo
    bar
    jar

You get the idea. Might be worth modeling this all out in advance especially to see where the odds and ends might fit. And probably use the App namespace for everything. This approach pretty much follows the Symfony 4 best practices. Can't really go to far wrong with it.

There is at least one other approach in which you group files by features. I won't go into much detail as it's definitely not the normal Symfony approach and will take some tweaking. But you could do:

src
    Blog
        routes.yaml
        services.yaml
        BlogEntity.php
        BlogVoter.php
        Edit
            BlogEditController.php
            BlogEditForm.php
            BlogEditTemplate.html.twig
            etc
        Show
            BlogShowController.php
            etc