The new Symfony Best Practices

Yesterday the initial preview of the new Symfony Best Practices was made available. A document like this is something that the Symfony community has needed. It is a much appreciated effort by those involved in producing this. The existing documentation is great but in order to introduce individual concepts it is necessary to simplify things whether it is the concept being introduced or others to avoid being sidetracked and bogged down in details other than the one at hand.

Symfony is a powerful, flexible framework which favours configuration over convention in general. There are conventions which can be followed in some cases but configured different if you have a particular need to. This means that it can be confusing for those moving from first starting out learning the framework into building applications with it. Faced with a lot of decisions which options should they choose?

The new best practices document does a good job of providing this next step. I have seen a lot of Symfony applications that would have been vastly improved had this guide been followed by those developing it. It has however not been entirely well received by the community with many questioning whether things in it are really best practices.

It was developed not by the community as a whole but by a fairly small group before being released. This in itself has made it difficult for some to accept but it was probably necessary if anything was ever going to be complete given the disagreements about content that would have made developing it openly a torturous process. Those involved in writing it are very well placed to have an in depth knowledge of the framework and a wealth of experience in creating applications with it. The repository for the document is to be opened up soon anyway so this will not be the case as it evolves.

I think there are some changes to it that could have and could continue to avoid some of the controversy and to better explain the purpose of the document. There are plenty of articles on why “best practices” is not a good name for documents like this. I won’t regurgitate them here but it being misleading that they are the one true way to do things and therefore anything else is inferior is a concern. Another is that best implies that there is little room for improvement. Whilst there are disclaimers included early on to say that these are optional and personal opinion a change of name would make this clearer.

The document opens by talking about how Symfony is suitable for a whole range of applications sizes and complexities up to enterprise software. I think this is true but that much of what follows makes a lot of assumptions about the nature of the application being built and only applies in those circumstances. Yes, a lot of applications built with Symfony will be relatively simple, database backed, CRUD applications. However there are many applications that this does not describe. A not inconsiderable number of people are using Symfony to build APIs, perhaps with a separate website frontend using a client side framework to communicate to this API. In that case many of the practices are not relevant or counter productive. Likewise many people do work on applications that communicate with other systems via HTTP clients, message queues and other means. These are not merely fringe cases and dealing with the complexity of multiple and potentially changing data sources is a real day to day issue for many not just an academic concern.

Making it clear that these are guidelines for building a certain type of application and not suitable in all cases would be good improvement in my opinion. Even better would be to provide some guidelines for working on applications outside of this relatively narrow remit. It is when moving past that point that a lot of questions about what approach to take arise in my experience.

In terms of specific content, there is some I disagree with but that is neither here nor there really. I do find that there is currently some confusion in it as to what the priority is. There are always factors pulling in different directions when building an application. Which of these are important depends on the individual application and the context it is being developed in.

Convenience and speed of development are important but can be odds with performance. Making full use of the short cuts and conventions that the framework provides doesn’t always fit well with making sure that it can be understood and maintained by some that lacks that in depth framework specific knowledge. The best practices seem a little muddled on this, param converters are good because they save time and boilerplate code but the @Template annotation is bad because some prior knowledge is needed and there is a performance issue. I don’t see there being much of a difference in the amount of prior knowledge required in each case. The performance issue of @Template may be a concern but depending on the project this may be less of a concern than the amount of developer time it saves.

Rather than single a single one as being the best, it may be better to say which is better for performance, for convenience or for clarity, when these pull in different directions. This still gives a clear recommendation to someone who knows which of these is more important to their application.

There is something I see no reason not to change to improve the perception of this document amongst the existing community and to avoid giving a bad impression to newcomers. That is the use of some unnecessarily inflammatory and opinionated language. The first thing that jumps out and no doubt was what rubbed a lot of people up the wrong way was the second paragraph:

“These community resources – like blog posts or presentations – have created an unofficial set of recommendations for developing Symfony applications. Unfortunately, a lot of these recommendations are in fact wrong.”

If this document is, as it states immediately after this, a subjective opinion then opening by dismissing a huge collective effort from the community as “in fact wrong” seems completely out of place in a document of this nature.

Likewise when talking about decoupling controllers then this does not seem like a calm and measured argument:

“And since your controllers should be thin and contain nothing more than a few lines of glue-code, spending hours trying to decouple them from your framework doesn’t benefit you in the long run. The amount of time wasted isn’t worth the benefit.”

Some people may benefit from doing this and saying that this is wasted time seems unnecessarily antagonistic attack on those with opposing views. The same advice could be presented in a much more neutral way in my opinion. There are better places for strong personal feelings about this topic to be shared.

So to reiterate, I think this is a much needed document and the effort that has gone into getting it to us is much appreciated. I personally think it could benefit from a change of name and some clarity about the nature of the applications it is suitable for. In some places it could be a bit less prescriptive and instead make recommendations based on the application’s needs and context. Longer terms further guidelines that cover some of the wider picture of different application being created with Symfony would be great. However, I do see no reason not to remove some of the more emotional and inflammatory language as soon as possible.

The repository is to be made public so that the community can contribute. I hope that this can be productive and further improve the excellent documentation that Symfony already benefits from.

Some, no doubt unoriginal, thoughts on BDD

BDD is primarily about designing object behaviour and interaction and not about testing. It does however produce a suite of regression tests as a side effect. This has value in allowing us to refactor code knowing that it still behaves as specified.

One issue people have with (T|B)DD is that it then makes it difficult to change things as you have lots of tests/specs to change. If the behaviour is changing then they should change. So is this a red herring? Well not exactly, this only holds true if you use only use them to specify the external behaviour at a boundary. For example, from the DDD world, an aggregate boundary.

If inside that boundary there are multiple objects and how they communicate is essentially an implementation detail then specs for these may well get in the way when refactoring the implementation within that boundary. The behaviour of the objects implementing maybe changing a lot without the external boundary changing.

It seems one view is that you should therefore avoid writing them in the first place and another is that this is the right thing to do and you should just maintain them and live with this. So, does this mean that you should not write these specs in the first place? Do you need to then keep updating these to change the implementation?

Well as Hegel would have it, there is a possible synthesis of these positions. Use specs to design the internal interactions where it helps you but don’t feel obliged to keep these as soon as they becomes a hindrance to improving that implementation later. Keep those that specify the external behaviour but discard those that are no longer helpful. The test suite is a side effect, its not something to be precious about if it gets in the way of the primary use of BDD as a design technique. Don’t throw the baby out with the bathwater though – if that side effect gets in the way don’t avoid the original primary benefit.