R
R
Roman2016-08-18 05:31:59
symfony
Roman, 2016-08-18 05:31:59

A project with complex logic in Symfony - how to design? Examples?

Hello!
NOTE: I immediately apologize for the long post .
I'm starting to design a new project that will:
* A lot of weird/complicated logic (like "when the fifth planet is in the Sirian phase on the sixth day from the seventh Wednesday after the 42nd week of a leap year, but only if that post is not older than weeks"), in which there can be more than one level of criteria for the state of something. However, the External API is a bit more complex than typical CRUD.
* Access levels for user groups (which can be created through the admin panel) down to every parameter of some business models. For example: "On this table, that column can only be seen by such and such groups of users."
* Many additional automatic actions when performing any action like "when changing the value in this cell of this table, do this, that, fifth, tenth and compote." Chains can be long and deep enough not to remember them without arming yourself with TK. Many of them should be deferred or asynchronous because they can be heavy.
* The main work is with external services via API, with duplication of some services at the level of business logic such as "If service1 fell off when performing an action, try services 2,3,...,100500 until it works, in such and such an order for such- then the criterion.
* Longevity of the project - and support, and finishing the logic, which cannot be foreseen now. For years.
* The project will be an API - no templates / layout / front are supposed to be there. More precisely, it will be, but a separate project, perhaps in Angular.
As a framework, I'm going to take Symfony - I haven't had a chance to work with it yet, but judging by their book, it seems that I won't need to struggle with it in this type of project.
More to the questions.
So that everything does not turn into very fat models - the repository is separate, the models are separate (Doctrine, I read it, it can - you don’t need to reinvent the wheel). How to store business logic so that models do not turn into monsters of tens of thousands of lines? I read about the Command Bus where, if I understood correctly, each action in the system has its own class? How do you organize them (there will be hundreds of them then)?
Does it make sense to take each domain model into a module/microservice , store all the related logic somewhere inside, and communicate with the rest via an external API? For answers to the client side - a separate front-end service? What is an overhead? Is this used in practice? What are the pitfalls?
Previously, for additional actions, it was enough for me to use something like beforeUpdate / afterCreatemodels. Now these methods run the risk of becoming gigantic and very complex, even if the logical pieces are taken out into separate methods. In addition, many of them will be placed in the task queue (in rabbitmq, for example) and processed asynchronously. But some don't, and in some cases the order in which the hooks are executed will be very important. How not to turn throwing/receiving events like PostBeforeEdit/PostBeforeEditHandler into "callback hell" ? In one similar project, I saw this (however, on js) - with each click, you never know how many dozens of actions will occur, even armed with a debugger. It would be nice to keep the config of such logic human-readable and in one place - how do you solve it?
ACL. Where do you store the specified logic? The grid is supposed to be stored in the database and cached. What are the structures for the above - best practice? In my understanding, it looks like a bunch of three-dimensional "crud - group - entity - field" access cubes, how to make it flatter so far only one idea is to make a bunch of many-to-many tables. But it seems to me that working with these "joins" on each request will be the second bottleneck after external api.
Versioning . How do you version projects like this? And if you need "N-1" working version in production? Now I store them in different git branches and deploy them separately. Does it make sense to separate versions within a single project codebase and how (namespaces, config, module, something else)?
And most importantly– how to combine all this? Separately, the above has already been applied in practice. But it doesn't fit in my head all at once. What projects (more precisely, on the code) can you advise to look at for a better understanding? Links to repositories ?
Thanks in advance to those who will master the long post, share their experience and, perhaps, send an example to the code of such a project.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
I
index0h, 2016-08-18
@TrogWarZ

How to store business logic so that models do not turn into monsters of tens of thousands of lines?

It's not exactly a model. Entity is just a data object, it can store them in itself and throw exceptions if you insert the wrong data, that's all. Repository - can work with its Entity AND database.
BL is in service classes.
In general, for each action - not necessarily, here you need to be guided by common sense.
Hierarchically. The classpath must be "understandable".
Only if you have already done the same projects and know exactly the boundaries of each domain as accurately as possible. Otherwise, it's not worth it. Make a monolithic system, and division into microservices - only when necessary.
If in "service" you put the concept of a simple class that can format the responses of your project - the idea is sound.
If the responses are asynchronous (from the server to another), it makes sense to put them in a separate client class.
Negligible.
Yes
In any case, the consequence of a serious decomposition will be extra entities, the sooner you get rid of them, the better.
If it is possible to abandon the event model, it is often better to refuse.
Listner doctrine is certainly a powerful thing, but it does not always work clearly.
The "PostBeforeEdit/PostBeforeEditHandler" functionality is often cheaper and easier to put into a service, but again use common sense.
If the ACL is not trivial, prepare yourself for the fact that it will be spread across the controller level.
If it is possible to bring it to a single-level view - do it. If, from a business point of view, a hierarchical (not fixed nesting) ACL may be required - convince yourself to the last that this is a bad idea, do not repeat other people's mistakes.
Flexible configuration up to each field 90% that is not needed. If you can reduce it to the concept of scopes of rights, do it.
The structure can only be proposed knowing your project.
Semver.
So your version with the "N-1" tag gets on sale))
Store eggs in separate baskets. If the module is developed completely separately and can be taken out as a project dependency in the vendor - do it.
  • USE COMMON SENSE
  • Accept strict conventions on coding rules, such as :
  • Try to convince the business that without code coverage by automated tests it will be more expensive, unstable and longer. + Write tests. If the volume of tests is 4 times more than the code they test, this is normal. I had cases when there were ~16 times more tests for critical functionality than code.
  • Rigid, obligatory code reviews.
  • If the task is large, decompose it.
  • Technical debt - be sure to return AND as soon as possible.
  • Before writing code to work with an external service, it makes sense to write its emulator.
  • Hurry only in case of serious problems on the sale)). Features "for yesterday" differ from features "for later" only in the priority of execution, nothing more.

A
Adamos, 2016-08-18
@Adamos

> a way to flatten the inheritance of groups like "manager can do everything that customer can do, but also this and that"? Is it more reasonable and more supported to duplicate all rights?
IMHO, all these troubles with the inheritance of groups are needed only for ease of administration. And their place is in the admin panel, not in groups. Make convenient editing of groups, with comparison with another group. Or templates that allow the user to apply several groups at once. Even more complex things like the fact that a group of managers cannot be applied in isolation from the customers.
But all this is not in groups, but in this section of the admin panel. Groups are assigned not as often as they are used. But for use they should be as simple as possible.

U
usr58, 2016-08-18
@usr58

https://github.com/akeneo/pim-community-dev
https://github.com/Sylius/Sylius
https://github.com/orocrm
https://github.com/orocommerce

S
saritskiy, 2016-08-19
@saritskiy

In order not to smear ACLs and not to increase the sizes of controllers to insane size, take a look at the aspects. https://github.com/goaop/goaop-symfony-bundle. Regarding the fact that you constantly have to pull some data and constantly recalculate them, etc., I advise you to look in the direction of the tarantula. Highly loaded services like Badoo and Mail.ru store user sessions and other hot information in it.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question