Other features of frameworks

Most frameworks have more than just the features that we described in the previous section, even though these are enough to build simple applications as you already did by yourself. Still, most web applications have a lot more common features, so the frameworks tried to implement generic solutions to each of them. Thanks to this, we do not have to reinvent the wheel with features that virtually all medium and big web applications need to implement. We will try to describe some of the most useful ones so that you have a better idea when choosing a framework.

Authentication and roles

Most websites enforce users to authenticate in order to perform some action. The reason for this is to let the system know whether the user trying to perform certain action has the right to do so. Therefore, managing users and their roles is something that you will probably end up implementing in all your web applications. The problem comes when way too many people try to attack your system in order to get the information of other users or performing actions authenticated as someone else, which is called impersonification. It is for this reason that your authentication and authorization systems should be as secure as possible—a task that is never easy.

Several frameworks include a pretty secure way of managing users, permissions, and sessions. Most of the time, you can manage this through a configuration file probably by pointing the credentials to a database where the framework can add the user data, your customized roles, and some other customizations. The downside is that each framework has its own way of configuring it, so you will have to dig into the documentation of the framework you are using at this time. Still, it will save you more time than if you had to implement it by yourself.

ORM

Object-relational mapping (ORM) is a technique that converts data from a database or any other data storage into objects. The main goal is to separate the business logic as much as possible from the structure of the database and to reduce the complexity of your code. When using ORM, you will probably never write a query in MySQL; instead, you will use a chain of methods. Behind the scenes, ORM will write the query with each method invocation.

There are good and bad things when using ORM. On one hand, you do not have to remember all the SQL syntax all the time and only the correct methods to invoke, which can be easier if you work with an IDE that can autocomplete methods. It is also good to abstract your code from the type of storage system, because even though it is not very common, you might want to change it later. If you use ORM, you probably have to change only the type of connection, but if you were writing raw queries, you would have a lot of work to do in order to migrate your code.

The arguable downside of using ORM could be that it may be quite difficult to write complicated queries using method chains, and you will end up writing them manually. You are also at the mercy of ORM in order to speed up the performance of your queries, whereas when writing them manually, it is you who can choose better what and how to use when querying. Finally, something that OOP purists complain about quite a lot is that using ORM fills your code with a large amount of dummy objects, similar to the domain objects that you already know.

As you can see, using ORM is not always an easy decision, but just in case you choose to use it, most of the big frameworks include one. Take your time in deciding whether or not to use one in your applications; in case you do, choose wisely which one. You might end up requiring an ORM different from the one that the framework provides.

Cache

The bookstore is a pretty good example that may help in describing the cache feature. It has a database of books that is queried every time that someone either lists all the books or asks for the details of a specific one. Most of the time the information related to books will be the same; the only change would be the stock of the books from time to time. We could say that our system has way more reads than writes, where reads means querying for data and writes means updating it. In this kind of system, it seems like a waste of time and resources to access the database each time, knowing that most of the time, we will get the same results. This feeling increases if we do some expensive transformation to the data that we retrieve.

A cache layer allows the application to store temporary data in a storage system faster than our database, usually in memory rather than disk. Even though cache systems are getting more complex, they usually allow you to store data by key-value pairs, as in an array.

The idea is not to access the database for data that we know is the same as the last time we accessed it in order to save time and resources. Implementations can vary quite a lot, but the main flow is as follows:

  1. You try to access a certain piece of data for the first time. We ask the cache whether a certain key is there, which it is not.
  2. You query the database, getting back the result. After processing it—and maybe transforming it to your domain objects—you store the result in the cache. The key would be the same you used in step 1, and the value would be the object/array/JSON that you generated.
  3. You try to access the same piece of data again. You ask the cache whether the key is there; here, it is, so you do not need to access the database at all.

It seems easy, right? The main problem with caches comes when we need to invalidate a certain key. How and when should we do it? There are a couple of approaches that are worth mentioning:

  • You will set an expiration time to the key-value pair in the cache. After this time passes, the cache will remove the key-value pair automatically, so you will have to query the database again. Even though this system might work for some applications, it does not for ours. If the stock changes to 0 before the cache expires, the user will see books that they cannot borrow or buy.
  • The data never expires, but each time we make a change in the database, we will identify which keys in the cache are affected by this change and then purge them. This is ideal since the data will be in the cache until it is no longer valid, whether this is 2 seconds or 3 weeks. The downside is that identifying these keys could be a hard task depending on your data structure. If you miss deleting some of them, you will have corrupted data in your cache, which is quite difficult to debug and detect.

You can see that cache is a double-edged sword, so we would recommend you to only use it when necessary and not just because your framework comes with it. As with ORM, if you are not convinced by the cache system that your framework provides, using a different one should not be difficult. In fact, your code should not be aware of which cache system you are using except when creating the connection object.

Internationalization

English is not the only language out there, and you would like to make your website as accessible as possible. Depending on your target, it would be a good idea to have your website translated to other languages too, but how do you do this? We hope that by now you did not answer: "Copy-pasting all the templates and translating them". This is way too inefficient; when making a little change in a template, you need to replicate the change everywhere.

There are tools that can be integrated with either controllers and/or template engines in order to translate strings. You usually keep a file for each language that you have, in which you will add all the strings that need to be translated plus their translation. One of the most common formats for this is PO files, in which you have a map of key-value pairs with originally translated pairs. Later on, you will invoke a translate method sending the original string, which will return the translated string depending on the language you selected.

When writing templates, it might be tiring to invoke the translation each time you want to display a string, but you will end up with only one template, which is much easier to maintain than any other option.

Usually, internationalization is very much tied to the framework that you use; however, if you have the opportunity to use the system of your choice, pay special attention to its performance, the translation files it uses, and how it manages strings with parameters—that is, how we can ask the system to translate messages such as "Hello %s, who are you?" in which "%s" needs to be injected each time.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.228.138