📜 ⬆️ ⬇️

Prefixes and Postfixes in PHP (and CSS)



A long time ago I took the practice of using prefixes and postfixes in PHP and in CSS. This is especially true when something goes beyond local visibility and is in global space, take the same models in Yii .

Prefixes and postfixes carry the main task - to make an entity as unique as possible, and so much so that it can be easily found with any text editor. To date, IDEs support a great thing - “Find Usages” (search for uses) , but this does not always help, and I will write about this a little lower.
')
I did not like the naming in the style of the Hungarian notation . I did not like this approach since the days of C ++ / Delphi - I considered it redundant and not always understandable. I liked the BEM implementation, but I do not fully use it either. I tried to isolate and combine the methods I liked most, and I’ll tell you about them.






CSS


All CSS classes I start with the prefix "cl_", identifiers with the prefix "id_". If a class or identifier refers to a block, add after the prefix "b_", if the module is "m_". I also specify any internal states or mini-blocks with prefixes.

.cl_b_promoblock {} #id_m_user_list {} #id_m_order_preview .cl_b_user_info {} .cl_user_list_item .cl_visible {} #id_b_main_menu .cl_main_menu_item.cl_selected {} 


Thus, I always have unique and structurally understandable names. Yes, and to find such names is much easier, if necessary, for example, to refactor and see where this may be reflected.

By the way, this code is easier to drive through compression and obfuscation . Moreover, do not need any analyzers - look for a regular prefix and compress. Actually, therefore, different prefixes for identifiers and classes are used. I think the article about compression and obfuscation will be interesting for the Habr audience, I will try to arrange it as time appears.




PHP (Yii)


It is somehow wrong that controllers, validators, etc. have additional prefixes and postfixes, but models do not. I decided that, in view of the “magic”, Yii would be hard to find where the User class is used, and by simply searching through the text, the word User will appear wherever possible.

Therefore, the model classes are referred to as WbUserModel, WbCatalogItemModel, etc., where:


Validators (WbExistsByPkValidator, WbCensureValidator) and own auxiliary libraries (LArray, LTime, LString) , where the prefix “L” is an abbreviation for Library, also fell under this pattern. As for the libraries, you can also use StringLib or ArrayLib, but my opinion - the prefix "L" puts them in the list of files one after another, which is convenient. By the way, for the “scope” methods, I also add prefixes, for example, ScopePublished () or ScopeLast (int $ limit), to distinguish them from “normal” methods.

The use of such names gives uniqueness, and in which case I can even find all the uses of one or another class without an IDE. I also try in every way to move away from the use of the textual representation of classes and attributes, I especially consider it a great evil when a reference to a class is generated from the union of strings — this cannot be found either through Find Usages or through a text search. For example:

 public function actionGetData($object_type) { $model_class = 'Wb' . $object_type . 'Model'; $model = new $model_class(); return $model; } 


For naming relations in Yii, I also use a special prefix - “R_” (short for Relation) . Thus, when looking at once, it is already clear that this is not an attribute of the model, but a connection with another model. Although, according to the concept of Yii, this is presented as one and the same (model attribute), I still think that these are different things. In addition to adding a prefix, I always add the model class name as well. Yes, this approach may be less beautiful, but it’s dry and concrete - when I look at the code, I immediately understand what it depends on and where the data came from.

 public function relations() { return array( 'R_PriceItems' => array(self::HAS_MANY, WbCatalogPriceItemModel::CLASS, 'category_id'), 'R_CategoryParent' => array(self::BELONGS_TO, WbCatalogCategoryModel::CLASS, array('parent_id' => 'id'), ) } public function RecalculatePriceItems() { foreach ($this->R_PriceItems as $price_item) { $price_item->price = $price_item->new_price; } } 


As you can see in the code above (the relations method) , I define classes for related models dynamically, not text. But this is only possible for PHP> 5.5 . If (and most likely it is) the server does not support this version of PHP, you can extend ActiveRecord and use the _CLASS_ () method instead of CLASS. Then, after switching to PHP> 5.5, it will be possible to easily replace _CLASS_ () with CLASS with the simple “Find And Replace”.

 class ActiveRecord extends CActiveRecord { public static function _CLASS_() { return get_called_class(); } } 





"FOR" or "AGAINST"


In my environment there are supporters of both “FOR” and “AGAINST” of this approach to naming.

In particular, they use the “_” prefix ($ _items, $ _version) for private properties and methods. There are often cases when a project prefix is ​​specified for tables in the database, for example, wb_catalog_item. The source code for YouTube pages everywhere contains in HTML and CSS the prefix "yt-" (this is most likely also so that when connecting to third-party sites there are no conflicts) .

Against such a naming scheme, it is possible to cite the fact that this information is superfluous, and (as it were) you should not litter the code with prefixes and postfixes. In addition, it is necessary to teach other (and new) employees to understand how and what should be called (although I personally do not see this as a problem).

Yes, prefixes and postfixes slow down the writing of code a little, but the code is written once, but more than one read and refactor is read. As for me, it is much easier to read the code in which you can immediately identify it by prefixes and case, where the attribute of the model is, where is the method, and where is scope or relation. The prefix “R_” clearly makes it clear that this is a link, and the postfix “Model” that this is a model. For example, there is a class WebUser - this is a component (extends CWebUser) , and there is a class User - and this is already a model.

And finally ... Yii uses call chains everywhere. For example, $ category-> first_item-> store. In this case, the store is a relation, meaning connection to the warehouse. But at one point, you need to add a new column called store to the catalog_item table. Here the problem begins, because with the usual approach, it is impossible to take and replace the store connection with something else without analyzing the code so that there is no name conflict. In the case of using prefixes, everything will be decided at the “Find And Replace” level in 1-2-3 minutes.




I want to hear from the audience Habr is a constructive discussion of this approach. Perhaps there are other solutions to problems with non-unique names.

Source: https://habr.com/ru/post/222133/


All Articles