
Despite numerous attempts to dissuade me from this undertaking, I still will continue as planned. Every comment of the previous part, I read and heeded. I met both my own wishes of some people and strong recommendations not to turn my own bike. I liked the comments of
ainu and
Fesor , in my opinion - a very constructive view of what is missing in the CMS & Framework for today. For example, the implementation of the task of a quick and easy way to create a blog for a person who is quite difficult to explain how to use it is extremely complex in nature. And since such tasks appear more and more often, I decided to take up this idea closely.
Can you imagine how convenient it is to realize the integration of social networks, the Analytics API and other “sweets” of the current capabilities of the information technology world for the end user? How simple and intuitive can you make an information resource interface? I can continue to describe my ideas and goals for quite a long time, but until this happens, progress is not progressing, which means time is wasted. We will come to all this in the following parts of my series of articles, but for now - on the case.
Project subdirectory hierarchy
')
Very often, working with large projects, I met a huge number of folders containing one or another “vital” component of a working system. What can not be said for example about Django / Symfony. Each of their folders is responsible for its own component that is, to some extent or other, autonomous, initially implying the fulfillment of certain goals. The same can be said about many other frameworks, but now is not about that.
The
engine folder will contain system classes, as well as services providing the execution of a task.
The
module folder includes controllers with a description of routing, configuration files, cache files, and traits.
The
public folder contains files that are supposed to be directly accessed by the client by issuing the server directly. In other words - files for download by users.
The
view folder will contain the themes folder with all the necessary components in the form of cascading styles, scripts, sass sources, pictures and other visible media content.
Architecture
In the last article, I was fascinated by the ignorance of design patterns. In my defense, I can say that design patterns are not appropriate in all situations. For example, using MVC / HMVC, I would easily be able to design a WEB application for PHP. But if you take the same Pattern Facade or Observer, the overall picture is not so obvious, although you can imagine it.
For a more visual explanation of what I want to achieve, I will give an example of the implementation of the authorization of a user in Django (Python):
def auth_controller(request): user = authenticate(username=request.POST['username'], password=request.POST['password']) if user.is_active: login(request, user)
Yes, I omitted many small details, but did not miss the most important thing and I want to achieve. Such things as authorization / registration should be implemented at the time, as the Django development team showed us. If the CMS services are designed using the
Facade pattern , it will be possible to achieve fairly good results. All checks, escapes and validations in this case should take place not in the controller, which I observe quite often, but in the service where the data will be filtered and the result will be reported as soon as the task is completed - to the controller, where the program cycle will continue. Such small things at first glance will ease, speed up and avoid elementary mistakes that we often make because of inattention or ignorance of the input data processing process and the correct task cycle. Therefore, I came to the conclusion that the Facade pattern will be the most correct in terms of the implementation of services of its CMS.
The module itself will be implemented according to a similar principle but with some nuances. Often there is a need to implement an elementary API, which with the use of CMS is a rather cumbersome and complex task, if this is not provided for by the system itself. Therefore, the entry point of each module will be the parent method of the base module, the "
request ", the argument of which will be the object that will contain the means for changing the resultant header set. Thus, we will achieve the most modifiable and convenient interface for modifying the server response for a particular request, which is the main task of our controller.
As an illustrative example - the implementation of RSS:
namespace Module/News; class RSS { public function request($request) { $request->response->headers['Content-Type'] = 'application/xml'; } public function route($router) { $router->map('^rss\.xml$', [$this, 'feed']); } public function feed($io) { return $this->service('Rss', $this->service('News')->getLatest(0, 50)); } }
The example is rather crude and does not show the whole idea of ​​what I wanted to show, but as I mentioned earlier, the modules may contain traits, in which we can store our controllers for clarity. And if the module is too voluminous, nothing prevents the routing from passing a callback of the form “Module / News / Feed :: xml” from the same namespace.
Finally
As always, I look forward to constructive criticism from your side. In the next part, taking into account the comments on this article, I’ll post all the edits, acknowledgments, and the Github repository. All the best!